Repository navigation
fix(core): accept interleaved Copilot reasoning_opaque values - #54207
Conversation
There was a problem hiding this comment.
No blocking problems found. On the base branch, the new interleaved-opaque stream fixture reproduces the Multiple reasoning_opaque values received in a single response error from #51466, and the replay test fails because base pairs the first opaque value with only the last reasoning text. With this PR both pass, along with the rest of test/github-copilot/ (37/37) and typecheck in packages/core. Each reasoning segment's reasoning-end and its tool call keep the opaque value that came with them, and the replayed text and opaque value stay scoped to one assistant message. Not checked against live Opus 5.5 traffic.
Public API unchanged: this only changes the internal Copilot chat stream parser and message conversion.
Closes #51466
Port of #54201 (merged on
v2).Claude models with thinking enabled (e.g. Opus 5.5) on Copilot's
/chat/completionsemit a newreasoning_opaquebefore each tool call, so one response can carry several. The stream parser threwMultiple reasoning_opaque values received in a single responseon the second one, aborting any multi-tool-call turn. Claude lands on this route when the Copilot/modelsrequest fails and the static catalogue is used.Changes:
reasoning_opaqueinstead of throwing. Each reasoning segment'sreasoning-endand its tool call carry the value that arrived with them; finish metadata carries the latest.reasoning_opaquewith the concatenated reasoning text. Previously it paired the first opaque with only the last reasoning part's text.This matches the Copilot VS Code client, which accumulates thinking text across deltas, overwrites the id with each new opaque, and replays the final pair.
Verification:
bun test test/github-copilot/andbun typecheckinpackages/corepass./chat/completions(Sonnet 5, Sonnet 5.5, Haiku 5.5; effort high/max) through the patched parser and replay: ~75 steps, no errors, all replayed opaques accepted. Those models only emitted one thinking segment per response, and Opus 5.5 was unavailable on the test account, so the interleaved case itself is covered by fixtures rather than live traffic.Also covers the joined-reasoning-text replay that #53191 leaves out.