fix: parse nested bare JSON tool calls - #2682
Open
alectimison-maker wants to merge 1 commit into
Open
Conversation
|
@alectimison-maker is attempting to deploy a commit to the esokullu's projects Team on Vercel. A member of the Team first needs to authorize it. |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
An unmatched opening brace before a valid tool call prevents the scanner from recovering that call.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
Updates fallback parsing to support nested bare-JSON tool calls while preserving browser parity.
Changes:
- Adds a string-aware balanced-object scanner.
- Adds nested and multiple-call regression tests.
- Keeps Chrome and Firefox implementations identical.
File summaries
| File | Description |
|---|---|
src/chrome/src/agent/tool-call-parser.js |
Adds balanced JSON extraction. |
src/firefox/src/agent/tool-call-parser.js |
Mirrors Chrome parser changes. |
test/run.js |
Tests nested arguments and call ordering. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Balanced
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
Comment on lines
+18
to
+22
| if (start < 0) { | ||
| if (char === '{') { | ||
| start = i; | ||
| depth = 1; | ||
| } |
Comment on lines
+18
to
+22
| if (start < 0) { | ||
| if (char === '{') { | ||
| start = i; | ||
| depth = 1; | ||
| } |
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.
Summary
Motivation
Local and OpenAI-compatible model backends can emit a tool call in ordinary message content
instead of the structured
tool_callsfield. The existing bare-JSON fallback matched onlyobjects without nested braces, so a valid call such as a
clickwith nested metadata wasignored and could surface as final assistant text instead of executing.
Design
The fallback now scans the already bounded model text for balanced JSON objects while respecting
quoted strings and escapes. Each candidate still has to parse as JSON and pass the existing tool
allowlist. Wrapped JSON, XML,
call:name{}handling, the 10,000-character cap, and the OpenAI-stylefallback output shape are unchanged.
The scanner is used only when the earlier wrapped/XML parsers did not find a call. A greedy regex
was rejected because it can merge adjacent calls, and parsing the entire response was rejected
because models commonly include prose around tool-call JSON.
Testing
node test/security/injection-corpus.mjs— 60/60 passednode --check src/chrome/src/agent/tool-call-parser.js— passednode --check src/firefox/src/agent/tool-call-parser.js— passednode test/run.js— 1,449 passed; one pre-existing repository-version assertion fails becausepackage.jsonis26.0.10while the newestCHANGELOG.mdentry is26.0.0git diff --check— passedCompatibility and risks
No public API or provider behavior changes for already supported formats. The parser remains
bounded and allowlisted. The main residual risk is accepting a valid allowlisted JSON object
embedded in explanatory model text; that is the intended purpose of this fallback and matches
the previous flat-object behavior.
Scope
This does not add new tool-call syntaxes, change provider normalization, or relax parser limits.