Repository navigation
Conversation
Copilot models with interleaved thinking (Claude Opus 5/5.5, Fable 5.1) emit a fresh signed reasoning_opaque before each tool call, so a single streamed response can carry several of them. The chat stream parser threw InvalidResponseDataError on the second value, which aborted the turn. The wire format carries a single reasoning_opaque per assistant message, and convert-to-openai-compatible-chat-messages already reconciles multiple parts with a first-wins rule. Apply the same rule in the stream parser instead of failing: keep the first signature and ignore later ones. Refs anomalyco#51466
Contributor
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 2 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
Contributor
|
Thanks for your contribution! This PR doesn't have a linked issue. All PRs must reference an existing issue. Please:
See CONTRIBUTING.md for details. |
Contributor
|
The following comment was made by an LLM, it may be inaccurate: |
Contributor
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window. Feel free to open a new pull request that follows our guidelines. |
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.
Fixes the
AI_InvalidResponseDataErrorreported in #51466 (also #17011, #20434).Problem
Copilot models that use interleaved thinking — Claude Opus 5/5.5 and Fable 5.1 — emit a fresh signed
reasoning_opaquebefore each tool call, so one streamed response legitimately carries several of them. The chat stream parser treats the second value as a protocol violation:The throw aborts the turn mid-stream. It reproduces on any multi-tool-call turn with thinking enabled, which is why it shows up as "opencode stops working during normal work" rather than as a specific action.
Why first-wins is the right behaviour
The transport carries exactly one
reasoning_opaqueper assistant message, and the outbound converter already reconciles multiple parts with a first-wins rule rather than erroring —convert-to-openai-compatible-chat-messages.ts:So the parser was strictly less tolerant than the converter feeding it. This change makes the two consistent: keep the first signature, ignore subsequent ones.
Changes
openai-compatible-chat-language-model.ts: replace the throw with a first-wins guard, with a comment explaining why multiple values are expected rather than exceptional.copilot-chat-model.test.ts: add amultipleReasoningOpaquefixture (interleaved thinking → two tool calls, two signatures) and a regression test asserting no stream error, first-wins metadata, and that both tool calls still arrive.Verification
devwith exactly the reported error, and passes with the fix.bun test test/github-copilot/→ 36 pass, 0 fail.oxlintwarning counts unchanged on both touched files (5 and 3, same as baseline).Scope / limitations
This is deliberately minimal — it stops a crash and does not attempt to preserve every signature. Full multi-signature fidelity for interleaved thinking would need a wire-format change, since the assistant message has a single
reasoning_opaquefield; that seems worth treating as separate work. If maintainers would prefer last-wins instead of first-wins, that is a one-line change, but first-wins is what keeps the parser aligned with the existing converter and leaves all current tests green.