Conversation
* fix: change fetch to http service
* fix(ai): fix ai plugin mcp issue
WalkthroughVersion bumps to 2.8.0 across packages. HTTP response helpers add a fallback return. Mock bundles add TinyGrid/version metadata. Canvas MCP tools gain titles, richer validation/errors, and a new addNode schema; Canvas overlay alignment logic refactored. Layout plugin filtering/type titles adjusted. Page tools add existence checks and a utility to flatten pages. Robot plugin overhauls chat/MCP flow, types, renderers, and server handling; adds system prompt and loading renderer. Minor style tweaks and dependency spec updates. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as User
participant RP as Robot Plugin UI
participant MS as McpServer (picker)
participant MU as useMcp/utils
participant LLM as MetaAPI Chat
participant TE as TinyEngine MCP Tools
U->>RP: Send message
RP->>MU: sendMcpRequest(messages)
MU->>LLM: fetchLLM(formatMessages(history))
LLM-->>MU: { content or tool_calls }
alt tool_calls present
loop For each tool call
MU->>TE: Invoke tool(args)
TE-->>MU: { result | errorCode }
MU->>MU: Update renderContent (loading -> result/error)
end
MU->>LLM: fetchLLM(with toolMessages)
LLM-->>MU: final content
else plain content
MU->>MU: Render markdown to renderContent
end
MU-->>RP: Update last message (content/renderContent)
RP-->>U: Display bubbles (markdown/loading)
sequenceDiagram
autonumber
participant Tool as addNode (MCP)
participant MR as Material Registry
participant DC as DesignCanvas
participant CL as Caller
CL->>Tool: invoke({ newNodeData })
Tool->>MR: useMaterial().getComponent(materialName)
alt component not found or no name
Tool-->>CL: { isError: true, errorCode: COMPONENT_NAME_REQUIRED, next_action: get_component_list }
else valid
Tool->>DC: operateNode({ newNodeData })
DC-->>Tool: { success }
Tool-->>CL: { isError: false, data: newNodeData }
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 19
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
designer-demo/package.json (1)
26-33: Ensure CI Runs on Node.js ≥18 and Specify in designer-demo/package.jsonVite v5.4.2 declares
"engines": { "node": "^18.0.0 || >=20.0.0" }Vitest v3.0.9 declares
"engines": { "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }(Verified via npm registry)
- The root package.json enforces only Node >=16, and designer-demo/package.json has no
enginesfield.- If your CI runs on Node 16, tests or builds will fail.
Action items:
- Confirm your CI is running Node.js 18 or above.
- Add an
enginesblock to designer-demo/package.json to enforce this:"devDependencies": { "@opentiny/tiny-engine-mock": "workspace:^", "@opentiny/tiny-engine-vite-config": "workspace:^", "@vitejs/plugin-vue": "^5.1.2", "cross-env": "^7.0.3", "vite": "^5.4.2", "vitest": "3.0.9" }, + "engines": { + "node": ">=18" + }This ensures consistency between local development and CI environments.
packages/plugins/i18n/src/composable/tools/updateI18n.ts (1)
41-54: Validation does not enforce “at least one translation”; currently always passes.The safeParse against optional fields will succeed even when both zh_CN and en_US are absent, allowing a no-op update to return success. Enforce presence of at least one non-empty translation.
Apply this diff to make the check effective and reject empty-string updates:
- // 验证至少有一个翻译字段 - const translationValidation = z - .object({ - zh_CN: z.string().optional(), - en_US: z.string().optional() - }) - .safeParse(args) - - if (!translationValidation.success) { - // 直接返回验证错误,已经符合新的结构化格式 - return createErrorResponse( - 'Invalid translation fields', - 'At least one translation (zh_CN or en_US) must be provided' - ) - } + // 验证至少有一个翻译字段(非空) + const hasTranslation = + (typeof zh_CN === 'string' && zh_CN.trim() !== '') || + (typeof en_US === 'string' && en_US.trim() !== '') + if (!hasTranslation) { + return createErrorResponse( + 'Missing translation', + 'At least one non-empty translation (zh_CN or en_US) must be provided' + ) + }packages/plugins/i18n/src/composable/tools/getI18n.ts (1)
36-42: EnsuregetLangscan’t produceundefinedbefore useI verified that all i18n composable tools consistently use
.shapefor bothinputSchemaandoutputSchema(e.g. in addI18n.ts, updateI18n.ts, getI18n.ts, delI18n.ts), so there’s no mismatch to address there. However, it is still possible—albeit unlikely—foruseTranslate().getLangs()to returnundefinedornull, which would lead to runtime errors when doingObject.keys(langs)or indexing intolangs[key].Please apply the following mandatory refactor in both getI18n.ts and delI18n.ts (around the callback’s
useTranslatecall):
- packages/plugins/i18n/src/composable/tools/getI18n.ts (lines ~36–42)
- packages/plugins/i18n/src/composable/tools/delI18n.ts (lines ~33–37)
- const { getLangs } = useTranslate() - const langs = getLangs() as Record<string, any> + const { getLangs } = useTranslate() + // guard against undefined/null + const langs = (getLangs?.() as Record<string, unknown>) ?? {}This small change ensures you always have a safe default object and prevents potential crashes if
getLangsever returns nothing.packages/engine-cli/template/designer/public/mock/bundle.json (1)
10521-10558: Typo in parameter name: "selction" should be "selection".This will leak into generated handler signatures and break code completion/mapping.
{ - "name": "selction", + "name": "selection", "type": "Array", "defaultValue": "", "description": { "zh_CN": "选中的表格数据数组" } }packages/plugins/page/src/mcp/tools/getPageDetail.ts (1)
1-86: Ensure consistent ID normalization across all page-related toolsA repo-wide scan for
page.id === idcomparisons uncovered three call sites that currently perform strict equality checks without any normalization:
packages/plugins/page/src/mcp/tools/getPageDetail.tsat line 26packages/plugins/page/src/mcp/tools/delPage.tsat line 24packages/plugins/page/src/mcp/tools/changePageBasicInfo.tsat line 36Strictly comparing raw
page.idand incomingidcan lead to subtle bugs if one is a number, a string with extra whitespace, or differently typed. To make these comparisons robust, normalize both operands before comparing. For example:- const page = allPages.find((page) => page.id === id) + const page = allPages.find((page) => String(page.id).trim() === String(id).trim())Recommended next steps:
- Apply the above normalization diff at each of the three locations.
- (Optional) Extract a shared helper for readability and consistency:
/** Compare two IDs by stringifying and trimming */ function idsEqual(a: unknown, b: unknown): boolean { return String(a).trim() === String(b).trim() } // Usage const page = allPages.find((page) => idsEqual(page.id, id))These changes will safeguard against type or formatting mismatches across all page-management tools.
packages/plugins/page/src/mcp/tools/editSpecificPage.ts (1)
48-64: Handle switchPage errors and return a structured failureIf
switchPagethrows (network/state issues), the tool currently leaks an exception. Wrap it and return a consistent error payload with guidance.- await switchPage(page.id) - - const res = { - status: 'success', - message: `Page now can be edited.`, - data: {} - } - - return { - content: [ - { - type: 'text', - text: JSON.stringify(res) - } - ] - } + try { + await switchPage(page.id) + } catch (error) { + return { + content: [ + { + isError: true, + type: 'text', + text: JSON.stringify({ + errorCode: 'SWITCH_PAGE_FAILED', + reason: error instanceof Error ? error.message : 'Unknown error occurred', + userMessage: 'Failed to open the page for editing.', + next_action: [ + { + type: 'tool_call', + name: 'get_page_list', + args: {}, + when: 'you want to reselect a valid page to edit' + } + ] + }) + } + ] + } + } + + const res = { + status: 'success', + message: `Page now can be edited.`, + data: {} + } + + return { + content: [ + { + type: 'text', + text: JSON.stringify(res) + } + ] + }packages/canvas/DesignCanvas/src/mcp/tools/changeNodeProps.ts (1)
71-78: Wrap operateNode in try/catch to return structured errors
operateNodecan throw on invalid state or schema issues. Return a stable MCP error payload instead of bubbling.- useCanvas().operateNode({ - type: 'changeProps', - id, - value: { props }, - option: { - overwrite - } - }) + try { + useCanvas().operateNode({ + type: 'changeProps', + id, + value: { props }, + option: { + overwrite + } + }) + } catch (error) { + return { + content: [ + { + isError: true, + type: 'text', + text: JSON.stringify({ + errorCode: 'CHANGE_PROPS_FAILED', + reason: error instanceof Error ? error.message : 'Unknown error occurred', + userMessage: `Failed to change props for node: ${id}.` + }) + } + ] + } + }
♻️ Duplicate comments (3)
packages/plugins/tutorial/package.json (1)
32-37: Engines constraint suggestion applies here as wellSame rationale as the help plugin: Vite 5.x implies Node 18+. Consider adding the engines field; if you add it repo-wide, feel free to skip per-package duplication.
packages/plugins/materials/package.json (1)
35-40: Add engines.node ≥18 for Vite 5Same recommendation as other packages in this release.
packages/settings/props/package.json (1)
34-39: Add engines.node ≥18 for consistency with Vite 5Recommend adding the engines constraint; track centrally if you prefer.
English | 简体中文
PR
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
Background and solution
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
New Features
Improvements
Chores