fix(agents): name the export and the empty value the sandbox refused - #5299
Merged
Conversation
Three sandbox refusals named the failure but not the remedy, and two of them
sent a caller after the wrong cause.
An unknown named import from a capability module fell through to QuickJS as
"Could not find export 'generateImage'" — no export list, no near match — so a
model that reaches for the camelCase spelling guesses again. `mountCapabilityModules`
already parses the body for its specifiers; it now checks the names too, and
refuses with the module's exports and the wire name that matches. `staticImportBindings`
in node-sdk is the AST half.
`missingArgsMessage` listed `Object.keys(args)` under "Got", including keys
whose value was null. `edit_storyboard({storyboard_id, ops})` with an unset
variable therefore read "missing required argument storyboard_id. Got:
storyboard_id, ops" — a report that contradicts itself and points at the
spelling, which was already right. It now says the key is right and the value
is missing.
The dynamic-import refusal names the static import to use instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Three sandbox refusals named the failure but not the remedy, and two of them sent the caller after the wrong cause. An unknown named import from a capability module fell through to QuickJS as
Could not find export 'generateImage'— no export list, no near match — so a model that reaches for the camelCase spelling just guesses again;mountCapabilityModulesalready parses the body for its specifiers, so it now checks the imported names too and refuses with the module's export list and the wire name that matches (staticImportBindingsin node-sdk is the AST half).missingArgsMessagelistedObject.keys(args)under "Got" including keys whose value was null, soedit_storyboard({storyboard_id, ops})with an unset variable readmissing required argument storyboard_id. Got: storyboard_id, ops— a report that contradicts itself and points at a spelling that was already right (withSnakeCaseAliasesacceptsstoryboardIdtoo); it now says the key is right and the value is missing. And the dynamic-import refusal names the static import to use instead.Verification
npm run test:affected— passes except@nodetool-ai/image-nodes, which fails identically on a clean stash: it is the documented headless-WebGPU gap (Dawn/Vulkan, no ICD installed), not this diff.npm run typecheck— web and electron clean;mobilefails on uninstalled Expo/React Native deps, unchanged by this diff and untouched by it.npm run lint— exit 0.npm run nodetool -- harness gate --base origin/main—Gate: 12/12 selfchecks passed.npm run test --workspace=packages/node-sdk— 1185 passed, 2 skipped.packages/agents:capability-module-exports,capabilities-args,capabilities-dispatcher,codeact-executor,chat-codeact(91 passed), plusjs-sandbox(137),js-sandbox-modules(38),js-scripts-capabilities(41) for the dynamic-import message.The import check is pinned in both directions rather than only in the failing one:
serves an import that names a real exportandleaves a default import alonepass through, and the four refusal cases fail. The registry cases derive the wire name from the live module spec, so the check is proven againstmedia/modelsas they actually declare themselves rather than against a literal that could go stale.Agent capabilities
No capability is added and no declared contract changes.
npm run capabilities:check—capability table is current (224 capabilities)Worth noting for reviewers: the first draft of the new test spelled
generate_imageandfind_modelas literals, andcapabilities:syncthen attributed the file as coverage forgenerate_image, displacingmcp-tools.test.tsfrom that entry — a test that only mentions a name reading as a test that exercises it. The test now derives every registry name it asserts on and names its session-graft exportsdo_a_thing/find_a_thing, so the table is untouched.New checks
packages/agents/tests/capability-module-exports.test.tsare the inverted direction, and the two pass-through cases prove it does not refuse everything.staticImportBindingsis pinned separately inpackages/node-sdk/tests/static-import-bindings.test.ts(5 cases, including a default/namespace import contributing no names).Generated by Claude Code