refactor: clarify tool input coercion - #380
Conversation
◈ PR Lens
Architecture 3 components touched across 3 lanes. Data flow
The other flows — 1 sequence
View
Tip Run 🪧 More tips
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
There was a problem hiding this comment.
🟡 Changes recommended
collectPositionalArgs() currently mishandles an explicit argumentCount = 0 (common when definitions use args: []), which can lead to incorrect coercion behavior and should be fixed before merging.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors tool-input coercion by moving positional-argument extraction into a shared, browser-safe module and wiring separate adapters for RPC-backed tools vs command-backed tools, while keeping the previous helper as a deprecated shim for compatibility.
Changes:
- Introduces
packages/devframe/src/tool-input.tswithtoolInputToRpcArgs()/toolInputToCommandArgs()and deprecatescoerceAgentPositionalArgs()/AgentArgsFallback. - Switches node-side and browser-side call sites (hub command execution, agent host RPC invoke, WebMCP execution) to the new conversion helpers.
- Replaces the old node-only coercion module/tests with new shared tests and updates internal API snapshots/exports.
File summaries
| File | Description |
|---|---|
| tests/snapshots/tsnapi/devframe/internal.snapshot.js | Updates internal snapshot exports to include toolInputToCommandArgs. |
| tests/snapshots/tsnapi/devframe/internal.snapshot.d.ts | Marks legacy coercion types/functions as deprecated and adds toolInputToCommandArgs typing to the internal snapshot. |
| packages/hub/src/node/host-commands.ts | Uses toolInputToCommandArgs when invoking tool-backed commands via the hub. |
| packages/devframe/src/tool-input.ts | Adds the shared, browser-safe tool-input → positional-args conversion utilities and the deprecated compatibility shim. |
| packages/devframe/src/node/host-agent.ts | Uses toolInputToRpcArgs for invoking RPC tools from the node-side agent host. |
| packages/devframe/src/node/agent-args.ts | Removes the old node-only coercion helper (superseded by shared module). |
| packages/devframe/src/node/tests/agent-args.test.ts | Removes old coercion tests (replaced by shared tool-input tests). |
| packages/devframe/src/internal/index.ts | Re-exports the new internal helper and re-exports legacy helpers from the new module with deprecation. |
| packages/devframe/src/client/webmcp.ts | Uses toolInputToRpcArgs to keep WebMCP tool execution aligned with node-side behavior. |
| packages/devframe/src/tests/tool-input.test.ts | Adds tests for the new shared coercion behavior. |
Review details
- Files reviewed: 9/10 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🔵 Needs a closer look
The new shared coercion helper uses prototype-chain key checks (in) for argN detection, which should be switched to own-property checks to avoid surprises with untrusted tool input.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
packages/devframe/src/tool-input.ts:22
collectPositionalArgsuses theinoperator to detectargNkeys. Becauseinwalks the prototype chain, a crafted input likeObject.create({ arg0: ... })(or a Proxy with ahastrap) could be treated as having positional args even when they’re not own properties. Prefer checking own-properties only to avoid prototype-chain surprises when tool input is untrusted.
- Files reviewed: 9/10 changed files
- Comments generated: 0 new
- Review effort level: Lite
Move tool-input conversion into a browser-safe shared module with explicit RPC and command adapters while retaining the old internal helper as a deprecated compatibility shim.
This is subjective but I found this to be clearer