import { Client, Interrupt } from "@langchain/langgraph-sdk"; import { ThreadStream } from "@langchain/langgraph-sdk/client"; import { AgentServerOptions, ChannelRegistry, CustomAdapterOptions, InferStateType, InferSubagentStates, InferToolCalls, StreamController, StreamRespondAllOptions, StreamRespondOptions, StreamStopOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, UseStreamOptions, WidenUpdateMessages } from "@langchain/langgraph-sdk/stream"; import { BaseMessage } from "@langchain/core/messages"; //#region src/use-stream.d.ts type AgentServerOptions$1 = AgentServerOptions; type CustomAdapterOptions$1 = CustomAdapterOptions; type UseStreamOptions$1> = UseStreamOptions; /** * Private field on the hook return that carries the * {@link StreamController} reference. Selector hooks (`useMessages`, * `useToolCalls`, …) read this to reach the shared * {@link ChannelRegistry}. Typed as a symbol-keyed field to discourage * end-user access — use the selector hooks instead. * * Exported as a unique symbol so type narrowing works across * `useMessages(stream, target)` call sites. */ declare const STREAM_CONTROLLER: unique symbol; interface UseStreamReturn, InterruptType = unknown, ConfigurableType extends object = Record, StateType extends object = InferStateType, SubagentStates = InferSubagentStates> { /** * The most recent `values`-channel snapshot emitted at the root * namespace — i.e. the thread-level state as the server sees it * after each superstep. Updated on every root `values` event, not * on token-level deltas: if you render `values.messages` directly * you'll see full turns appear at once instead of streaming * token-by-token. Use {@link messages} (or `useMessages`) for the * token-streamed view. * * Equivalent to calling `useValues(stream)`. */ readonly values: StateType; /** * Type-only: the resolved state shape. Exposed so consumers can * derive companion hook argument types (`useValues`) * without plumbing `T` through their component hierarchy. * * @internal */ readonly "~stateType"?: StateType; /** * The root message projection. Assembled from two sources and * merged in real time: * * 1. `messages`-channel deltas — token-level streaming events * (`message-start`, `content-block-delta`, `message-finish`) * emitted by the runtime. These drive live, token-by-token * updates. * 2. `values.messages` snapshots — the authoritative ordering * and any messages the agent produces without token streaming * (human turns, tool results, echoes from subagents). * * If the backend only emits `values` events (no `messages` * channel), every message will appear fully-formed on each * values update rather than streaming. This is a backend/runtime * concern — the React layer faithfully renders whatever the * server sends. * * Equivalent to calling `useMessages(stream)` with no target. */ readonly messages: BaseMessage[]; /** * Root-namespace tool calls assembled from the `tools` channel. * Each entry is a fully parsed {@link AssembledToolCall} with * name, args, and id — suitable for rendering approval UIs or * forwarding to headless tool handlers. * * When the stream is typed with an agent brand or tool list, * entries are narrowed via {@link InferToolCalls}. Equivalent to * calling `useToolCalls(stream)` with no target. */ readonly toolCalls: InferToolCalls[]; /** * All unresolved protocol interrupts observed on the root * namespace during the active thread. Populated from lifecycle / * input events and seeded on hydration from `thread.getState()`. * Cleared optimistically when a new run starts or an interrupt is * resolved via {@link respond}. */ readonly interrupts: Interrupt[]; /** * Convenience alias for {@link interrupts}[0] — the primary * interrupt most UIs should act on when only one is pending. * `undefined` when no interrupt is active. */ readonly interrupt: Interrupt | undefined; /** * `true` while a run is active or being started on the current * thread. Driven by root-namespace lifecycle events (`running` → * `true`, terminal phases → `false`). Use this to disable submit * buttons and show in-flight spinners. */ readonly isLoading: boolean; /** * `true` while the initial `thread.getState()` hydration for the * active thread is in flight. Distinct from {@link isLoading} — * thread loading covers the one-time fetch that seeds * {@link values} / {@link messages} before any user submit. */ readonly isThreadLoading: boolean; /** * Promise that settles when the current thread's initial hydration * completes. Exposed so Suspense wrappers can `throw` it until the * first {@link StreamController.hydrate} call resolves (or rejects) * for the active thread. A fresh promise is installed on every * `switchThread`/`threadId` change. */ readonly hydrationPromise: Promise; /** * The last error observed on the active run or hydration attempt. * `undefined` when no error has occurred. Cleared optimistically * when a new {@link submit} starts. */ readonly error: unknown; /** * Id of the thread the controller is bound to. `null` until the * first {@link submit} creates or selects a thread (or until an * explicit `threadId` option is provided and hydrated). */ readonly threadId: string | null; /** * Subagents discovered on the root run. For DeepAgent-typed * streams the key set is narrowed to the subagent names declared * on the agent brand (`keyof InferSubagentStates`). */ readonly subagents: ReadonlyMap; /** * Subgraphs discovered on the root run. * * A namespace is classified as a subgraph iff at least one * strictly-deeper namespace has been observed with it as a prefix. * This is inferred from the lifecycle event stream — plain function * nodes (`orchestrator`, `writer` in the nested-stategraph example) * never appear here even though the server emits namespaced * lifecycle events for them. Promotion is monotonic and retroactive; * an entry appears as soon as the first descendant event lands. */ readonly subgraphs: ReadonlyMap; /** * Subgraphs indexed by the graph node that produced them * (`addNode("visualizer_0", …)`). Each value is an array because * parallel fan-outs and loops can spawn multiple invocations of * the same node; arrays preserve insertion order. Updates in * lock-step with {@link subgraphs}. */ readonly subgraphsByNode: ReadonlyMap; /** * Dispatch a new run on the bound thread. * * `input` is typed as `Partial` so IDE autocompletion * surfaces the state keys declared on the root hook. */ submit(input: WidenUpdateMessages> | null | undefined, options?: StreamSubmitOptions): Promise; /** * Stop the active run on the current thread. By default cancels the * run server-side and disconnects the client; pass `{ cancel: false }` * or use {@link disconnect} for join/rejoin. Sets {@link isLoading} to * `false` immediately; {@link values} and {@link messages} are preserved. */ stop(options?: StreamStopOptions): Promise; /** * Disconnect the client without cancelling the run server-side. * Alias for `stop({ cancel: false })`. */ disconnect(): Promise; /** * Resume a pending protocol interrupt by sending a response payload * back to the interrupted namespace. * * When `options.interruptId` is omitted, walks `getThread()?.interrupts` * from newest to oldest and resumes the first not yet resolved by a prior * `respond()` call. That may be a root or subgraph interrupt and is * **not** necessarily {@link interrupt} (`interrupts[0]`, root-only). * Safe when exactly one interrupt is pending; otherwise pass an explicit * `options.interruptId` (and `options.namespace` for subgraph * interrupts). * * The server validates `namespace` against the pending interrupt. Root * interrupts use `namespace: []` (default when omitted). For subgraph * interrupts, copy `namespace` from `getThread()?.interrupts`. * * Pass `options.config` / `options.metadata` to fold run-level config * (model, user context, …) and metadata (trigger source, test flags, * …) into the resumed run, mirroring `submit()`. * * @example * ```tsx * // Single pending interrupt * await stream.respond({ approved: true }); * ``` * * @example * ```tsx * // Resume carrying run config + metadata * await stream.respond({ approved: true }, { * config: { configurable: { model: "gpt-4o" } }, * metadata: { source: "ui" }, * }); * ``` * * @example * ```tsx * // Multiple root interrupts — one at a time * stream.interrupts.map((intr) => ( *