fix(agent): skip invalid JSON candidates - #2683
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. |
There was a problem hiding this comment.
Pull request overview
Updates shared planner/classifier JSON extraction to skip malformed balanced objects and continue to the first valid object.
Changes:
- Continues scanning after
JSON.parsefailures. - Mirrors behavior across Chrome and Firefox.
- Adds regression coverage for both planners.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/chrome/src/agent/json-extract.js |
Adds resilient candidate scanning. |
src/firefox/src/agent/json-extract.js |
Mirrors Chrome parser behavior. |
test/run.js |
Tests malformed-candidate recovery. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Skipping unparseable candidates covered the illustrative-object case but
not the neighbouring one: a `{` that never closes still abandoned the
whole candidate, so a stray brace in prose ahead of the real object
discarded it. Scanning now resumes one character past an unbalanced
opener, capped at 16 restarts so a "{{{{..." response stays linear.
This mirrors the scanner in tool-call-parser.js so the two agree on
recovery, and adds coverage for the brace flood plus the still-standing
limitation that an earlier *valid* non-plan object wins.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Pushed a commit extending the recovery to one more case. No Copilot findings on this one — its review was a summary only. What I added. Skipping unparseable candidates covered the illustrative-object case but not its neighbour: a This is the same fix as #2682, deliberately. The two scanners had drifted apart on exactly this behaviour — each handled one half of the problem — which is worth knowing about since it's how the same bug ended up in both trees. They agree now. Worth noting for reviewers, since the description mentions only the planner: this function also backs three classifier paths — Tests. An unbalanced opener followed by two broken candidates then the real plan; the bounded brace flood; and one pinning the limitation this PR correctly scopes out — an earlier valid non-plan object still wins and returns 1453 passed, security corpus 60/60, Chrome and Firefox copies |
|
Thanks. I reviewed the current head ( I also traced the extractor's planner, classifier/terminal, and visible-media consumers. Their existing shape checks remain in place, so the scanner change makes later parseable JSON reachable but does not make an arbitrary object a valid plan, refusal, plan-only result, or media location. The known first-valid-object limitation remains unchanged. I've updated the PR description to include the unbalanced-opener behavior and the wider consumer set. Local validation is 1,453 passing runner tests with only the existing package/CHANGELOG mismatch, 60/60 security-corpus checks, syntax checks, Chrome/Firefox parity, and |
Problem
Planner and classifier responses can contain an illustrative or malformed object before the intended JSON result. The extractor stopped after either a balanced candidate that failed
JSON.parseor an opening brace that never closed, so a later valid result was discarded.Change
JSON.parseScope and consumers
The extractor serves the planner, progress-intent, safety-refusal, plan-only, and visible-media location paths. Each consumer still applies its existing shape checks; this change only makes a later parseable JSON value reachable. An earlier valid but semantically unrelated object still wins and can cause the consumer to return
null; choosing the first value that normalizes is intentionally out of scope.Validation
node test/run.js? 1,453 passed; the only failure is the pre-existingpackage.json26.0.10 vsCHANGELOG.md26.0.0 assertionnode test/security/injection-corpus.mjs? 60/60 passednode --checkfor both extractor modules ? passedgit diff --check? passed