Skip to content

fix: preserve streamed reasoning details - #2604

Merged
hallerite merged 3 commits into
mainfrom
fix/reasoning-details-hash
Sep 15, 2026
Merged

hallerite merged 3 commits into
mainfrom
fix/reasoning-details-hash

Conversation

@mikasenghaas

@mikasenghaas mikasenghaas commented Sep 15, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Rebuild streamed reasoning from raw chat completion chunks in the bundled harness.
  • Support current vLLM reasoning, legacy reasoning_content, and structured reasoning_details fields.
  • Join reasoning text while preserving structured scalar metadata such as id, index, format, and signature.
  • Use one field-aware override path for repeated role metadata and provider reasoning fields.
  • Keep the interception parser and graph hashing unchanged.

Verification

  • Before: two structured reasoning chunks with id: "r1" and format: "unknown" replayed as id: "r1r1" and format: "unknownunknown". The intercepted and replayed message hashes differed.
  • After: the harness replays scalar metadata once and joins text deltas. The intercepted and replayed message hashes match.
  • uv run eval terminal-bench-2 --env.taskset.tasks '["fix-git"]' --env.agent.harness.id bash -n 1 -r 2 -c 2 --no-push: both rollouts solved the task with reward 1.0. They took 13 and 12 turns, with 1 branch each.
  • A scripted uv run eval echo-tool-v1 ... comparison completed with reward 1.0. Base main produced 2 turns and 2 branches. This branch produced 2 turns and 1 branch.
  • The regression test covers repeated role metadata plus reasoning, reasoning_content, and reasoning_details stream fields.
  • uv run pytest tests/: 87 passed, 75 skipped.
  • uv run pre-commit run --all-files: passed.
    \n- Current-head live rerun after the review refactor: reward 1.0, 15 turns, 1 branch, and no errors.\n\n

Note

Preserve streamed reasoning details and role in core.chat

  • Adds _accumulate_streamed_message to core.py to concatenate reasoning text and merge compatible reasoning-detail fragments across streamed chunks.
  • Updates core.chat to apply these accumulated fields to the final completion message, defaulting the role to assistant when missing.
  • Adds a mocked SSE test in test_e2e.py to verify the chat harness preserves concatenated reasoning and details.

Macroscope summarized 5367fa3.


Note

Medium Risk
Changes the shared harness streaming completion assembly path used by eval rollouts; incorrect merging could alter intercepted messages and downstream replay/hash behavior.

Overview
Fixes how the bundled harness chat() rebuilds assistant messages from streaming chat completion chunks so provider reasoning fields survive without SDK mis-merging.

Instead of forcing role = "assistant" on the final snapshot, the stream loop now accumulates per-choice overrides for role, reasoning, reasoning_content, and reasoning_details. String reasoning fields are concatenated across deltas; reasoning_details entries of the same type merge text/summary while keeping scalar metadata (id, index, format, signature) from the first chunk rather than duplicating them.

Adds test_chat_harness_preserves_streamed_reasoning, which mocks an SSE stream and asserts the assembled message matches joined reasoning text and a single structured reasoning.text detail.

Reviewed by Cursor Bugbot for commit 5367fa3. Bugbot is set up for automated code reviews on this repo. Configure here.

@mikasenghaas
mikasenghaas force-pushed the fix/reasoning-details-hash branch from bea1899 to d110415 Compare September 15, 2026 03:47
@mikasenghaas mikasenghaas changed the title fix: dedup replayed reasoning details onto their node fix: preserve streamed reasoning details Sep 15, 2026

@mikasenghaas mikasenghaas left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make sure this works for any streamed reasoning (no standards since oai chat completions doesnt support)

Comment thread verifiers/v1/harnesses/utils/core.py Resolved
The OpenAI stream accumulator concatenates repeated string metadata in
provider-specific reasoning details. Preserve scalar fields while joining
reasoning text so tool requests replay the message that the interceptor
recorded.
@mikasenghaas
mikasenghaas force-pushed the fix/reasoning-details-hash branch from d110415 to 4f30b22 Compare September 15, 2026 04:20
@mikasenghaas
mikasenghaas requested review from eligotts, hallerite and samsja and removed request for samsja September 15, 2026 04:35
Comment thread verifiers/v1/harnesses/utils/core.py Resolved
@mikasenghaas
mikasenghaas marked this pull request as ready for review September 15, 2026 05:32
@macroscopeapp

macroscopeapp Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 5367fa3

Macroscope's review found this PR approvable — This is a narrowly scoped harness bug fix that preserves streamed reasoning fields and adds a mocked SSE regression test. Runtime impact is confined to the affected streamed-completion metadata path, with no schema, infrastructure, security, billing, or authentication changes.

You can add or adjust custom eligibility rules. Learn more.

@hallerite
hallerite merged commit ac2ec29 into main Sep 15, 2026
18 of 19 checks passed
@hallerite
hallerite deleted the fix/reasoning-details-hash branch September 15, 2026 10:32
mikasenghaas added a commit that referenced this pull request Sep 15, 2026
Main fixed the cause in the bash harness's streaming path (#2604), so
replayed reasoning details match verbatim and the hash needs no
special case; the regression test for the mangled form goes with it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants