Skip to content

Stream responses.create - #17

Merged
theQuert merged 2 commits into
mainfrom
claude/responses-stream
Oct 7, 2026
Merged

theQuert merged 2 commits into
mainfrom
claude/responses-stream

Conversation

@theQuert

@theQuert theQuert commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Refs #15.

responses.create(stream=True) (sync and async) sends "stream": true and returns Stream[ResponseStreamEvent] (AsyncStream for the async client).

  • Events. Each event keeps its type and every field the API sent. delta is typed Any, so an unforeseen shape cannot end the stream. Other common fields are declared: text, item, part, response, sequence_number, item_id. The last two are optional, because the gateway's own events do not carry them yet.
  • End of stream. The stream ends at data: [DONE] (the gateway's own streams) or at the end of the body (passed-through OpenAI streams).
  • Errors. An error event raises the matching APIError subclass and closes the response. The SDK picks the subclass from the error's code, falling back to its type (for example RateLimitError for rate_limit_exceeded). response.failed is still yielded as an ordinary event. Both shapes are handled: OpenAI's {"type": "error", ...} and a gateway-style {"error": {...}}.
  • Refactor. The sync resource used its own copy of the body builder; both resources now share one.
  • Spec. OpenSpec change add-responses-stream.

Proof

  • pytest: 132 passed (8 new) on Python 3.13, 3.9, and 3.9 with minimum dependencies.
  • mypy apertis: the same 12 errors as main, none new.
  • Real-socket smoke against a local stdlib server, on all three environments. It sends the exact bytes the gateway's SSE writer produces (event: <type>\ndata: <json>\n\n … data: [DONE]\n\n) and covers:
    • a sync stream
    • an error event mid-stream: RateLimitError is raised and the response is closed
    • an async stream
    • the existing chat, messages and audio cases

🤖 Generated with Claude Code

https://claude.ai/code/session_01Uy5vXsRpMhug7v3XwTMZHv

theQuert and others added 2 commits October 7, 2026 12:36
responses.create(stream=True), sync and async, sends "stream": true and returns
a Stream of ResponseStreamEvent through the shared SSE reader. Events keep their
type and every field; the stream ends at [DONE] or at the end of the body. An
error event raises the APIError subclass for its code and closes the response.
Sync and async now share one request-body builder.

Refs #15

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uy5vXsRpMhug7v3XwTMZHv
An error whose code is not in the table now falls back to its type, so
{"type": "invalid_request_error", "code": "model_not_found"} is a 400, not a 500.
delta is typed Any so an event with a non-string delta cannot end the stream.
Tests lock response.failed as an ordinary event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uy5vXsRpMhug7v3XwTMZHv
@theQuert
theQuert force-pushed the claude/responses-stream branch from 81dbfef to f889e0c Compare October 7, 2026 04:36
@theQuert
theQuert merged commit ad7bce8 into main Oct 7, 2026
3 checks passed
This was referenced Oct 7, 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