You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fixes truncated responses whose continuation parts get glued together with no separator. When _should_treat_stop_as_truncated() fires and the agent requests a continuation, each partial chunk is collected into truncated_response_parts and later joined with "".join(...). If the truncation cut mid-token (no whitespace on either boundary), the end of one part sticks directly onto the start of the next, producing corrupted output such as index.htmlReview the 5 changes.
Root Cause
Two call sites in agent/conversation_loop.py join the truncated parts with an empty separator:
Neither boundary check exists: a part ending without whitespace followed by a part starting without whitespace is concatenated verbatim.
Change
Add a module-level helper _join_truncated_parts(parts, trailing="") in agent/conversation_loop.py:
Joins parts with "\n" only when the previous part does not end with whitespace AND the next part does not start with whitespace.
Skips empty parts (an empty chunk must not force a separator decision between its non-empty neighbors).
Applies the same whitespace-aware boundary treatment to an optional trailing suffix (the final, untruncated response) against the last part.
Both call sites now use the helper. Output that already carries whitespace at the boundary is left byte-for-byte unchanged.
Verification
New unit tests in tests/run_agent/test_truncated_parts_join.py cover:
parts that would glue (no whitespace on either boundary) get a newline inserted (including the exact index.html / Review the 5 changes case from the issue);
parts already separated by whitespace (space, tab, newline) are preserved unchanged;
empty parts are skipped, including all-empty and single-part lists;
the trailing suffix boundary, with and without existing whitespace.
pytest tests/ -k "truncat" -q -> 183 passed, 3 skipped, 1 failed. The single failure (test_discord_clarify_buttons.py::test_truncates_long_no_space_choice_on_soft_boundary) is order-dependent flakiness in the batch: it passes in isolation and in its full file with this diff applied.
Summary:
The join fix this PR describes is already on main: _join_truncated_parts exists in the tree and both call sites the root-cause section names already route through it, so the diff is a refactor of code already on main, not the fix the description presents.
Problems:
On origin/main, the exhausted-continuation path calls _join_truncated_parts(truncated_response_parts) (agent/conversation_loop.py:3314) and the codex finalization path calls _join_truncated_parts([*truncated_response_parts, final_response]) (agent/conversation_loop.py:7266) — both with the newline-insertion boundary check this PR's diff extends with a trailing parameter.
The root-cause section quotes both sites as "".join(truncated_response_parts) joins and states "Neither boundary check exists"; the PR's own diff base already contains _join_truncated_parts with that check.
The diff's call-site change is the codex finalization site moving to _join_truncated_parts(truncated_response_parts, trailing=final_response); the exhausted-continuation site is not part of the diff.
Solution:
Update the description to state that the fix is already on main and to present the diff as a refactor of the existing helper (the trailing parameter and empty-part skip) rather than as the first fix for #78577. The PR's Closes #78577 will auto-close the issue on merge; the behavior it describes is already fixed on main.
Checked against 38e44ed — the tip of fix-78577-work when this was written — and 1c94338, main at the same moment.
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
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
Fixes truncated responses whose continuation parts get glued together with no separator. When
_should_treat_stop_as_truncated()fires and the agent requests a continuation, each partial chunk is collected intotruncated_response_partsand later joined with"".join(...). If the truncation cut mid-token (no whitespace on either boundary), the end of one part sticks directly onto the start of the next, producing corrupted output such asindex.htmlReview the 5 changes.Root Cause
Two call sites in
agent/conversation_loop.pyjoin the truncated parts with an empty separator:run_conversation()— exhausted-continuation path (~L3103):partial_response = agent._strip_think_blocks("".join(truncated_response_parts)).strip()run_conversation()— codex finalization path (~L6926):final_response = "".join(truncated_response_parts) + final_responseNeither boundary check exists: a part ending without whitespace followed by a part starting without whitespace is concatenated verbatim.
Change
Add a module-level helper
_join_truncated_parts(parts, trailing="")inagent/conversation_loop.py:"\n"only when the previous part does not end with whitespace AND the next part does not start with whitespace.trailingsuffix (the final, untruncated response) against the last part.Both call sites now use the helper. Output that already carries whitespace at the boundary is left byte-for-byte unchanged.
Verification
tests/run_agent/test_truncated_parts_join.pycover:index.html/Review the 5 changescase from the issue);trailingsuffix boundary, with and without existing whitespace.pytest tests/run_agent/test_truncated_parts_join.py tests/run_agent/test_anthropic_truncation_continuation.py -q-> 20 passed.pytest tests/ -k "truncat" -q-> 183 passed, 3 skipped, 1 failed. The single failure (test_discord_clarify_buttons.py::test_truncates_long_no_space_choice_on_soft_boundary) is order-dependent flakiness in the batch: it passes in isolation and in its full file with this diff applied.Closes
Closes #78577