fix(agents): recover wrapped Pi JSON output - #195
Merged
kunchenguid merged 5 commits intoAug 11, 2026
Merged
Conversation
PiAgent parsed its final assistant message with raw JSON.parse, unlike every other adapter (acp, copilot, opencode, rovodev) which route through parseAgentJson. When the pi agent prefixes a short prose summary before the JSON object (e.g. "Iteration 3 complete. ..."), JSON.parse throws on the first non-JSON token, every iteration fails, and gnhf hits its maxConsecutiveFailures limit and aborts. Route PiAgent through parseAgentJson with the schema validator as the accept predicate and a no-predicate fallback (mirroring opencode), so schema-invalid JSON still surfaces as "Invalid pi output" instead of "Failed to parse pi output". Add a regression test for prose-then-JSON. Fixes kunchenguid#154
The parseAgentJson + validateAgentOutput fallback shape was duplicated identically in parsePiOutput, parseOpenCodeOutput, and parseCopilotOutput (only the function name and the no-JSON error string differed). Extract a single parseAgentOutput(text, schema, agentLabel) next to validateAgentOutput in types.ts and route all three adapters through it. Behavior is preserved: the per-agent SyntaxError message is retained via agentLabel, and each adapter keeps its own caller-side error formatting (pi distinguishes Failed vs Invalid; opencode/copilot use a single message).
5 tasks
Owner
|
Thanks @jasonqlwilliams-alt - merged! Really appreciate the contribution. |
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.
Intent
Resolve GNHF issues #154 and #185 by routing the Pi adapter through the repository's shared JSON-recovery path instead of calling JSON.parse(finalText) directly. Review community PR #164 in full, including discussion and its failing Windows check, and reuse its sound implementation with contributor attribution preserved, correcting remaining defects only on this task branch. Pi must accept schema-valid JSON wrapped in Markdown fences and a prose prefix followed by the final schema-valid JSON object, with adapter-level regression tests for both. Existing Copilot, OpenCode, and other shared JSON-recovery behavior must remain green. Understand the Windows failure and either fix it or show with concrete evidence that it is unrelated. Produce a review-ready PR through the no-mistakes pipeline. Do not merge, publish a package, change release policy, waive checks, or modify the contributor's branch or PR.
What Changed
parseAgentOutputhelper.Risk Assessment
✅ Low: The change reuses the existing recovery logic without altering sibling semantics, adds behavioral Pi regressions for both required cases, preserves contributor attribution, and PR #164's Windows failure was confined to unchanged timeout-prone tests while all affected adapter suites passed.
Testing
Inspected the full target and community PR context, ran focused Pi/Copilot/OpenCode/shared-parser plus ACP/Rovo recovery tests, exercised both required Pi wrappers through the bundled CLI, reproduced the prose failure on the base build, recorded reviewer-visible evidence, and cleaned all generated worktree artifacts; everything passed with no actionable findings.
Evidence: Pi recovery end-to-end transcript
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
✅ **Test** - passed
✅ No issues found.
Inspected the target withgit diff 3041614ba7f45fc758eb156716a1343942b4a052 c68a596f2c4312c2ef086960f209e065322a4586and verified contributor-authored commits usinggit show -s --format=fuller.Reviewed PR #164 usinggh-axi pr view 164 --full --comments --reviews,gh-axi pr diff 164 --full,gh-axi pr checks 164, andgh-axi run view 28320260845 --job 84188300892 --log-failed.pnpm exec vitest run src/core/agents/pi.test.ts src/core/agents/copilot.test.ts src/core/agents/opencode.test.ts src/core/agents/types.test.ts src/core/agents/json-extract.test.tspnpm exec vitest run src/core/agents/rovodev.test.ts src/core/agents/acp.test.ts -t "recovers JSON when rovodev|strips a leading|extracts a JSON object"Built the target withpnpm run build.Ran the bundled target CLI with a mock Pimessage_endcontaining prose followed by schema-valid JSON; GNHF reported1 good / 0 failedand committedRecovered prose-prefixed Pi output.Ran the bundled target CLI with a mock Pimessage_endcontaining Markdown-fenced schema-valid JSON; GNHF reported1 good / 0 failedand committedRecovered fenced Pi output.Archived and built base commit3041614ba7f45fc758eb156716a1343942b4a052, then ran the identical prose-prefixed mock Pi stream; GNHF reproducedFailed to parse pi output,0 good / 1 failed, and no commit.Removed generatednode_modules,dist, and the temporary base-build source, then verified the worktree remained clean.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.