fix(agent): parse single-line fenced JSON in _parse_json#483
Merged
Conversation
_parse_json split the fenced block on newlines to strip the code fence,
so a response where the opening fence, language tag, and JSON payload
share one line (e.g. ```json{"site": "MAIN"}```) left it with an
empty string after splitting and joining, and the JSON was discarded
even though it was valid.
Replace the line-splitting with a single regex that matches the fence
and optional language tag regardless of whether they share a line with
the payload, covering both layouts uniformly.
Fixes IBM#482
Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
DhavalRepo18
self-requested a review
July 26, 2026 10:38
DhavalRepo18
approved these changes
Jul 26, 2026
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.
_parse_jsonsplit a fenced response on newlines to strip the```code fence:When the opening fence, language tag, and JSON share one line (e.g.
```json{"site": "MAIN"}```, no internal newline),text.splitlines()returns a single-element list.lines[-1].strip() == "```"is then false, soinner = lines[1:]is[], andtextbecomes an empty string beforejson.loadsor the brace-scanning fallback ever run. Valid JSON is discarded and_parse_jsonreturnsNone; the caller (_resolve_args_with_llm) treats that as unparseable and calls the tool with no arguments instead of the arguments the LLM produced.Replaced the split/join with a single regex that matches the fence and optional language tag whether or not they share a line with the payload, so both layouts extract the same content.
Verified
Docker (
python:3.12-slim, editable install,python3 -c 'import agent.plan_execute.executor as m; print(m.__file__)'confirmed the real repo module, not a stale install):pytest src/agent/tests/on this branch: 74 passed, including the two new regression tests.executor.pyto HEAD (e5dc83b) while keeping the new tests:pytest -k single_line_fencefails withassert None == {'site': 'MAIN'}on both, confirming they fail on main and pass on the fix.ruff check/ruff format --checkon both changed files: clean. The 6 pre-existingruff checkfindings elsewhere inexecutor.py(import order, an undefined forward-ref type, twoSIM117nested-withsuggestions, and aremoveprefixsuggestion in the unrelated_parse_tool_callhelper) are unchanged from HEAD and outside this diff's scope.Not touched:
_parse_tool_calla few lines below has the same fence-splitting shape and would show the same bug on a single-line input, but its own docstring says it's "utility, not used in main path," so it isn't part of this fix.Fixes #482