{"version":3,"file":"controller.cjs","names":["#options","#messagesKey","#subagents","SubagentDiscovery","#subgraphs","SubgraphDiscovery","#messageMetadata","MessageMetadataTracker","#resolvedInterrupts","#selfCreatedThreadIds","#missingThreadIds","#namespaceResolves","#scopedHistorySeeds","#rootEventListeners","#rootBus","#heldLifecycleReleases","ToolCallAssembler","#threadListeners","#currentThreadId","#trySeedProjectionFromHistory","ChannelRegistry","StreamStore","#createInitialSnapshot","#rootMessages","RootMessageProjection","#lifecycleLoading","LifecycleLoadingTracker","#disposed","#submitter","#submittedRunMatch","EMPTY_QUEUE","SubmitCoordinator","#ensureThread","#startDeferredRootPump","#abandonDeferredRootPump","#rootPumpReady","#awaitNextTerminal","#awaitResumedRunTerminal","#submitGeneration","#interruptCommandPending","#hydratedActiveInterruptIds","#pendingInterruptEvents","#pendingHydrationInterruptEvents","#markLocalRunStart","#submittedRunId","#submittedRunIdPending","#advanceInterruptReplayBarrier","#notifyCreated","#notifyCompleted","#markLocalRunEnd","#beginOptimistic","#settleOptimistic","#hydrationPromise","#createHydrationPromise","#resolveHydration","#rejectHydration","#fetchHydrationState","#discoverySeedPromise","#resetHydrationPromise","#teardownThread","#hydratedCheckpointTime","#applyValues","seedToolCallsFromMessages","ensureMessageInstances","upsertToolCall","#interruptReplayThroughSeq","#seedDiscoveryFromHistory","getHistoryPage","#primeScopedHistorySeedsFromHistory","collectSubgraphHostNamespaces","mapSubagentNamespaces","resolveSubagentNamespaces","#rootPumpDeferred","#skipDefaultSubagentProjection","#getScopedHistorySeed","namespaceKey","#activeRunId","#localRunDepth","#runLifecycleListener","isRootNamespace","#thread","#resolveNamespaceForInterruptId","#resolveInterruptForResume","#resolveDispatchUpdate","normalizeHitlResponseForServer","#markInterruptResolvedInRootStore","#discardPendingInterruptEvents","#cancelPendingDispose","#pendingDisposeTimer","#rootPump","#startRootPump","#notifyThreadListeners","#rootPumpGeneration","#threadEventUnsubscribe","#threadErrorUnsubscribe","#rootSubscription","#rootToolAssembler","#onWildcardEvent","#usesEventStreamTransport","#onRootEvent","#recordInterrupt","#settleParkedInterruptsOnTerminal","isInternalWorkNamespace","isLegacySubagentNamespace","prepareOptimisticInput","#sawValuesForRun","serializeUpdateMessages","reconcileToolCallsFromMessages","normalizeInterruptForClient","#reconcilePendingInterruptsFromServer","#settleParkedInterrupts","#settleParkedInterruptsPromise","#awaitRootTerminal","resolveInterruptTargetForHeadlessResume","DEFAULT_MESSAGES_KEY"],"sources":["../../src/stream/controller.ts"],"sourcesContent":["/**\n * Framework-agnostic controller for the experimental v2 stream.\n *\n * Responsibilities:\n *  - Owns at most one {@link ThreadStream} at a time (swapped on\n *    `hydrate(newThreadId)` or `dispose`).\n *  - Exposes three always-on observable surfaces via {@link StreamStore}:\n *      - `rootStore`      : root values/messages/toolCalls/interrupts/…\n *      - `subagentStore`  : discovery map of subagents (no content)\n *      - `subgraphStore`  : discovery map of subgraphs  (no content)\n *  - Owns a {@link ChannelRegistry} that framework selector hooks\n *    (`useMessages`, `useToolCalls`, `useExtension`, `useChannel`)\n *    use to lazily open per-namespace subscriptions.\n *  - Imperative run surface: `submit`, `stop`, `respond`, `joinStream`.\n *\n * A single multi-channel subscription (`values`, `lifecycle`, `input`,\n * `messages`, `tools`) powers every always-on projection and both\n * discovery runners. Selector hooks add their own (deduped)\n * subscriptions on top — so even a UI with many subagents only opens\n * one extra subscription per `(channels, namespace)` actually\n * rendered on screen.\n */\nimport { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport { AIMessage, type BaseMessage } from \"@langchain/core/messages\";\nimport type {\n  Channel,\n  Event,\n  LifecycleEvent,\n  MessagesEvent,\n  ToolsEvent,\n  ValuesEvent,\n} from \"@langchain/protocol\";\nimport type { Interrupt, ThreadState } from \"../schema.js\";\nimport type { ThreadStream } from \"../client/stream/index.js\";\nimport type { SubscriptionHandle } from \"../client/stream/index.js\";\nimport { ToolCallAssembler } from \"../client/stream/handles/tools.js\";\nimport type { AssembledToolCall } from \"../client/stream/handles/tools.js\";\nimport { normalizeInterruptForClient } from \"../ui/interrupts.js\";\nimport { normalizeHitlResponseForServer } from \"../ui/hitl-interrupt-payload.js\";\nimport type { Message } from \"../types.messages.js\";\nimport { NAMESPACE_SEPARATOR, DEFAULT_MESSAGES_KEY } from \"./constants.js\";\nimport { StreamStore } from \"./store.js\";\nimport { ChannelRegistry } from \"./channel-registry.js\";\nimport { ensureMessageInstances } from \"./message-coercion.js\";\nimport {\n  SubagentDiscovery,\n  type SubagentMap,\n  SubgraphDiscovery,\n  type SubgraphMap,\n  type SubgraphByNodeMap,\n} from \"./discovery/index.js\";\nimport {\n  collectSubgraphHostNamespaces,\n  getHistoryPage,\n  mapSubagentNamespaces,\n  resolveSubagentNamespaces,\n} from \"./discovery/namespace-from-history.js\";\nimport type { SubagentDiscoverySnapshot } from \"./types.js\";\nimport {\n  isInternalWorkNamespace,\n  isLegacySubagentNamespace,\n  isRootNamespace,\n  namespaceKey,\n} from \"./namespace.js\";\nimport {\n  MessageMetadataTracker,\n  type CheckpointEnvelope,\n  type MessageMetadata,\n  type MessageMetadataMap,\n} from \"./message-metadata-tracker.js\";\nimport { LifecycleLoadingTracker } from \"./lifecycle-loading-tracker.js\";\nimport { RootMessageProjection } from \"./root-message-projection.js\";\nimport {\n  prepareOptimisticInput,\n  serializeUpdateMessages,\n  type OptimisticHandle,\n} from \"./optimistic-input.js\";\nimport {\n  EMPTY_QUEUE,\n  SubmitCoordinator,\n  type SubmissionQueueEntry,\n  type SubmissionQueueSnapshot,\n} from \"./submit-coordinator.js\";\nimport {\n  reconcileToolCallsFromMessages,\n  seedToolCallsFromMessages,\n  upsertToolCall,\n} from \"./tool-calls.js\";\nimport { resolveInterruptTargetForHeadlessResume } from \"../headless-tools.js\";\nimport type {\n  RootEventBus,\n  RootSnapshot,\n  RunExecutionReason,\n  StreamControllerOptions,\n  StreamRespondAllOptions,\n  StreamRespondOptions,\n  StreamStopOptions,\n  StreamSubmitOptions,\n} from \"./types.js\";\n\nfunction isAbortLikeError(error: unknown): boolean {\n  if (error == null || typeof error !== \"object\") return false;\n  const maybeError = error as { name?: unknown; message?: unknown };\n  return (\n    maybeError.name === \"AbortError\" ||\n    (typeof maybeError.message === \"string\" &&\n      maybeError.message.includes(\"aborted\"))\n  );\n}\n\nfunction lifecycleReason(event: string | undefined): RunExecutionReason | null {\n  if (event === \"completed\") return \"success\";\n  if (event === \"failed\") return \"error\";\n  if (event === \"interrupted\") return \"interrupt\";\n  return null;\n}\n\ninterface ScopedHistorySeed {\n  readonly messages: BaseMessage[];\n  readonly toolCalls: AssembledToolCall[];\n}\n\n/**\n * Decide whether a hydrated thread is *active* (a run is executing or\n * paused awaiting resume) from the `getState()` snapshot alone — no\n * extra request.\n *\n * Why this gate exists: a finished thread does not need either of the\n * always-on SSE pumps. Subagent/subgraph cards are already seeded from\n * the `getState()` messages and a single bounded `getHistory()` page, so\n * opening the depth-1 content pump + the wildcard lifecycle watcher only\n * to replay a completed run and then idle forever is pure waste. We open\n * the pumps eagerly only when the thread is active; otherwise they come\n * up on the first local `submit()` (the existing deferred-pump path) or\n * a thread swap that lands on an active thread.\n *\n * The gate is deliberately conservative: we only conclude *idle* when\n * the state proves it. A thread is treated as active unless `next` is a\n * present, empty array AND no task carries a pending interrupt:\n *  - `next` missing / not an array: unknown shape (a server or custom\n *    client may omit it). Treat as active so an already-running\n *    server-side run is still observed on reconnect — never silently\n *    disable streaming on an unfamiliar `getState` shape.\n *  - `next.length > 0`: the checkpoint still has nodes to execute, i.e.\n *    a run is mid-flight or paused at an interrupt.\n *  - `next` is `[]` but a `tasks[].interrupts` is non-empty: the thread\n *    is interrupted and a resume (which starts a run) must be observable.\n *  - `next` is `[]` and no pending interrupts: a completed run → idle.\n */\nfunction isThreadStateActive(\n  state: { next?: unknown; tasks?: unknown } | null | undefined\n): boolean {\n  if (state == null) return true;\n  // Only a present, empty `next` array proves \"no nodes pending\". A\n  // missing/non-array `next` is an unknown shape → assume active.\n  if (!Array.isArray(state.next)) return true;\n  if (state.next.length > 0) return true;\n  if (Array.isArray(state.tasks)) {\n    for (const task of state.tasks) {\n      const interrupts = (task as { interrupts?: unknown } | null)?.interrupts;\n      if (Array.isArray(interrupts) && interrupts.length > 0) return true;\n    }\n  }\n  return false;\n}\n\nconst ROOT_NAMESPACE: readonly string[] = [];\n\n/**\n * Channel set covered by the always-on root subscription. Exported so\n * projections (and transports) can reason about what the root pump\n * already delivers before opening additional server subscriptions.\n */\nexport const ROOT_PUMP_CHANNELS: readonly Channel[] = [\n  \"values\",\n  \"checkpoints\",\n  \"lifecycle\",\n  \"input\",\n  \"messages\",\n  \"tools\",\n];\n\n// The server writes an interrupt into thread state shortly after it streams\n// the `input.requested` event, so a state fetch on the terminal lifecycle can\n// miss it; mirrors the server's own interrupt settle window.\nconst PARKED_INTERRUPT_SETTLE_MS = 5_000;\nconst PARKED_INTERRUPT_SETTLE_POLL_MS = 500;\n\ninterface ResolvedInterrupt {\n  interruptId: string;\n  namespace: string[];\n}\n\nexport type {\n  MessageMetadata,\n  MessageMetadataMap,\n  SubmissionQueueEntry,\n  SubmissionQueueSnapshot,\n};\n\n/**\n * Coordinates one thread's protocol-v2 stream and exposes stable\n * observable projections for framework bindings.\n *\n * The controller owns the root subscription, lazily binds scoped\n * projections through {@link ChannelRegistry}, and normalizes protocol\n * events into class-message, tool-call, discovery, interrupt, and queue\n * stores.\n *\n * @typeParam StateType - Shape of the graph state exposed on `values`.\n * @typeParam InterruptType - Shape of protocol interrupt payloads.\n * @typeParam ConfigurableType - Shape of `config.configurable` accepted by submit.\n */\nexport class StreamController<\n  StateType extends object = Record<string, unknown>,\n  InterruptType = unknown,\n  ConfigurableType extends object = Record<string, unknown>,\n> {\n  readonly rootStore: StreamStore<RootSnapshot<StateType, InterruptType>>;\n  readonly subagentStore: StreamStore<SubagentMap>;\n  readonly subgraphStore: StreamStore<SubgraphMap>;\n  readonly subgraphByNodeStore: StreamStore<SubgraphByNodeMap>;\n  readonly messageMetadataStore: StreamStore<MessageMetadataMap>;\n  readonly queueStore: StreamStore<SubmissionQueueSnapshot<StateType>>;\n  readonly registry: ChannelRegistry;\n\n  readonly #options: StreamControllerOptions<StateType>;\n  readonly #messagesKey: string;\n  readonly #subagents = new SubagentDiscovery();\n  readonly #subgraphs = new SubgraphDiscovery();\n  readonly #messageMetadata = new MessageMetadataTracker();\n\n  #thread: ThreadStream | undefined;\n  #currentThreadId: string | null;\n  #rootSubscription: SubscriptionHandle<Event> | undefined;\n  #rootPump: Promise<void> | undefined;\n  #rootPumpReady: Promise<void> | undefined;\n  /**\n   * `true` while a self-created thread has its root pump deferred until\n   * the first `submitRun` / `respondInput` commits the thread row\n   * server-side. See `#ensureThread` and `#startDeferredRootPump`.\n   */\n  #rootPumpDeferred = false;\n  #threadEventUnsubscribe: (() => void) | undefined;\n  #threadErrorUnsubscribe: (() => void) | undefined;\n  #disposed = false;\n  #pendingDisposeTimer: ReturnType<typeof setTimeout> | null = null;\n  /**\n   * Interrupt ids this controller has locally marked resolved via\n   * {@link respond} / {@link respondAll}. Used only to suppress\n   * *historical* SSE replay of those `input.requested` events (there\n   * is no `input.responded` protocol event). A live event after the\n   * resume barrier clears an id from this set so an interrupt raised\n   * again by a later run can reappear on `rootStore.interrupts`.\n   */\n  readonly #resolvedInterrupts = new Set<string>();\n  /**\n   * Set of interrupt IDs the server reports as currently *active* on\n   * the thread (from `state.tasks[].interrupts`). Populated during\n   * {@link hydrate} from `client.threads.getState()` and used as a\n   * strict allowlist when processing replayed `input.requested`\n   * events from the persistent SSE subscription. Without this guard,\n   * SSE replay re-adds historically-requested interrupts that have\n   * since been resolved (no `input.responded` event exists in the\n   * protocol, so the SDK has no other way to tell replay from live\n   * for an idle thread). After a command is accepted, events newer\n   * than {@link #interruptReplayThroughSeq} bypass the allowlist.\n   */\n  #hydratedActiveInterruptIds: Set<string> | null = null;\n  /**\n   * Creation time of the checkpoint the latest {@link hydrate} seeded\n   * from. A new stream subscription replays the thread's retained\n   * history, and events produced before this moment are already part of\n   * the seed: applying them again rewinds `messages`, `values` and\n   * `toolCalls` to older turns and then rebuilds them.\n   */\n  #hydratedCheckpointTime: number | undefined;\n  /**\n   * Highest event sequence already applied when the latest run command\n   * was accepted. Interrupts outside the hydrate-time allowlist remain\n   * filtered through this sequence, while newer events are live output\n   * from the newly-started run and must be accepted.\n   */\n  #interruptReplayThroughSeq: number | undefined;\n  /** Unknown inputs waiting to be classified as live or replayed history. */\n  #pendingHydrationInterruptEvents: Event[] = [];\n  #settleParkedInterruptsPromise: Promise<void> | undefined;\n  /**\n   * Unknown interrupt events received between local command dispatch and its\n   * response. The response supplies the sequence barrier needed to classify\n   * each event as historical replay or live output from the new run.\n   */\n  #pendingInterruptEvents: Event[] = [];\n  #interruptCommandPending = false;\n  /**\n   * Monotonic counter bumped at the start of each `submit()` and used\n   * by {@link hydrate} to skip its post-fetch allowlist write when a\n   * submit started while the state fetch was in flight. Without this\n   * guard, a submit-then-hydrate race could re-install a stale\n   * allowlist that filters out genuinely-new live interrupts emitted\n   * by the just-started run.\n   */\n  #submitGeneration = 0;\n  /**\n   * Monotonic counter bumped at the start of each `#teardownThread`.\n   * The root pump captures the generation when it starts and drops\n   * any event whose generation no longer matches — including queued\n   * events that `SubscriptionHandle.close()` still drains after the\n   * snapshot has already been cleared by `hydrate()`.\n   */\n  #rootPumpGeneration = 0;\n  /**\n   * Thread ids this controller minted client-side on first `submit()`.\n   * `hydrate()` skips `threads.getState()` for these — we know there\n   * is nothing checkpointed yet. Cleared once dispatch commits the\n   * thread server-side.\n   */\n  readonly #selfCreatedThreadIds = new Set<string>();\n  /**\n   * Caller-supplied thread ids that 404'd on hydrate. Unlike\n   * {@link #selfCreatedThreadIds}, these are revalidated on every\n   * hydrate: another client may create the same id between visits.\n   * While marked missing, `submit()` still defers the root SSE pump\n   * until `run.start` / `commands` commits the row — joining\n   * `/stream/events` beforehand leaves a dead subscription on\n   * langgraph_api's in-mem runtime.\n   */\n  readonly #missingThreadIds = new Set<string>();\n  /**\n   * In-flight per-subagent namespace resolutions, keyed by tool-call\n   * id. De-dupes concurrent {@link resolveSubagentNamespace} calls so\n   * re-renders / multiple consumers of the same subagent don't issue\n   * parallel `getHistory` walks.\n   */\n  readonly #namespaceResolves = new Map<string, Promise<void>>();\n  /**\n   * In-flight hydrate-time discovery seed ({@link #seedDiscoveryFromHistory}):\n   * a single bounded `getHistory` page that bulk-promotes every\n   * still-default subagent namespace and seeds subgraph hosts. Per-card\n   * {@link resolveSubagentNamespace} calls await this shared promise\n   * instead of each firing their own `getHistory` walk, so opening N\n   * cards right after reconnect costs one history read, not N. Re-armed\n   * per hydrate cycle and cleared once it settles.\n   */\n  #discoverySeedPromise: Promise<void> | undefined;\n  readonly #scopedHistorySeeds = new Map<\n    string,\n    Promise<ScopedHistorySeed | null>\n  >();\n  readonly #rootEventListeners = new Set<(event: Event) => void>();\n  readonly #rootBus: RootEventBus;\n  #activeRunId: string | undefined;\n  /**\n   * Run id `run.start` returned for the in-flight local `submit()`. Kept\n   * apart from {@link #activeRunId}, which a rolled-back submit's late\n   * response can still overwrite.\n   */\n  #submittedRunId: string | undefined;\n  /** `true` from a local run's dispatch until its `run.start` answers. */\n  #submittedRunIdPending = false;\n  /** One per armed terminal wait: re-runs the lifecycle events it held until `run.start` answered. */\n  readonly #heldLifecycleReleases = new Set<() => void>();\n  #localRunDepth = 0;\n  /**\n   * `true` once a root `values` event has been applied for the current\n   * optimistic run. Reset to `false` in {@link #beginOptimistic} and\n   * read in {@link #settleOptimistic}: when a run terminates without\n   * the server ever echoing a `values` snapshot, optimistically-merged\n   * non-message keys are rolled back to their pre-submit values.\n   */\n  #sawValuesForRun = false;\n\n  /**\n   * Single-shot hydration promise. Exposed via `hydrationPromise`\n   * so Suspense wrappers can throw it until the first hydrate\n   * completes (resolve) or fails (reject). Reset whenever a new\n   * hydrate cycle begins so `<Suspense>` boundaries re-suspend on\n   * thread switch.\n   */\n  #hydrationPromise: Promise<void>;\n  #resolveHydration!: () => void;\n  #rejectHydration!: (error: unknown) => void;\n\n  /**\n   * Tool assembler lives for the lifetime of a thread; reset on\n   * rebind so a fresh thread starts with a clean slate.\n   */\n  #rootToolAssembler = new ToolCallAssembler();\n  #rootMessages!: RootMessageProjection<StateType, InterruptType>;\n  #lifecycleLoading!: LifecycleLoadingTracker<\n    RootSnapshot<StateType, InterruptType>\n  >;\n  #submitter!: SubmitCoordinator<StateType, InterruptType, ConfigurableType>;\n\n  readonly #threadListeners = new Set<\n    (thread: ThreadStream | undefined) => void\n  >();\n\n  /**\n   * Create a controller around a LangGraph client and optional initial thread.\n   *\n   * @param options - Runtime configuration, client, thread id, and initial state.\n   */\n  constructor(options: StreamControllerOptions<StateType>) {\n    this.#options = options;\n    this.#messagesKey = options.messagesKey ?? DEFAULT_MESSAGES_KEY;\n    this.#currentThreadId = options.threadId ?? null;\n    this.#rootBus = {\n      channels: ROOT_PUMP_CHANNELS,\n      subscribe: (listener) => {\n        this.#rootEventListeners.add(listener);\n        return () => {\n          this.#rootEventListeners.delete(listener);\n        };\n      },\n      trySeedFromHistory: (params) =>\n        this.#trySeedProjectionFromHistory(params),\n    };\n    this.registry = new ChannelRegistry(this.#rootBus);\n    this.subagentStore = this.#subagents.store;\n    this.subgraphStore = this.#subgraphs.store;\n    this.subgraphByNodeStore = this.#subgraphs.byNodeStore;\n    this.rootStore = new StreamStore<RootSnapshot<StateType, InterruptType>>(\n      this.#createInitialSnapshot()\n    );\n    this.#rootMessages = new RootMessageProjection({\n      messagesKey: this.#messagesKey,\n      store: this.rootStore,\n    });\n    this.#lifecycleLoading = new LifecycleLoadingTracker({\n      store: this.rootStore,\n      isDisposed: () => this.#disposed,\n      // `#submitter` is assigned just below; this callback only ever\n      // fires later (async), by which point construction has finished.\n      onSettled: () => this.#submitter.scheduleQueueDrainOnObservedIdle(),\n      // `submit()` settles `isLoading` itself, so skipping a pending\n      // event here can't leave the flag stuck.\n      ignore: (event) => this.#submittedRunMatch(event) != null,\n    });\n    this.messageMetadataStore = this.#messageMetadata.store;\n    this.queueStore = new StreamStore<SubmissionQueueSnapshot<StateType>>(\n      EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n    );\n    this.#submitter = new SubmitCoordinator({\n      options: this.#options,\n      rootStore: this.rootStore,\n      queueStore: this.queueStore,\n      getDisposed: () => this.#disposed,\n      getCurrentThreadId: () => this.#currentThreadId,\n      setCurrentThreadId: (threadId) => {\n        this.#currentThreadId = threadId;\n      },\n      rememberSelfCreatedThreadId: (threadId) => {\n        this.#selfCreatedThreadIds.add(threadId);\n      },\n      isSelfCreatedThreadId: (threadId) =>\n        this.#selfCreatedThreadIds.has(threadId) ||\n        this.#missingThreadIds.has(threadId),\n      hydrate: (threadId) => this.hydrate(threadId),\n      ensureThread: (threadId, deferRootPump) =>\n        this.#ensureThread(threadId, deferRootPump),\n      startDeferredRootPump: () => this.#startDeferredRootPump(),\n      abandonDeferredRootPump: () => this.#abandonDeferredRootPump(),\n      forgetSelfCreatedThreadId: (threadId) => {\n        this.#selfCreatedThreadIds.delete(threadId);\n        this.#missingThreadIds.delete(threadId);\n      },\n      waitForRootPumpReady: () => this.#rootPumpReady,\n      awaitNextTerminal: (signal) => this.#awaitNextTerminal(signal),\n      awaitResumedRunTerminal: (signal) =>\n        this.#awaitResumedRunTerminal(signal),\n      onSubmitStart: () => {\n        // Bump the generation so any in-flight hydrate skips its\n        // allowlist write on return. Keep an existing allowlist until\n        // dispatch is accepted: the root pump may still be replaying\n        // historical events while the command is in flight.\n        this.#submitGeneration += 1;\n        this.#interruptCommandPending =\n          this.#hydratedActiveInterruptIds != null;\n        this.#pendingInterruptEvents = this.#pendingHydrationInterruptEvents;\n        this.#pendingHydrationInterruptEvents = [];\n      },\n      onRunStart: () => this.#markLocalRunStart(),\n      onRunStartReturned: (runId) => {\n        this.#submittedRunId = runId;\n        this.#submittedRunIdPending = false;\n        for (const release of [...this.#heldLifecycleReleases]) release();\n      },\n      onRunCreated: (runId) => {\n        this.#advanceInterruptReplayBarrier();\n        this.#notifyCreated(runId);\n      },\n      onRunCompleted: (reason, runId) => this.#notifyCompleted(reason, runId),\n      onRunEnd: () => {\n        // Stop buffering new events, but keep any already-queued\n        // `input.requested` frames. A fast run can emit its interrupt\n        // and terminal before `run.start` returns; `onRunCreated` still\n        // has to classify those frames against `applied_through_seq`.\n        this.#interruptCommandPending = false;\n        this.#markLocalRunEnd();\n      },\n      beginOptimistic: (input) => this.#beginOptimistic(input),\n      settleOptimistic: (handle, event) =>\n        this.#settleOptimistic(handle, event),\n    });\n    this.#hydrationPromise = this.#createHydrationPromise();\n    /**\n     * Attach a default no-op catch so orphaned hydrationPromise\n     * rejections (e.g. controllers spawned during Suspense retries\n     * whose promise never gets subscribed to because the suspense\n     * cache already holds an earlier one) don't surface as unhandled\n     * rejections. Callers that attach their own handlers via .then()\n     * still receive the rejection on their derived promise.\n     */\n    this.#hydrationPromise.catch(() => undefined);\n    /**\n     * Kick off the initial hydrate eagerly when a caller-supplied\n     * thread id is present. Suspense consumers throw\n     * `hydrationPromise` on the very first render, which unmounts the\n     * subtree before any `useEffect` can run — so if we waited for an\n     * effect to drive the hydrate we'd deadlock. Firing here makes\n     * the promise settle independently of the component lifecycle.\n     */\n    if (this.#currentThreadId != null) {\n      void this.hydrate(this.#currentThreadId);\n    } else {\n      this.#resolveHydration();\n    }\n  }\n\n  /**\n   * Promise that settles the first time {@link hydrate} finishes on\n   * the current thread. Resolves on a clean hydration, rejects when\n   * the thread-state fetch errors. A fresh promise is installed on\n   * every thread swap so `<Suspense>` wrappers re-suspend on\n   * `switchThread`.\n   */\n  get hydrationPromise(): Promise<void> {\n    return this.#hydrationPromise;\n  }\n\n  /**\n   * Create the deferred promise backing the current hydration cycle.\n   */\n  #createHydrationPromise(): Promise<void> {\n    return new Promise<void>((resolve, reject) => {\n      this.#resolveHydration = resolve;\n      this.#rejectHydration = reject;\n    });\n  }\n\n  /**\n   * Replace the current hydration promise before a thread swap.\n   */\n  #resetHydrationPromise(): void {\n    /**\n     * Swallow rejection on the orphaned promise so Node doesn't\n     * flag it as unhandled; Suspense callers that still hold a\n     * reference see the rejection they subscribed to.\n     */\n    this.#hydrationPromise.catch(() => undefined);\n    this.#hydrationPromise = this.#createHydrationPromise();\n  }\n\n  // ---------- public imperatives ----------\n\n  /**\n   * Load thread state for hydration, preferring the active custom\n   * adapter's `getState()` when present.\n   */\n  async #fetchHydrationState(): Promise<ThreadState<StateType> | null> {\n    const threadId = this.#currentThreadId;\n    if (threadId == null) return null;\n\n    const transport = this.#options.transport;\n    if (\n      transport != null &&\n      typeof transport === \"object\" &&\n      typeof transport.getState === \"function\"\n    ) {\n      return (await transport.getState<StateType>()) as ThreadState<StateType> | null;\n    }\n\n    return this.#options.client.threads.getState<StateType>(threadId);\n  }\n\n  /**\n   * Fetch the checkpointed thread state and seed the root snapshot.\n   * Re-calling with a different `threadId` swaps the underlying\n   * {@link ThreadStream}, rewires the registry to the new thread, and\n   * resets assemblers.\n   *\n   * @param threadId - Optional replacement thread id; `null` clears the active thread.\n   */\n  async hydrate(threadId?: string | null): Promise<void> {\n    if (this.#disposed) return;\n    const target = threadId === undefined ? this.#currentThreadId : threadId;\n    const changed = target !== this.#currentThreadId;\n    this.#currentThreadId = target ?? null;\n    // Re-arm per hydrate cycle: a stale seed from a previous thread must\n    // not be awaited by this thread's lazy namespace resolves.\n    this.#discoverySeedPromise = undefined;\n    this.#scopedHistorySeeds.clear();\n    this.rootStore.setState((s) => ({ ...s, threadId: this.#currentThreadId }));\n\n    if (changed) {\n      /**\n       * Swap to a new thread: re-arm the hydration promise so any\n       * Suspense boundary remounted against the new id suspends again.\n       */\n      this.#resetHydrationPromise();\n      /**\n       * Kick teardown so the synchronous abort (unbind, drop onEvent,\n       * close the root subscription, reset assemblers) runs before we\n       * touch the snapshot. Then reset immediately so the UI does not\n       * wait on pump/close. An interrupted thread parks the root pump\n       * on `waitForResume()`; awaiting teardown *before* this reset\n       * left `threadId` null while `messages` still showed the previous\n       * conversation (`useStream` fire-and-forgets `hydrate()`).\n       */\n      const teardown = this.#teardownThread();\n      this.rootStore.setState(() => ({\n        ...this.#createInitialSnapshot(),\n        threadId: this.#currentThreadId,\n      }));\n      /**\n       * Drop queued submissions — they were targeted at the previous\n       * thread so dispatching them against the new thread would be\n       * surprising. Mirrors the legacy `StreamOrchestrator` behaviour.\n       */\n      this.queueStore.setState(\n        () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n      );\n      await teardown;\n    }\n\n    if (this.#currentThreadId == null) {\n      this.rootStore.setState((s) => ({ ...s, isThreadLoading: false }));\n      this.#resolveHydration();\n      return;\n    }\n\n    /**\n     * Self-generated thread ids have nothing to fetch server-side yet\n     * — the thread is created lazily by the first `run.start`. Calling\n     * `threads.getState()` here would return a 404 and surface a\n     * spurious error to the UI.\n     */\n    if (this.#selfCreatedThreadIds.has(this.#currentThreadId)) {\n      this.rootStore.setState((s) => ({ ...s, isThreadLoading: false }));\n      this.#resolveHydration();\n      return;\n    }\n\n    this.rootStore.setState((s) => ({ ...s, isThreadLoading: true }));\n    // Thread id this hydrate cycle is fetching for; used to detect a thread\n    // clear/swap across the getState() await below.\n    const hydratedThreadId = this.#currentThreadId;\n    let hydrationError: unknown;\n    let threadExists = false;\n    // True only when getState 404s — the id is bound in the client but\n    // the server row doesn't exist yet. A null state payload is\n    // different (thread may exist with nothing to seed) and still\n    // opens the pump below. Distinct from `hydrationError` so a\n    // transport failure still takes the eager pump path.\n    let threadMissing = false;\n    // Default active so a getState error / non-404 failure never\n    // silently disables streaming — the pumps open eagerly as before.\n    // Flipped to the real signal once we have the state in hand.\n    let threadActive = true;\n    // Set below from `state.tasks[].interrupts`, if present. Combined\n    // with `threadActive` where it's used, to decide whether to seed\n    // `isLoading`.\n    let hasActiveInterrupts = false;\n    try {\n      const state = await this.#fetchHydrationState();\n      // The await above yields. If the thread id changed or was cleared while\n      // we were suspended (host cleared it, hydrate(null), or the component\n      // unmounted during navigation), this hydrate is stale: applying its\n      // fetched state would repopulate rootStore for a thread we've left, and\n      // the reconnect below would call threads.stream(null, …) → `.fetch` on\n      // null. Bail before touching any state. Hydration is settled in finally.\n      if (this.#disposed || this.#currentThreadId !== hydratedThreadId) return;\n      threadExists = state != null;\n      threadActive = isThreadStateActive(state);\n      const checkpointTime = Date.parse(state?.created_at ?? \"\");\n      this.#hydratedCheckpointTime = Number.isNaN(checkpointTime)\n        ? undefined\n        : checkpointTime;\n      // A prior hydrate-404 may have marked this id missing; clear it\n      // now that the server row exists (e.g. another client created it).\n      this.#missingThreadIds.delete(hydratedThreadId);\n      if (state?.values != null) {\n        /**\n         * `threads.getState()` returns the legacy `ThreadState` shape\n         * where `parent_checkpoint` is an object (`{ thread_id,\n         * checkpoint_id, checkpoint_ns }`). Synthesize the v2\n         * `Checkpoint` envelope (matching the `checkpoints` channel\n         * payload) so hydrated messages also get their\n         * `parentCheckpointId` populated for fork / edit flows.\n         */\n        const checkpointId = state.checkpoint?.checkpoint_id;\n        const parentCheckpointId =\n          state.parent_checkpoint?.checkpoint_id ?? undefined;\n        /**\n         * Carry the checkpoint `step` from `getState()` metadata so the\n         * root message projection treats this seed as the authoritative\n         * latest superstep. The content pump's reconnect replay emits\n         * older checkpoints (lower step); marking the seed's step lets\n         * the projection reject those as stale instead of letting them\n         * remove the seeded message tail (the final assistant turn).\n         */\n        const seedStep = (state.metadata as { step?: unknown } | undefined)\n          ?.step;\n        const syntheticCheckpoint =\n          typeof checkpointId === \"string\"\n            ? {\n                id: checkpointId,\n                ...(parentCheckpointId != null\n                  ? { parent_id: parentCheckpointId }\n                  : {}),\n                ...(typeof seedStep === \"number\" ? { step: seedStep } : {}),\n              }\n            : undefined;\n        this.#applyValues(state.values as unknown, syntheticCheckpoint);\n\n        /**\n         * Seed subagent discovery from checkpoint messages so deep-agent\n         * cards render on refresh without waiting for SSE replay. Zero\n         * extra HTTP (reuses the `getState` payload); mirrors the\n         * interrupt-seeding below. `#subagents` was cleared in\n         * `#teardownThread`, and `seedFromCheckpointMessages` is\n         * idempotent, so this is safe on re-hydrate.\n         */\n        const seedMessages = (state.values as Record<string, unknown>)[\n          this.#messagesKey\n        ];\n        if (Array.isArray(seedMessages)) {\n          this.#subagents.seedFromCheckpointMessages(seedMessages);\n\n          // Root `toolCalls` are otherwise only built from `tools` events,\n          // and the replayed ones predate the seed and are skipped. A call\n          // with no result yet is left to the live stream, as an open tab\n          // would only show it once it starts.\n          const finishedToolCalls = seedToolCallsFromMessages(\n            ROOT_NAMESPACE,\n            ensureMessageInstances(seedMessages as (Message | BaseMessage)[])\n          ).filter((toolCall) => toolCall.status === \"finished\");\n          if (finishedToolCalls.length > 0) {\n            this.rootStore.setState((s) => ({\n              ...s,\n              toolCalls: finishedToolCalls.reduce(\n                (toolCalls, toolCall) => upsertToolCall(toolCalls, toolCall),\n                s.toolCalls\n              ),\n            }));\n          }\n\n          /**\n           * An idle (finished) thread defers its root SSE pump; the first\n           * `submit()` brings it up and the transport replays the finished\n           * run from `seq=0`. Seal the seeded message ids so that replay's\n           * `messages` channel deltas can't downgrade the already-complete\n           * tail to empty partials (a visible \"messages replay\"). Only safe\n           * for idle threads, where every seeded message is final — an\n           * active thread's tail may still be streaming and must keep\n           * receiving deltas. New ids from the next run are never sealed,\n           * and the seal lifts once a newer checkpoint advances the\n           * timeline.\n           */\n          if (!threadActive) {\n            const sealedIds = (seedMessages as Array<{ id?: unknown }>)\n              .map((message) => message?.id)\n              .filter((id): id is string => typeof id === \"string\");\n            if (sealedIds.length > 0) {\n              this.#rootMessages.sealMessageIds(sealedIds);\n            }\n          }\n        }\n      }\n      /**\n       * Converge to server truth: drop any optimistic messages the\n       * server state does not contain (`pending` / `failed` that were\n       * never persisted — e.g. a failed run's user message). Echoed\n       * ids were flipped to `\"sent\"` by `#applyValues` above and so are\n       * excluded from `unpersistedOptimisticIds()`.\n       */\n      const unpersisted = this.#messageMetadata.unpersistedOptimisticIds();\n      if (unpersisted.size > 0) {\n        this.#rootMessages.dropMessages(unpersisted);\n        this.#messageMetadata.forget(unpersisted);\n      }\n      /**\n       * Sync the visible interrupt list to the server's authoritative\n       * `state.tasks[].interrupts`. Without this, SSE replay of past\n       * `input.requested` events would re-add resolved interrupts to\n       * the UI on every page navigation back to the thread.\n       *\n       * Only runs when `state.tasks` is an array — runtimes that don't\n       * surface tasks in `threads.getState()` are left untouched (an\n       * unconditional overwrite would wipe any in-flight interrupt\n       * state the wildcard watcher may already have recorded).\n       */\n      if (Array.isArray(state?.tasks)) {\n        const generationAtFetch = this.#submitGeneration;\n        const { activeInterrupts, activeIds } =\n          collectActiveInterruptsFromTasks<InterruptType>(state.tasks);\n        // A thread parked at an unresolved interrupt is \"active\" (the pump\n        // must stay open to observe a resume) but not \"loading\" — it's\n        // waiting on a human, not mid-computation.\n        hasActiveInterrupts = activeInterrupts.length > 0;\n        // Server still lists these as pending — drop any local\n        // \"resolved\" tombstone so live replay / later reconcile can\n        // keep them visible.\n        for (const id of activeIds) {\n          this.#resolvedInterrupts.delete(id);\n        }\n        this.rootStore.setState((s) => ({\n          ...s,\n          interrupts: activeInterrupts,\n          interrupt: activeInterrupts[0],\n        }));\n        // Only seed the allowlist when no submit started while the\n        // state fetch was in flight. If one did, leave the existing\n        // filter untouched so this stale fetch cannot overwrite the\n        // active run's replay boundary.\n        if (this.#submitGeneration === generationAtFetch) {\n          this.#hydratedActiveInterruptIds = activeIds;\n          this.#interruptReplayThroughSeq = undefined;\n        }\n      }\n    } catch (error) {\n      /**\n       * A 404 on hydrate means the thread does not exist server-side\n       * yet (most commonly because the caller supplied a brand-new,\n       * externally-minted thread id and is about to create it via the\n       * first `submit()`). Treat it as \"empty state\" rather than a\n       * fatal hydration error so Suspense boundaries resolve cleanly\n       * and no spurious error renders in the UI.\n       */\n      const status = (error as { status?: number } | null)?.status;\n      if (status !== 404) {\n        hydrationError = error;\n        this.rootStore.setState((s) => ({ ...s, error }));\n      } else {\n        // Caller supplied a brand-new / externally-minted thread id.\n        // There is no server row yet — same lifecycle as a client-\n        // minted id on first `submit()`.\n        threadMissing = true;\n      }\n    } finally {\n      this.rootStore.setState((s) => ({ ...s, isThreadLoading: false }));\n      if (hydrationError != null) {\n        this.#rejectHydration(hydrationError);\n      } else {\n        this.#resolveHydration();\n      }\n    }\n\n    /**\n     * Missing threads must not open `/stream/events`. The in-mem\n     * runtime accepts the join against a not-yet-created id but the\n     * subscription never attaches to the live channel — the first run\n     * then delivers 0 bytes until idle reconnect. Park the pump until\n     * `submit()`'s `run.start` creates the row (see\n     * {@link #startDeferredRootPump}). Tracked in `#missingThreadIds`\n     * (not `#selfCreatedThreadIds`) so a later hydrate revalidates —\n     * another client may create the same id between visits.\n     */\n    if (threadMissing) {\n      this.#missingThreadIds.add(hydratedThreadId);\n      return;\n    }\n\n    /**\n     * Open the shared subscription on mount so in-flight server-side\n     * runs are observed even when no local `submit()` is active — BUT\n     * only when the thread is actually active (see\n     * {@link isThreadStateActive}). A finished thread's cards are seeded\n     * from `getState()` + the bounded `getHistory()` below, so opening\n     * the depth-1 content pump just to replay a completed run and idle\n     * forever is pure waste. When idle we take the deferred path: the\n     * pump (and watcher) come up on the first local `submit()` via\n     * {@link #startDeferredRootPump}, exactly like a self-created thread.\n     * The transport replays from `seq=0` on the deferred subscribe, so\n     * nothing is missed.\n     */\n    const thread = this.#ensureThread(hydratedThreadId, !threadActive);\n\n    /**\n     * Picks up runs pending from before this page load, or another tab.\n     * Fire-and-forget. Must run after `#ensureThread` above, not before:\n     * `AgentServerQueueAdapter`'s own `getThread` callback also calls\n     * `#ensureThread(threadId, true)`, which would otherwise create\n     * `#thread` with the pump deferred before the line above decides it\n     * should be eager.\n     */\n    void this.#submitter.hydrateQueue(hydratedThreadId);\n\n    /**\n     * Start the wildcard lifecycle watcher up-front for existing,\n     * active threads. The root content pump runs at `depth: 1`, which\n     * covers root-namespace and one-deep events but not arbitrarily-\n     * nested subagent / subgraph lifecycle — the dedicated watcher\n     * handles those.\n     *\n     * Skipped when:\n     *  - the thread is idle/finished — there are no live events to\n     *    watch; discovery is seeded from history below, and the watcher\n     *    starts with the deferred pump on the first `submit()`.\n     *  - the thread is self-created (new) — the watcher would 404\n     *    against a not-yet-existent thread; `submitRun` / `respondInput`\n     *    call `startLifecycleWatcher` on first submission instead.\n     */\n    if (threadExists && threadActive) {\n      thread.startLifecycleWatcher();\n      /**\n       * Seed `isLoading` from the checkpoint itself, not just a live\n       * lifecycle event: a subscriber that joins after a foreign run's\n       * own `running` event already fired would otherwise never observe\n       * it. Excludes a thread merely parked at an interrupt — that's\n       * waiting on a human, not \"loading\", matching\n       * `LifecycleLoadingTracker`'s own `interrupted → isLoading = false`.\n       */\n      if (threadActive && !hasActiveInterrupts) {\n        this.rootStore.setState((s) =>\n          s.isLoading ? s : { ...s, isLoading: true }\n        );\n      }\n    }\n    if (threadExists) {\n      /**\n       * Seed subgraph discovery and promote subagent execution\n       * namespaces from a single bounded `getHistory` page. Subgraph\n       * structure is not present in the root checkpoint messages\n       * (unlike subagents), so it can only be reconstructed from\n       * history. Fire-and-forget — not awaited into the hydration\n       * promise, so Suspense / first paint stay unblocked; cards fill\n       * in progressively when it resolves.\n       *\n       * Held in `#discoverySeedPromise` so lazy per-card\n       * {@link resolveSubagentNamespace} calls coalesce onto this single\n       * read instead of each firing their own `getHistory` walk.\n       */\n      const seed: Promise<void> = this.#seedDiscoveryFromHistory(\n        this.#currentThreadId\n      ).finally(() => {\n        // Only clear if a later hydrate cycle hasn't re-armed it.\n        if (this.#discoverySeedPromise === seed) {\n          this.#discoverySeedPromise = undefined;\n        }\n      });\n      this.#discoverySeedPromise = seed;\n    }\n  }\n\n  /**\n   * One bounded, non-blocking `getHistory` read at hydrate that seeds\n   * subgraph hosts and bulk-promotes still-default subagent execution\n   * namespaces. O(1) in requests regardless of subagent/subgraph count.\n   */\n  async #seedDiscoveryFromHistory(threadId: string): Promise<void> {\n    try {\n      const history = await getHistoryPage(this.#options.client, threadId, {\n        limit: 20,\n      });\n      // A thread swap (or dispose) during the fetch invalidates this seed.\n      if (this.#disposed || this.#currentThreadId !== threadId) return;\n\n      this.#primeScopedHistorySeedsFromHistory(threadId, history);\n\n      const hosts = collectSubgraphHostNamespaces(history);\n      this.#subgraphs.seedFromHistory(hosts);\n\n      const defaultOnlyIds = [...this.#subagents.snapshot.values()]\n        .filter(namespaceIsDefaultOnly)\n        .map((entry) => entry.id);\n      if (defaultOnlyIds.length > 0) {\n        const map = mapSubagentNamespaces(\n          history,\n          defaultOnlyIds,\n          this.#messagesKey\n        );\n        for (const [id, segment] of map) {\n          this.#subagents.applyExecutionNamespace(id, segment);\n        }\n      }\n    } catch {\n      /* non-fatal: SSE replay still reconciles discovery */\n    }\n  }\n\n  /**\n   * Lazily resolve a single subagent's execution namespace from\n   * checkpoint history. Intended call site: the first scoped\n   * `useMessages` / `useToolCalls` mount for a subagent whose namespace\n   * is still the default `tools:<toolCallId>`. A fallback for the\n   * hydrate-time bulk seed ({@link #seedDiscoveryFromHistory}) — most\n   * subagents are already promoted by the time a panel opens.\n   *\n   * Skips ids already promoted past default-only (SSE replay or a prior\n   * resolve). Concurrent calls for the same id share one `getHistory`\n   * walk via {@link #namespaceResolves}.\n   *\n   * @param toolCallId - Parent `task` tool-call id (the subagent's discovery key).\n   */\n  async resolveSubagentNamespace(toolCallId: string): Promise<void> {\n    if (this.#disposed) return;\n    const threadId = this.#currentThreadId;\n    if (threadId == null) return;\n    if (!namespaceIsDefaultOnly(this.#subagents.snapshot.get(toolCallId))) {\n      return;\n    }\n    const inflight = this.#namespaceResolves.get(toolCallId);\n    if (inflight != null) return inflight;\n\n    const run = (async () => {\n      try {\n        /**\n         * Coalesce onto the hydrate-time discovery seed. That single\n         * bounded `getHistory` page bulk-promotes every default-only\n         * subagent, so when many cards mount at once (the common\n         * reconnect case) they all await this one read instead of each\n         * firing their own walk. Re-check after it settles: usually the\n         * bulk seed already promoted us and no further fetch is needed.\n         */\n        const seed = this.#discoverySeedPromise;\n        if (seed != null) {\n          await seed;\n          if (this.#disposed || this.#currentThreadId !== threadId) return;\n          if (\n            !namespaceIsDefaultOnly(this.#subagents.snapshot.get(toolCallId))\n          ) {\n            return;\n          }\n        }\n        const map = await resolveSubagentNamespaces(\n          this.#options.client,\n          threadId,\n          [toolCallId],\n          { messagesKey: this.#messagesKey }\n        );\n        if (this.#disposed || this.#currentThreadId !== threadId) return;\n        const segment = map.get(toolCallId);\n        if (segment != null) {\n          this.#subagents.applyExecutionNamespace(toolCallId, segment);\n        }\n      } catch {\n        /* non-fatal: SSE replay still reconciles the namespace */\n      } finally {\n        this.#namespaceResolves.delete(toolCallId);\n      }\n    })();\n    this.#namespaceResolves.set(toolCallId, run);\n    return run;\n  }\n\n  /**\n   * Try to satisfy a scoped selector projection from checkpoint history\n   * instead of opening a scoped `/events` replay.\n   *\n   * This is only valid while the root pump is deferred, which means hydrate\n   * has classified the thread as idle/stale. Active and interrupted threads\n   * must keep using SSE so ongoing work and resumes are observed. For an idle\n   * thread, though, a late-mounted subagent card only needs the latest scoped\n   * checkpoint snapshot; opening `/events` just asks the server to replay work\n   * that already finished and can be slow for namespaces discovered from\n   * history.\n   *\n   * Returns `true` when the projection was handled without `/events`. That can\n   * mean either the store was seeded from namespace-specific history, or the\n   * projection targeted a default subagent namespace that should be skipped\n   * because hydrate promoted it to its execution namespace. Returns `false`\n   * when the caller should fall back to the normal subscription path.\n   */\n  async #trySeedProjectionFromHistory<T>(params: {\n    kind: \"messages\" | \"toolCalls\";\n    namespace: readonly string[];\n    store: StreamStore<T>;\n  }): Promise<boolean> {\n    const threadId = this.#currentThreadId;\n    if (\n      this.#disposed ||\n      threadId == null ||\n      params.namespace.length === 0 ||\n      !this.#rootPumpDeferred ||\n      this.#selfCreatedThreadIds.has(threadId) ||\n      this.#missingThreadIds.has(threadId)\n    ) {\n      return false;\n    }\n\n    if (await this.#skipDefaultSubagentProjection(params.namespace, threadId)) {\n      return true;\n    }\n    if (\n      this.#disposed ||\n      this.#currentThreadId !== threadId ||\n      !this.#rootPumpDeferred\n    ) {\n      return false;\n    }\n\n    const seed = await this.#getScopedHistorySeed(threadId, params.namespace);\n    if (\n      seed == null ||\n      this.#disposed ||\n      this.#currentThreadId !== threadId ||\n      !this.#rootPumpDeferred\n    ) {\n      return false;\n    }\n\n    if (await this.#skipDefaultSubagentProjection(params.namespace, threadId)) {\n      return true;\n    }\n\n    if (params.kind === \"messages\") {\n      params.store.setValue(seed.messages as T);\n      return true;\n    }\n    params.store.setValue(seed.toolCalls as T);\n    return true;\n  }\n\n  /**\n   * Suppress subscriptions for placeholder subagent namespaces once hydrate has\n   * resolved the real execution namespace.\n   *\n   * Deep-agent discovery first creates cards at `tools:<toolCallId>`. The\n   * actual worker history usually lives under a different checkpoint namespace\n   * such as `tools:<uuid>`, and hydrate resolves that mapping from the bounded\n   * root history seed. React/Vue/Svelte/Angular selector effects can mount\n   * while that seed is still in flight, so this helper waits for it and then\n   * returns `true` when the original placeholder namespace is stale. Returning\n   * `true` tells the projection runtime not to open an `/events` subscription\n   * for the wrong namespace; the framework will re-render with the promoted\n   * card namespace and acquire the real projection.\n   */\n  async #skipDefaultSubagentProjection(\n    namespace: readonly string[],\n    threadId: string\n  ): Promise<boolean> {\n    const toolCallId = defaultSubagentToolCallId(namespace);\n    if (toolCallId == null) return false;\n    if (!namespaceIsDefaultOnly(this.#subagents.snapshot.get(toolCallId))) {\n      return false;\n    }\n    const seed = this.#discoverySeedPromise;\n    if (seed != null) {\n      await seed;\n    }\n    if (this.#disposed || this.#currentThreadId !== threadId) return true;\n    return !namespaceIsDefaultOnly(this.#subagents.snapshot.get(toolCallId));\n  }\n\n  /**\n   * Load and cache the latest checkpoint snapshot for one scoped namespace.\n   *\n   * `useMessages(stream, subagent)` and `useToolCalls(stream, subagent)` often\n   * mount together. Both need the same namespace-specific history page, so the\n   * controller keeps an in-flight promise per `threadId + checkpoint_ns`.\n   * The cache may already be primed by the hydrate-time discovery history page;\n   * otherwise this method performs a narrow `checkpoint_ns` read and derives\n   * both projection snapshots from that one response:\n   *\n   * - `messages` are coerced with the stream-local message coercion rules, so\n   *   serialized `content_blocks` and tool-call metadata hydrate correctly.\n   * - `toolCalls` are reconstructed from AI tool calls plus matching\n   *   ToolMessages, enough for finished/stale card panels without replaying\n   *   the `tools` channel.\n   *\n   * Returns `null` when history does not contain usable values, or the request\n   * fails. Callers treat that as a signal to fall back to `/events` so custom\n   * servers or unusual state shapes still work.\n   */\n  #getScopedHistorySeed(\n    threadId: string,\n    namespace: readonly string[]\n  ): Promise<ScopedHistorySeed | null> {\n    const checkpointNs = namespaceKey(namespace);\n    const key = `${threadId}|${checkpointNs}`;\n    const existing = this.#scopedHistorySeeds.get(key);\n    if (existing != null) return existing;\n\n    const seed = (async (): Promise<ScopedHistorySeed | null> => {\n      try {\n        const history = await getHistoryPage(this.#options.client, threadId, {\n          limit: 1,\n          checkpoint: { checkpoint_ns: checkpointNs },\n        });\n        const values = history[0]?.values;\n        if (values == null || typeof values !== \"object\") return null;\n        const messages = extractAndCoerceMessagesWithFallback(\n          values as Record<string, unknown>,\n          this.#messagesKey\n        );\n        if (messages == null) return null;\n        return {\n          messages,\n          toolCalls: seedToolCallsFromMessages(namespace, messages),\n        };\n      } catch {\n        return null;\n      }\n    })();\n    this.#scopedHistorySeeds.set(key, seed);\n    return seed;\n  }\n\n  /**\n   * Reuse the hydrate-time discovery history page as scoped projection data\n   * when it already contains checkpoint values for a namespace.\n   *\n   * The discovery read is required to resolve subagent execution namespaces and\n   * subgraph hosts. That same page often includes the latest values for those\n   * namespaces, so priming `#scopedHistorySeeds` here lets later\n   * `useMessages(stream, subagent)` / `useToolCalls(stream, subagent)` mounts\n   * hydrate from memory instead of issuing an immediate second `getHistory`\n   * request. If a namespace is not present in the bounded page,\n   * `#getScopedHistorySeed` still falls back to a targeted `checkpoint_ns`\n   * history read.\n   */\n  #primeScopedHistorySeedsFromHistory(\n    threadId: string,\n    history: Array<{\n      checkpoint?: { checkpoint_ns?: unknown };\n      values?: unknown;\n    }>\n  ): void {\n    for (const state of history) {\n      const checkpointNs = state.checkpoint?.checkpoint_ns;\n      if (typeof checkpointNs !== \"string\" || checkpointNs.length === 0) {\n        continue;\n      }\n      const namespace = checkpointNs\n        .split(NAMESPACE_SEPARATOR)\n        .filter((segment) => segment.length > 0);\n      if (namespace.length === 0) continue;\n      const key = `${threadId}|${namespaceKey(namespace)}`;\n      if (this.#scopedHistorySeeds.has(key)) continue;\n      const values = state.values;\n      if (values == null || typeof values !== \"object\") continue;\n      const messages = extractAndCoerceMessagesWithFallback(\n        values as Record<string, unknown>,\n        this.#messagesKey\n      );\n      if (messages == null) continue;\n      this.#scopedHistorySeeds.set(\n        key,\n        Promise.resolve({\n          messages,\n          toolCalls: seedToolCallsFromMessages(namespace, messages),\n        })\n      );\n    }\n  }\n\n  /**\n   * Submit input to the active thread.\n   *\n   * To resume a pending interrupt, use {@link respond} instead.\n   *\n   * @param input - Input payload for a new run.\n   * @param options - Per-run config, metadata, multitask behavior, and callbacks.\n   */\n  async submit(\n    input: unknown,\n    options?: StreamSubmitOptions<StateType, ConfigurableType>\n  ): Promise<void> {\n    await this.#submitter.submit(input, options);\n  }\n\n  /**\n   * Disconnect the client from the active run and mark the controller\n   * idle. By default also cancels the run server-side; pass\n   * `{ cancel: false }` or call {@link disconnect} to keep the agent\n   * running (join/rejoin).\n   */\n  async stop(options?: StreamStopOptions): Promise<void> {\n    const shouldCancel = options?.cancel ?? true;\n    if (shouldCancel) {\n      const threadId = this.#currentThreadId;\n      const runId = this.#activeRunId;\n      if (runId != null && this.rootStore.getSnapshot().isLoading) {\n        // Drop the partial reply now rather than on the server's terminal.\n        const dropped = this.#rootMessages.closeRun({\n          sync: true,\n          unfinishedOnly: true,\n        });\n        if (dropped.size > 0) this.#messageMetadata.forget(dropped);\n      }\n      if (threadId != null && runId != null) {\n        try {\n          await this.#options.client.runs.cancel(threadId, runId);\n        } catch {\n          /* server cancel failures must not block client disconnect */\n        }\n      }\n    }\n    await this.#submitter.stop();\n  }\n\n  /**\n   * Disconnect the client without cancelling the run server-side.\n   * Alias for `stop({ cancel: false })`.\n   */\n  async disconnect(): Promise<void> {\n    return this.stop({ cancel: false });\n  }\n\n  #markLocalRunStart(): void {\n    this.#localRunDepth += 1;\n    this.#submittedRunId = undefined;\n    this.#submittedRunIdPending = true;\n  }\n\n  #markLocalRunEnd(): void {\n    this.#localRunDepth = Math.max(0, this.#localRunDepth - 1);\n    if (this.#localRunDepth === 0) this.#submittedRunIdPending = false;\n  }\n\n  #notifyCreated(runId: string): void {\n    this.#activeRunId = runId;\n    try {\n      this.#options.onCreated?.({ runId });\n    } catch {\n      /* caller-supplied callback errors must not crash the stream */\n    }\n  }\n\n  #notifyCompleted(\n    reason: RunExecutionReason,\n    runId = this.#activeRunId\n  ): void {\n    if (runId != null && runId === this.#activeRunId) {\n      this.#activeRunId = undefined;\n    }\n    setTimeout(() => {\n      if (this.#disposed) return;\n      try {\n        this.#options.onCompleted?.(\n          runId == null ? { reason } : { runId, reason }\n        );\n      } catch {\n        /* caller-supplied callback errors must not crash the stream */\n      }\n    }, 0);\n  }\n\n  readonly #runLifecycleListener = (event: Event): void => {\n    if (this.#localRunDepth > 0) return;\n    if (event.method !== \"lifecycle\") return;\n    if (!isRootNamespace(event.params.namespace)) return;\n    if (!this.rootStore.getSnapshot().isLoading) return;\n    const lifecycle = (event as LifecycleEvent).params.data as {\n      event?: string;\n    };\n    const reason = lifecycleReason(lifecycle?.event);\n    if (reason == null) return;\n    this.#notifyCompleted(reason);\n  };\n\n  /**\n   * Cancel a queued submission by id. Returns `true` when the entry\n   * was found and removed, `false` otherwise.\n   *\n   * Removes the client-side entry either way; also issues a server-side\n   * cancel when the configured queue adapter is server-backed (see\n   * `AgentServerAdapter.serverQueue`). A no-op for the default,\n   * client-only adapter.\n   *\n   * @param id - Client-side queue entry id to remove.\n   */\n  async cancelQueued(id: string): Promise<boolean> {\n    return this.#submitter.cancelQueued(id);\n  }\n\n  /**\n   * Drop every queued submission. Cancels the underlying server-side\n   * runs too when the configured queue adapter is server-backed.\n   */\n  async clearQueue(): Promise<void> {\n    await this.#submitter.clearQueue();\n  }\n\n  /**\n   * Respond to a single pending protocol interrupt.\n   *\n   * When `options.interruptId` is omitted, resolution walks\n   * {@link ThreadStream.interrupts `thread.interrupts`} from newest to\n   * oldest and picks the first entry whose `interruptId` has not already\n   * been resolved by a prior `respond()` call. That entry may be at the\n   * root (`namespace: []`) or inside a subgraph (non-empty `namespace`).\n   * {@link RootSnapshot.interrupts `rootStore.interrupts`} /\n   * framework `stream.interrupts` mirrors the same pending interrupts\n   * (including nested namespaces) for UI rendering.\n   *\n   * Omitting `interruptId` is fine when exactly one interrupt is pending.\n   * When several can be active (parallel subagents, fan-out, nested\n   * graphs), pass an explicit `interruptId` so you resume the interrupt\n   * the user acted on. `namespace` is resolved automatically from\n   * `thread.interrupts` / `stream.interrupts` when omitted.\n   *\n   * To resume several interrupts pending at the same checkpoint in one\n   * command, use {@link respondAll} — sequential single `respond()` calls\n   * would not work, since the first resume starts a run, leaving the\n   * others with no interrupted run to respond to.\n   *\n   * The server validates `namespace` against the pending interrupt. Root\n   * interrupts use `namespace: []`. Subgraph interrupts carry the exact\n   * tuple on each {@link Interrupt} / {@link InterruptPayload} entry.\n   *\n   * @param response - Payload sent back to the interrupted namespace.\n   * @param options - Optional target (`interruptId` / `namespace`) and\n   *   run-level `config` / `metadata` folded into the run that services\n   *   the resume (model/user config, trigger source, test flags, …).\n   *   Equivalent to the same fields on {@link StreamSubmitOptions}.\n   *\n   * @example Single pending interrupt (safe to omit a target)\n   * ```ts\n   * await controller.respond({ approved: true });\n   * ```\n   *\n   * @example Carry run config / metadata onto the resume\n   * ```ts\n   * await controller.respond(\n   *   { approved: true },\n   *   { config: { configurable: { model: \"gpt-4o\" } }, metadata: { source: \"ui\" } },\n   * );\n   * ```\n   *\n   * @example Multiple / nested interrupts — target by id\n   * ```tsx\n   * for (const intr of stream.interrupts) {\n   *   await stream.respond(decide(intr.value), { interruptId: intr.id! });\n   * }\n   * ```\n   *\n   * Each {@link InterruptPayload} on `thread.interrupts` and each\n   * {@link Interrupt} on `stream.interrupts` mirrors an\n   * `input.requested` event with its protocol `namespace`.\n   */\n  async respond(\n    response: unknown,\n    options?: StreamRespondOptions<ConfigurableType>\n  ): Promise<void> {\n    if (this.#disposed || this.#thread == null) {\n      throw new Error(\"No active thread to respond to.\");\n    }\n\n    const resolved =\n      options?.interruptId != null\n        ? {\n            interruptId: options.interruptId,\n            namespace: this.#resolveNamespaceForInterruptId(\n              options.interruptId,\n              options.namespace\n            ),\n          }\n        : this.#resolveInterruptForResume();\n    if (resolved == null) {\n      throw new Error(\"No pending interrupt to respond to.\");\n    }\n    const thread = this.#thread;\n\n    // Apply the state `update` optimistically, mirroring `submit()`: append its\n    // messages to the root projection and mint stable ids so the resumed run's\n    // echo reconciles by id. Without this the interrupt is cleared the instant\n    // `respond()` dispatches while the pushed messages only reappear after a\n    // server round-trip — so a HITL \"card\" pushed via `update` would vanish for\n    // that window (the flicker). The id-injected payload is what we dispatch,\n    // so the server echoes the same ids back and `#applyValues` flips them\n    // `pending` → `sent` in place (no duplicate, no gap).\n    const prepared =\n      options?.update != null\n        ? this.#beginOptimistic(options.update)\n        : undefined;\n    const dispatchUpdate = this.#resolveDispatchUpdate(\n      options?.update,\n      prepared\n    );\n\n    try {\n      // Route through the coordinator so a resumed run that fails (e.g. a\n      // missing model key surfaced after the user answers) lands in the\n      // reactive `rootStore.error` slot, exactly like a `submit()` failure.\n      // The dispatch (`respondInput` + interrupt-resolved bookkeeping) is\n      // what's awaited; the resumed run's terminal is watched in the\n      // background (see {@link SubmitCoordinator.dispatchResume}), which also\n      // settles the optimistic handle (rolls back un-echoed keys on failure).\n      await this.#submitter.dispatchResume(async () => {\n        await thread.respondInput({\n          namespace: resolved.namespace,\n          interrupt_id: resolved.interruptId,\n          response: normalizeHitlResponseForServer(response),\n          // Fold an optional state update / directed jump into the same\n          // superstep as the resume (HITL \"push card into state + resume\").\n          // Omitted when absent so the server still sees a plain resume.\n          // `BaseMessage` instances under the messages key are serialized to\n          // plain dicts (like `submit()`) so they coerce server-side.\n          ...(dispatchUpdate != null ? { update: dispatchUpdate } : {}),\n          ...(options?.goto != null ? { goto: options.goto } : {}),\n          config: options?.config,\n          metadata: options?.metadata,\n        });\n        this.#advanceInterruptReplayBarrier();\n        this.#markInterruptResolvedInRootStore(resolved.interruptId);\n      }, prepared?.handle);\n    } catch (error) {\n      this.#discardPendingInterruptEvents();\n      if (this.#disposed && isAbortLikeError(error)) {\n        return;\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Resume several pending interrupts at the same checkpoint in a single\n   * command.\n   *\n   * Required when a run pauses on multiple interrupts simultaneously\n   * (e.g. parallel tool-authorization prompts): a single\n   * `Command({ resume })` carrying every interrupt's payload resumes them\n   * together. Sequential {@link respond} calls would fail because the\n   * first resume starts a run, leaving the rest with no interrupted run to\n   * respond to.\n   *\n   * `responsesById` maps each pending `interruptId` to the payload sent\n   * back to it, so different interrupts can receive different responses\n   * (approve one, deny another). To send the *same* payload to several\n   * interrupts, build the map with that value for each id, e.g.\n   * `Object.fromEntries(ids.map((id) => [id, response]))`.\n   *\n   * The server resumes by `interruptId`, so namespaces are resolved\n   * internally from `getThread()?.interrupts` and need not be supplied.\n   *\n   * @param responsesById - Map of pending `interruptId` to its response\n   *   payload. Must contain at least one entry.\n   * @param options - Optional run-level `config` / `metadata` folded into\n   *   the single run that services the batched resume. Equivalent to the\n   *   same fields on {@link StreamSubmitOptions}.\n   *\n   * @example Distinct payloads per interrupt\n   * ```tsx\n   * await stream.respondAll({\n   *   [interruptA.id]: { approved: true },\n   *   [interruptB.id]: { approved: false },\n   * });\n   * ```\n   *\n   * @example Same payload to every pending interrupt\n   * ```tsx\n   * await stream.respondAll(\n   *   Object.fromEntries(stream.interrupts.map((i) => [i.id!, { approved: true }])),\n   * );\n   * ```\n   */\n  async respondAll(\n    responsesById: Record<string, unknown>,\n    options?: StreamRespondAllOptions<ConfigurableType>\n  ): Promise<void> {\n    if (this.#disposed || this.#thread == null) {\n      throw new Error(\"No active thread to respond to.\");\n    }\n    const entries = Object.entries(responsesById);\n    if (entries.length === 0) {\n      throw new Error(\"respondAll() requires at least one response.\");\n    }\n    const thread = this.#thread;\n    const responses = entries.map(([interruptId, response]) => ({\n      interrupt_id: interruptId,\n      response: normalizeHitlResponseForServer(response),\n      namespace: this.#resolveNamespaceForInterruptId(interruptId),\n    }));\n    // Apply the run-level `update` optimistically (see `respond()` for the\n    // rationale): the batched resume's pushed messages paint immediately and\n    // reconcile by id when the single servicing run echoes them back.\n    const prepared =\n      options?.update != null\n        ? this.#beginOptimistic(options.update)\n        : undefined;\n    const dispatchUpdate = this.#resolveDispatchUpdate(\n      options?.update,\n      prepared\n    );\n\n    try {\n      // See `respond()` — route through the coordinator so the single run\n      // that services the batched resume surfaces failures on the reactive\n      // `rootStore.error` slot and settles the optimistic handle.\n      await this.#submitter.dispatchResume(async () => {\n        await thread.respondInput({\n          responses,\n          // A batched resume services every targeted interrupt in one run, so\n          // the update / jump are run-level (not per-entry) — applied once in\n          // that run's superstep alongside all the resumes. `BaseMessage`\n          // instances under the messages key are serialized to plain dicts\n          // (like `submit()`) so they coerce server-side.\n          ...(dispatchUpdate != null ? { update: dispatchUpdate } : {}),\n          ...(options?.goto != null ? { goto: options.goto } : {}),\n          config: options?.config,\n          metadata: options?.metadata,\n        });\n        this.#advanceInterruptReplayBarrier();\n        for (const { interrupt_id: interruptId } of responses) {\n          this.#markInterruptResolvedInRootStore(interruptId);\n        }\n      }, prepared?.handle);\n    } catch (error) {\n      this.#discardPendingInterruptEvents();\n      if (this.#disposed && isAbortLikeError(error)) {\n        return;\n      }\n      throw error;\n    }\n  }\n\n  /**\n   * Dispose the active thread, subscriptions, registry entries, and listeners.\n   */\n  async dispose(): Promise<void> {\n    if (this.#disposed) return;\n    this.#cancelPendingDispose();\n    this.#disposed = true;\n    this.#submitter.abortActiveRun();\n    await this.#teardownThread();\n    await this.registry.dispose();\n    this.#threadListeners.clear();\n  }\n\n  /**\n   * StrictMode-safe lifecycle hook for framework bindings.\n   *\n   * React 18+ `StrictMode` intentionally mounts → unmounts → remounts\n   * components in dev to surface effect-cleanup bugs. A naive\n   * `useEffect(() => () => controller.dispose())` would permanently\n   * tear the controller down on that first synthetic unmount, leaving\n   * every subsequent `submit()` a silent no-op.\n   *\n   * Call {@link activate} from the bind site's effect and return the\n   * result as the effect's cleanup. The controller uses deferred\n   * disposal: a `release()` only schedules a dispose on the next\n   * microtask, which is cancelled if another `activate()` arrives\n   * before it fires (the normal StrictMode remount path).\n   */\n  activate(): () => void {\n    this.#cancelPendingDispose();\n    return () => {\n      if (this.#disposed) return;\n      this.#pendingDisposeTimer = setTimeout(() => {\n        this.#pendingDisposeTimer = null;\n        void this.dispose().catch(() => undefined);\n      }, 0);\n    };\n  }\n\n  /**\n   * Cancel a deferred dispose scheduled by {@link activate}.\n   */\n  #cancelPendingDispose(): void {\n    if (this.#pendingDisposeTimer != null) {\n      clearTimeout(this.#pendingDisposeTimer);\n      this.#pendingDisposeTimer = null;\n    }\n  }\n\n  // ---------- thread access ----------\n\n  /**\n   * Returns the bound {@link ThreadStream}, if one exists. Prefer\n   * {@link StreamController.rootStore} and selector projections for\n   * UI work; use this for low-level protocol access.\n   */\n  getThread(): ThreadStream | undefined {\n    return this.#thread;\n  }\n\n  /**\n   * Listen for `ThreadStream` lifecycle (swap on thread-id change,\n   * detach on dispose). The listener fires immediately with the\n   * current thread (may be `undefined`).\n   *\n   * @param listener - Callback invoked immediately and on every thread swap.\n   */\n  subscribeThread(\n    listener: (thread: ThreadStream | undefined) => void\n  ): () => void {\n    this.#threadListeners.add(listener);\n    listener(this.#thread);\n    return () => {\n      this.#threadListeners.delete(listener);\n    };\n  }\n\n  // ---------- internals ----------\n\n  /**\n   * Build the initial root snapshot from configured initial values.\n   */\n  #createInitialSnapshot(): RootSnapshot<StateType, InterruptType> {\n    const values = (this.#options.initialValues ??\n      ({} as StateType)) as StateType;\n    const messages = extractAndCoerceMessages(\n      values as unknown as Record<string, unknown>,\n      this.#messagesKey\n    );\n    /**\n     * Seed `isThreadLoading: true` synchronously when a caller-supplied\n     * threadId is on the controller at construction/swap time. Without\n     * this Suspense wrappers would render their fallback for a tick\n     * because `isThreadLoading` flips false → true → false once the\n     * deferred `hydrate()` starts, and the synchronous render observes\n     * the initial `false`.\n     */\n    const willHydrate =\n      this.#currentThreadId != null &&\n      !this.#selfCreatedThreadIds.has(this.#currentThreadId);\n    return {\n      values,\n      messages,\n      toolCalls: [],\n      interrupts: [],\n      interrupt: undefined,\n      isLoading: false,\n      isThreadLoading: willHydrate,\n      error: undefined,\n      threadId: this.#currentThreadId,\n    };\n  }\n\n  /**\n   * Return the active thread stream, creating and binding one when needed.\n   *\n   * @param threadId - Thread id used when constructing the stream.\n   * @param deferRootPump - When `true`, build the ThreadStream and bind\n   *   the registry but skip starting the persistent root SSE pump. Used\n   *   for client-self-created thread ids whose server-side thread row\n   *   doesn't exist yet — opening the pump's `subscription.subscribe`\n   *   against a not-yet-existent thread produces a `404: Thread not\n   *   found` protocol error that strands terminal lifecycle events and\n   *   leaves the UI showing nothing until the user reloads. The pump is\n   *   started later via {@link #startDeferredRootPump} after `submitRun`\n   *   / `respondInput` commits the thread server-side.\n   *\n   *   Note: PR 2381's `#runStartReady` gate covers the analogous race\n   *   for the in-flight `run.start` send, but only when that send is\n   *   already pending. `#ensureThread` runs *before* `submitRun` is\n   *   called (and thus before the gate is armed), so on transports\n   *   that subscribe synchronously (WebSocket) the deferred path is\n   *   still required.\n   */\n  #ensureThread(threadId: string, deferRootPump = false): ThreadStream {\n    if (this.#thread != null) {\n      if (!deferRootPump && !this.#rootPumpDeferred && this.#rootPump == null) {\n        this.#startRootPump(this.#thread);\n      }\n      return this.#thread;\n    }\n    this.#thread = this.#options.client.threads.stream(threadId, {\n      assistantId: this.#options.assistantId,\n      transport: this.#options.transport,\n      fetch: this.#options.fetch,\n      webSocketFactory: this.#options.webSocketFactory,\n      maxReconnectAttempts: this.#options.maxReconnectAttempts,\n      streamIdleReconnect: this.#options.streamIdleReconnect,\n      reconnectDelayMs: this.#options.reconnectDelayMs,\n      onReconnect: this.#options.onReconnect,\n      onConnected: this.#options.onConnected,\n    });\n    this.registry.bind(this.#thread);\n    if (deferRootPump) {\n      // Resolve `#rootPumpReady` immediately so `submit()`'s `await\n      // this.#rootPumpReady` doesn't block — the dispatch path only\n      // needs the ThreadStream wired up to call `submitRun`, not the\n      // persistent subscription.\n      this.#rootPumpReady = Promise.resolve();\n      this.#rootPumpDeferred = true;\n    } else {\n      this.#startRootPump(this.#thread);\n    }\n    this.#notifyThreadListeners();\n    return this.#thread;\n  }\n\n  /**\n   * Start the previously-deferred root SSE pump after the first\n   * `submitRun` / `respondInput` has committed the thread server-side.\n   *\n   * No-op when the pump was started eagerly in {@link #ensureThread}\n   * (i.e. for hydrated existing threads, or for any thread whose pump\n   * has already been brought up).\n   */\n  #startDeferredRootPump(): void {\n    if (!this.#rootPumpDeferred) return;\n    if (this.#thread == null) return;\n    this.#rootPumpDeferred = false;\n    this.#startRootPump(this.#thread);\n  }\n\n  /**\n   * Abandon a deferred root pump that never started because its\n   * triggering dispatch (`submitRun` / `respondInput`) failed.\n   *\n   * Without this, the controller would be wedged in a state where:\n   *   - `#thread` is wired but no content pump is open\n   *   - `#rootPumpDeferred` stays `true`\n   *\n   * A retry submit must re-run `#ensureThread` from scratch (with\n   * `deferRootPump` still true — the id stays in\n   * `#selfCreatedThreadIds` until a successful dispatch). Tearing\n   * down `#thread` is the simplest recovery; the failed dispatch\n   * means there was nothing to subscribe to anyway.\n   */\n  #abandonDeferredRootPump(): void {\n    if (!this.#rootPumpDeferred) return;\n    this.#rootPumpDeferred = false;\n    void this.#teardownThread();\n  }\n\n  /**\n   * Close the current thread stream and reset per-thread assembly state.\n   */\n  async #teardownThread(): Promise<void> {\n    /**\n     * Invalidate the in-flight root pump before `close()` unparks it.\n     * `SubscriptionHandle.close()` leaves queued events intact and the\n     * iterator drains them before observing `closed`, so without this\n     * bump a parked interrupted pump would still dispatch stale\n     * `values` / `messages` into a snapshot `hydrate()` already cleared.\n     */\n    this.#rootPumpGeneration += 1;\n    const thread = this.#thread;\n    this.#thread = undefined;\n    this.registry.bind(undefined);\n    this.#threadEventUnsubscribe?.();\n    this.#threadEventUnsubscribe = undefined;\n    this.#threadErrorUnsubscribe?.();\n    this.#threadErrorUnsubscribe = undefined;\n    /**\n     * Persistent lifecycle driver is scoped to the current thread\n     * stream. Remove it so a swap to a new thread starts with a clean\n     * listener set (a new one is installed in `#startRootPump`).\n     */\n    this.#rootEventListeners.delete(this.#lifecycleLoading.listener);\n    this.#rootEventListeners.delete(this.#runLifecycleListener);\n    /**\n     * Close first so a pump parked on `waitForResume()` (interrupted\n     * run) unparks even if the unsubscribe RPC is slow. `close()` is\n     * idempotent; `unsubscribe()` is then a no-op once closed.\n     */\n    const subscription = this.#rootSubscription;\n    this.#rootSubscription = undefined;\n    subscription?.close();\n    this.#rootPumpReady = undefined;\n    // Reset so a swap to a new thread doesn't carry over a stale\n    // deferred flag — `#ensureThread` will set it again if the new\n    // thread is self-created.\n    this.#rootPumpDeferred = false;\n\n    // Reset per-thread assembly state before any awaits so hydrate()\n    // can clear the UI snapshot without waiting on pump/close.\n    this.#rootMessages.reset();\n    this.#rootToolAssembler = new ToolCallAssembler();\n    this.#lifecycleLoading.reset();\n    this.#subagents.reset();\n    this.#subgraphs.reset();\n    this.#scopedHistorySeeds.clear();\n    this.#activeRunId = undefined;\n    this.#localRunDepth = 0;\n    this.#messageMetadata.reset();\n    // Drop the hydrate-window allowlist — the next thread's hydrate\n    // will repopulate it from that thread's `state.tasks[].interrupts`.\n    this.#hydratedActiveInterruptIds = null;\n    this.#hydratedCheckpointTime = undefined;\n    this.#interruptReplayThroughSeq = undefined;\n    this.#pendingHydrationInterruptEvents = [];\n    this.#discardPendingInterruptEvents();\n    this.queueStore.setState(\n      () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n    );\n    this.#submitter.detachQueue();\n\n    try {\n      await subscription?.unsubscribe();\n    } catch {\n      /* already closed */\n    }\n    try {\n      await this.#rootPump;\n    } catch {\n      /* ignore */\n    }\n    this.#rootPump = undefined;\n\n    if (thread != null) {\n      try {\n        await thread.close();\n      } catch {\n        /* already closed */\n      }\n      this.#notifyThreadListeners();\n    }\n  }\n\n  /**\n   * Determine whether the configured transport uses the resumable event-stream path.\n   */\n  #usesEventStreamTransport(): boolean {\n    const transport = this.#options.transport;\n    if (transport === \"websocket\") return false;\n    if (transport == null || transport === \"sse\") return true;\n    return typeof transport.openEventStream === \"function\";\n  }\n\n  /**\n   * Start the always-on root subscription pump for the provided thread.\n   *\n   * @param thread - Thread stream to subscribe to and fan out from.\n   */\n  #startRootPump(thread: ThreadStream): void {\n    if (this.#rootPump != null) return;\n    const pumpGeneration = this.#rootPumpGeneration;\n    let resolveReady: (() => void) | undefined;\n    this.#rootPumpReady = new Promise<void>((resolve) => {\n      resolveReady = resolve;\n    });\n\n    /**\n     * Wildcard discovery + interrupt tracking is delivered via the\n     * thread's dedicated lifecycle watcher (see `ThreadStream.onEvent`).\n     * This callback fires once per globally-unique event across both\n     * the content pump AND the watcher, so we can drive discovery\n     * runners and nested HITL capture without widening the content\n     * pump's narrow filter.\n     */\n    this.#threadEventUnsubscribe = thread.onEvent((event) =>\n      this.#onWildcardEvent(event)\n    );\n    this.#threadErrorUnsubscribe = thread.onError((error) => {\n      this.rootStore.setState((s) => ({ ...s, error, isLoading: false }));\n      this.#rootSubscription?.close();\n    });\n\n    /**\n     * Persistent isLoading driver. Drives `isLoading` from\n     * root-namespace lifecycle events so that in-flight runs observed\n     * via `hydrate()` (not initiated by a local `submit()`) still flip\n     * the UI to loading. `running` → true; terminals → false. The\n     * optimistic `isLoading = true` inside `submit()` stays because\n     * that fires before any subscription event arrives.\n     */\n    this.#rootEventListeners.add(this.#lifecycleLoading.listener);\n    this.#rootEventListeners.add(this.#runLifecycleListener);\n\n    const pump = (async () => {\n      try {\n        /**\n         * Root content pump: depth 1 is required because the controller\n         * classifies tool events at namespace length ≤ 1 as root-level\n         * (see `#onWildcardEvent`'s `isRootLevelTool` check). The deep-\n         * agent `task` dispatcher fires `tools.tool-started` at\n         * `[\"tools:<id>\"]` (length 1), so a depth-0 filter would drop\n         * those events server-side before they reached `root.toolCalls`.\n         *\n         * Deeper content (subagent message tokens, values snapshots) is\n         * pulled in on demand by per-namespace selector projections\n         * (e.g. `useMessages(sub)`).\n         */\n        const subscriptionPromise = thread.subscribe({\n          channels: [...ROOT_PUMP_CHANNELS] as Channel[],\n          namespaces: [[] as string[]],\n          depth: 1,\n        });\n        if (this.#usesEventStreamTransport()) {\n          /**\n           * SSE streams can legitimately withhold response headers until\n           * the first event is available. Waiting for `subscribe()` here\n           * would deadlock new-thread submits: the run is not dispatched\n           * until the root pump is \"ready\", but the pump does not become\n           * ready until the run emits. `thread.subscribe()` has already\n           * registered the local subscription and scheduled the stream\n           * rotation by this point; waiting one microtask lets the fetch\n           * get kicked off without requiring headers to arrive.\n           */\n          queueMicrotask(() => {\n            resolveReady?.();\n            resolveReady = undefined;\n          });\n        }\n        const subscription = await subscriptionPromise;\n        if (pumpGeneration !== this.#rootPumpGeneration) {\n          resolveReady?.();\n          resolveReady = undefined;\n          try {\n            subscription.close();\n          } catch {\n            /* ignore */\n          }\n          return;\n        }\n        resolveReady?.();\n        resolveReady = undefined;\n        this.#rootSubscription = subscription;\n        /**\n         * The SSE transport pauses the underlying subscription when\n         * a terminal root lifecycle event arrives (so `for await`\n         * loops observing a single run exit cleanly) and re-opens\n         * the next run's server stream on `#prepareForNextRun`,\n         * resuming the subscription handle. The root pump needs to\n         * survive that hand-off: we re-enter the inner `for await`\n         * for every resumed iteration until the subscription is\n         * permanently closed or the controller is disposed.\n         */\n        while (!this.#disposed && pumpGeneration === this.#rootPumpGeneration) {\n          for await (const event of subscription) {\n            if (this.#disposed || pumpGeneration !== this.#rootPumpGeneration) {\n              break;\n            }\n            /**\n             * Resilience: isolate per-event dispatch from the pump loop.\n             *\n             * `#onRootEvent` runs synchronously and, transitively,\n             * invokes every root-bus listener (selector projections that\n             * opted into the shared stream) plus every `rootStore`\n             * subscriber. Some of those subscribers live in a React\n             * render tree — `useStream` drives\n             * `useSyncExternalStore`, so a misbehaving component can\n             * surface a render-phase error (\"Maximum update depth\n             * exceeded\", \"The result of getSnapshot should be cached\",\n             * etc.) that propagates out here.\n             *\n             * Without this guard, a single throw bubbles through the\n             * `for await` loop and terminates the root pump permanently.\n             * That is catastrophic: no more root events get processed —\n             * the terminal `lifecycle: completed` never lands, so\n             * `#awaitNextTerminal` never resolves, `isLoading` stays\n             * `true`, composers stay disabled, and the final assistant\n             * turn never commits to `stream.messages`. The UI looks\n             * hung even though the server is still emitting events\n             * (and `ThreadStream.onEvent` keeps firing).\n             *\n             * We therefore swallow the error and keep pumping. The\n             * the pump's correctness guarantees do not depend on any\n             * consumer behaving well.\n             */\n            try {\n              this.#onRootEvent(event);\n            } catch {\n              /**\n               * Best-effort — a consumer-facing store subscriber should not\n               * terminate the root pump. Store mutations happen before\n               * listeners are notified, so continuing with later events keeps\n               * the controller's authoritative state moving forward.\n               */\n            }\n          }\n          if (this.#disposed || pumpGeneration !== this.#rootPumpGeneration) {\n            break;\n          }\n          if (!subscription.isPaused) {\n            const snapshot = this.rootStore.getSnapshot();\n            if (snapshot.isLoading && snapshot.error == null) {\n              this.rootStore.setState((s) => ({\n                ...s,\n                error: new Error(\n                  \"Thread event stream closed before the active run completed.\"\n                ),\n                isLoading: false,\n              }));\n            }\n            break;\n          }\n          await subscription.waitForResume();\n        }\n      } catch {\n        resolveReady?.();\n        resolveReady = undefined;\n        /* thread closed or errored */\n      }\n    })();\n    this.#rootPump = pump;\n    void pump.finally(() => {\n      if (pumpGeneration !== this.#rootPumpGeneration) return;\n      if (this.#rootPump !== pump) return;\n      this.#rootPumpGeneration += 1;\n      this.#rootSubscription = undefined;\n      this.#rootPump = undefined;\n      this.#rootPumpReady = undefined;\n      this.#threadEventUnsubscribe?.();\n      this.#threadEventUnsubscribe = undefined;\n      this.#threadErrorUnsubscribe?.();\n      this.#threadErrorUnsubscribe = undefined;\n      this.#rootEventListeners.delete(this.#lifecycleLoading.listener);\n      this.#rootEventListeners.delete(this.#runLifecycleListener);\n    });\n  }\n\n  /**\n   * Handle an event delivered via {@link ThreadStream.onEvent}.\n   *\n   * `onEvent` fires once per globally-unique event across the content\n   * pump and the wildcard lifecycle watcher, so this is the single\n   * entry point for wildcard discovery / interrupt tracking. It does\n   * NOT fan events out to the root bus (that's driven by the content\n   * pump iterator so root-bus short-circuits stay depth-1 scoped) and\n   * it does NOT process root content — messages/tools/values at root\n   * are handled by `#onRootEvent` off the content pump.\n   *\n   * @param event - Raw protocol event observed by the thread-wide listener.\n   */\n  #onWildcardEvent(event: Event): void {\n    try {\n      this.#subagents.push(event);\n    } catch {\n      /**\n       * Discovery store subscribers are user/UI code. If one throws, still\n       * let the wildcard watcher update subgraphs, loading, and interrupts.\n       */\n    }\n    this.#subgraphs.push(event);\n    this.#lifecycleLoading.handle(event);\n\n    /**\n     * `input.requested` events (including HITL inside a subagent /\n     * subgraph) are not always observable via the narrow content pump.\n     * Mirror every namespace into `rootStore.interrupts` here so UI\n     * state does not depend on the content pump being the first\n     * consumer. `ThreadStream.interrupts` is updated in parallel for\n     * resume targeting.\n     */\n    this.#recordInterrupt(event);\n    this.#settleParkedInterruptsOnTerminal(event);\n  }\n\n  /**\n   * Process one root-pump event and update all root projections.\n   *\n   * @param event - Event yielded by the root subscription.\n   */\n  #onRootEvent(event: Event): void {\n    try {\n      this.#subagents.push(event);\n    } catch {\n      /**\n       * Discovery store subscribers are user/UI code. If one throws, still\n       * process the root event below so orchestrator messages and terminal\n       * state continue to advance.\n       */\n    }\n\n    /**\n     * Fan root-pump events out to every root-bus listener (selector\n     * projections that opted into the shared stream,\n     * `#awaitTerminal`, etc.). The root bus mirrors the content\n     * pump's narrow scope (depth 1 at root) so projections that\n     * short-circuit via the bus stay bounded.\n     */\n    if (this.#rootEventListeners.size > 0) {\n      for (const listener of this.#rootEventListeners) {\n        try {\n          listener(event);\n        } catch {\n          /**\n           * Best-effort — a bad listener should not wedge other\n           * projections or the root pump itself.\n           */\n        }\n      }\n    }\n\n    // After discovery and the root bus on purpose: root selector projections\n    // start empty and build from the replayed history.\n    const floor = this.#hydratedCheckpointTime;\n    if (floor != null && event.params.timestamp < floor) return;\n\n    /**\n     * `messages` and `tools` events are emitted under a node's\n     * namespace — for a typical StateGraph the LLM's token deltas\n     * land on `[\"model:<uuid>\"]`, tool executions on\n     * `[\"tools:<uuid>\"]`, etc. The orchestrator's own turns (root\n     * agent, or an orchestrator-scoped subgraph like `model:*` /\n     * `model_request:*`) belong in `root.messages` and\n     * `root.toolCalls`.\n     *\n     * Subagent / tool-internal branches do NOT:\n     *   - `task:*` segment — legacy subagent convention.\n     *   - `tools:*` segment — every tool execution is wrapped in a\n     *     `tools` subgraph. For simple tools its only content is\n     *     the eventual tool result (also echoed verbatim by\n     *     `values.messages` so we don't lose anything). For the\n     *     deep-agent `task` tool its content IS the spawned\n     *     subagent's full message + tool stream, which is surfaced\n     *     separately via `useMessages(stream, subagent)` /\n     *     `useToolCalls(stream, subagent)`.\n     *\n     * We therefore drop `messages` events from any namespace that\n     * contains a `task:*` or `tools:*` segment; the authoritative\n     * tool-result text lands in `root.messages` via the root\n     * `values.messages` snapshot merge in `#applyValues`.\n     */\n    const isInternalNamespace = isInternalWorkNamespace(event.params.namespace);\n    const hasLegacySubagentNamespace = isLegacySubagentNamespace(\n      event.params.namespace\n    );\n\n    if (event.method === \"messages\") {\n      if (!isInternalNamespace) {\n        this.#rootMessages.handleMessage(event as MessagesEvent);\n      }\n      return;\n    }\n\n    if (event.method === \"tools\") {\n      /**\n       * Root-level tool events (both for simple orchestrator tools\n       * and the deep-agent `task` dispatcher) fire at a\n       * single-segment `[\"tools:<id>\"]` namespace. Anything deeper\n       * (e.g. `[tools:<outer>, tools:<inner>]`) is a subagent's own\n       * tool call and belongs to that subagent's `useToolCalls`\n       * view, not the orchestrator's `root.toolCalls`.\n       */\n      const isRootLevelTool =\n        event.params.namespace.length <= 1 && !hasLegacySubagentNamespace;\n      if (isRootLevelTool) {\n        /**\n         * Record the `namespace → tool_call_id` association so that\n         * the ensuing `message-start` (role: \"tool\") at the same\n         * namespace can recover the `tool_call_id` (the `messages`\n         * channel's start event doesn't carry it directly).\n         */\n        const toolData = event.params.data as {\n          event?: string;\n          tool_call_id?: string;\n        };\n        if (\n          toolData.event === \"tool-started\" &&\n          typeof toolData.tool_call_id === \"string\"\n        ) {\n          this.#rootMessages.recordToolCallNamespace(\n            event.params.namespace,\n            toolData.tool_call_id\n          );\n        }\n        const tc = this.#rootToolAssembler.consume(event as ToolsEvent);\n        if (tc != null) {\n          this.rootStore.setState((s) => ({\n            ...s,\n            toolCalls: upsertToolCall(s.toolCalls, tc),\n          }));\n        }\n      }\n      return;\n    }\n\n    /**\n     * The `checkpoints` channel carries the lightweight envelope\n     * (`id`, `parent_id`, `step`, `source`) emitted immediately\n     * before its companion `values` event on the same superstep.\n     * Buffer the envelope per-namespace so the ensuing `values`\n     * event at the same namespace can pair with it in `#applyValues`.\n     * The buffer is read-and-cleared on consumption so a subsequent\n     * `values` event without a new checkpoint doesn't reuse stale\n     * metadata.\n     */\n    if (event.method === \"checkpoints\") {\n      const data = event.params.data as {\n        id?: unknown;\n        parent_id?: unknown;\n        step?: unknown;\n      } | null;\n      this.#messageMetadata.bufferCheckpoint(event.params.namespace, data);\n      return;\n    }\n\n    // Channels below are only meaningful at the root namespace.\n    const isRoot = isRootNamespace(event.params.namespace);\n    if (!isRoot) return;\n\n    if (event.method === \"values\") {\n      const valuesEvent = event as ValuesEvent;\n      const bufferedCheckpoint = this.#messageMetadata.consumeCheckpoint(\n        event.params.namespace\n      );\n      this.#applyValues(valuesEvent.params.data, bufferedCheckpoint);\n      return;\n    }\n\n    if (event.method === \"input.requested\") {\n      this.#recordInterrupt(event);\n      return;\n    }\n\n    if (event.method === \"lifecycle\") {\n      /**\n       * Root lifecycle transitions are observed elsewhere\n       * (#awaitTerminal) to unblock `submit`. Here they drop a closed\n       * run's never-checkpointed messages.\n       */\n      const lifecycle = (event as LifecycleEvent).params.data as {\n        event?: string;\n      };\n      const dropped = this.#rootMessages.applyLifecycle(lifecycle?.event);\n      if (dropped.size > 0) this.#messageMetadata.forget(dropped);\n    }\n  }\n\n  /**\n   * How a lifecycle event relates to the run a local `submit()` started.\n   * New subscriptions replay earlier runs' terminals, and accepting one\n   * would end the submitted run early: `\"other\"` marks those, `\"pending\"`\n   * an event that names a run before `run.start` has answered. `undefined`\n   * when it can't be told apart (no submit in flight, no run named, or no\n   * run id returned).\n   */\n  #submittedRunMatch(event: Event): \"other\" | \"pending\" | undefined {\n    if (event.method !== \"lifecycle\" || this.#localRunDepth === 0) {\n      return undefined;\n    }\n    const runId = synthesizedEventRunId(event.event_id);\n    if (runId == null) return undefined;\n    if (this.#submittedRunIdPending) return \"pending\";\n    if (this.#submittedRunId == null) return undefined;\n    return runId === this.#submittedRunId ? undefined : \"other\";\n  }\n\n  /**\n   * Merge a `values` payload into root values and root messages.\n   *\n   * @param raw - Raw `values` channel payload.\n   * @param checkpoint - Optional checkpoint envelope paired with the values event.\n   */\n  /**\n   * Apply a submit input optimistically to the root projection before\n   * the server responds. Mints stable ids for id-less messages (so the\n   * server echo reconciles by id), appends them to the projection, and\n   * shallow-merges non-message input keys into `values`.\n   *\n   * Returns the dispatch payload (id-injected) for the coordinator to\n   * send, plus an {@link OptimisticHandle} for terminal reconciliation.\n   * Returns `undefined` when optimistic UI is disabled or there is\n   * nothing to echo, in which case the coordinator dispatches the raw\n   * input unchanged.\n   *\n   * @param input - Raw input passed to `submit()`.\n   */\n  #beginOptimistic(\n    input: unknown\n  ): { dispatchInput: unknown; handle: OptimisticHandle } | undefined {\n    if (this.#options.optimistic === false) return undefined;\n    if (input == null || typeof input !== \"object\" || Array.isArray(input)) {\n      return undefined;\n    }\n    const prepared = prepareOptimisticInput(\n      input as Record<string, unknown>,\n      this.#messagesKey,\n      () => uuidv7()\n    );\n    const extraKeys = Object.keys(prepared.extraValues);\n    if (prepared.echoedIds.length === 0 && extraKeys.length === 0) {\n      return undefined;\n    }\n\n    const currentValues = this.rootStore.getSnapshot().values as Record<\n      string,\n      unknown\n    >;\n    const restoreKeys = extraKeys.map((key) => ({\n      key,\n      hadKey: Object.prototype.hasOwnProperty.call(currentValues, key),\n      prevValue: currentValues[key],\n    }));\n\n    this.#sawValuesForRun = false;\n    // Commit synchronously: this runs inside the user's `submit()` /\n    // `respond()` call (before the first await), so the optimistic\n    // message lands in the same tick — and therefore the same React /\n    // framework commit — as any local UI state the caller flips\n    // alongside it. A macrotask-deferred flush would paint the message\n    // one tick late, leaving a blink (e.g. a HITL card vanishing between\n    // \"form hidden\" and \"resolved card shown\").\n    this.#rootMessages.appendOptimistic(\n      prepared.optimisticMessages,\n      prepared.extraValues,\n      { sync: true }\n    );\n    if (prepared.echoedIds.length > 0) {\n      this.#messageMetadata.markPending(prepared.echoedIds);\n    }\n    return {\n      dispatchInput: prepared.dispatchInput,\n      handle: { echoedIds: prepared.echoedIds, restoreKeys },\n    };\n  }\n\n  /**\n   * Pick the `update` payload to dispatch on a resume (`respond` /\n   * `respondAll`).\n   *\n   * When the optimistic path ran ({@link #beginOptimistic} returned a handle),\n   * its `dispatchInput` already carries the minted message ids the server must\n   * echo back, so dispatch that — the echo reconciles the optimistic messages\n   * by id (no duplicate). Otherwise (optimistic UI disabled, or an `update`\n   * with no echoable messages — e.g. the tuple-entry form) fall back to\n   * serializing `BaseMessage` instances to dicts, exactly as before. Returns\n   * `undefined` when there is no `update`, so the server still sees a plain\n   * resume.\n   */\n  #resolveDispatchUpdate(\n    update: Record<string, unknown> | [string, unknown][] | undefined,\n    prepared: { dispatchInput: unknown; handle: OptimisticHandle } | undefined\n  ): Record<string, unknown> | [string, unknown][] | undefined {\n    if (prepared != null) {\n      return prepared.dispatchInput as Record<string, unknown>;\n    }\n    if (update == null) return undefined;\n    return serializeUpdateMessages(update, this.#messagesKey);\n  }\n\n  /**\n   * Reconcile optimistic state when a run terminates.\n   *\n   *   - Messages: any echoed id still `\"pending\"` (never echoed by the\n   *     server) is flipped to `\"sent\"` on success/interrupt, or\n   *     `\"failed\"` on failure/abort. Ids the server already echoed were\n   *     flipped to `\"sent\"` in {@link #applyValues} and are untouched.\n   *   - Non-message keys: rolled back to their pre-submit values when no\n   *     server `values` event landed during the run (otherwise the\n   *     server snapshot already reconciled them). Skipped on abort,\n   *     where a superseding run (or `stop()`) owns subsequent state.\n   *\n   * @param handle - Handle returned by {@link #beginOptimistic}.\n   * @param event  - Terminal lifecycle event for the run.\n   */\n  #settleOptimistic(\n    handle: OptimisticHandle,\n    event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\"\n  ): void {\n    const failed = event === \"failed\" || event === \"aborted\";\n    this.#messageMetadata.resolvePending(\n      handle.echoedIds,\n      failed ? \"failed\" : \"sent\"\n    );\n    if (event !== \"aborted\" && !this.#sawValuesForRun) {\n      this.#rootMessages.restoreValueKeys(handle.restoreKeys);\n    }\n  }\n\n  #applyValues(raw: unknown, checkpoint?: CheckpointEnvelope): void {\n    if (raw == null || typeof raw !== \"object\" || Array.isArray(raw)) {\n      return;\n    }\n    const state = raw as Record<string, unknown>;\n    // A root `values` snapshot landed: optimistic non-message keys are\n    // now reconciled against server truth (see #settleOptimistic).\n    this.#sawValuesForRun = true;\n    /**\n     * Surface parent_checkpoint per-message when the values event\n     * carries the lightweight checkpoint envelope (populated by\n     * `@langchain/langgraph-core`'s `_emitValuesWithCheckpointMeta` and\n     * forwarded through `convertToProtocolEvent`). Consumers surface\n     * this as `useMessageMetadata(stream, msg.id).parentCheckpointId`\n     * for fork / edit flows.\n     */\n    const parentCheckpointId = checkpoint?.parent_id;\n    if (parentCheckpointId != null && Array.isArray(state[this.#messagesKey])) {\n      this.#messageMetadata.recordMessages(\n        state[this.#messagesKey] as Array<{ id?: string }>,\n        { parentCheckpointId }\n      );\n    }\n    const maybeMessages = state[this.#messagesKey];\n    let nextValues: StateType;\n    let nextMessages: BaseMessage[];\n    if (Array.isArray(maybeMessages)) {\n      const coerced = ensureMessageInstances(\n        maybeMessages as (Message | BaseMessage)[]\n      );\n      nextValues = {\n        ...(state as StateType),\n        [this.#messagesKey]: coerced,\n      } as StateType;\n      nextMessages = coerced;\n    } else {\n      nextValues = state as StateType;\n      nextMessages = [];\n    }\n    this.#rootMessages.applyValues(nextValues, nextMessages, {\n      step: checkpoint?.step,\n    });\n    if (nextMessages.length > 0) {\n      // Any optimistic message the server just echoed is now\n      // server-authoritative: flip its status `pending` → `sent`.\n      this.#messageMetadata.resolvePending(\n        nextMessages\n          .map((m) => m.id)\n          .filter((id): id is string => typeof id === \"string\"),\n        \"sent\"\n      );\n      this.rootStore.setState((s) => {\n        const toolCalls = reconcileToolCallsFromMessages(\n          s.toolCalls,\n          nextMessages\n        );\n        if (toolCalls === s.toolCalls) return s;\n        return { ...s, toolCalls };\n      });\n    }\n  }\n\n  /**\n   * Mirror protocol interrupts (any namespace) into the root snapshot.\n   *\n   * This can be called from both the wildcard lifecycle/input watcher and the\n   * root content pump. Store-level dedup keeps the user-facing list stable.\n   */\n  #recordInterrupt(event: Event): void {\n    if (event.method !== \"input.requested\") return;\n    const data = event.params.data as {\n      interrupt_id?: string;\n      payload?: unknown;\n    };\n    const interruptId = data?.interrupt_id;\n    if (typeof interruptId !== \"string\") {\n      return;\n    }\n    // Before a run command is accepted, accept only ids the hydrated\n    // state reported as active. After acceptance, the command response's\n    // `applied_through_seq` separates replayed history from live events:\n    // unknown ids at or below the barrier are stale, while newer ids are\n    // interrupts raised by the new run.\n    const eventSeq = typeof event.seq === \"number\" ? event.seq : undefined;\n    // Locally-resolved ids: still drop historical replay, but accept a\n    // live reappearance (server still pending after sequential\n    // multi-interrupt resume, or the same interrupt site re-raised).\n    if (this.#resolvedInterrupts.has(interruptId)) {\n      const isLiveReappearance =\n        this.#hydratedActiveInterruptIds == null ||\n        (typeof this.#interruptReplayThroughSeq === \"number\" &&\n          eventSeq != null &&\n          eventSeq > this.#interruptReplayThroughSeq);\n      if (!isLiveReappearance) {\n        return;\n      }\n      this.#resolvedInterrupts.delete(interruptId);\n    }\n    const isUnknownInterrupt =\n      this.#hydratedActiveInterruptIds != null &&\n      !this.#hydratedActiveInterruptIds.has(interruptId);\n    if (isUnknownInterrupt && this.#interruptCommandPending) {\n      this.#pendingInterruptEvents.push(event);\n      return;\n    }\n    const barrier = this.#interruptReplayThroughSeq;\n    if (isUnknownInterrupt && barrier == null) {\n      this.#pendingHydrationInterruptEvents.push(event);\n      return;\n    }\n    const isHistoricalUnknownInterrupt =\n      isUnknownInterrupt &&\n      barrier != null &&\n      eventSeq != null &&\n      eventSeq <= barrier;\n    if (isHistoricalUnknownInterrupt) {\n      return;\n    }\n    const namespace = Array.isArray(event.params.namespace)\n      ? [...event.params.namespace]\n      : [...ROOT_NAMESPACE];\n    const interrupt: Interrupt<InterruptType> = normalizeInterruptForClient({\n      id: interruptId,\n      value: data.payload as InterruptType,\n      namespace,\n    });\n    this.rootStore.setState((s) => {\n      if (s.interrupts.some((entry) => entry.id === interruptId)) return s;\n      const interrupts = [...s.interrupts, interrupt];\n      return { ...s, interrupts, interrupt: interrupts[0] };\n    });\n  }\n\n  /**\n   * Convert the hydrate-time allowlist into a replay barrier after a command\n   * is accepted. Built-in transports update `lastAppliedThroughSeq` from the\n   * command response before resolving `submitRun` / `respondInput`.\n   */\n  #advanceInterruptReplayBarrier(): void {\n    if (this.#hydratedActiveInterruptIds == null) {\n      this.#discardPendingInterruptEvents();\n      return;\n    }\n    const throughSeq = this.#thread?.ordering?.lastAppliedThroughSeq;\n    if (typeof throughSeq === \"number\") {\n      this.#interruptReplayThroughSeq = throughSeq;\n    } else {\n      // Custom transports may not implement sequence metadata. Preserve the\n      // previous behavior so their genuinely new interrupts are not dropped.\n      this.#hydratedActiveInterruptIds = null;\n      this.#interruptReplayThroughSeq = undefined;\n    }\n    this.#interruptCommandPending = false;\n    const pendingEvents = this.#pendingInterruptEvents;\n    this.#pendingInterruptEvents = [];\n    for (const event of pendingEvents) {\n      this.#recordInterrupt(event);\n    }\n  }\n\n  #discardPendingInterruptEvents(): void {\n    this.#interruptCommandPending = false;\n    this.#pendingInterruptEvents = [];\n  }\n\n  /**\n   * Resolve the protocol namespace for a targeted resume.\n   *\n   * Prefer an explicit caller-supplied namespace, then the matching\n   * {@link ThreadStream.interrupts} entry, then the UI mirror on\n   * `rootStore.interrupts`, finally root (`[]`).\n   */\n  #resolveNamespaceForInterruptId(\n    interruptId: string,\n    explicitNamespace?: string[]\n  ): string[] {\n    if (explicitNamespace != null) return [...explicitNamespace];\n    const fromThread = this.#thread?.interrupts.find(\n      (entry) => entry.interruptId === interruptId\n    )?.namespace;\n    if (fromThread != null) return [...fromThread];\n    const fromRoot = this.rootStore\n      .getSnapshot()\n      .interrupts.find((entry) => entry.id === interruptId)?.namespace;\n    if (fromRoot != null) return [...fromRoot];\n    return [...ROOT_NAMESPACE];\n  }\n\n  /**\n   * Mark an interrupt resolved for historical-replay filtering and\n   * mirror the removal into the root snapshot the framework hooks read.\n   *\n   * Tombstones are not permanent: a live `input.requested` after the\n   * resume barrier clears the id when the same interrupt is raised again.\n   */\n  #markInterruptResolvedInRootStore(interruptId: string): void {\n    this.#resolvedInterrupts.add(interruptId);\n    this.rootStore.setState((s) => {\n      const interrupts = s.interrupts.filter(\n        (entry) => entry.id !== interruptId\n      );\n      if (\n        interrupts.length === s.interrupts.length &&\n        s.interrupt?.id !== interruptId\n      ) {\n        return s;\n      }\n      return {\n        ...s,\n        interrupts,\n        interrupt: interrupts[0],\n      };\n    });\n  }\n\n  /**\n   * Re-sync `rootStore.interrupts` from the server's authoritative\n   * `state.tasks[].interrupts` after a resumed run settles.\n   *\n   * Sequential `respond()` of parallel interrupts optimistically clears\n   * each targeted id client-side. The server checkpoint can continue to\n   * list the original interrupt batch after accepting a partial response,\n   * so locally-resolved ids remain filtered while untouched siblings are\n   * restored. This keeps `stream.interrupts` truthful without re-exposing\n   * an already-consumed interrupt.\n   *\n   * Uses the same transport-aware state fetch as {@link hydrate}, and\n   * drops the result if the thread swapped or a new submit/respond\n   * started while the fetch was in flight.\n   */\n  async #reconcilePendingInterruptsFromServer(): Promise<ThreadState<StateType> | null> {\n    const threadId = this.#currentThreadId;\n    if (threadId == null || this.#disposed) return null;\n    const generationAtFetch = this.#submitGeneration;\n    try {\n      const state = await this.#fetchHydrationState();\n      if (\n        this.#disposed ||\n        this.#currentThreadId !== threadId ||\n        this.#submitGeneration !== generationAtFetch\n      ) {\n        return null;\n      }\n      if (!Array.isArray(state?.tasks)) return null;\n      const { activeInterrupts, activeIds } =\n        collectActiveInterruptsFromTasks<InterruptType>(state.tasks);\n      const pendingInterrupts = activeInterrupts.filter(\n        (interrupt) =>\n          interrupt.id == null || !this.#resolvedInterrupts.has(interrupt.id)\n      );\n      this.rootStore.setState((s) => ({\n        ...s,\n        interrupts: pendingInterrupts,\n        interrupt: pendingInterrupts[0],\n      }));\n      this.#hydratedActiveInterruptIds = activeIds;\n      return state;\n    } catch {\n      /* best-effort — leave the optimistic interrupt list alone */\n      return null;\n    }\n  }\n\n  #settleParkedInterruptsOnTerminal(event: Event): void {\n    if (this.#pendingHydrationInterruptEvents.length === 0) return;\n    if (event.method !== \"lifecycle\") return;\n    if (!isRootNamespace(event.params.namespace)) return;\n    const status = (event as LifecycleEvent).params.data?.event;\n    if (\n      status !== \"interrupted\" &&\n      status !== \"completed\" &&\n      status !== \"failed\"\n    ) {\n      return;\n    }\n    void this.#settleParkedInterrupts();\n  }\n\n  /**\n   * Decide parked interrupts with server state instead of a stream marker.\n   *\n   * After a passive rejoin the stream cannot tell a replayed, already\n   * resolved `input.requested` from one the current run just raised: the\n   * SSE replays the thread buffer on connect with no marker for where the\n   * replay ends. `state.tasks[].interrupts` is authoritative: parked ids it\n   * lists are live, the rest are history.\n   */\n  async #settleParkedInterrupts(): Promise<void> {\n    const makePromise = async () => {\n      try {\n        const threadId = this.#currentThreadId;\n        const generation = this.#submitGeneration;\n        const deadline = Date.now() + PARKED_INTERRUPT_SETTLE_MS;\n        for (;;) {\n          if (\n            this.#disposed ||\n            this.#currentThreadId !== threadId ||\n            this.#submitGeneration !== generation ||\n            this.#pendingHydrationInterruptEvents.length === 0\n          ) {\n            return;\n          }\n          const parkedIds = new Set(\n            this.#pendingHydrationInterruptEvents.map(\n              (event) =>\n                (event.params.data as { interrupt_id?: string }).interrupt_id\n            )\n          );\n          // A null state is a failed or unusable fetch; the terminal that\n          // started this loop will not come again, so keep trying until the\n          // deadline rather than stranding the parked interrupts.\n          const state = await this.#reconcilePendingInterruptsFromServer();\n          if (state != null) {\n            const settled = [...(this.#hydratedActiveInterruptIds ?? [])].some(\n              (id) => parkedIds.has(id)\n            );\n            if (settled || !isThreadStateActive(state)) {\n              this.#pendingHydrationInterruptEvents = [];\n              return;\n            }\n          }\n          if (Date.now() >= deadline) return;\n          await new Promise<void>((resolve) => {\n            setTimeout(resolve, PARKED_INTERRUPT_SETTLE_POLL_MS);\n          });\n        }\n      } finally {\n        this.#settleParkedInterruptsPromise = undefined;\n      }\n    };\n    this.#settleParkedInterruptsPromise ??= makePromise();\n    return this.#settleParkedInterruptsPromise;\n  }\n\n  /**\n   * Resolve on the next root-namespace terminal lifecycle event\n   * (`completed` / `failed` / `interrupted`) or on abort.\n   *\n   * Attaches to the controller's root event bus instead of opening\n   * a second server subscription. Callers should register the\n   * returned promise **before** dispatching the command that\n   * triggers the run (`thread.run.start` / `thread.input.respond`)\n   * — the root pump fans events out synchronously on arrival, so a\n   * late registration would miss the terminal for fast runs.\n   *\n   * @param signal - Abort signal for the local submit lifecycle.\n   */\n  #awaitNextTerminal(signal: AbortSignal): Promise<{\n    event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n    error?: string;\n  }> {\n    return this.#awaitRootTerminal(signal, {\n      skipInterruptedUntilRunning: false,\n    });\n  }\n\n  /**\n   * Resolve on the resumed run's root terminal lifecycle.\n   *\n   * Unlike {@link #awaitNextTerminal}, ignores `interrupted` events until a\n   * root `running` lifecycle has been observed. Headless-tool flows can emit\n   * a stale `interrupted` for the run being resumed after `input.requested`\n   * but before `respondInput` calls `#prepareForNextRun`; accepting that\n   * terminal would unsubscribe the watcher before the resumed run's `failed`\n   * terminal arrives.\n   *\n   * On `interrupted` / `completed`, reconciles pending interrupts from\n   * server state so optimistic clears from {@link respond} cannot leave\n   * `stream.interrupts` empty while the checkpoint still has siblings.\n   */\n  async #awaitResumedRunTerminal(signal: AbortSignal): Promise<{\n    event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n    error?: string;\n  }> {\n    const terminal = await this.#awaitRootTerminal(signal, {\n      skipInterruptedUntilRunning: true,\n    });\n    if (\n      !signal.aborted &&\n      !this.#disposed &&\n      (terminal.event === \"interrupted\" || terminal.event === \"completed\")\n    ) {\n      await this.#reconcilePendingInterruptsFromServer();\n    }\n    return terminal;\n  }\n\n  #awaitRootTerminal(\n    signal: AbortSignal,\n    options: { skipInterruptedUntilRunning: boolean }\n  ): Promise<{\n    event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n    error?: string;\n  }> {\n    return new Promise((resolve) => {\n      let settled = false;\n      let sawRunning = false;\n      const held: Event[] = [];\n      const heldReleases = this.#heldLifecycleReleases;\n      function finish(result: {\n        event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n        error?: string;\n      }) {\n        if (settled) return;\n        settled = true;\n        heldReleases.delete(releaseHeld);\n        unsubscribeRoot?.();\n        unsubscribeThread?.();\n        unsubscribeError?.();\n        signal.removeEventListener(\"abort\", finishAborted);\n        resolve(result);\n      }\n      const finishAborted = () => finish({ event: \"aborted\" });\n      const onEvent = (event: Event) => {\n        if (settled) return;\n        if (event.method !== \"lifecycle\") return;\n        if (!isRootNamespace(event.params.namespace)) return;\n        const match = this.#submittedRunMatch(event);\n        if (match === \"other\") return;\n        if (match === \"pending\") {\n          held.push(event);\n          return;\n        }\n        const lifecycle = (event as LifecycleEvent).params.data as {\n          event?: string;\n          error?: string;\n        };\n        if (lifecycle?.event === \"running\") {\n          sawRunning = true;\n          return;\n        }\n        if (lifecycle?.event === \"completed\") {\n          setTimeout(() => finish({ event: \"completed\" }), 0);\n        } else if (lifecycle?.event === \"failed\") {\n          setTimeout(\n            () => finish({ event: \"failed\", error: lifecycle.error }),\n            0\n          );\n        } else if (lifecycle?.event === \"interrupted\") {\n          if (options.skipInterruptedUntilRunning && !sawRunning) {\n            return;\n          }\n          setTimeout(() => finish({ event: \"interrupted\" }), 0);\n        }\n      };\n      const releaseHeld = () => {\n        for (const event of held.splice(0)) onEvent(event);\n      };\n      heldReleases.add(releaseHeld);\n      const unsubscribeRoot = this.#rootBus.subscribe(onEvent);\n      const unsubscribeThread = this.#thread?.onEvent(onEvent);\n      const unsubscribeError = this.#thread?.onError((error) =>\n        finish({ event: \"failed\", error: error.message })\n      );\n      if (signal.aborted) {\n        finishAborted();\n      } else {\n        signal.addEventListener(\"abort\", finishAborted, { once: true });\n      }\n    });\n  }\n\n  /**\n   * Resolve which protocol interrupt a resume command should target.\n   * Headless-tool resumes are keyed by tool-call id; without matching\n   * on that id, parallel tool handlers would respond to the wrong\n   * interrupt (always the newest).\n   */\n  #resolveInterruptForResume(resume?: unknown): ResolvedInterrupt | null {\n    const thread = this.#thread;\n    if (thread == null) return null;\n    return resolveInterruptTargetForHeadlessResume(\n      resume,\n      thread.interrupts,\n      this.#resolvedInterrupts\n    );\n  }\n\n  /**\n   * Notify listeners that the underlying thread stream changed.\n   */\n  #notifyThreadListeners(): void {\n    for (const listener of this.#threadListeners) listener(this.#thread);\n  }\n}\n\n// ---------- helpers ----------\n\n/**\n * True when a subagent still sits on its default `tools:<toolCallId>`\n * namespace — i.e. no execution namespace has been observed (via SSE\n * replay) or resolved (via history) yet. Used to gate lazy namespace\n * resolution so already-promoted subagents aren't re-fetched.\n */\nfunction namespaceIsDefaultOnly(\n  entry: SubagentDiscoverySnapshot | undefined\n): boolean {\n  if (entry == null) return false;\n  return (\n    entry.namespace.length === 1 && entry.namespace[0] === `tools:${entry.id}`\n  );\n}\n\nfunction defaultSubagentToolCallId(\n  namespace: readonly string[]\n): string | undefined {\n  if (namespace.length !== 1) return undefined;\n  const segment = namespace[0];\n  if (!segment.startsWith(\"tools:\")) return undefined;\n  const id = segment.slice(\"tools:\".length);\n  return id.length > 0 ? id : undefined;\n}\n\n/**\n * Extract and coerce the configured messages key from a values object.\n *\n * @param values - State values object to read from.\n * @param messagesKey - Key that contains the message array.\n */\nfunction extractAndCoerceMessages(\n  values: Record<string, unknown>,\n  messagesKey: string\n): BaseMessage[] {\n  const raw = values[messagesKey];\n  if (!Array.isArray(raw)) return [];\n  return ensureMessageInstances(\n    raw as (Message | BaseMessage)[]\n  ) as BaseMessage[];\n}\n\nfunction extractAndCoerceMessagesWithFallback(\n  values: Record<string, unknown>,\n  messagesKey: string\n): BaseMessage[] | null {\n  let raw = values[messagesKey];\n  if (!Array.isArray(raw) && messagesKey !== DEFAULT_MESSAGES_KEY) {\n    raw = values[DEFAULT_MESSAGES_KEY];\n  }\n  if (!Array.isArray(raw)) return null;\n  return ensureMessageInstances(\n    raw as (Message | BaseMessage)[]\n  ) as BaseMessage[];\n}\n\n/**\n * Collect pending interrupts from a `threads.getState()` `tasks` array.\n *\n * Shared by {@link StreamController.hydrate} and the post-resume\n * reconcile path so both stay aligned on namespace derivation and\n * id dedupe.\n */\nfunction collectActiveInterruptsFromTasks<InterruptType>(tasks: unknown[]): {\n  activeInterrupts: Interrupt<InterruptType>[];\n  activeIds: Set<string>;\n} {\n  const activeInterrupts: Interrupt<InterruptType>[] = [];\n  const activeIds = new Set<string>();\n  for (const task of tasks) {\n    if (!Array.isArray((task as { interrupts?: unknown } | null)?.interrupts)) {\n      continue;\n    }\n    const typedTask = task as {\n      interrupts: unknown[];\n      checkpoint?: { checkpoint_ns?: unknown } | null;\n    };\n    const checkpointNs = typedTask.checkpoint?.checkpoint_ns;\n    const namespace =\n      typeof checkpointNs === \"string\" && checkpointNs.length > 0\n        ? checkpointNs.split(\"|\").filter((segment) => segment.length > 0)\n        : [...ROOT_NAMESPACE];\n    for (const interrupt of typedTask.interrupts) {\n      const typed = interrupt as\n        | { id?: string; value?: unknown; namespace?: string[] }\n        | null\n        | undefined;\n      const id = typed?.id;\n      if (typeof id !== \"string\" || activeIds.has(id)) continue;\n      activeIds.add(id);\n      activeInterrupts.push(\n        normalizeInterruptForClient({\n          id,\n          value: typed?.value as InterruptType,\n          namespace: Array.isArray(typed?.namespace)\n            ? [...typed.namespace]\n            : namespace,\n        })\n      );\n    }\n  }\n  return { activeInterrupts, activeIds };\n}\n\n// Unused import guard — `AIMessage` is only referenced by type tests.\nvoid AIMessage;\n\n/**\n * Run id from a `synth:<run_id>:...` event id, the form the agent server\n * uses for events it synthesizes such as root `lifecycle`. Events carry no\n * run id field.\n */\nfunction synthesizedEventRunId(\n  eventId: string | undefined\n): string | undefined {\n  if (eventId == null || !eventId.startsWith(\"synth:\")) return undefined;\n  return eventId.split(\":\")[1] || undefined;\n}\n"],"mappings":"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"}