Part of #1. Depends on #3.
Goal
The Responses API streams a richer event vocabulary than chat/completions. We need a faithful translator on both consumer surfaces:
/v1/responses clients should see canonical OpenAI Responses SSE events
/v1/messages clients should see Anthropic SSE with thinking_delta interleaved correctly
Event vocabulary to handle
From upstream (forward as-is on /v1/responses, translate on /v1/messages):
| Event |
Forwarded? |
Maps to (Anthropic) |
response.created |
✅ |
initial message_start |
response.in_progress |
✅ |
drop / ping |
response.output_item.added (type=reasoning) |
✅ |
content_block_start { type:'thinking' } |
response.reasoning.delta |
✅ |
thinking_delta |
response.reasoning_summary_text.delta |
✅ |
additional thinking_delta (configurable channel) |
response.reasoning.done |
✅ |
signature_delta (carry encrypted_content) + content_block_stop |
response.output_item.added (type=message) |
✅ |
content_block_start { type:'text' } |
response.output_text.delta |
✅ |
text_delta |
response.output_text.done |
✅ |
content_block_stop |
response.output_item.added (type=function_call) |
✅ |
content_block_start { type:'tool_use' } |
response.function_call_arguments.delta |
✅ |
input_json_delta |
response.output_item.done |
✅ |
content_block_stop |
response.completed |
✅ |
message_delta (usage) + message_stop |
response.failed |
✅ |
error envelope |
Tasks
Acceptance criteria
- Manual test: stream a
gpt-5.3-codex agent loop with tool use through /v1/messages, confirm Claude Code renders thinking, tool calls, and text in correct order
- Event ordering tests added to
tests/ covering reasoning-then-text, text-then-tool, tool-then-text-then-reasoning sequences
File pointers
Part of #1. Depends on #3.
Goal
The Responses API streams a richer event vocabulary than chat/completions. We need a faithful translator on both consumer surfaces:
/v1/responsesclients should see canonical OpenAI Responses SSE events/v1/messagesclients should see Anthropic SSE withthinking_deltainterleaved correctlyEvent vocabulary to handle
From upstream (forward as-is on
/v1/responses, translate on/v1/messages):response.createdmessage_startresponse.in_progresspingresponse.output_item.added(type=reasoning)content_block_start { type:'thinking' }response.reasoning.deltathinking_deltaresponse.reasoning_summary_text.deltathinking_delta(configurable channel)response.reasoning.donesignature_delta(carry encrypted_content) +content_block_stopresponse.output_item.added(type=message)content_block_start { type:'text' }response.output_text.deltatext_deltaresponse.output_text.donecontent_block_stopresponse.output_item.added(type=function_call)content_block_start { type:'tool_use' }response.function_call_arguments.deltainput_json_deltaresponse.output_item.donecontent_block_stopresponse.completedmessage_delta(usage) +message_stopresponse.failedTasks
src/routes/responses/stream.tsfor the OpenAI-shape passthrough (mostly forward + minimal normalization)src/routes/messages/responses-stream-translation.ts(created by Reasoning types & reasoning_effort passthrough in chat-completions #7) that carefully sequencescontent_block_start/delta/stopper item indexoutput_indexandcontent_index; Anthropic uses a singleindexper content block — must allocate Anthropic indexes in arrival order)function_call_arguments.deltaaccumulates, or streaminput_json_deltachunks faithfullymessage_stopeven on stream errors, so Claude Code clients don't hangAcceptance criteria
gpt-5.3-codexagent loop with tool use through/v1/messages, confirm Claude Code renders thinking, tool calls, and text in correct ordertests/covering reasoning-then-text, text-then-tool, tool-then-text-then-reasoning sequencesFile pointers
src/routes/messages/stream-translation.ts— reference state machine