Harden review JSON parsing against reasoning models

Some Fireworks models emit chain-of-thought before the JSON review, and
that preamble can contain stray "{". The old first-"{"-to-last-"}" span
then grabbed reasoning braces and failed to parse (seen live on a real
PR). Scan each "{" and return the first substring that actually decodes
to an object instead, so a preamble or trailing prose no longer breaks
the review.
This commit is contained in:
Adam Moussa 2026-07-01 19:11:09 -04:00
parent 89494c1710
commit c07e4397aa
No known key found for this signature in database
2 changed files with 21 additions and 4 deletions

View file

@ -173,7 +173,18 @@ def _safe_json(text: str) -> dict[str, Any]:
try:
return json.loads(text)
except json.JSONDecodeError:
start, end = text.find("{"), text.rfind("}")
if start != -1 and end != -1:
return json.loads(text[start : end + 1])
raise
pass
# Reasoning models often emit chain-of-thought (which may contain stray "{")
# before the JSON object. Scan every "{" and return the first that decodes to
# an object, rather than assuming the span from the first "{" to the last "}".
decoder = json.JSONDecoder()
for i, ch in enumerate(text):
if ch != "{":
continue
try:
obj, _ = decoder.raw_decode(text[i:])
except json.JSONDecodeError:
continue
if isinstance(obj, dict):
return obj
raise json.JSONDecodeError("no JSON object found", text, 0)

View file

@ -36,6 +36,12 @@ def test_safe_json_prose_wrapped() -> None:
assert _safe_json(text) == {"summary": "ok"}
def test_safe_json_skips_reasoning_braces() -> None:
# A reasoning preamble containing stray "{" must not confuse extraction.
text = 'We should return {the result}. Final: {"summary": "ok", "block": []} done.'
assert _safe_json(text) == {"summary": "ok", "block": []}
def test_safe_json_malformed_raises() -> None:
with pytest.raises(json.JSONDecodeError):
_safe_json("this is not json at all")