diff --git a/fern/products/sdks/deep-dives/sse-metadata.mdx b/fern/products/sdks/deep-dives/sse-metadata.mdx index 07007044ef..23ae5f6dc7 100644 --- a/fern/products/sdks/deep-dives/sse-metadata.mdx +++ b/fern/products/sdks/deep-dives/sse-metadata.mdx @@ -3,7 +3,7 @@ title: SSE metadata access description: Access server-sent event metadata (event ID, event type, retry interval) in Fern-generated SDKs for stream resumption and protocol-level control. --- -When your API uses [server-sent events](/learn/api-definitions/openapi/endpoints/sse#server-sent-events), iterating the generated SDK's streaming response yields parsed data objects. To also read the SSE protocol fields — event ID, event type, and retry interval — TypeScript and Go SDKs expose metadata-aware iteration, typically used to [resume a stream](#stream-resumption) by event ID. +When your API uses [server-sent events](/learn/api-definitions/openapi/endpoints/sse#server-sent-events), iterating the generated SDK's streaming response yields parsed data objects. To also read the SSE protocol fields — event ID, event type, and retry interval — TypeScript, Python, and Go SDKs expose metadata-aware iteration, typically used to [resume a stream](#stream-resumption) by event ID. ## Metadata-aware iteration @@ -22,6 +22,17 @@ Each event exposes the parsed data alongside its protocol fields. Default iterat } ``` + + ```python + stream = client.plants.stream(query="fern") + + for event in stream.with_metadata(): + event.data # parsed response object (same type as default iteration) + event.id # SSE event ID (str | None) + event.event # SSE event type (str | None) + event.retry # SSE retry interval in ms (int | None) + ``` + ```go stream := client.Plants.Stream(ctx, &PlantRequest{Query: "fern"}) @@ -44,8 +55,14 @@ Each event exposes the parsed data alongside its protocol fields. Default iterat +Each stream owns the underlying HTTP response, and releases it differently per language: + +* **TypeScript**: the body is released when iteration ends and cancelled when you break out of the loop. An `abortSignal` in the request options stops the stream from outside. +* **Python**: the stream is lazy, issuing the request on first iteration, and releases the response when it's exhausted, when iteration raises, on `close()`, or on exiting a `with` block. `AsyncStream` supports `async with` and is awaitable. +* **Go**: the stream never closes the body on its own, so `defer stream.Close()` is required. + -`withMetadata()` requires TypeScript SDK generator version 3.73.0+, and `RecvEvent()` requires Go SDK generator version 1.32.0+. +`withMetadata()` requires TypeScript SDK generator version 3.73.0+, and `RecvEvent()` requires Go SDK generator version 1.32.0+. In Python, `with_metadata()` requires generator version 5.29.0+ with [`stream_abstraction`](/learn/sdks/generators/python/configuration#stream_abstraction) enabled. ## Stream resumption diff --git a/fern/products/sdks/generators/python/configuration.mdx b/fern/products/sdks/generators/python/configuration.mdx index aed978aed4..69a9c68553 100644 --- a/fern/products/sdks/generators/python/configuration.mdx +++ b/fern/products/sdks/generators/python/configuration.mdx @@ -246,6 +246,17 @@ When enabled, the generated SDK resolves the version it reports in the `X-Fern-S When enabled, skips code formatting (like black) on the generated Python code. + +When enabled, streaming endpoints return a `Stream[T]` (`AsyncStream[T]` for async clients) instead of a generator. Iterating yields the parsed payloads; `with_metadata()` yields them wrapped with the [server-sent event metadata](/learn/sdks/deep-dives/sse-metadata) fields `id`, `event`, and `retry`. + +```python +for event in client.plants.stream(query="fern").with_metadata(): + print(event.id, event.data) +``` + +This option changes the return type of streaming methods, so it remains opt-in until the next major generator version. + + Sets the client timeout in seconds, or `infinity` to disable timeouts.