Skip to content

fix(ai): preserve terminal reasoning metadata - #44997

Merged
rekram1-node merged 1 commit into
v2from
terminal-reasoning
Aug 25, 2026
Merged

rekram1-node merged 1 commit into
v2from
terminal-reasoning

Conversation

@rekram1-node

Copy link
Copy Markdown
Collaborator

Summary

  • reconcile pending reasoning items against authoritative response.completed.response.output when providers omit response.output_item.done
  • preserve terminal encrypted reasoning metadata in canonical reasoning events, assistant messages, and subsequent stateless requests
  • avoid duplicating reasoning items already finalized normally and preserve completed-output ordering alongside pending function calls
  • cover native OpenAI Responses and generic Responses-compatible provider metadata namespaces

Before and after

Some Responses streams start a reasoning item and stream its summary but omit the individual item-completion event:

{ "type": "response.output_item.added", "item": { "type": "reasoning", "id": "rs_1", "encrypted_content": null } }
{ "type": "response.reasoning_summary_text.delta", "item_id": "rs_1", "delta": "Checked the diff." }
{ "type": "response.completed", "response": { "output": [
  { "type": "reasoning", "id": "rs_1", "encrypted_content": "terminal-state", "summary": [{ "type": "summary_text", "text": "Checked the diff." }] }
] } }

Before: Generic stream finalization closed the reasoning block without its authoritative terminal metadata, so the assistant message retained reasoningEncryptedContent: null. A later store: false request omitted the reasoning item because it lacked encrypted continuation state.

After: The terminal output item closes the pending reasoning block with its authoritative metadata:

{ "type": "reasoning-end", "id": "rs_1:0", "providerMetadata": { "openai": { "itemId": "rs_1", "reasoningEncryptedContent": "terminal-state" } } }

The next stateless request can therefore replay the reasoning item:

{ "type": "reasoning", "id": "rs_1", "summary": [{ "type": "summary_text", "text": "Checked the diff." }], "encrypted_content": "terminal-state" }

Already-finalized reasoning items are not emitted twice.

Verification

  • bun test test/partial-json.test.ts test/tool-stream.test.ts test/provider/openai-responses.test.ts test/provider/openai-compatible-responses.test.ts test/provider/openai-responses-websocket.recorded.test.ts test/provider/openai-chat.test.ts test/provider/anthropic-messages.test.ts test/provider/bedrock-converse.test.ts test/provider/xai-responses.test.ts test/response.test.ts test/tool-runtime.test.ts --timeout 30000 --only-failures (352 passing)
  • RECORDED_PREFIX=openai-responses bun test test/provider/golden.recorded.test.ts --timeout 30000 --only-failures
  • bun typecheck from packages/ai
  • bunx prettier --check packages/ai/src/protocols/open-responses.ts packages/ai/test/provider/openai-responses.test.ts packages/ai/test/provider/openai-compatible-responses.test.ts

@rekram1-node
rekram1-node merged commit 7f51da5 into v2 Aug 25, 2026
8 of 9 checks passed
@rekram1-node
rekram1-node deleted the terminal-reasoning branch August 25, 2026 15:37
jinhuang712 pushed a commit to jinhuang712/opencode that referenced this pull request Sep 26, 2026
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.

1 participant