Skip to content

fix(core): tolerate multiple reasoning_opaque values from Copilot - #52190

Closed
param087 wants to merge 1 commit into
anomalyco:devfrom
param087:fix/copilot-multiple-reasoning-opaque
Closed

param087 wants to merge 1 commit into
anomalyco:devfrom
param087:fix/copilot-multiple-reasoning-opaque

Conversation

@param087

Copy link
Copy Markdown

Fixes the AI_InvalidResponseDataError reported 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_opaque before each tool call, so one streamed response legitimately carries several of them. The chat stream parser treats the second value as a protocol violation:

if (delta.reasoning_opaque) {
  if (reasoningOpaque != null) {
    throw new InvalidResponseDataError({
      data: delta,
      message: "Multiple reasoning_opaque values received in a single response. Only one thinking part per response is supported.",
    })
  }
  reasoningOpaque = delta.reasoning_opaque
}

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_opaque per 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:

if (partOpaque && !reasoningOpaque) {
  reasoningOpaque = partOpaque
}

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 a multipleReasoningOpaque fixture (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

  • The new test fails on dev with exactly the reported error, and passes with the fix.
  • bun test test/github-copilot/ → 36 pass, 0 fail.
  • Prettier clean; oxlint warning 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_opaque field; 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.

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
@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Sep 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

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.

@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@github-actions

Copy link
Copy Markdown
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.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Sep 30, 2026
@github-actions github-actions Bot closed this Sep 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant