ChappieStreamEvent values over an AsyncThrowingStream.
Basic Streaming
Callclient.stream(_:) with a prompt string and iterate the resulting AsyncThrowingStream with for try await:
ChappieInputMessage directly, or a full ChappieResponseRequest via streamResponse(_:), when you need control over message role, fast mode, or per-request options.
Stream Events
Every value yourfor try await loop receives is a ChappieStreamEvent. Handle each case you care about and ignore the rest with default:
.textDelta(String)
.textDelta(String)
An incremental text chunk from the model. Append each delta to a
String buffer to build the full response. Deltas arrive in order and are never empty..usageLimits(ChappieUsageLimitSnapshot)
.usageLimits(ChappieUsageLimitSnapshot)
A mid-stream usage snapshot. The snapshot may include a
primary window (usedPercent, windowMinutes, resetsAt) and a secondary window. Use it to drive a live usage indicator without polling the rate-limits endpoint..toolCallRequested(ChappieToolExecutionRequest)
.toolCallRequested(ChappieToolExecutionRequest)
The model has decided to call a host tool and the SDK is about to execute it. The event carries the
ChappieToolExecutionRequest, which contains the tool name, arguments, and the policy applied (automatic, ask, or deny). You can use this event to show a “thinking…” indicator..toolCallCompleted(ChappieToolExecutionResult)
.toolCallCompleted(ChappieToolExecutionResult)
The host tool finished executing. The result contains the tool call details, execution status (
completed, failed, denied, cancelled), the output string, and timing. The SDK automatically feeds the output back to the model as a follow-up turn..approvalRequested(ChappieApprovalRequest)
.approvalRequested(ChappieApprovalRequest)
A tool whose policy is
.ask is waiting for explicit user approval. Present a consent prompt; call the toolApprovalHandler closure you registered on the client with .approved() or .denied() to continue..completed
.completed
The model has finished generating for this turn. The stream will end cleanly after this event. Use it to hide loading spinners or finalize your text buffer.
.raw(type:payload:)
.raw(type:payload:)
The raw SSE event type and payload string before any parsing. Useful for debugging unexpected server events or building advanced integrations that need access to fields the SDK does not yet surface.
Cancelling a Stream with ChappieStreamHandle
When you need to cancel a stream from outside the iteration loop — for example, when the user taps a stop button — use streamHandle(_:) instead of stream(_:). It returns a ChappieStreamHandle whose cancel() method immediately stops the underlying transport and finishes the event stream.
Task and calling cancel() on it:
Transport Behaviour
WebSocket with Automatic Fallback
By default, Chappie opens a WebSocket connection for every streaming turn. If the WebSocket fails, the SDK retries before falling back to HTTP/SSE for the remainder of the session. Once HTTP/SSE is active, all subsequent turns in that client instance use HTTP/SSE — WebSocket is not re-attempted mid-session.Replay Divergence Protection
If a reconnection attempt results in the server sending a different continuation than what was already delivered to your UI, the SDK throwsChappieClientError.streamingTransportReplayDiverged.
If your error handler catches
.streamingTransportReplayDiverged, the associated String value contains the text that was already delivered to your UI before the divergence. You can use it to display a partial response or prompt the user to retry.Forcing HTTP/SSE Only
If your environment blocks WebSocket connections or you want deterministic transport for testing, opt into HTTP/SSE exclusively:Streaming With a Full Request
When you need to customise reasoning effort, service tier, or search tool access on a streaming turn, build aChappieResponseRequest and call streamResponse(_:):