High-level wrapper around a protocol connection to a specific thread.
In the thread-centric protocol, threads are durable (backed by
checkpoints) and connections are ephemeral. A ThreadStream is the
client-side handle for interacting with a thread: starting runs,
subscribing to events, consuming assembled projections (messages,
values, toolCalls, etc.), and responding to interrupts.
Construct via client.threads.stream(threadId?, { assistantId? }).
interface ThreadStreamWhether the run was interrupted (a lifecycle "interrupted" event
was received). Mirrors the in-process run.interrupted.
Interrupt payloads collected during the run, if any.
Mirrors the in-process run.interrupts.
Register a listener for every globally-unique event on the thread.
Fires exactly once per event_id across both the content pump
(user subscribe() calls) and the lifecycle watcher. Events
without an event_id always fire through (dedup is best-effort).
Returns an unsubscribe function. Primary consumer is
StreamController, which uses the listener to feed discovery
runners and pick up deeply-nested interrupts that the narrow
content pump wouldn't deliver.
Respond to an interrupt without the v1 eager lazy-getter shims. See submitRun for why this exists alongside input.respond.
Start a run without the v1 eager lazy-getter shims.
run.start (the v1 entry point) eagerly opens a wildcard values
projection so thread.output / thread.values resolve regardless
of access order, and calls #ensureLifecycleTracking which opens
another wildcard ["lifecycle", "input"] subscription. Both
subscriptions widen #computeUnionFilter to wildcard, defeating
the progressive-expansion rotation strategy.
submitRun skips those shims — callers that manage their own
content subscriptions (such as StreamController) get the narrow
union filter they asked for. Lifecycle / interrupt tracking is
instead served by the dedicated #startLifecycleWatcher, which
opens a wildcard ["lifecycle", "input"] stream alongside the
narrow content pump on both SSE and WebSocket transports.
Subscribe to raw wire channels and receive protocol events.
For assembled projections, use the lazy getters instead:
thread.messages, thread.values, thread.toolCalls,
thread.subgraphs, thread.subagents, thread.output.