{"version":3,"file":"index.cjs","names":["ensureMessageInstances","#transportAdapter","#pending","#subscriptions","#seenEventIds","#headlessInterruptsAwaitingTerminal","#pendingSubResolves","#onEventListeners","#extensionsCache","#extensionsEvents","#extensionsEventListeners","#extensionsEndListeners","#mediaHandles","#audioBuffer","MultiCursorBuffer","#imagesBuffer","#videoBuffer","#filesBuffer","#fetchOption","#nextCommandId","#prepareForNextRun","#withRunStartGate","#ensureLifecycleTracking","#send","#consumeEvents","#ensureOpen","#opened","#openPromise","#lifecycleStartPromise","#lifecycleSubId","#subscribeRaw","#lifecycleChannels","#runStartReady","#terminalPauseTimer","#terminalPauseSeq","#messagesIterable","StreamingMessageAssembler","#startProjection","toStreamingMessageHandle","#valuesProjection","#outputPromise","#toolCallsIterable","ToolCallAssembler","toClientAssembledToolCall","#subgraphsIterable","SubgraphDiscoveryHandle","#subagentsIterable","SubagentDiscoveryHandle","#ensureMediaDispatcher","#extensionsProxy","#createExtension","#extensionsDispatcherStarted","#extensionsEnded","#mediaDispatcherStarted","MediaAssembler","#mediaAssembler","#ensureExtensionsDispatcher","#startLifecycleWatcher","#lifecycleWatcherStartPromise","#startLifecycleWatcherSse","#startLifecycleWatcherWebSocket","#closed","#lifecycleWatcherHandle","#handleLifecycleWatcherMessage","#applyThreadLevelEffects","#fireOnEvent","isHeadlessToolInterrupt","#sharedStream","#sharedStreamFilter","#subscribeViaSharedStream","#subscribeViaCommand","#scheduleReconcile","#rotationState","#reconcileStream","#computeUnionFilter","#rejectUncoveredPending","#resolvePending","#pumpStream","#handleIncoming","#failThreadWithError","ProtocolError","matchesSubscription","#scheduleTerminalPause"],"sources":["../../../src/client/stream/index.ts"],"sourcesContent":["import type {\n  Channel,\n  Command,\n  CommandResponse,\n  Event,\n  LifecycleEvent,\n  ListCheckpointsResult,\n  Message,\n  MessagesEvent,\n  Namespace,\n  RunResult,\n  StateForkResult,\n  StateGetResult,\n  SubscribeParams,\n  SubscribeResult,\n  ToolsEvent,\n  ValuesEvent,\n} from \"@langchain/protocol\";\nimport { matchesSubscription } from \"./subscription.js\";\nimport { MultiCursorBuffer } from \"./multi-cursor-buffer.js\";\nimport { ensureMessageInstances } from \"../../ui/messages.js\";\nimport {\n  ToolCallAssembler,\n  toClientAssembledToolCall,\n  SubgraphDiscoveryHandle,\n  SubgraphHandle,\n  SubagentDiscoveryHandle,\n  SubagentHandle,\n} from \"./handles/index.js\";\nimport type { ClientAssembledToolCall } from \"./handles/tools.js\";\nimport {\n  StreamingMessageAssembler,\n  toStreamingMessageHandle,\n} from \"./messages.js\";\nimport type { StreamingMessageHandle } from \"./messages.js\";\nimport { MediaAssembler } from \"./media.js\";\nimport type {\n  AnyMediaHandle,\n  AudioMedia,\n  FileMedia,\n  ImageMedia,\n  VideoMedia,\n} from \"./media.js\";\nimport type {\n  EventSubscription,\n  EventForChannel,\n  EventForChannels,\n  InterruptPayload,\n  ThreadExtension,\n  ThreadExtensions,\n  ThreadModules,\n  ThreadStreamOptions,\n  SessionOrderingState,\n  SubscribeOptions,\n  YieldForChannel,\n  YieldForChannels,\n} from \"./types.js\";\nimport type { EventStreamHandle, TransportAdapter } from \"./transport.js\";\nimport { ProtocolError } from \"./error.js\";\nimport { NAMESPACE_SEPARATOR } from \"../../stream/constants.js\";\nimport { isHeadlessToolInterrupt } from \"../../headless-tools.js\";\n\ntype PendingCommand = {\n  resolve: (response: CommandResponse) => void;\n  reject: (error: Error) => void;\n};\n\ntype CommandResultMap = {\n  \"run.start\": RunResult;\n  \"subscription.subscribe\": SubscribeResult;\n  \"subscription.unsubscribe\": Record<string, unknown>;\n  \"agent.getTree\": Record<string, unknown>;\n  \"input.respond\": Record<string, unknown>;\n  \"input.inject\": Record<string, unknown>;\n  \"state.get\": StateGetResult;\n  \"state.listCheckpoints\": ListCheckpointsResult;\n  \"state.fork\": StateForkResult;\n};\n\ntype CommandParamsMap = {\n  \"run.start\": Record<string, unknown>;\n  \"subscription.subscribe\": SubscribeParams;\n  \"subscription.unsubscribe\": { subscription_id: string };\n  \"agent.getTree\": { run_id?: string };\n  \"input.respond\": Record<string, unknown>;\n  \"input.inject\": Record<string, unknown>;\n  \"state.get\": Record<string, unknown>;\n  \"state.listCheckpoints\": Record<string, unknown>;\n  \"state.fork\": Record<string, unknown>;\n};\n\ntype InternalEventSubscription = EventSubscription<unknown> & {\n  filter: SubscribeParams;\n  push(event: Event): void;\n  close(): void;\n  pause(): void;\n  resume(): void;\n  /**\n   * Highest sequence observed by the thread before this subscription was\n   * registered. Replayed terminal events at or before this point belong to a\n   * run that already ended before the subscription existed, so they must not\n   * pause the subscription before it can drain server replay.\n   */\n  registeredAfterSeq: number | undefined;\n  /**\n   * Per-subscription dedup window. Guards against redelivery during\n   * shared-stream rotation overlap and from WebSocket server-side\n   * fan-out, while still letting newly-registered subs receive the\n   * replayed events that existing subs already consumed. Event IDs\n   * are session-local but stable across sessions for the same run\n   * (the session's monotonic `_next_seq` processes events in order),\n   * so a set-per-sub is sufficient.\n   */\n  seenEventIds: Set<string>;\n};\n\ntype PendingSubResolve = {\n  filter: SubscribeParams;\n  resolve: () => void;\n  reject: (err: unknown) => void;\n};\n\nconst MESSAGE_LIKE_TYPES = new Set([\n  \"human\",\n  \"user\",\n  \"ai\",\n  \"assistant\",\n  \"tool\",\n  \"system\",\n  \"function\",\n  \"remove\",\n]);\n\n/**\n * When the state payload has a `messages` array containing plain\n * serialized messages (objects with a recognized `type` field), coerce\n * them into `@langchain/core/messages` class instances so remote runs\n * expose the same shape as in-process runs.\n *\n * Returns the input unchanged when the payload is not an object, does\n * not include a `messages` key, or contains entries that are already\n * class instances / not message-like.\n */\nfunction coerceStateMessages(value: unknown): unknown {\n  if (value == null || typeof value !== \"object\" || Array.isArray(value)) {\n    return value;\n  }\n  const state = value as Record<string, unknown>;\n  const messages = state.messages;\n  if (!Array.isArray(messages) || messages.length === 0) return value;\n\n  const needsCoercion = messages.some((msg) => {\n    if (msg == null || typeof msg !== \"object\") return false;\n    if (typeof (msg as { getType?: () => string }).getType === \"function\") {\n      return false;\n    }\n    const type = (msg as { type?: unknown }).type;\n    return typeof type === \"string\" && MESSAGE_LIKE_TYPES.has(type);\n  });\n  if (!needsCoercion) return value;\n\n  return {\n    ...state,\n    messages: ensureMessageInstances(\n      messages as Parameters<typeof ensureMessageInstances>[0]\n    ),\n  };\n}\n\nfunction namespaceKey(ns: Namespace): string {\n  return ns.join(NAMESPACE_SEPARATOR);\n}\n\nfunction maxSeq(\n  current: number | undefined,\n  next: number | undefined\n): number | undefined {\n  if (next == null) return current;\n  if (current == null) return next;\n  return Math.max(current, next);\n}\n\nconst ROOT_TERMINAL_LIFECYCLE_EVENTS = new Set([\n  \"completed\",\n  \"failed\",\n  \"interrupted\",\n]);\n\n/**\n * Detect a root-namespace terminal lifecycle event. Used by\n * `#startProjection`'s `endOnRootTerminal` guard to settle per-run\n * dispatchers regardless of whether the shared-stream pause logic\n * applies to their underlying subscription.\n */\nfunction isRootTerminalLifecycle(event: Event): boolean {\n  if (event.method !== \"lifecycle\") return false;\n  if (event.params.namespace.length !== 0) return false;\n  const data = event.params.data as { event?: string } | undefined;\n  return data?.event != null && ROOT_TERMINAL_LIFECYCLE_EVENTS.has(data.event);\n}\n\nfunction namespaceListsEqual(\n  a: readonly Namespace[] | undefined,\n  b: readonly Namespace[] | undefined\n): boolean {\n  if (a === b) return true;\n  if (a === undefined || b === undefined) return false;\n  if (a.length !== b.length) return false;\n  const aKeys = new Set<string>();\n  for (const ns of a) aKeys.add(namespaceKey(ns));\n  for (const ns of b) {\n    if (!aKeys.has(namespaceKey(ns))) return false;\n  }\n  return true;\n}\n\n/**\n * Structural equality on filters. Two filters are equal iff they\n * request the same channel set, the same namespace prefix set\n * (with `undefined` meaning wildcard), and the same depth\n * (with `undefined` meaning unbounded).\n */\nfunction filterEqual(\n  a: SubscribeParams | null,\n  b: SubscribeParams | null\n): boolean {\n  if (a === b) return true;\n  if (a == null || b == null) return false;\n  if (a.channels.length !== b.channels.length) return false;\n  const aChannels = new Set(a.channels as Channel[]);\n  for (const ch of b.channels as Channel[]) {\n    if (!aChannels.has(ch)) return false;\n  }\n  if (!namespaceListsEqual(a.namespaces, b.namespaces)) return false;\n  const aDepth = a.depth ?? null;\n  const bDepth = b.depth ?? null;\n  if (aDepth !== bDepth) return false;\n  return true;\n}\n\nfunction isPrefix(prefix: Namespace, candidate: Namespace): boolean {\n  if (prefix.length > candidate.length) return false;\n  for (let i = 0; i < prefix.length; i += 1) {\n    if (prefix[i] !== candidate[i]) return false;\n  }\n  return true;\n}\n\n/**\n * Whether the `coverer` filter delivers every event a subscription\n * opened with `target` could want.\n *\n * Rules:\n *  - Channels: target.channels must be a subset of coverer.channels.\n *  - Namespaces:\n *    - coverer wildcard (`undefined`) → coverer covers all prefixes.\n *    - coverer explicit + target wildcard → not covered.\n *    - both explicit → every target prefix must have some coverer\n *      prefix that is its ancestor (coverer's prefix delivers events\n *      for all descendants, modulo depth).\n *  - Depth:\n *    - coverer unbounded (`undefined`) → depth is covered.\n *    - otherwise, for each target prefix `tp` covered by coverer\n *      prefix `cp`, the maximum event depth target wants\n *      (`tp.length + (target.depth ?? ∞) - cp.length`) must be\n *      `<= coverer.depth`. For a wildcard target with bounded depth,\n *      target's max absolute depth is `target.depth` (prefix is `[]`).\n */\nfunction filterCovers(\n  coverer: SubscribeParams,\n  target: SubscribeParams\n): boolean {\n  const covererChannels = new Set(coverer.channels as Channel[]);\n  for (const ch of target.channels as Channel[]) {\n    if (!covererChannels.has(ch)) return false;\n  }\n\n  const covererDepth = coverer.depth;\n  const targetDepth = target.depth;\n\n  if (coverer.namespaces == null) {\n    if (covererDepth == null) return true;\n    if (targetDepth == null) return false;\n    return targetDepth <= covererDepth;\n  }\n\n  if (target.namespaces == null) return false;\n\n  for (const tp of target.namespaces) {\n    const covered = coverer.namespaces.some((cp) => {\n      if (!isPrefix(cp, tp)) return false;\n      if (covererDepth == null) return true;\n      if (targetDepth == null) return false;\n      return tp.length - cp.length + targetDepth <= covererDepth;\n    });\n    if (!covered) return false;\n  }\n  return true;\n}\n\nfunction normalizeSubscribeParams(\n  paramsOrChannels: SubscribeParams | Channel | readonly Channel[],\n  options: SubscribeOptions = {}\n): SubscribeParams {\n  if (\n    typeof paramsOrChannels === \"object\" &&\n    !Array.isArray(paramsOrChannels) &&\n    \"channels\" in paramsOrChannels\n  ) {\n    return paramsOrChannels;\n  }\n\n  const channels = Array.isArray(paramsOrChannels)\n    ? ([...paramsOrChannels] as Channel[])\n    : ([paramsOrChannels] as Channel[]);\n  return {\n    ...options,\n    channels,\n  };\n}\n\n/**\n * Async iterable handle for raw event subscriptions.\n *\n * An optional `transform` maps each incoming event before it is queued\n * or delivered to a waiting consumer. This is used by named custom\n * channel subscriptions (e.g. `\"custom:a2a\"`) to unwrap the payload\n * so callers receive the raw emitted data instead of the protocol\n * event envelope.\n */\nexport class SubscriptionHandle<TEvent extends Event = Event, TYield = TEvent>\n  implements AsyncIterable<TYield>, EventSubscription<TYield>\n{\n  // Mutated by `#subscribeViaCommand` on WS once the server-assigned\n  // subscription id arrives — see the placeholder→resolved transition\n  // there. SSE paths set this once at construction and never change it.\n  subscriptionId: string;\n  readonly params: SubscribeParams;\n  private readonly queue: TYield[] = [];\n  private readonly waiters: Array<(value: IteratorResult<TYield>) => void> = [];\n  private closed = false;\n  private paused = false;\n  private resumeResolve?: () => void;\n  private readonly onUnsubscribe: (id: string) => Promise<void>;\n  private readonly transform: (event: TEvent) => TYield;\n\n  constructor(\n    subscriptionId: string,\n    params: SubscribeParams,\n    onUnsubscribe: (id: string) => Promise<void>,\n    transform?: (event: TEvent) => TYield\n  ) {\n    this.subscriptionId = subscriptionId;\n    this.params = params;\n    this.onUnsubscribe = onUnsubscribe;\n    this.transform = transform ?? ((event) => event as unknown as TYield);\n  }\n\n  push(event: TEvent): void {\n    if (this.closed) {\n      return;\n    }\n    const value = this.transform(event);\n    const waiter = this.waiters.shift();\n    if (waiter) {\n      waiter({ done: false, value });\n      return;\n    }\n    this.queue.push(value);\n  }\n\n  /**\n   * Pause the subscription: resolve all waiting iterators with `done: true`\n   * so `for await` loops exit, but keep the subscription alive. New events\n   * arriving while paused are still buffered. Call `resume()` to allow\n   * iterators to consume again.\n   */\n  pause(): void {\n    if (this.closed) return;\n    this.paused = true;\n    while (this.waiters.length > 0) {\n      this.waiters.shift()?.({ done: true, value: undefined });\n    }\n  }\n\n  /**\n   * Resume a paused subscription so new `for await` loops can consume\n   * buffered and future events.\n   */\n  resume(): void {\n    this.paused = false;\n    this.resumeResolve?.();\n    this.resumeResolve = undefined;\n  }\n\n  /**\n   * Returns a promise that resolves when `resume()` is called. Resolves\n   * immediately if not currently paused.\n   */\n  waitForResume(): Promise<void> {\n    if (!this.paused) return Promise.resolve();\n    return new Promise<void>((resolve) => {\n      this.resumeResolve = resolve;\n    });\n  }\n\n  get isPaused(): boolean {\n    return this.paused;\n  }\n\n  close(): void {\n    this.closed = true;\n    this.paused = false;\n    while (this.waiters.length > 0) {\n      this.waiters.shift()?.({ done: true, value: undefined });\n    }\n    // A paused iterator may be parked on `waitForResume()` instead of\n    // on a regular iterator waiter. Resolving here prevents closed\n    // subscriptions from stranding pumps that observe `isPaused` and\n    // block on `waitForResume()` (e.g. the root pump in\n    // `StreamController`).\n    this.resumeResolve?.();\n    this.resumeResolve = undefined;\n  }\n\n  async unsubscribe(): Promise<void> {\n    if (this.closed) {\n      return;\n    }\n    this.close();\n    await this.onUnsubscribe(this.subscriptionId);\n  }\n\n  [Symbol.asyncIterator](): AsyncIterator<TYield> {\n    return {\n      next: async () => {\n        if (this.queue.length > 0) {\n          const value = this.queue.shift()!;\n          return { done: false, value };\n        }\n        if (this.closed || this.paused) {\n          return { done: true, value: undefined };\n        }\n        return await new Promise<IteratorResult<TYield>>((resolve) => {\n          this.waiters.push(resolve);\n        });\n      },\n      return: async () => {\n        this.close();\n        return { done: true, value: undefined };\n      },\n    };\n  }\n}\n\n/**\n * High-level wrapper around a protocol connection to a specific thread.\n *\n * In the thread-centric protocol, threads are durable (backed by\n * checkpoints) and connections are ephemeral. A `ThreadStream` is the\n * client-side handle for interacting with a thread: starting runs,\n * subscribing to events, consuming assembled projections (`messages`,\n * `values`, `toolCalls`, etc.), and responding to interrupts.\n *\n * Construct via `client.threads.stream(threadId?, { assistantId? })`.\n *\n * @typeParam TExtensions - Optional map of `{ name: payload }` pairs\n *   describing the transformer projections the bound assistant exposes\n *   on `custom:<name>` channels. Narrows `thread.extensions.<name>` to\n *   `ThreadExtension<payload>`. Defaults to `Record<string, unknown>`.\n */\nexport class ThreadStream<\n  TExtensions extends Record<string, unknown> = Record<string, unknown>,\n> {\n  readonly threadId: string;\n  readonly ordering: SessionOrderingState = {};\n  readonly run: ThreadModules[\"run\"];\n  readonly agent: ThreadModules[\"agent\"];\n  readonly input: ThreadModules[\"input\"];\n  readonly state: ThreadModules[\"state\"];\n\n  /**\n   * Whether the run was interrupted (a lifecycle \"interrupted\" event\n   * was received). Mirrors the in-process `run.interrupted`.\n   */\n  interrupted = false;\n\n  /**\n   * Interrupt payloads collected during the run, if any.\n   * Mirrors the in-process `run.interrupts`.\n   */\n  readonly interrupts: InterruptPayload[] = [];\n\n  readonly assistantId: string;\n\n  #nextCommandId: number;\n  readonly #transportAdapter: TransportAdapter;\n  readonly #pending = new Map<number, PendingCommand>();\n  readonly #subscriptions = new Map<string, InternalEventSubscription>();\n  // Tracks `event_id`s that have already been processed for thread-level\n  // side effects (interrupt tracking, `input.requested` capture) AND to\n  // drop duplicate fan-outs during the overlap window of SSE stream\n  // rotation (see `#reconcileStream`): the old stream and the new stream\n  // are both pumping briefly, and the server replays buffered events on\n  // new streams, so the same `event_id` can arrive twice.\n  //\n  // The set grows at the rate of unique events per thread, but its\n  // lifetime is bounded by `ThreadStream` (it's GC'd when the run\n  // completes and the stream is disposed), and each entry is a short\n  // numeric string. A bounded sliding-window alternative was considered\n  // and rejected: any cap smaller than the server's replay buffer\n  // (`maxBufferSize` in `protocol/session`) would risk evicting still-\n  // live ids and re-processing real events, which trades a hypothetical\n  // memory win for a real correctness failure mode and cross-repo\n  // coupling. Revisit only if a concrete long-run memory profile\n  // justifies the added complexity.\n  readonly #seenEventIds = new Set<string>();\n  /**\n   * Headless tool interrupts can be auto-resumed by the React hook before\n   * the shared SSE content pump has processed the root `interrupted`\n   * lifecycle event. `respondInput()` clears `interrupts`, so keep a\n   * short-lived marker here until that stale terminal passes through the\n   * content pump and we can avoid pausing it.\n   */\n  readonly #headlessInterruptsAwaitingTerminal = new Set<string>();\n  #closed = false;\n  #opened = false;\n  #openPromise?: Promise<void>;\n\n  // ---------- Shared SSE stream state ----------\n  // Under the SSE transport a single connection is shared across all\n  // subscriptions. Its filter is the union of every active subscription's\n  // filter (`#computeUnionFilter`); the client fans out incoming events\n  // to matching subscriptions via `matchesSubscription` in\n  // `#handleIncoming`. The stream rotates (open-before-close) whenever\n  // `subscribe`/`unsubscribe` changes the channel union.\n  #sharedStream: EventStreamHandle | null = null;\n  #sharedStreamFilter: SubscribeParams | null = null;\n  #rotationState: \"idle\" | \"scheduled\" | \"rotating\" = \"idle\";\n  /** Pending `subscribe()` promises waiting for a covering rotation. */\n  readonly #pendingSubResolves: PendingSubResolve[] = [];\n  #terminalPauseTimer: ReturnType<typeof setTimeout> | undefined;\n  #terminalPauseSeq: number | null | undefined;\n\n  #lifecycleSubId: string | null = null;\n  #lifecycleStartPromise?: Promise<void>;\n\n  // Set to the in-flight `run.start` send while it is awaiting the\n  // server response, then cleared. Sites that open server-side\n  // resources against `/threads/{id}/stream/events` (the SSE content\n  // pump, the SSE lifecycle watcher, and the WS `subscription.subscribe`\n  // command) await this so they don't race the thread's server-side\n  // creation and trip a `404: Thread not found`. Subscribers that\n  // arrive after `run.start` resolves see `null` and proceed\n  // immediately — `await null` is a microtask, not a real wait — so\n  // late selector-hook mounts (`useToolCalls` after subagent discovery)\n  // take no extra latency.\n  #runStartReady: Promise<void> | null = null;\n\n  // ---------- v2 lifecycle watcher ----------\n  // Dedicated wildcard `{channels: [\"lifecycle\", \"input\"]}` stream\n  // opened by `submitRun` / `respondInput` (v2 entry points). Carries\n  // every interrupt and lifecycle event at any depth so consumers of\n  // `onEvent` (discovery runners, nested HITL capture) don't depend\n  // on the content pump's narrow filter.\n  //\n  //  - SSE: opened via `openEventStream` as an independent stream\n  //    that sits outside `#computeUnionFilter`, so the shared SSE\n  //    content pump stays narrow. Tracked in `#lifecycleWatcherHandle`\n  //    so `close()` can tear it down.\n  //  - WebSocket: opened via `#subscribeRaw` on the shared command\n  //    connection. The resulting `SubscriptionHandle` is managed by\n  //    the normal `#subscriptions` lifecycle, so no separate handle\n  //    reference is needed — `close()` fans `SubscriptionHandle.close`\n  //    across all registered subs.\n  #lifecycleWatcherHandle: EventStreamHandle | null = null;\n  #lifecycleWatcherStartPromise?: Promise<void>;\n\n  // ---------- v2 unified event fan-out ----------\n  // Listeners invoked once per globally-unique event across BOTH the\n  // content pump and the lifecycle watcher. Used by `StreamController`\n  // to consume discovery and interrupt events without opening extra\n  // server subscriptions.\n  readonly #onEventListeners = new Set<(event: Event) => void>();\n\n  #messagesIterable?: AsyncIterable<StreamingMessageHandle>;\n  #valuesProjection?: AsyncIterable<unknown> & PromiseLike<unknown>;\n  #toolCallsIterable?: AsyncIterable<ClientAssembledToolCall>;\n  #subgraphsIterable?: AsyncIterable<SubgraphHandle>;\n  #subagentsIterable?: AsyncIterable<SubagentHandle>;\n  #outputPromise?: Promise<unknown>;\n  #extensionsProxy?: ThreadExtensions<TExtensions>;\n  readonly #extensionsCache = new Map<string, ThreadExtension<unknown>>();\n\n  /**\n   * Shared state for the single `\"custom\"` channel subscription that\n   * backs every `thread.extensions.<name>` handle.\n   *\n   * One subscription is opened eagerly from {@link run.start} (mirroring\n   * the {@link values} eager-start pattern) so that per-name handles\n   * created before, during, or after the run can all resolve correctly.\n   *\n   *  - `events` retains every custom event for backfill into\n   *    late-constructed handles.\n   *  - `eventListeners` fan new events out to live per-name handlers.\n   *  - `endListeners` fire when the dispatcher's run terminates, so each\n   *    handle can resolve its `PromiseLike` side with its last-seen\n   *    payload.\n   */\n  #extensionsDispatcherStarted = false;\n  #extensionsEnded = false;\n  readonly #extensionsEvents: Event[] = [];\n  readonly #extensionsEventListeners: Array<(event: Event) => void> = [];\n  readonly #extensionsEndListeners: Array<() => void> = [];\n\n  /**\n   * Shared state for the single `messages`-channel subscription that\n   * backs every media handle iterable (`thread.audio`, `thread.images`,\n   * `thread.video`, `thread.files`). One subscription serves all four\n   * iterables; per-type buffers track the handles already emitted so\n   * late attachers replay through {@link MultiCursorBuffer}.\n   */\n  #mediaDispatcherStarted = false;\n  #mediaAssembler: MediaAssembler | undefined;\n  /** Object URLs minted by media handles, tracked for {@link close} cleanup. */\n  readonly #mediaHandles = new Set<AnyMediaHandle>();\n  readonly #audioBuffer = new MultiCursorBuffer<AudioMedia>();\n  readonly #imagesBuffer = new MultiCursorBuffer<ImageMedia>();\n  readonly #videoBuffer = new MultiCursorBuffer<VideoMedia>();\n  readonly #filesBuffer = new MultiCursorBuffer<FileMedia>();\n  readonly #fetchOption: typeof fetch | undefined;\n\n  constructor(\n    transportAdapter: TransportAdapter,\n    options: ThreadStreamOptions\n  ) {\n    if (!options?.assistantId) {\n      throw new Error(\"ThreadStream requires an assistantId option.\");\n    }\n    this.#transportAdapter = transportAdapter;\n    this.threadId = transportAdapter.threadId;\n    this.assistantId = options.assistantId;\n    this.#nextCommandId = options.startingCommandId ?? 1;\n    this.#fetchOption = options.fetch;\n    this.run = {\n      start: async (params) => {\n        this.#prepareForNextRun();\n        // Kick off the lifecycle watcher and the values projection\n        // SYNCHRONOUSLY so the React layer (and any other consumer that\n        // races subagent discovery) sees them registered immediately.\n        // Both open server-side subscriptions on\n        // `/threads/{id}/stream/events`, which would 404 if they landed\n        // before `run.start` committed the thread server-side — so we\n        // stage them behind `#runStartReady`, a promise resolved when\n        // the in-flight `run.start` send completes. Sites that open\n        // SSE/WS resources await this gate; everything else (event\n        // dispatch, projection bookkeeping) runs without delay.\n        return await this.#withRunStartGate(() => {\n          this.#ensureLifecycleTracking();\n          // Eagerly start the values projection so `thread.output` /\n          // `thread.values` resolve with the final state regardless of\n          // whether they are accessed before or after the run completes.\n          // Without this, late access would open a fresh subscription\n          // that misses every `values` event from the run.\n          void this.values;\n          // NOTE: `thread.extensions.<name>` is NOT eagerly subscribed.\n          // The shared custom dispatcher is opened lazily on first\n          // extension access and relies on the server's event buffer to\n          // replay any custom events that were emitted before the\n          // subscription landed. This keeps the zero-extensions hot path\n          // free of an unused `custom` subscription per run.\n          return this.#send(\"run.start\", {\n            ...params,\n            assistant_id: this.assistantId,\n          });\n        });\n      },\n    };\n    this.agent = {\n      getTree: async (params = {}) =>\n        (await this.#send(\"agent.getTree\", params)) as {\n          tree: unknown;\n        } as never,\n    };\n    this.input = {\n      respond: async (params) => {\n        this.#prepareForNextRun();\n        this.#ensureLifecycleTracking();\n        // See note in `run.start` — keep `thread.output` working\n        // across resumes regardless of access order.\n        void this.values;\n        await this.#send(\n          \"input.respond\",\n          params as unknown as CommandParamsMap[\"input.respond\"]\n        );\n      },\n      inject: async (params) => {\n        await this.#send(\n          \"input.inject\",\n          params as unknown as CommandParamsMap[\"input.inject\"]\n        );\n      },\n    };\n    this.state = {\n      get: async (params) =>\n        await this.#send(\n          \"state.get\",\n          params as unknown as CommandParamsMap[\"state.get\"]\n        ),\n      listCheckpoints: async (params) =>\n        await this.#send(\n          \"state.listCheckpoints\",\n          params as unknown as CommandParamsMap[\"state.listCheckpoints\"]\n        ),\n      fork: async (params) =>\n        await this.#send(\n          \"state.fork\",\n          params as unknown as CommandParamsMap[\"state.fork\"]\n        ),\n    };\n    // SSE transports deliver events via openEventStream — the events()\n    // iterable is inert. Skip the consumer loop in that case.\n    if (this.#transportAdapter.openEventStream == null) {\n      void this.#consumeEvents();\n    }\n  }\n\n  /**\n   * Ensure the underlying transport is connected.\n   *\n   * For HTTP/SSE this is a no-op. For WebSocket this performs the\n   * handshake. Called lazily on first command; safe to call multiple times.\n   */\n  async #ensureOpen(): Promise<void> {\n    if (this.#opened) return;\n    if (this.#openPromise == null) {\n      this.#openPromise = this.#transportAdapter.open().then(() => {\n        this.#opened = true;\n      });\n    }\n    await this.#openPromise;\n  }\n\n  /**\n   * Channels bundled into every lazy getter's SSE filter so that\n   * interrupt tracking works without a separate lifecycle subscription.\n   */\n  #lifecycleChannels(): Channel[] {\n    return [\"lifecycle\", \"input\"];\n  }\n\n  /**\n   * Lazily start a dedicated lifecycle+input subscription so that\n   * `thread.interrupted` / `thread.interrupts` work even when the\n   * caller never accesses a lazy getter (e.g. they only call\n   * `run.start` and `subscribe({ channels: [\"custom:...\"] })`).\n   *\n   * Idempotent and fire-and-forget — invoked from `run.start` and\n   * `input.respond`.\n   */\n  #ensureLifecycleTracking(): void {\n    if (this.#lifecycleStartPromise != null) return;\n    this.#lifecycleStartPromise = (async () => {\n      const sub = await this.#subscribeRaw({\n        channels: this.#lifecycleChannels(),\n      });\n      this.#lifecycleSubId = sub.subscriptionId;\n    })().catch(() => undefined);\n  }\n\n  /**\n   * Run `operation` (a `run.start` send) while holding the run-start\n   * gate. Sets `#runStartReady` before invoking `operation` so any\n   * subscription kicked off synchronously inside it (e.g. the lifecycle\n   * watcher and the values projection) sees the gate when it eventually\n   * reaches `#startLifecycleWatcherSse` / `#reconcileStream` /\n   * `#subscribeViaCommand` and awaits it. The gate resolves the moment\n   * `operation` settles, so server-side subscribes land immediately\n   * after the thread is committed.\n   */\n  async #withRunStartGate<T>(operation: () => Promise<T>): Promise<T> {\n    let resolveGate!: () => void;\n    let rejectGate!: (err: unknown) => void;\n    const gate = new Promise<void>((resolve, reject) => {\n      resolveGate = resolve;\n      rejectGate = reject;\n    });\n    this.#runStartReady = gate;\n    // Swallow unhandled rejection: gate-awaiters that surface the\n    // rejection via their own error path don't need a second log line,\n    // and consumers that never await it (the typical case once\n    // `run.start` resolves successfully) shouldn't trigger\n    // `unhandledrejection` either.\n    gate.catch(() => undefined);\n    try {\n      const result = await operation();\n      resolveGate();\n      return result;\n    } catch (err) {\n      rejectGate(err);\n      throw err;\n    } finally {\n      // Only clear the gate if it's still our gate. Concurrent\n      // run.start calls (multitaskStrategy: enqueue) would otherwise\n      // null out a later call's gate when this earlier call's finally\n      // ran, leaving subscribers that raced in after our finally but\n      // before the later run.start commits with no gate to wait on.\n      if (this.#runStartReady === gate) {\n        this.#runStartReady = null;\n      }\n    }\n  }\n\n  /**\n   * Reset interrupt state and resume all paused user subscriptions.\n   * Called before `run.start()` and `input.respond()` so that\n   * iterators on the same handle pick up the next run's events.\n   *\n   * @param respondedInterruptId - When responding to one of several\n   *   pending interrupts, only that entry is removed. Clearing the\n   *   full list here would drop other headless-tool interrupts that\n   *   are still awaiting client execution.\n   */\n  #prepareForNextRun(respondedInterruptId?: string): void {\n    this.interrupted = false;\n    if (respondedInterruptId != null) {\n      const index = this.interrupts.findIndex(\n        (entry) => entry.interruptId === respondedInterruptId\n      );\n      if (index >= 0) {\n        this.interrupts.splice(index, 1);\n      }\n    } else {\n      this.interrupts.length = 0;\n    }\n    if (this.#terminalPauseTimer != null) {\n      clearTimeout(this.#terminalPauseTimer);\n      this.#terminalPauseTimer = undefined;\n    }\n    this.#terminalPauseSeq = undefined;\n    for (const [id, subscription] of this.#subscriptions) {\n      if (id !== this.#lifecycleSubId) {\n        subscription.resume();\n      }\n    }\n  }\n\n  // ---------- Lazy getters mirroring in-process GraphRunStream ----------\n\n  /**\n   * Streaming messages. Each `for await` loop gets an independent cursor\n   * over the shared buffer; late consumers see all previously emitted\n   * messages.  Mirrors the in-process `run.messages`.\n   */\n  get messages(): AsyncIterable<StreamingMessageHandle> {\n    if (this.#messagesIterable) return this.#messagesIterable;\n    const buffer = new MultiCursorBuffer<StreamingMessageHandle>();\n    this.#messagesIterable = buffer;\n    const assembler = new StreamingMessageAssembler();\n    void this.#startProjection(\n      [\"messages\", ...this.#lifecycleChannels()],\n      (event) => {\n        if (event.method !== \"messages\") return;\n        const msg = assembler.consume(event as MessagesEvent);\n        if (msg) buffer.push(toStreamingMessageHandle(msg));\n      },\n      () => buffer.close()\n    );\n    return buffer;\n  }\n\n  /**\n   * State values. Iterable for intermediate snapshots; also\n   * `PromiseLike` — `await thread.values` resolves with the final\n   * state.  Mirrors the in-process `run.values`.\n   */\n  get values(): AsyncIterable<unknown> & PromiseLike<unknown> {\n    if (this.#valuesProjection) return this.#valuesProjection;\n    const buffer = new MultiCursorBuffer<unknown>();\n    let lastValue: unknown;\n    let resolveOutput!: (value: unknown) => void;\n    const outputPromise = new Promise<unknown>((resolve) => {\n      resolveOutput = resolve;\n    });\n    this.#outputPromise = outputPromise;\n    const projection = Object.assign(buffer, {\n      then: <TResult1 = unknown, TResult2 = never>(\n        onfulfilled?:\n          | ((value: unknown) => TResult1 | PromiseLike<TResult1>)\n          | null,\n        onrejected?:\n          | ((reason: unknown) => TResult2 | PromiseLike<TResult2>)\n          | null\n      ): Promise<TResult1 | TResult2> =>\n        outputPromise.then(onfulfilled, onrejected),\n    }) as AsyncIterable<unknown> & PromiseLike<unknown>;\n    this.#valuesProjection = projection;\n    void this.#startProjection(\n      [\"values\", ...this.#lifecycleChannels()],\n      (event) => {\n        if (event.method !== \"values\") return;\n        const data = coerceStateMessages((event as ValuesEvent).params.data);\n        lastValue = data;\n        buffer.push(data);\n      },\n      () => {\n        resolveOutput(lastValue);\n        buffer.close();\n      }\n    );\n    return projection;\n  }\n\n  /**\n   * Tool calls with a promise-based {@link output} for script consumers.\n   * Mirrors the in-process `run.toolCalls`.\n   */\n  get toolCalls(): AsyncIterable<ClientAssembledToolCall> {\n    if (this.#toolCallsIterable) return this.#toolCallsIterable;\n    const buffer = new MultiCursorBuffer<ClientAssembledToolCall>();\n    this.#toolCallsIterable = buffer;\n    const assembler = new ToolCallAssembler();\n    void this.#startProjection(\n      [\"tools\", ...this.#lifecycleChannels()],\n      (event) => {\n        if (event.method !== \"tools\") return;\n        const tc = assembler.consume(event as ToolsEvent);\n        if (tc) buffer.push(toClientAssembledToolCall(tc));\n      },\n      () => buffer.close()\n    );\n    return buffer;\n  }\n\n  /**\n   * Discovered subgraphs. Mirrors the in-process `run.subgraphs`.\n   */\n  get subgraphs(): AsyncIterable<SubgraphHandle> {\n    if (this.#subgraphsIterable) return this.#subgraphsIterable;\n    const buffer = new MultiCursorBuffer<SubgraphHandle>();\n    this.#subgraphsIterable = buffer;\n    void (async () => {\n      const rawHandle = await this.#subscribeRaw({\n        channels: [\"tools\", ...this.#lifecycleChannels()],\n      });\n      const discovery = new SubgraphDiscoveryHandle(rawHandle, this, []);\n      for await (const sub of discovery) {\n        buffer.push(sub);\n      }\n      buffer.close();\n    })();\n    return buffer;\n  }\n\n  /**\n   * Discovered subagents.\n   */\n  get subagents(): AsyncIterable<SubagentHandle> {\n    if (this.#subagentsIterable) return this.#subagentsIterable;\n    const buffer = new MultiCursorBuffer<SubagentHandle>();\n    this.#subagentsIterable = buffer;\n    void (async () => {\n      const rawHandle = await this.#subscribeRaw({\n        channels: [\"tools\", ...this.#lifecycleChannels()],\n      });\n      const discovery = new SubagentDiscoveryHandle(rawHandle, this);\n      for await (const sub of discovery) {\n        buffer.push(sub);\n      }\n      buffer.close();\n    })();\n    return buffer;\n  }\n\n  /**\n   * Audio media handles, one per message containing at least one\n   * `AudioBlock`. Each `for await` opens an independent cursor over\n   * the shared buffer; late consumers replay every previously emitted\n   * audio handle.\n   *\n   * Yields one item per message on the first matching\n   * `content-block-start` — messages with no audio blocks are skipped.\n   */\n  get audio(): AsyncIterable<AudioMedia> {\n    this.#ensureMediaDispatcher();\n    return this.#audioBuffer;\n  }\n\n  /**\n   * Image media handles, one per message containing at least one\n   * `ImageBlock`. See {@link audio} for shared semantics.\n   */\n  get images(): AsyncIterable<ImageMedia> {\n    this.#ensureMediaDispatcher();\n    return this.#imagesBuffer;\n  }\n\n  /**\n   * Video media handles, one per message containing at least one\n   * `VideoBlock`. See {@link audio} for shared semantics.\n   */\n  get video(): AsyncIterable<VideoMedia> {\n    this.#ensureMediaDispatcher();\n    return this.#videoBuffer;\n  }\n\n  /**\n   * File media handles, one per message containing at least one\n   * `FileBlock`. See {@link audio} for shared semantics.\n   */\n  get files(): AsyncIterable<FileMedia> {\n    this.#ensureMediaDispatcher();\n    return this.#filesBuffer;\n  }\n\n  /**\n   * Promise that resolves with the final state value when the run\n   * completes.  Shares the `values` getter's SSE connection.\n   * Mirrors the in-process `run.output`.\n   */\n  get output(): Promise<unknown> {\n    // Accessing `this.values` ensures the projection is started.\n    void this.values;\n    return this.#outputPromise!;\n  }\n\n  /**\n   * Proxy over compile-time {@link StreamTransformer} projections\n   * exposed by the bound assistant on `custom:<name>` channels.\n   *\n   * Each access (e.g. `thread.extensions.toolActivity`) lazily opens a\n   * dedicated `custom:<name>` subscription, returns a cached\n   * {@link ThreadExtension} handle that is both `AsyncIterable<T>`\n   * (streaming items as they arrive) and `PromiseLike<T>` (resolves\n   * with the final value when the run terminates), and reuses the same\n   * handle on subsequent access.\n   *\n   * Mirrors the in-process `run.extensions.<name>` shape.\n   */\n  get extensions(): ThreadExtensions<TExtensions> {\n    if (this.#extensionsProxy) return this.#extensionsProxy;\n    const cache = this.#extensionsCache;\n    const createExtension = (name: string) => this.#createExtension(name);\n    this.#extensionsProxy = new Proxy(\n      Object.create(null) as ThreadExtensions<TExtensions>,\n      {\n        get: (_target, prop) => {\n          if (typeof prop !== \"string\") return undefined;\n          const cached = cache.get(prop);\n          if (cached) return cached;\n          const extension = createExtension(prop);\n          cache.set(prop, extension);\n          return extension;\n        },\n        has: (_target, prop) => typeof prop === \"string\",\n      }\n    );\n    return this.#extensionsProxy;\n  }\n\n  /**\n   * Lazily open one shared subscription on the `custom` channel that\n   * buffers every custom event for this run and fans it out to any\n   * per-name extension handles.\n   *\n   * Deliberately **lazy**: the dispatcher only starts on first access\n   * to `thread.extensions.<name>`. Runs that never touch extensions\n   * pay no subscription cost. Runs that touch extensions after events\n   * have already fired rely on the server's per-session event buffer,\n   * which replays matching events to new subscriptions.\n   *\n   * Each handle retains a PromiseLike that resolves with the\n   * transformer's last-observed payload, independent of when the\n   * caller grabs the handle (before, during, or after the run), as\n   * long as the server still has the events buffered.\n   *\n   * Idempotent. Invoked only from {@link #createExtension}.\n   */\n  #ensureExtensionsDispatcher(): void {\n    if (this.#extensionsDispatcherStarted) return;\n    this.#extensionsDispatcherStarted = true;\n    void this.#startProjection(\n      [\"custom\", ...this.#lifecycleChannels()],\n      (event) => {\n        if (event.method !== \"custom\") return;\n        this.#extensionsEvents.push(event);\n        for (const listener of this.#extensionsEventListeners) {\n          listener(event);\n        }\n      },\n      () => {\n        this.#extensionsEnded = true;\n        const listeners = this.#extensionsEndListeners.splice(0);\n        for (const listener of listeners) listener();\n      },\n      // Late-bound dispatchers (created after the run already terminated)\n      // are skipped by the shared-stream pause logic — their\n      // `registeredAfterSeq` is already past the terminal seq, which is\n      // intended to keep nested replays draining for raw `subscribe()`\n      // callers. The dispatcher needs the OPPOSITE: once the run's\n      // terminal lifecycle replays through, settle the per-name\n      // `PromiseLike`s with their last-observed payload. Detect the\n      // terminal explicitly here so a late `thread.extensions.<name>`\n      // access still resolves.\n      { endOnRootTerminal: true }\n    );\n  }\n\n  /**\n   * Open the single shared `messages`-channel subscription that backs\n   * every media iterable (audio/images/video/files). Idempotent.\n   *\n   * The {@link MediaAssembler} fans out to four per-type\n   * {@link MultiCursorBuffer}s; each buffer feeds its corresponding\n   * lazy getter. One handle is yielded per `(messageId, blockType)` on\n   * the first matching `content-block-start`, so messages without any\n   * media blocks of a given type never appear on that iterable.\n   */\n  #ensureMediaDispatcher(): void {\n    if (this.#mediaDispatcherStarted) return;\n    this.#mediaDispatcherStarted = true;\n    const assembler = new MediaAssembler({\n      fetch: this.#fetchOption,\n      onAudio: (m) => {\n        this.#mediaHandles.add(m);\n        this.#audioBuffer.push(m);\n      },\n      onImage: (m) => {\n        this.#mediaHandles.add(m);\n        this.#imagesBuffer.push(m);\n      },\n      onVideo: (m) => {\n        this.#mediaHandles.add(m);\n        this.#videoBuffer.push(m);\n      },\n      onFile: (m) => {\n        this.#mediaHandles.add(m);\n        this.#filesBuffer.push(m);\n      },\n    });\n    this.#mediaAssembler = assembler;\n    void this.#startProjection(\n      [\"messages\", ...this.#lifecycleChannels()],\n      (event) => {\n        if (event.method !== \"messages\") return;\n        assembler.consume(event as MessagesEvent);\n      },\n      () => {\n        assembler.close();\n        this.#audioBuffer.close();\n        this.#imagesBuffer.close();\n        this.#videoBuffer.close();\n        this.#filesBuffer.close();\n      }\n    );\n  }\n\n  /**\n   * Build a single {@link ThreadExtension} handle for a named\n   * `custom:<name>` projection.\n   *\n   * The handle reads from the shared extensions dispatcher: past events\n   * matching {@link name} are backfilled on construction, future events\n   * arrive via a registered listener, and the handle's `PromiseLike`\n   * side resolves with its last-seen payload once the run terminates\n   * (which may already have happened, in which case it resolves on the\n   * next microtask).\n   */\n  #createExtension(name: string): ThreadExtension<unknown> {\n    this.#ensureExtensionsDispatcher();\n\n    const buffer = new MultiCursorBuffer<unknown>();\n    let lastValue: unknown;\n    let resolveFinal!: (value: unknown) => void;\n    const finalPromise = new Promise<unknown>((resolve) => {\n      resolveFinal = resolve;\n    });\n\n    const handleEvent = (event: Event) => {\n      const data = event.params.data as\n        | {\n            name?: string;\n            payload?: unknown;\n          }\n        | undefined;\n      if (data?.name !== name) return;\n      lastValue = data.payload;\n      buffer.push(data.payload);\n    };\n\n    // Backfill from events already seen by the dispatcher so handles\n    // constructed mid-run or post-run still observe their payload.\n    for (const event of this.#extensionsEvents) handleEvent(event);\n\n    // Live events — routed through the shared dispatcher.\n    this.#extensionsEventListeners.push(handleEvent);\n\n    const settle = () => {\n      resolveFinal(lastValue);\n      buffer.close();\n    };\n    if (this.#extensionsEnded) {\n      settle();\n    } else {\n      this.#extensionsEndListeners.push(settle);\n    }\n\n    return Object.assign(buffer, {\n      then: <TResult1 = unknown, TResult2 = never>(\n        onfulfilled?:\n          | ((value: unknown) => TResult1 | PromiseLike<TResult1>)\n          | null,\n        onrejected?:\n          | ((reason: unknown) => TResult2 | PromiseLike<TResult2>)\n          | null\n      ): Promise<TResult1 | TResult2> =>\n        finalPromise.then(onfulfilled, onrejected),\n    }) as ThreadExtension<unknown>;\n  }\n\n  /**\n   * Generic projection starter: opens a raw subscription with the given\n   * channels, feeds events through the consumer, and calls onDone when\n   * the stream ends.\n   *\n   * When `endOnRootTerminal` is set, the projection unsubscribes its\n   * own handle one macrotask after observing a root-namespace terminal\n   * lifecycle event. This is needed by projections that may be opened\n   * AFTER a run already terminated: the shared-stream pause logic\n   * skips subscriptions whose `registeredAfterSeq` is past the\n   * terminal so raw `subscribe()` callers can keep draining replayed\n   * descendants — but a per-run dispatcher (e.g. the extensions\n   * pipeline) needs the projection to settle so its `PromiseLike`\n   * surface resolves. The macrotask deferral mirrors the deferred\n   * pause in `#handleIncoming`, giving trailing same-tick custom\n   * events (transformer `finalize()` flushes) a chance to drain.\n   */\n  async #startProjection(\n    channels: Channel[],\n    onEvent: (event: Event) => void,\n    onDone: () => void,\n    options: { endOnRootTerminal?: boolean } = {}\n  ): Promise<void> {\n    let endTimer: ReturnType<typeof setTimeout> | undefined;\n    let rawHandle: SubscriptionHandle<Event> | undefined;\n    try {\n      rawHandle = await this.#subscribeRaw({ channels });\n      const handle = rawHandle;\n      for await (const event of handle) {\n        onEvent(event);\n        if (\n          options.endOnRootTerminal &&\n          endTimer == null &&\n          isRootTerminalLifecycle(event)\n        ) {\n          endTimer = setTimeout(() => {\n            endTimer = undefined;\n            void handle.unsubscribe().catch(() => undefined);\n          }, 0);\n        }\n      }\n    } catch {\n      // Projection streams are best-effort views over the shared thread\n      // stream. Surface-level errors are reflected through the controller\n      // state; this background task only needs to settle cleanly.\n    } finally {\n      if (endTimer != null) clearTimeout(endTimer);\n      onDone();\n    }\n  }\n\n  // ---------- v2 entry points ----------\n\n  /**\n   * Start a run without the v1 eager lazy-getter shims.\n   *\n   * `run.start` (the v1 entry point) eagerly opens a wildcard `values`\n   * projection so `thread.output` / `thread.values` resolve regardless\n   * of access order, and calls `#ensureLifecycleTracking` which opens\n   * another wildcard `[\"lifecycle\", \"input\"]` subscription. Both\n   * subscriptions widen `#computeUnionFilter` to wildcard, defeating\n   * the progressive-expansion rotation strategy.\n   *\n   * `submitRun` skips those shims — callers that manage their own\n   * content subscriptions (such as `StreamController`) get the narrow\n   * union filter they asked for. Lifecycle / interrupt tracking is\n   * instead served by the dedicated `#startLifecycleWatcher`, which\n   * opens a wildcard `[\"lifecycle\", \"input\"]` stream alongside the\n   * narrow content pump on both SSE and WebSocket transports.\n   */\n  async submitRun(params: {\n    input?: unknown;\n    config?: unknown;\n    metadata?: Record<string, unknown>;\n    /**\n     * Fork the new run from an explicit checkpoint instead of the\n     * thread's latest. Forwarded verbatim on the `/run.start` protocol\n     * message; the API layer picks it up and routes it to\n     * `graph.streamEvents(input, { version: \"v3\", forkFrom })`\n     * (see plan-roadmap.md R2.4 / A0.1).\n     */\n    forkFrom?: { checkpointId: string };\n    /**\n     * Controls how concurrent submissions on the same thread are\n     * handled by the server (`reject` | `rollback` | `interrupt` |\n     * `enqueue`). Forwarded to the server; the SDK does not interpret\n     * it locally (see plan-roadmap.md S1.3 / A0.3).\n     */\n    multitaskStrategy?: \"reject\" | \"rollback\" | \"interrupt\" | \"enqueue\";\n  }): Promise<RunResult> {\n    this.#prepareForNextRun();\n    // See `this.run.start` for the gating rationale — the lifecycle\n    // watcher must register synchronously (so subagent discovery and\n    // its downstream `useToolCalls` / `useMessages` subscriptions\n    // don't race the run), but its server-side SSE/WS open is staged\n    // behind `#runStartReady` to avoid a `404: Thread not found`.\n    return await this.#withRunStartGate(() => {\n      this.#startLifecycleWatcher();\n      return this.#send(\"run.start\", {\n        ...(params as Record<string, unknown>),\n        assistant_id: this.assistantId,\n      });\n    });\n  }\n\n  /**\n   * Respond to an interrupt without the v1 eager lazy-getter shims.\n   * See {@link submitRun} for why this exists alongside\n   * {@link input.respond}.\n   */\n  async respondInput(params: {\n    namespace: readonly string[];\n    interrupt_id: string;\n    response: unknown;\n    config?: Record<string, unknown>;\n    metadata?: Record<string, unknown>;\n  }): Promise<void> {\n    this.#prepareForNextRun(params.interrupt_id);\n    this.#startLifecycleWatcher();\n    await this.#send(\n      \"input.respond\",\n      params as unknown as CommandParamsMap[\"input.respond\"]\n    );\n  }\n\n  /**\n   * Register a listener for every globally-unique event on the thread.\n   *\n   * Fires exactly once per `event_id` across both the content pump\n   * (user `subscribe()` calls) and the lifecycle watcher. Events\n   * without an `event_id` always fire through (dedup is best-effort).\n   *\n   * Returns an unsubscribe function. Primary consumer is\n   * `StreamController`, which uses the listener to feed discovery\n   * runners and pick up deeply-nested interrupts that the narrow\n   * content pump wouldn't deliver.\n   */\n  onEvent(listener: (event: Event) => void): () => void {\n    this.#onEventListeners.add(listener);\n    return () => {\n      this.#onEventListeners.delete(listener);\n    };\n  }\n\n  /**\n   * Lazily open the wildcard discovery watcher stream.\n   *\n   * Idempotent. Used by both transports, but through different\n   * mechanisms:\n   *\n   *  - **SSE**: opens a dedicated event stream via\n   *    {@link TransportAdapter.openEventStream}. The stream runs\n   *    outside `#computeUnionFilter`, so the shared SSE stream's\n   *    content pump can stay narrow (e.g. `depth: 1`) while we still\n   *    capture every lifecycle/input event at any depth.\n   *  - **WebSocket**: opens a wildcard watcher subscription\n   *    subscription via the normal command path. The WS server\n   *    delivers matching events on the shared command connection and\n   *    `#handleIncoming` dispatches them through `#fireOnEvent` and\n   *    the thread-level effects — same downstream semantics as the\n   *    SSE watcher, just reusing the transport that's already open.\n   *\n   * Why this matters: consumers of {@link onEvent} (notably\n   * `StreamController`'s subgraph/subagent discovery runners and\n   * nested interrupt capture) depend on observing namespaced\n   * lifecycle events at any depth. Without this watcher, WS clients\n   * would only ever receive events matching the content pump's\n   * narrow filter (depth 1 from the root), breaking inference rules\n   * that require deeper descendants (e.g. the \"has-descendants\"\n   * signal used to promote a subgraph host).\n   */\n  #startLifecycleWatcher(): void {\n    if (this.#lifecycleWatcherStartPromise != null) return;\n\n    if (this.#transportAdapter.openEventStream != null) {\n      this.#lifecycleWatcherStartPromise = this.#startLifecycleWatcherSse();\n      return;\n    }\n\n    this.#lifecycleWatcherStartPromise = this.#startLifecycleWatcherWebSocket();\n  }\n\n  /**\n   * Public, idempotent entry point to start the wildcard lifecycle\n   * watcher.\n   *\n   * The watcher is normally started lazily by `submitRun` /\n   * `respondInput` because for fresh (self-created) threads the SSE\n   * stream would 404 if opened before the server has the thread row.\n   * Callers that already know the thread exists server-side\n   * (`StreamController.hydrate` of an existing thread) can use this\n   * to start the watcher up front. The watcher subscribes to wildcard\n   * lifecycle events across every namespace, so it sees arbitrarily-\n   * nested subagent lifecycle messages that the narrow root content\n   * pump (running at `depth: 1`) wouldn't reach — that's what makes\n   * subagent discovery work for historical thread loads.\n   *\n   * Idempotent — repeat calls reuse the in-flight start promise.\n   */\n  startLifecycleWatcher(): void {\n    this.#startLifecycleWatcher();\n  }\n\n  async #startLifecycleWatcherSse(): Promise<void> {\n    // Wait for any in-flight `run.start` send to commit the thread\n    // server-side. Without this the SSE GET on\n    // `/threads/{id}/stream/events` 404s and the watcher tears down\n    // before delivering any lifecycle event.\n    if (this.#runStartReady != null) {\n      try {\n        await this.#runStartReady;\n      } catch {\n        return;\n      }\n    }\n    const filter: SubscribeParams = {\n      channels: [\"lifecycle\", \"input\"],\n    };\n    let handle: EventStreamHandle;\n    try {\n      handle = this.#transportAdapter.openEventStream!(filter);\n    } catch {\n      return;\n    }\n    try {\n      await handle.ready;\n    } catch {\n      try {\n        handle.close();\n      } catch {\n        // best-effort\n      }\n      return;\n    }\n    if (this.#closed) {\n      try {\n        handle.close();\n      } catch {\n        // best-effort\n      }\n      return;\n    }\n    this.#lifecycleWatcherHandle = handle;\n    try {\n      for await (const message of handle.events) {\n        if (this.#closed) break;\n        this.#handleLifecycleWatcherMessage(message);\n      }\n    } catch {\n      // Best-effort; the content pump handles surface-level errors.\n    }\n  }\n\n  async #startLifecycleWatcherWebSocket(): Promise<void> {\n    // `#subscribeRaw` on WS registers the subscription with the\n    // server and buffers incoming events on a `SubscriptionHandle`.\n    // All the side effects we care about (global dedup,\n    // `#fireOnEvent` fan-out to `onEvent` listeners, interrupt\n    // capture) already run in `#handleIncoming` regardless of which\n    // subscription matched, so we don't need to process events on\n    // the handle itself — we just drain it so its buffer doesn't\n    // accumulate.\n    let handle: SubscriptionHandle<Event>;\n    try {\n      handle = await this.#subscribeRaw({\n        channels: [\"lifecycle\", \"input\"],\n      });\n    } catch {\n      return;\n    }\n    if (this.#closed) {\n      try {\n        handle.close();\n      } catch {\n        // best-effort\n      }\n      return;\n    }\n    try {\n      for await (const _event of handle) {\n        if (this.#closed) break;\n      }\n    } catch {\n      // Best-effort; surface-level errors are reported by the\n      // content pump.\n    }\n  }\n\n  /**\n   * Process an event from the dedicated lifecycle watcher stream.\n   *\n   * Unlike `#handleIncoming`, this does NOT fan out to user\n   * subscriptions — user subs with namespace wildcards already widen\n   * `#computeUnionFilter` and therefore receive the event on the\n   * content pump. Delivering via both streams would only add per-sub\n   * dedup churn without expanding what the user can observe.\n   *\n   * We still run global-dedup thread-level side effects (interrupt\n   * capture, `onEvent` fan-out) so deeply-nested interrupts outside\n   * the content pump's narrow scope are recorded.\n   */\n  #handleLifecycleWatcherMessage(message: Message): void {\n    if (message.type !== \"event\") return;\n    if (typeof message.seq === \"number\") {\n      this.ordering.lastSeenSeq = maxSeq(\n        this.ordering.lastSeenSeq,\n        message.seq\n      );\n    }\n    if (message.event_id) {\n      this.ordering.lastEventId = message.event_id;\n    }\n    const eventId = message.event_id ?? undefined;\n    const globallyProcessed =\n      eventId != null && this.#seenEventIds.has(eventId);\n    if (eventId != null) this.#seenEventIds.add(eventId);\n    if (globallyProcessed) return;\n    this.#applyThreadLevelEffects(message);\n    this.#fireOnEvent(message);\n  }\n\n  #applyThreadLevelEffects(event: Event): void {\n    if (event.method === \"lifecycle\") {\n      const lifecycle = event as LifecycleEvent;\n      if (lifecycle.params.data.event === \"interrupted\") {\n        this.interrupted = true;\n      }\n    }\n    if (event.method === \"input.requested\") {\n      const data = event.params.data;\n      const interruptId =\n        data.interrupt_id ?? `interrupt_${this.interrupts.length}`;\n      this.interrupts.push({\n        interruptId,\n        payload: data.payload,\n        namespace: [...event.params.namespace],\n      });\n      if (isHeadlessToolInterrupt(data.payload)) {\n        this.#headlessInterruptsAwaitingTerminal.add(interruptId);\n      }\n    }\n  }\n\n  #fireOnEvent(event: Event): void {\n    if (this.#onEventListeners.size === 0) return;\n    for (const listener of this.#onEventListeners) {\n      try {\n        listener(event);\n      } catch {\n        // Best-effort — a bad listener should not wedge event delivery.\n      }\n    }\n  }\n\n  async close(): Promise<void> {\n    if (this.#closed) {\n      return;\n    }\n    this.#closed = true;\n    if (this.#terminalPauseTimer != null) {\n      clearTimeout(this.#terminalPauseTimer);\n      this.#terminalPauseTimer = undefined;\n    }\n    this.#terminalPauseSeq = undefined;\n    // Reject any `subscribe()` promises still waiting for a covering\n    // rotation, and tear down the shared SSE stream. A rotation in\n    // flight will observe `#closed` after its `await ready` and bail.\n    for (const pending of this.#pendingSubResolves) {\n      pending.reject(new Error(\"ThreadStream closed\"));\n    }\n    this.#pendingSubResolves.length = 0;\n    if (this.#sharedStream != null) {\n      try {\n        this.#sharedStream.close();\n      } catch {\n        // best-effort\n      }\n      this.#sharedStream = null;\n      this.#sharedStreamFilter = null;\n    }\n    if (this.#lifecycleWatcherHandle != null) {\n      try {\n        this.#lifecycleWatcherHandle.close();\n      } catch {\n        // best-effort\n      }\n      this.#lifecycleWatcherHandle = null;\n    }\n    const lifecycleWatcherStartPromise = this.#lifecycleWatcherStartPromise;\n    this.#lifecycleWatcherStartPromise = undefined;\n    this.#onEventListeners.clear();\n    for (const subscription of this.#subscriptions.values()) {\n      subscription.close();\n    }\n    this.#subscriptions.clear();\n    try {\n      await lifecycleWatcherStartPromise;\n    } catch {\n      // best-effort\n    }\n    // Safety net: revoke any object URLs minted by media handles so\n    // long-lived consumers don't leak after thread teardown.\n    for (const handle of this.#mediaHandles) {\n      try {\n        handle.revoke();\n      } catch {\n        // best-effort\n      }\n    }\n    this.#mediaHandles.clear();\n    this.#mediaAssembler?.close();\n    this.#audioBuffer.close();\n    this.#imagesBuffer.close();\n    this.#videoBuffer.close();\n    this.#filesBuffer.close();\n    await this.#transportAdapter.close();\n  }\n\n  /**\n   * Subscribe to raw wire channels and receive protocol events.\n   *\n   * For assembled projections, use the lazy getters instead:\n   * `thread.messages`, `thread.values`, `thread.toolCalls`,\n   * `thread.subgraphs`, `thread.subagents`, `thread.output`.\n   */\n  async subscribe<TChannel extends Channel>(\n    channel: TChannel,\n    options?: SubscribeOptions\n  ): Promise<\n    SubscriptionHandle<EventForChannel<TChannel>, YieldForChannel<TChannel>>\n  >;\n  async subscribe<const TChannels extends readonly Channel[]>(\n    channels: TChannels,\n    options?: SubscribeOptions\n  ): Promise<\n    SubscriptionHandle<EventForChannels<TChannels>, YieldForChannels<TChannels>>\n  >;\n  async subscribe(params: SubscribeParams): Promise<SubscriptionHandle<Event>>;\n  async subscribe(\n    paramsOrChannels: SubscribeParams | Channel | readonly Channel[],\n    options: SubscribeOptions = {}\n  ): Promise<unknown> {\n    // The string / string-array overloads are typed to unwrap\n    // `custom:<name>` payloads for ergonomic single-extension\n    // subscriptions (`thread.subscribe(\"custom:a2a\")` yields the\n    // raw payload). The `SubscribeParams` object overload, however,\n    // is typed as `SubscriptionHandle<Event>` — it must deliver the\n    // full event envelope so callers like `channelProjection` (which\n    // backs `useChannel`) can see the `method`, `namespace`, and\n    // `data.name` fields needed for filtering and rendering.\n    const isParamsObject =\n      typeof paramsOrChannels === \"object\" &&\n      !Array.isArray(paramsOrChannels) &&\n      \"channels\" in paramsOrChannels;\n    const params = normalizeSubscribeParams(\n      paramsOrChannels as SubscribeParams | Channel | readonly Channel[],\n      options\n    );\n    return await this.#subscribeRaw(params, {\n      unwrapNamedCustom: !isParamsObject,\n    });\n  }\n\n  async #subscribeRaw(\n    params: SubscribeParams,\n    options: { unwrapNamedCustom?: boolean } = {}\n  ): Promise<SubscriptionHandle<Event>> {\n    await this.#ensureOpen();\n    const { unwrapNamedCustom = true } = options;\n    const hasOnlyNamedCustom =\n      params.channels.length > 0 &&\n      params.channels.every((ch) => ch.startsWith(\"custom:\"));\n    const transform =\n      unwrapNamedCustom && hasOnlyNamedCustom\n        ? (event: Event) =>\n            (\n              (event.params as Record<string, unknown>).data as {\n                payload?: unknown;\n              }\n            )?.payload ?? event\n        : undefined;\n\n    if (this.#transportAdapter.openEventStream != null) {\n      return this.#subscribeViaSharedStream(params, transform);\n    }\n\n    return this.#subscribeViaCommand(params, transform);\n  }\n\n  /**\n   * Subscribe via the single shared SSE connection.\n   *\n   * The subscription is registered immediately in `#subscriptions` so\n   * fan-out can reach it the moment events begin flowing. The returned\n   * promise resolves after a stream rotation completes whose union\n   * filter covers this subscription's channels — mirroring the per-sub\n   * `await streamHandle.ready` semantics callers depended on.\n   *\n   * Every subscribe schedules a stream rotation, even when the current\n   * stream's filter already covers `params`. Rotating opens a fresh\n   * server-side session that replays the run's full history from\n   * `seq=0`; without it a late-joining sub would only see events that\n   * arrive after it registered, because the shared pump's dedup drops\n   * events the existing sub already consumed. Per-sub dedup\n   * (`seenEventIds`) protects existing subs from receiving the\n   * replay as duplicates. Rapid subscribes in the same microtask are\n   * coalesced by `#scheduleReconcile` into a single rotation.\n   */\n  async #subscribeViaSharedStream(\n    params: SubscribeParams,\n    transform?: (event: Event) => unknown\n  ): Promise<SubscriptionHandle<Event>> {\n    const subscriptionId = `sse-${this.#nextCommandId++}`;\n    const handle = new SubscriptionHandle<Event, unknown>(\n      subscriptionId,\n      params,\n      async (id) => {\n        this.#subscriptions.delete(id);\n        this.#scheduleReconcile();\n      },\n      transform\n    );\n    const subscription = Object.assign(handle, {\n      filter: params,\n      registeredAfterSeq: this.ordering.lastSeenSeq,\n      seenEventIds: new Set<string>(),\n    });\n    this.#subscriptions.set(subscriptionId, subscription);\n\n    const covered = new Promise<void>((resolve, reject) => {\n      this.#pendingSubResolves.push({ filter: params, resolve, reject });\n    });\n    this.#scheduleReconcile();\n\n    try {\n      await covered;\n    } catch (err) {\n      this.#subscriptions.delete(subscriptionId);\n      throw err;\n    }\n    return handle as SubscriptionHandle<Event>;\n  }\n\n  /**\n   * Progressive-expansion union of every currently-registered\n   * subscription's filter. The server receives the narrowest filter\n   * that still covers every active sub so deeply-namespaced or\n   * selectively-opened projections don't pull down the entire thread's\n   * event firehose.\n   *\n   * Unioning rules (matching the server's matching semantics in\n   * `matchesSinkFilter`):\n   *  - Channels: set union.\n   *  - Namespaces: if any subscription requests a wildcard\n   *    (`namespaces === undefined`) the union is wildcard; otherwise\n   *    the union is the deduplicated list of every explicit prefix.\n   *  - Depth: if any subscription is unbounded (`depth === undefined`)\n   *    the union is unbounded; otherwise the union is the maximum\n   *    depth across all subscriptions (matching the per-sub \"max\n   *    reach below the prefix\" semantics).\n   *\n   * Returns `null` when there are no subscriptions.\n   */\n  #computeUnionFilter(): SubscribeParams | null {\n    if (this.#subscriptions.size === 0) return null;\n\n    const channels = new Set<Channel>();\n    let wildcardNamespaces = false;\n    const namespaceMap = new Map<string, Namespace>();\n    let unboundedDepth = false;\n    let maxDepth = 0;\n\n    for (const sub of this.#subscriptions.values()) {\n      for (const ch of sub.filter.channels) channels.add(ch);\n\n      if (sub.filter.namespaces == null) {\n        wildcardNamespaces = true;\n      } else if (!wildcardNamespaces) {\n        for (const ns of sub.filter.namespaces) {\n          namespaceMap.set(namespaceKey(ns), ns);\n        }\n      }\n\n      if (sub.filter.depth == null) {\n        unboundedDepth = true;\n      } else if (!unboundedDepth && sub.filter.depth > maxDepth) {\n        maxDepth = sub.filter.depth;\n      }\n    }\n\n    const result: SubscribeParams = {\n      channels: [...channels] as Channel[],\n    };\n    if (!wildcardNamespaces) {\n      result.namespaces = [...namespaceMap.values()];\n    }\n    if (!unboundedDepth) {\n      result.depth = maxDepth;\n    }\n    return result;\n  }\n\n  /**\n   * Schedule a stream reconciliation for the next microtask.\n   *\n   * Coalesces multiple subscribe/unsubscribe calls in the same tick\n   * into a single rotation, and serializes across ticks (no two\n   * rotations ever run concurrently).\n   */\n  #scheduleReconcile(): void {\n    if (this.#closed) return;\n    if (this.#rotationState !== \"idle\") return;\n    this.#rotationState = \"scheduled\";\n    queueMicrotask(() => {\n      if (this.#closed) {\n        this.#rotationState = \"idle\";\n        return;\n      }\n      this.#rotationState = \"idle\";\n      void this.#reconcileStream().catch(() => {\n        this.#rotationState = \"idle\";\n      });\n    });\n  }\n\n  /**\n   * Reconcile the shared SSE stream to match the desired union filter.\n   *\n   * Rotation strategy: open the new stream first, await its `ready`,\n   * then close the old one. Overlap is absorbed by `#seenEventIds`\n   * dedup in `#handleIncoming`.\n   *\n   * Error handling:\n   *   - Failure before `ready` resolves: reject all pending `subscribe`\n   *     promises whose filter isn't covered by the existing stream,\n   *     and keep the existing stream running for other subscriptions.\n   *   - Failure mid-pump on the active stream: close the thread via\n   *     {@link #failThreadWithError} so higher layers can rebind.\n   */\n  async #reconcileStream(): Promise<void> {\n    if (this.#closed) return;\n    if (this.#rotationState === \"rotating\") return;\n\n    const desired = this.#computeUnionFilter();\n    if (desired == null) return;\n\n    // Wait for any in-flight `run.start` send so the SSE GET on\n    // `/threads/{id}/stream/events` doesn't 404 against a thread the\n    // server hasn't created yet. Late subscribers (after `run.start`\n    // resolves) see a null gate and proceed immediately. The\n    // `openEventStream` adapter contract requires implementations to\n    // buffer events and replay them on new opens, so the rotation\n    // doesn't lose events that were emitted during the wait.\n    if (this.#runStartReady != null) {\n      try {\n        await this.#runStartReady;\n      } catch (err) {\n        // The pending `run.start` failed; abandon this rotation and\n        // let the rejected `run.start` surface the error to callers.\n        // Forward the original cause so pending subscribers see the\n        // real reason rather than a generic \"run.start failed\".\n        const normalized =\n          // oxlint-disable-next-line no-instanceof/no-instanceof\n          err instanceof Error ? err : new Error(\"run.start failed\");\n        this.#rejectUncoveredPending(normalized);\n        return;\n      }\n      if (this.#closed) return;\n      // Re-read through a local — TS narrowed `#rotationState` above\n      // and doesn't widen it back across the await, but another\n      // reconcile may have set it in the interim.\n      const stateNow: string = this.#rotationState;\n      if (stateNow === \"rotating\") return;\n    }\n\n    // Bail only when nothing structurally changed AND nobody is\n    // waiting on a fresh replay. A pending sub always needs a\n    // rotation even when the filter is unchanged, because the server\n    // replays buffered events only at the moment the SSE connection\n    // is opened.\n    if (\n      this.#sharedStreamFilter != null &&\n      filterEqual(desired, this.#sharedStreamFilter) &&\n      this.#pendingSubResolves.length === 0\n    ) {\n      this.#resolvePending();\n      return;\n    }\n\n    this.#rotationState = \"rotating\";\n    let newHandle: EventStreamHandle;\n    try {\n      newHandle = this.#transportAdapter.openEventStream!(desired);\n    } catch (err) {\n      this.#rotationState = \"idle\";\n      this.#rejectUncoveredPending(err);\n      return;\n    }\n\n    try {\n      await newHandle.ready;\n    } catch (err) {\n      this.#rotationState = \"idle\";\n      try {\n        newHandle.close();\n      } catch {\n        // best-effort\n      }\n      this.#rejectUncoveredPending(err);\n      return;\n    }\n\n    if (this.#closed) {\n      try {\n        newHandle.close();\n      } catch {\n        // best-effort\n      }\n      this.#rotationState = \"idle\";\n      return;\n    }\n\n    void this.#pumpStream(newHandle);\n\n    const oldHandle = this.#sharedStream;\n    this.#sharedStream = newHandle;\n    this.#sharedStreamFilter = desired;\n    if (oldHandle != null) {\n      try {\n        oldHandle.close();\n      } catch {\n        // best-effort\n      }\n    }\n\n    this.#rotationState = \"idle\";\n    this.#resolvePending();\n\n    const next = this.#computeUnionFilter();\n    if (next != null && !filterEqual(next, this.#sharedStreamFilter)) {\n      this.#scheduleReconcile();\n    }\n  }\n\n  /**\n   * Pump events from a shared-stream handle into `#handleIncoming`.\n   * One pump task runs per open stream; during rotation overlap two\n   * pumps may be active briefly, with `#seenEventIds` deduping.\n   */\n  async #pumpStream(handle: EventStreamHandle): Promise<void> {\n    try {\n      for await (const message of handle.events) {\n        if (this.#closed) {\n          break;\n        }\n        this.#handleIncoming(message);\n      }\n    } catch (err) {\n      if (handle === this.#sharedStream && !this.#closed) {\n        this.#failThreadWithError(err);\n      }\n      // Errors on an old (being-rotated-out) stream are ignored —\n      // the new stream is already pumping and holds authoritative state.\n    }\n  }\n\n  /**\n   * Resolve any pending `subscribe()` promises whose filter is now\n   * covered by the active shared stream. Called after every successful\n   * rotation (and after no-op reconciliations).\n   */\n  #resolvePending(): void {\n    if (this.#sharedStreamFilter == null) return;\n    const current = this.#sharedStreamFilter;\n    if (this.#pendingSubResolves.length === 0) return;\n    const stillPending: PendingSubResolve[] = [];\n    for (const pending of this.#pendingSubResolves) {\n      if (filterCovers(current, pending.filter)) {\n        pending.resolve();\n      } else {\n        stillPending.push(pending);\n      }\n    }\n    this.#pendingSubResolves.length = 0;\n    this.#pendingSubResolves.push(...stillPending);\n  }\n\n  /**\n   * Reject pending `subscribe()` promises whose filter isn't covered\n   * by the existing stream (they're the ones that triggered the\n   * failed rotation). Covered pending subs are resolved normally —\n   * they didn't need the new stream.\n   */\n  #rejectUncoveredPending(err: unknown): void {\n    if (this.#pendingSubResolves.length === 0) return;\n    const current = this.#sharedStreamFilter;\n    const stillPending: PendingSubResolve[] = [];\n    for (const pending of this.#pendingSubResolves) {\n      if (current != null && filterCovers(current, pending.filter)) {\n        pending.resolve();\n      } else {\n        stillPending.push(pending);\n      }\n    }\n    this.#pendingSubResolves.length = 0;\n    for (const pending of stillPending) pending.reject(err);\n  }\n\n  /**\n   * Terminate the thread due to an unrecoverable shared-stream error.\n   * Rejects pending commands, closes subscriptions, and marks the\n   * thread closed so no further rotations occur.\n   */\n  #failThreadWithError(err: unknown): void {\n    const normalized =\n      // oxlint-disable-next-line no-instanceof/no-instanceof\n      err instanceof Error ? err : new Error(String(err));\n    for (const pending of this.#pending.values()) {\n      pending.reject(normalized);\n    }\n    this.#pending.clear();\n    for (const pending of this.#pendingSubResolves) {\n      pending.reject(normalized);\n    }\n    this.#pendingSubResolves.length = 0;\n    for (const subscription of this.#subscriptions.values()) {\n      subscription.close();\n    }\n  }\n\n  /**\n   * Command-based subscription (WebSocket fallback). The server replays\n   * matching buffered events on subscribe via the same WebSocket stream.\n   */\n  async #subscribeViaCommand(\n    params: SubscribeParams,\n    transform?: (event: Event) => unknown\n  ): Promise<SubscriptionHandle<Event>> {\n    // Register the subscription on the client BEFORE sending the\n    // ``subscription.subscribe`` command. The WebSocket server replays\n    // buffered events through ``install_subscription_with_replay``\n    // *before* returning the success response that carries the\n    // ``subscription_id``. If we waited for the response and only then\n    // ran ``this.#subscriptions.set(...)``, those replayed events would\n    // arrive at ``#handleIncoming`` while no matching subscription is\n    // registered — they would never reach the iterator, so\n    // namespace-scoped projections (``useMessages``) would render\n    // empty after click-to-expand on the WebSocket transport.\n    //\n    // ``#handleIncoming``'s fan-out matches purely on\n    // ``subscription.filter`` (channels + namespaces + depth), so a\n    // pre-registered entry under any temporary key already catches\n    // every replayed event. Once the server-assigned id arrives, we\n    // re-key the entry so a later ``unsubscribe`` finds it.\n    // ``#nextCommandId`` is post-incremented inside ``#send``; reading\n    // it here doesn't reserve the value, so two concurrent subscribes\n    // (typical under React StrictMode's mount→unmount→mount) would\n    // collide on the same placeholder. Mint a UUID-like suffix instead.\n    const placeholderId = `pending:${this.#nextCommandId}:${Math.random().toString(36).slice(2, 10)}`;\n    let resolvedId = placeholderId;\n    const handle = new SubscriptionHandle<Event, unknown>(\n      placeholderId,\n      params,\n      async () => {\n        // Use the server-assigned id once we have it; fall back to the\n        // placeholder while the subscribe command is still in flight\n        // (unsubscribe before subscribe-response is unusual but\n        // possible — disposing a projection that mounted and unmounted\n        // in the same React tick).\n        this.#subscriptions.delete(resolvedId);\n        if (!this.#closed && resolvedId !== placeholderId) {\n          await this.#send(\"subscription.unsubscribe\", {\n            subscription_id: resolvedId,\n          }).catch((err: unknown) => {\n            if (\n              // oxlint-disable-next-line no-instanceof/no-instanceof\n              err instanceof ProtocolError &&\n              err.code === \"no_such_subscription\"\n            ) {\n              return;\n            }\n            throw err;\n          });\n        }\n      },\n      transform\n    );\n    const subscription = Object.assign(handle, {\n      filter: params,\n      registeredAfterSeq: this.ordering.lastSeenSeq,\n      seenEventIds: new Set<string>(),\n    });\n    this.#subscriptions.set(placeholderId, subscription);\n    // Wait for any in-flight `run.start` send to commit the thread\n    // server-side. WS `subscription.subscribe` is rejected with\n    // `404: Thread not found` if it arrives before the thread is\n    // created — mirroring the SSE gates in `#startLifecycleWatcherSse`\n    // and `#reconcileStream`.\n    if (this.#runStartReady != null) {\n      try {\n        await this.#runStartReady;\n      } catch (err) {\n        this.#subscriptions.delete(placeholderId);\n        throw err;\n      }\n    }\n    let result: SubscribeResult;\n    try {\n      result = await this.#send(\"subscription.subscribe\", params);\n    } catch (err) {\n      this.#subscriptions.delete(placeholderId);\n      throw err;\n    }\n    this.#subscriptions.delete(placeholderId);\n    resolvedId = result.subscription_id;\n    // Re-key the map AND update the handle's public id. Without the\n    // second write, `#lifecycleSubId === handle.subscriptionId` checks\n    // (see `#prepareForNextRun` and the terminal-pause logic) compare\n    // the cached placeholder against the live map key and silently\n    // fail, causing the lifecycle subscription to be paused at\n    // terminal events on the WS transport.\n    handle.subscriptionId = resolvedId;\n    this.#subscriptions.set(resolvedId, subscription);\n    return handle as SubscriptionHandle<Event>;\n  }\n\n  async #consumeEvents(): Promise<void> {\n    try {\n      for await (const message of this.#transportAdapter.events()) {\n        this.#handleIncoming(message);\n      }\n      for (const subscription of this.#subscriptions.values()) {\n        subscription.close();\n      }\n    } catch (error) {\n      const normalized =\n        // oxlint-disable-next-line no-instanceof/no-instanceof\n        error instanceof Error ? error : new Error(String(error));\n      for (const pending of this.#pending.values()) {\n        pending.reject(normalized);\n      }\n      for (const subscription of this.#subscriptions.values()) {\n        subscription.close();\n      }\n      this.#pending.clear();\n    }\n  }\n\n  /**\n   * Pause non-lifecycle subscriptions after a root terminal lifecycle.\n   *\n   * The pause is deferred one macrotask so same-run trailing events\n   * emitted immediately after terminal (for example final `values`)\n   * can still drain. `terminalSeq` lets replay attachers skip terminals\n   * that happened before they registered, so late subscribers can keep\n   * consuming the replayed history they joined for.\n   */\n  #scheduleTerminalPause(terminalSeq: number | undefined): void {\n    if (this.#terminalPauseTimer != null) {\n      clearTimeout(this.#terminalPauseTimer);\n    }\n    this.#terminalPauseSeq = terminalSeq ?? null;\n    this.#terminalPauseTimer = setTimeout(() => {\n      this.#terminalPauseTimer = undefined;\n      if (this.#closed) return;\n      for (const [id, subscription] of this.#subscriptions) {\n        if (id === this.#lifecycleSubId) continue;\n        if (\n          terminalSeq != null &&\n          subscription.registeredAfterSeq != null &&\n          subscription.registeredAfterSeq >= terminalSeq\n        ) {\n          continue;\n        }\n        subscription.pause();\n      }\n    }, 0);\n  }\n\n  #handleIncoming(message: Message): void {\n    if (message.type === \"event\") {\n      if (typeof message.seq === \"number\") {\n        this.ordering.lastSeenSeq = maxSeq(\n          this.ordering.lastSeenSeq,\n          message.seq\n        );\n      }\n      if (message.event_id) {\n        this.ordering.lastEventId = message.event_id;\n      }\n\n      // Two flavors of dedup live here:\n      //   1. Thread-level side effects (interrupt state, interrupt\n      //      capture) — must run AT MOST ONCE per unique event_id\n      //      regardless of how many times the event is redelivered\n      //      (rotation overlap, WebSocket fan-out). Gated by the\n      //      global `#seenEventIds`.\n      //   2. Per-subscription fan-out — gated by each sub's own\n      //      `seenEventIds`. This is what lets a rotation-triggered\n      //      replay (the server opens a fresh session that replays\n      //      from seq=0) reach newly-registered subs while NOT\n      //      redelivering events to subs that have already consumed\n      //      them. Event IDs are stable across sessions for the same\n      //      run, so per-sub set membership is the correct predicate.\n      const eventId = message.event_id ?? undefined;\n      const globallyProcessed =\n        eventId != null && this.#seenEventIds.has(eventId);\n      if (eventId != null) {\n        this.#seenEventIds.add(eventId);\n      }\n\n      const TERMINAL_LIFECYCLE_EVENTS = new Set([\n        \"interrupted\",\n        \"completed\",\n        \"failed\",\n      ]);\n\n      if (!globallyProcessed) {\n        this.#applyThreadLevelEffects(message);\n        this.#fireOnEvent(message);\n      }\n\n      // Unified fan-out: both SSE (shared stream) and WebSocket paths\n      // deliver every event through a single connection; the client\n      // dispatches to matching subscriptions based on each sub's\n      // advertised filter, with per-sub dedup.\n      let fannedToAny = false;\n      for (const subscription of this.#subscriptions.values()) {\n        if (!matchesSubscription(message, subscription.filter)) continue;\n        if (eventId != null) {\n          if (subscription.seenEventIds.has(eventId)) {\n            continue;\n          }\n          subscription.seenEventIds.add(eventId);\n        }\n        subscription.push(message);\n        fannedToAny = true;\n      }\n\n      // A root terminal schedules subscription pause on a macrotask,\n      // but reconnect/replay can still deliver same-run trailing state\n      // afterward (for example the final `values` snapshot). Drain that\n      // event, briefly resume any paused consumers, then re-arm the\n      // terminal pause so idle subscriptions still settle.\n      if (\n        fannedToAny &&\n        this.#terminalPauseSeq !== undefined &&\n        !(\n          message.method === \"lifecycle\" &&\n          message.params.namespace.length === 0\n        )\n      ) {\n        const eventSeq =\n          typeof message.seq === \"number\" ? message.seq : undefined;\n        const terminalSeq = this.#terminalPauseSeq;\n        if (\n          terminalSeq === null ||\n          eventSeq == null ||\n          eventSeq > terminalSeq\n        ) {\n          if (this.#terminalPauseTimer != null) {\n            clearTimeout(this.#terminalPauseTimer);\n            this.#terminalPauseTimer = undefined;\n          }\n          for (const [id, subscription] of this.#subscriptions) {\n            if (id !== this.#lifecycleSubId) {\n              subscription.resume();\n            }\n          }\n          this.#scheduleTerminalPause(\n            terminalSeq === null ? undefined : terminalSeq\n          );\n        }\n      }\n\n      if (\n        fannedToAny &&\n        message.method === \"lifecycle\" &&\n        message.params.namespace.length === 0 &&\n        TERMINAL_LIFECYCLE_EVENTS.has(message.params.data.event)\n      ) {\n        const shouldSkipPause =\n          message.params.data.event === \"interrupted\" &&\n          this.#headlessInterruptsAwaitingTerminal.size > 0;\n        if (shouldSkipPause) {\n          this.#headlessInterruptsAwaitingTerminal.clear();\n          return;\n        }\n        // A single shared stream delivers every subscription's events,\n        // so a terminal event applies to all currently active\n        // non-lifecycle subscriptions. Defer the pause one macrotask:\n        // transformer `finalize()` hooks can emit trailing custom events\n        // immediately after root lifecycle completion, and pausing\n        // synchronously would buffer those same-run events until the\n        // next submit resumes subscriptions.\n        this.#scheduleTerminalPause(\n          typeof message.seq === \"number\" ? message.seq : undefined\n        );\n      }\n      return;\n    }\n\n    const messageId = typeof message.id === \"number\" ? message.id : undefined;\n    const pending =\n      messageId === undefined ? undefined : this.#pending.get(messageId);\n    if (!pending) {\n      return;\n    }\n    if (messageId !== undefined) {\n      this.#pending.delete(messageId);\n    }\n    if (message.type === \"error\") {\n      pending.reject(new ProtocolError(message));\n      return;\n    }\n    if (typeof message.meta?.applied_through_seq === \"number\") {\n      this.ordering.lastAppliedThroughSeq = message.meta.applied_through_seq;\n    }\n    pending.resolve(message);\n  }\n\n  async #send<TMethod extends keyof CommandResultMap>(\n    method: TMethod,\n    params: CommandParamsMap[TMethod]\n  ): Promise<CommandResultMap[TMethod]> {\n    await this.#ensureOpen();\n    const id = this.#nextCommandId++;\n    const command = {\n      id,\n      method,\n      params,\n    } as Command;\n    const responsePromise = new Promise<CommandResponse>((resolve, reject) => {\n      this.#pending.set(id, { resolve, reject });\n    });\n    const immediate = await this.#transportAdapter.send(command);\n    if (immediate) {\n      this.#pending.delete(id);\n      if (immediate.type === \"error\") {\n        throw new ProtocolError(immediate);\n      }\n      if (typeof immediate.meta?.applied_through_seq === \"number\") {\n        this.ordering.lastAppliedThroughSeq =\n          immediate.meta.applied_through_seq;\n      }\n      return immediate.result as CommandResultMap[TMethod];\n    }\n    const response = await responsePromise;\n    return response.result as CommandResultMap[TMethod];\n  }\n}\n\nexport {\n  MessageAssembler,\n  StreamingMessageAssembler,\n  StreamingMessage,\n} from \"./messages.js\";\nexport type { AssembledMessage, MessageAssemblyUpdate } from \"./messages.js\";\nexport {\n  ToolCallAssembler,\n  toClientAssembledToolCall,\n  SubgraphDiscoveryHandle,\n  SubgraphHandle,\n  SubagentHandle,\n  SubagentDiscoveryHandle,\n} from \"./handles/index.js\";\nexport type {\n  ClientAssembledToolCall,\n  ClientAssembledToolCall as AssembledToolCall,\n  ToolCallStatus,\n  Subscribable,\n} from \"./handles/index.js\";\nexport { inferChannel, matchesSubscription } from \"./subscription.js\";\nexport type { TransportAdapter, AgentServerAdapter } from \"./transport.js\";\nexport type * from \"./types.js\";\nexport { ProtocolError } from \"./error.js\";\nexport { MediaAssembler, MediaAssemblyError } from \"./media.js\";\nexport type {\n  AnyMediaHandle,\n  AudioMedia,\n  FileMedia,\n  ImageMedia,\n  MediaAssemblerCallbacks,\n  MediaAssemblerOptions,\n  MediaAssemblyErrorKind,\n  MediaBase,\n  MediaBlockType,\n  VideoMedia,\n} from \"./media.js\";\n"],"mappings":"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"}