@langchain/langgraph-sdk
Version:
Client library for interacting with the LangGraph API
1 lines • 55.5 kB
Source Map (JSON)
{"version":3,"file":"orchestrator.cjs","names":["#options","#accessors","#runMetadataStorage","#callbackStreamModes","#trackedStreamModes","MessageTupleManager","StreamManager","toMessageClass","PendingRunsTracker","#threadId","#history","#mutate","#streamUnsub","#flushPendingHeadlessToolInterrupts","#notify","#queueUnsub","#listeners","#version","#disposed","#handledHeadlessToolInterruptIds","#fetchHistoryForThread","#threadIdStreaming","#branch","getBranchContext","StreamError","#getMessages","ensureMessageInstances","getToolCallsWithResults","userFacingInterruptsFromValuesArray","userFacingInterruptsFromThreadTasks","extractInterrupts","ensureHistoryMessageInstances","getMessagesMetadataMap","onFinishRequiresThreadState","filterStream","#setMessages","#threadIdPromise","#setThreadIdFromSubmit","unique","#submitting","#drainQueue"],"sources":["../../src/ui/orchestrator.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\n\nimport { Client } from \"../client.js\";\nimport type { ThreadState, Interrupt } from \"../schema.js\";\nimport type { StreamMode } from \"../types.stream.js\";\nimport type { StreamEvent } from \"../types.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { BagTemplate } from \"../types.template.js\";\nimport { StreamManager, type EventStreamEvent } from \"./manager.js\";\nimport {\n MessageTupleManager,\n toMessageClass,\n ensureMessageInstances,\n ensureHistoryMessageInstances,\n} from \"./messages.js\";\nimport { PendingRunsTracker } from \"./queue.js\";\nimport { getBranchContext, getMessagesMetadataMap } from \"./branching.js\";\nimport { StreamError } from \"./errors.js\";\nimport {\n extractInterrupts,\n userFacingInterruptsFromThreadTasks,\n userFacingInterruptsFromValuesArray,\n} from \"./interrupts.js\";\nimport { unique, filterStream, onFinishRequiresThreadState } from \"./utils.js\";\nimport { getToolCallsWithResults } from \"../utils/tools.js\";\nimport { flushPendingHeadlessToolInterrupts } from \"../headless-tools.js\";\nimport type {\n UseStreamThread,\n AnyStreamOptions,\n SubmitOptions,\n RunCallbackMeta,\n MessageMetadata,\n GetUpdateType,\n GetCustomEventType,\n GetInterruptType,\n GetConfigurableType,\n SubagentStreamInterface,\n} from \"./types.js\";\n\ninterface RunMetadataStorage {\n getItem(key: `lg:stream:${string}`): string | null;\n setItem(key: `lg:stream:${string}`, value: string): void;\n removeItem(key: `lg:stream:${string}`): void;\n}\n\n/**\n * Fetch the history of a thread.\n * @param client - The client to use.\n * @param threadId - The ID of the thread to fetch the history of.\n * @param options - The options to use.\n * @returns The history of the thread.\n */\nfunction fetchHistory<StateType extends Record<string, unknown>>(\n client: Client,\n threadId: string,\n options?: { limit?: boolean | number }\n) {\n if (options?.limit === false) {\n return client.threads.getState<StateType>(threadId).then((state) => {\n if (state.checkpoint == null) return [];\n return [state];\n });\n }\n\n const limit = typeof options?.limit === \"number\" ? options.limit : 10;\n return client.threads.getHistory<StateType>(threadId, { limit });\n}\n\n/**\n * Resolve the run metadata storage.\n * @param reconnectOnMount - The reconnect on mount option.\n * @returns The run metadata storage.\n */\nfunction resolveRunMetadataStorage(\n reconnectOnMount: boolean | (() => RunMetadataStorage) | undefined\n): RunMetadataStorage | null {\n if (typeof globalThis.window === \"undefined\") return null;\n if (reconnectOnMount === true) return globalThis.window.sessionStorage;\n if (typeof reconnectOnMount === \"function\") return reconnectOnMount();\n return null;\n}\n\n/**\n * Resolve the callback stream modes.\n * @param options - The options to use.\n * @returns The callback stream modes.\n */\nfunction resolveCallbackStreamModes<\n S extends Record<string, unknown>,\n B extends BagTemplate,\n>(options: AnyStreamOptions<S, B>): StreamMode[] {\n const modes: StreamMode[] = [];\n if (options.onUpdateEvent) modes.push(\"updates\");\n if (options.onCustomEvent) modes.push(\"custom\");\n if (options.onCheckpointEvent) modes.push(\"checkpoints\");\n if (options.onTaskEvent) modes.push(\"tasks\");\n if (\"onDebugEvent\" in options && options.onDebugEvent) modes.push(\"debug\");\n if (\"onLangChainEvent\" in options && options.onLangChainEvent)\n modes.push(\"events\");\n return modes;\n}\n\n/**\n * Callbacks for resolving dynamic/reactive option values.\n * Framework adapters provide implementations that unwrap reactive primitives.\n */\nexport interface OrchestratorAccessors {\n getClient(): Client;\n getAssistantId(): string;\n getMessagesKey(): string;\n}\n\n/**\n * Framework-agnostic orchestrator for LangGraph Platform streams.\n *\n * Encapsulates all business logic shared across React, Vue, Svelte, and Angular:\n * thread management, history fetching, stream lifecycle, queue management,\n * branching, subagent management, and auto-reconnect.\n *\n * Framework adapters subscribe to state changes via {@link subscribe} and\n * map the orchestrator's getters to framework-specific reactive primitives.\n */\nexport class StreamOrchestrator<\n StateType extends Record<string, unknown> = Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n> {\n readonly stream: StreamManager<StateType, Bag>;\n\n readonly messageManager: MessageTupleManager;\n\n readonly pendingRuns: PendingRunsTracker<\n StateType,\n SubmitOptions<StateType, GetConfigurableType<Bag>>\n >;\n\n readonly #options: AnyStreamOptions<StateType, Bag>;\n\n readonly #accessors: OrchestratorAccessors;\n\n readonly historyLimit: boolean | number;\n\n readonly #runMetadataStorage: RunMetadataStorage | null;\n\n readonly #callbackStreamModes: StreamMode[];\n\n readonly #trackedStreamModes: StreamMode[] = [];\n\n #threadId: string | undefined;\n\n #threadIdPromise: Promise<string> | null = null;\n\n #threadIdStreaming: string | null = null;\n\n #history: UseStreamThread<StateType>;\n\n #branch: string = \"\";\n\n #submitting = false;\n\n #listeners = new Set<() => void>();\n\n #version = 0;\n\n #streamUnsub: (() => void) | null = null;\n\n #queueUnsub: (() => void) | null = null;\n\n #disposed = false;\n\n #handledHeadlessToolInterruptIds = new Set<string>();\n\n /**\n * Create a new StreamOrchestrator.\n *\n * @param options - Configuration options for the stream, including callbacks,\n * throttle settings, reconnect behaviour, and subagent filters.\n * @param accessors - Framework-specific accessors that resolve reactive\n * primitives (client, assistant ID, messages key) at call time.\n */\n constructor(\n options: AnyStreamOptions<StateType, Bag>,\n accessors: OrchestratorAccessors\n ) {\n this.#options = options;\n this.#accessors = accessors;\n\n this.#runMetadataStorage = resolveRunMetadataStorage(\n options.reconnectOnMount\n );\n this.#callbackStreamModes = resolveCallbackStreamModes(options);\n\n this.historyLimit =\n typeof options.fetchStateHistory === \"object\" &&\n options.fetchStateHistory != null\n ? (options.fetchStateHistory.limit ?? false)\n : (options.fetchStateHistory ?? false);\n\n this.messageManager = new MessageTupleManager();\n this.stream = new StreamManager<StateType, Bag>(this.messageManager, {\n throttle: options.throttle ?? false,\n subagentToolNames: options.subagentToolNames,\n filterSubagentMessages: options.filterSubagentMessages,\n toMessage: options.toMessage ?? toMessageClass,\n });\n\n this.pendingRuns = new PendingRunsTracker<\n StateType,\n SubmitOptions<StateType, GetConfigurableType<Bag>>\n >();\n\n this.#threadId = undefined;\n this.#history = {\n data: undefined,\n error: undefined,\n isLoading: false,\n mutate: this.#mutate,\n };\n\n this.#streamUnsub = this.stream.subscribe(() => {\n this.#flushPendingHeadlessToolInterrupts(\n this.stream.values as Record<string, unknown> | null\n );\n this.#notify();\n });\n\n this.#queueUnsub = this.pendingRuns.subscribe(() => {\n this.#notify();\n });\n }\n\n /**\n * Register a listener that is called whenever the orchestrator's internal\n * state changes (stream updates, queue changes, history mutations, etc.).\n *\n * @param listener - Callback invoked on every state change.\n * @returns An unsubscribe function that removes the listener.\n */\n subscribe(listener: () => void): () => void {\n this.#listeners.add(listener);\n return () => {\n this.#listeners.delete(listener);\n };\n }\n\n /**\n * Return the current version number, incremented on every state change.\n * Useful as a React `useSyncExternalStore` snapshot.\n *\n * @returns The current monotonically increasing version counter.\n */\n getSnapshot(): number {\n return this.#version;\n }\n\n /**\n * Increment the version counter and invoke all registered listeners.\n * No-op if the orchestrator has been disposed.\n */\n #notify(): void {\n if (this.#disposed) return;\n this.#version += 1;\n for (const listener of this.#listeners) {\n listener();\n }\n }\n\n /**\n * The current thread ID, or `undefined` if no thread is active.\n */\n get threadId(): string | undefined {\n return this.#threadId;\n }\n\n /**\n * Update thread ID from an external source (e.g. reactive prop change).\n * Clears the current stream and triggers a history fetch.\n * @param newId - The new thread ID to set.\n * @returns The new thread ID.\n */\n setThreadId(newId: string | undefined): void {\n if (newId === this.#threadId) return;\n this.#threadId = newId;\n this.#handledHeadlessToolInterruptIds.clear();\n this.stream.clear();\n this.#fetchHistoryForThread(newId);\n this.#notify();\n }\n\n /**\n * Update the thread ID from within a submit flow. Sets both the\n * streaming and canonical thread IDs, fires the `onThreadId` callback,\n * and notifies listeners.\n *\n * @param newId - The newly created or resolved thread ID.\n */\n #setThreadIdFromSubmit(newId: string): void {\n this.#threadIdStreaming = newId;\n this.#threadId = newId;\n this.#handledHeadlessToolInterruptIds.clear();\n this.#options.onThreadId?.(newId);\n this.#notify();\n }\n\n #fetchHistoryForThread(threadId: string | undefined): void {\n if (\n this.#threadIdStreaming != null &&\n this.#threadIdStreaming === threadId\n ) {\n return;\n }\n\n if (threadId != null) {\n this.#history = {\n ...this.#history,\n isLoading: true,\n mutate: this.#mutate,\n };\n this.#notify();\n void this.#mutate(threadId);\n } else {\n this.#history = {\n data: undefined,\n error: undefined,\n isLoading: false,\n mutate: this.#mutate,\n };\n this.#notify();\n }\n }\n\n /**\n * The current thread history fetch state, including data, loading status,\n * error, and a {@link UseStreamThread.mutate | mutate} function to\n * manually re-fetch.\n */\n get historyData(): UseStreamThread<StateType> {\n return this.#history;\n }\n\n async #mutate(\n mutateId?: string\n ): Promise<ThreadState<StateType>[] | undefined> {\n const tid = mutateId ?? this.#threadId;\n if (!tid) return undefined;\n try {\n const data = await fetchHistory<StateType>(\n this.#accessors.getClient(),\n tid,\n { limit: this.historyLimit }\n );\n this.#history = {\n data,\n error: undefined,\n isLoading: false,\n mutate: this.#mutate,\n };\n this.#flushPendingHeadlessToolInterrupts(\n data?.at(0)?.values as Record<string, unknown> | null | undefined\n );\n this.#notify();\n return data;\n } catch (err) {\n this.#history = {\n ...this.#history,\n error: err,\n isLoading: false,\n };\n this.#notify();\n this.#options.onError?.(err, undefined);\n return undefined;\n }\n }\n\n /**\n * Trigger initial history fetch for the current thread ID.\n * Should be called once after construction when the initial threadId is known.\n */\n initThreadId(threadId: string | undefined): void {\n this.#threadId = threadId;\n this.#handledHeadlessToolInterruptIds.clear();\n this.#fetchHistoryForThread(threadId);\n }\n\n /**\n * The currently active branch identifier. An empty string represents\n * the main (default) branch.\n */\n get branch(): string {\n return this.#branch;\n }\n\n /**\n * Set the active branch and notify listeners if the value changed.\n *\n * @param value - The branch identifier to switch to.\n */\n setBranch(value: string): void {\n if (value === this.#branch) return;\n this.#branch = value;\n this.#notify();\n }\n\n /**\n * Derived branch context computed from the current branch and thread\n * history. Contains the thread head, branch tree, and checkpoint-to-branch\n * mapping for the active branch.\n */\n get branchContext() {\n return getBranchContext(this.#branch, this.#history.data ?? undefined);\n }\n\n #getMessages(value: StateType): Message[] {\n const messagesKey = this.#accessors.getMessagesKey();\n return Array.isArray(value[messagesKey]) ? value[messagesKey] : [];\n }\n\n #setMessages(current: StateType, messages: Message[]): StateType {\n const messagesKey = this.#accessors.getMessagesKey();\n return { ...current, [messagesKey]: messages };\n }\n\n /**\n * The state values from the thread head of the current branch history,\n * falling back to {@link AnyStreamOptions.initialValues | initialValues}\n * or an empty object.\n */\n get historyValues(): StateType {\n return (\n this.branchContext.threadHead?.values ??\n this.#options.initialValues ??\n ({} as StateType)\n );\n }\n\n /**\n * The error from the last task in the thread head, if any.\n * Attempts to parse structured {@link StreamError} instances from JSON.\n */\n get historyError(): unknown {\n const error = this.branchContext.threadHead?.tasks?.at(-1)?.error;\n if (error == null) return undefined;\n try {\n const parsed = JSON.parse(error) as unknown;\n if (StreamError.isStructuredError(parsed)) return new StreamError(parsed);\n return parsed;\n } catch {\n // do nothing\n }\n return error;\n }\n\n /**\n * The latest state values received from the active stream, or `null` if\n * no stream is running or no values have been received yet.\n */\n get streamValues(): StateType | null {\n return this.stream.values;\n }\n\n /**\n * The error from the active stream, if one occurred during streaming.\n */\n get streamError(): unknown {\n return this.stream.error;\n }\n\n /**\n * The merged state values, preferring live stream values over history.\n * This is the primary way to read the current thread state.\n */\n get values(): StateType {\n return this.stream.values ?? this.historyValues;\n }\n\n /**\n * The first available error from the stream, history, or thread fetch.\n * Returns `undefined` when no error is present.\n */\n get error(): unknown {\n return this.stream.error ?? this.historyError ?? this.#history.error;\n }\n\n /**\n * Whether the stream is currently active and receiving events.\n */\n get isLoading(): boolean {\n return this.stream.isLoading;\n }\n\n /**\n * The messages array extracted from the current {@link values} using the\n * configured messages key.\n */\n get messages(): Message[] {\n return this.#getMessages(this.values);\n }\n\n /**\n * The current messages converted to LangChain {@link BaseMessage} instances.\n * Automatically tracks the `\"messages-tuple\"` stream mode.\n */\n get messageInstances(): BaseMessage[] {\n this.trackStreamMode(\"messages-tuple\");\n return ensureMessageInstances(this.messages) as BaseMessage[];\n }\n\n /**\n * All tool calls with their corresponding results extracted from\n * the current messages. Automatically tracks the `\"messages-tuple\"`\n * stream mode.\n */\n get toolCalls() {\n this.trackStreamMode(\"messages-tuple\");\n return getToolCallsWithResults(this.#getMessages(this.values));\n }\n\n /**\n * Get tool calls with results for a specific AI message.\n * Automatically tracks the `\"messages-tuple\"` stream mode.\n *\n * @param message - The AI message to extract tool calls from.\n * @returns Tool calls whose AI message ID matches the given message.\n */\n getToolCalls(message: Message) {\n this.trackStreamMode(\"messages-tuple\");\n const allToolCalls = getToolCallsWithResults(\n this.#getMessages(this.values)\n );\n return allToolCalls.filter((tc) => tc.aiMessage.id === message.id);\n }\n\n /**\n * All active interrupts for the current thread state.\n * Returns an empty array when the stream is loading or no interrupts\n * are present. Falls back to a `{ when: \"breakpoint\" }` sentinel when\n * there are pending next nodes but no explicit interrupt data.\n */\n get interrupts(): Interrupt<GetInterruptType<Bag>>[] {\n const v = this.values;\n if (v != null && \"__interrupt__\" in v && Array.isArray(v.__interrupt__)) {\n return userFacingInterruptsFromValuesArray<GetInterruptType<Bag>>(\n v.__interrupt__ as Interrupt<GetInterruptType<Bag>>[]\n );\n }\n\n if (this.isLoading) return [];\n\n const allTasks = this.branchContext.threadHead?.tasks ?? [];\n const allInterrupts = allTasks.flatMap((t) => t.interrupts ?? []);\n\n const taskInterrupts = userFacingInterruptsFromThreadTasks<\n GetInterruptType<Bag>\n >(allInterrupts as Interrupt<GetInterruptType<Bag>>[]);\n if (taskInterrupts != null) return taskInterrupts;\n\n const next = this.branchContext.threadHead?.next ?? [];\n if (!next.length || this.error != null) return [];\n return [{ when: \"breakpoint\" }];\n }\n\n /**\n * The single most relevant interrupt for the current thread state,\n * or `undefined` if no interrupt is active. Convenience accessor that\n * delegates to {@link extractInterrupts}.\n */\n get interrupt(): Interrupt<GetInterruptType<Bag>> | undefined {\n return extractInterrupts<GetInterruptType<Bag>>(this.values, {\n isLoading: this.isLoading,\n threadState: this.branchContext.threadHead,\n error: this.error,\n });\n }\n\n /**\n * Flattened history messages as LangChain {@link BaseMessage} instances,\n * ordered chronologically across all branch checkpoints.\n *\n * @throws If `fetchStateHistory` was not enabled in the options.\n */\n get flatHistory() {\n if (this.historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `history`\"\n );\n }\n return ensureHistoryMessageInstances(\n this.branchContext.flatHistory,\n this.#accessors.getMessagesKey()\n );\n }\n\n /**\n * Whether the initial thread history is still being loaded and no data\n * is available yet. Returns `false` once the first fetch completes.\n */\n get isThreadLoading(): boolean {\n return this.#history.isLoading && this.#history.data == null;\n }\n\n /**\n * The full branch tree structure for the current thread history.\n *\n * @experimental This API may change in future releases.\n * @throws If `fetchStateHistory` was not enabled in the options.\n */\n get experimental_branchTree() {\n if (this.historyLimit === false) {\n throw new Error(\n \"`fetchStateHistory` must be set to `true` to use `experimental_branchTree`\"\n );\n }\n return this.branchContext.branchTree;\n }\n\n /**\n * A map of metadata entries for all messages, derived from history\n * and branch context. Used internally by {@link getMessagesMetadata}.\n */\n get messageMetadata() {\n return getMessagesMetadataMap({\n initialValues: this.#options.initialValues,\n history: this.#history.data,\n getMessages: (value: StateType) => this.#getMessages(value),\n branchContext: this.branchContext,\n });\n }\n\n /**\n * Look up metadata for a specific message, merging stream-time metadata\n * with history-derived metadata.\n *\n * @param message - The message to look up metadata for.\n * @param index - Optional positional index used as a fallback identifier.\n * @returns The merged metadata, or `undefined` if none is available.\n */\n getMessagesMetadata(\n message: Message,\n index?: number\n ): MessageMetadata<StateType> | undefined {\n const streamMetadata = this.messageManager.get(message.id)?.metadata;\n const historyMetadata = this.messageMetadata?.find(\n (m) => m.messageId === (message.id ?? index)\n );\n\n if (streamMetadata != null || historyMetadata != null) {\n return {\n ...historyMetadata,\n streamMetadata,\n } as MessageMetadata<StateType>;\n }\n\n return undefined;\n }\n\n /**\n * The list of pending run entries currently waiting in the queue.\n */\n get queueEntries() {\n return this.pendingRuns.entries;\n }\n\n /**\n * The number of pending runs in the queue.\n */\n get queueSize() {\n return this.pendingRuns.size;\n }\n\n /**\n * Cancel and remove a specific pending run from the queue.\n * If the run exists and a thread is active, the run is also cancelled\n * on the server.\n *\n * @param id - The run ID to cancel.\n * @returns `true` if the run was found and removed, `false` otherwise.\n */\n async cancelQueueItem(id: string): Promise<boolean> {\n const tid = this.#threadId;\n const removed = this.pendingRuns.remove(id);\n if (removed && tid) {\n await this.#accessors.getClient().runs.cancel(tid, id);\n }\n return removed;\n }\n\n /**\n * Remove all pending runs from the queue and cancel them on the server.\n */\n async clearQueue(): Promise<void> {\n const tid = this.#threadId;\n const removed = this.pendingRuns.removeAll();\n if (tid && removed.length > 0) {\n await Promise.all(\n removed.map((e) => this.#accessors.getClient().runs.cancel(tid, e.id))\n );\n }\n }\n\n /**\n * A map of all known subagent stream interfaces, keyed by tool call ID.\n */\n get subagents(): Map<string, SubagentStreamInterface> {\n return this.stream.getSubagents();\n }\n\n /**\n * The subset of subagents that are currently active (streaming).\n */\n get activeSubagents(): SubagentStreamInterface[] {\n return this.stream.getActiveSubagents();\n }\n\n /**\n * Retrieve a specific subagent stream interface by its tool call ID.\n *\n * @param toolCallId - The tool call ID that spawned the subagent.\n * @returns The subagent interface, or `undefined` if not found.\n */\n getSubagent(toolCallId: string) {\n return this.stream.getSubagent(toolCallId);\n }\n\n /**\n * Retrieve all subagent stream interfaces that match a given agent type.\n *\n * @param type - The agent type name to filter by.\n * @returns An array of matching subagent interfaces.\n */\n getSubagentsByType(type: string) {\n return this.stream.getSubagentsByType(type);\n }\n\n /**\n * Retrieve all subagent stream interfaces associated with a specific\n * AI message.\n *\n * @param messageId - The ID of the parent AI message.\n * @returns An array of subagent interfaces spawned by that message.\n */\n getSubagentsByMessage(messageId: string) {\n return this.stream.getSubagentsByMessage(messageId);\n }\n\n /**\n * Reconstruct subagents from history messages if applicable.\n * Call this when history finishes loading and the stream isn't active.\n * Returns an AbortController for cancelling the subagent history fetch,\n * or null if no reconstruction was needed.\n */\n reconstructSubagentsIfNeeded(): AbortController | null {\n const hvMessages = this.#getMessages(this.historyValues);\n const should =\n this.#options.filterSubagentMessages &&\n !this.isLoading &&\n !this.#history.isLoading &&\n hvMessages.length > 0;\n\n if (!should) return null;\n\n this.stream.reconstructSubagents(hvMessages, { skipIfPopulated: true });\n\n const tid = this.#threadId;\n if (this.historyLimit !== false && tid) {\n const controller = new AbortController();\n void this.stream.fetchSubagentHistory(\n this.#accessors.getClient().threads,\n tid,\n {\n messagesKey: this.#accessors.getMessagesKey(),\n historyLimit:\n typeof this.historyLimit === \"number\"\n ? this.historyLimit\n : undefined,\n signal: controller.signal,\n }\n );\n return controller;\n }\n\n return null;\n }\n\n /**\n * Register additional stream modes that should be included in future\n * stream requests. Modes are deduplicated automatically.\n *\n * @param modes - One or more stream modes to track.\n */\n trackStreamMode(...modes: StreamMode[]): void {\n for (const mode of modes) {\n if (!this.#trackedStreamModes.includes(mode)) {\n this.#trackedStreamModes.push(mode);\n }\n }\n }\n\n /**\n * Stop the currently active stream. If reconnect metadata storage is\n * configured, also cancels the run on the server and cleans up stored\n * run metadata.\n */\n async stop(): Promise<void> {\n const wasLoading = this.stream.isLoading;\n const threadId = this.#threadId;\n\n const includeImplicitBranch =\n this.historyLimit === true || typeof this.historyLimit === \"number\";\n const shouldRefetch =\n includeImplicitBranch ||\n onFinishRequiresThreadState(this.#options.onFinish);\n\n await this.stream.stop(this.historyValues, {\n onStop: (args) => {\n if (this.#runMetadataStorage && this.#threadId) {\n const runId = this.#runMetadataStorage.getItem(\n `lg:stream:${this.#threadId}`\n );\n if (runId) {\n void this.#accessors.getClient().runs.cancel(this.#threadId, runId);\n }\n this.#runMetadataStorage.removeItem(`lg:stream:${this.#threadId}`);\n }\n this.#options.onStop?.(args);\n },\n });\n\n // A cancelled run makes `enqueue()` throw `AbortError`, which skips its\n // `onSuccess` history reconciliation (see `StreamManager.enqueue`). Left\n // alone, the locally-buffered stream values — including any message\n // chunk still being assembled when `stop()` was called — stay stuck in\n // `stream.values` and keep outranking `historyValues` on every render\n // until a thread switch or a full remount. Re-sync so the buffer only\n // reflects what was actually persisted: refetch when the caller needs\n // authoritative thread state (branching / `onFinish`), otherwise fall\n // back to the already-cached `historyValues` to avoid an extra round\n // trip on every cancel.\n if (wasLoading && threadId) {\n if (shouldRefetch) {\n const newHistory = await this.#mutate(threadId);\n this.stream.setStreamValues(newHistory?.at(0)?.values ?? null);\n } else {\n this.stream.setStreamValues(this.historyValues);\n }\n }\n }\n\n /**\n * Join an existing run's event stream by run ID. Used for reconnecting\n * to in-progress runs or consuming queued runs.\n *\n * @param runId - The ID of the run to join.\n * @param lastEventId - The last event ID received, for resuming mid-stream.\n * Defaults to `\"-1\"` (start from the beginning).\n * @param joinOptions - Additional options for stream mode and event filtering.\n */\n async joinStream(\n runId: string,\n lastEventId?: string,\n joinOptions?: {\n streamMode?: StreamMode | StreamMode[];\n filter?: (event: {\n id?: string;\n event: StreamEvent;\n data: unknown;\n }) => boolean;\n }\n ): Promise<void> {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n\n // eslint-disable-next-line no-param-reassign\n lastEventId ??= \"-1\";\n const tid = this.#threadId;\n if (!tid) return;\n this.#threadIdStreaming = tid;\n\n const callbackMeta: RunCallbackMeta = {\n thread_id: tid,\n run_id: runId,\n };\n\n const includeImplicitBranch =\n this.historyLimit === true || typeof this.historyLimit === \"number\";\n const shouldRefetchJoin =\n includeImplicitBranch ||\n onFinishRequiresThreadState(this.#options.onFinish);\n\n const client = this.#accessors.getClient();\n\n await this.stream.start(\n async (signal: AbortSignal) => {\n const rawStream = client.runs.joinStream(tid, runId, {\n signal,\n lastEventId,\n streamMode: joinOptions?.streamMode,\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n\n return joinOptions?.filter != null\n ? filterStream(rawStream, joinOptions.filter)\n : rawStream;\n },\n {\n getMessages: (value: StateType) => this.#getMessages(value),\n setMessages: (current: StateType, messages: Message[]) =>\n this.#setMessages(current, messages),\n initialValues: this.historyValues,\n callbacks: this.#options,\n onSuccess: async () => {\n this.#runMetadataStorage?.removeItem(`lg:stream:${tid}`);\n if (!shouldRefetchJoin) {\n if (\n this.#options.onFinish != null &&\n !onFinishRequiresThreadState(this.#options.onFinish)\n ) {\n this.#options.onFinish(\n undefined as unknown as ThreadState<StateType>,\n callbackMeta\n );\n }\n return;\n }\n const newHistory = await this.#mutate(tid);\n const lastHead = newHistory?.at(0);\n if (lastHead) this.#options.onFinish?.(lastHead, callbackMeta);\n },\n onError: (error) => {\n this.#options.onError?.(error, callbackMeta);\n },\n onFinish: () => {\n this.#threadIdStreaming = null;\n },\n }\n );\n }\n\n /**\n * Submit input values directly to the LangGraph Platform, creating a new\n * thread if necessary. Starts a streaming run and processes events until\n * completion. Unlike {@link submit}, this does not handle queueing — if\n * a stream is already active, a concurrent run will be started.\n *\n * @param values - The state values to send as run input.\n * @param submitOptions - Optional configuration for the run (config,\n * checkpoint, multitask strategy, optimistic values, etc.).\n */\n submitDirect(\n values: StateType,\n submitOptions?: SubmitOptions<StateType, GetConfigurableType<Bag>>\n ) {\n type UpdateType = GetUpdateType<Bag, StateType>;\n type CustomType = GetCustomEventType<Bag>;\n\n const currentBranchContext = this.branchContext;\n\n const checkpointId = submitOptions?.checkpoint?.checkpoint_id;\n this.#branch =\n checkpointId != null\n ? (currentBranchContext.branchByCheckpoint[checkpointId]?.branch ?? \"\")\n : \"\";\n\n const includeImplicitBranch =\n this.historyLimit === true || typeof this.historyLimit === \"number\";\n\n const shouldRefetch =\n includeImplicitBranch ||\n onFinishRequiresThreadState(this.#options.onFinish);\n\n let checkpoint =\n submitOptions?.checkpoint ??\n (includeImplicitBranch\n ? currentBranchContext.threadHead?.checkpoint\n : undefined) ??\n undefined;\n\n if (submitOptions?.checkpoint === null) checkpoint = undefined;\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n if (checkpoint != null) delete checkpoint.thread_id;\n\n let callbackMeta: RunCallbackMeta | undefined;\n let rejoinKey: `lg:stream:${string}` | undefined;\n let usableThreadId: string | undefined;\n\n const client = this.#accessors.getClient();\n const assistantId = this.#accessors.getAssistantId();\n\n return this.stream.start(\n async (signal) => {\n usableThreadId = this.#threadId;\n if (usableThreadId) {\n this.#threadIdStreaming = usableThreadId;\n }\n if (!usableThreadId) {\n const threadPromise = client.threads.create({\n threadId: submitOptions?.threadId,\n metadata: submitOptions?.metadata,\n });\n\n this.#threadIdPromise = threadPromise.then((t) => t.thread_id);\n\n const thread = await threadPromise;\n\n usableThreadId = thread.thread_id;\n this.#setThreadIdFromSubmit(usableThreadId);\n }\n\n const streamMode = unique([\n \"values\" as StreamMode,\n \"updates\" as StreamMode,\n ...(submitOptions?.streamMode ?? []),\n ...this.#trackedStreamModes,\n ...this.#callbackStreamModes,\n ]);\n\n this.stream.setStreamValues(() => {\n const prev = { ...this.historyValues, ...this.stream.values };\n\n if (submitOptions?.optimisticValues != null) {\n return {\n ...prev,\n ...(typeof submitOptions.optimisticValues === \"function\"\n ? submitOptions.optimisticValues(prev)\n : submitOptions.optimisticValues),\n };\n }\n\n return { ...prev };\n });\n\n const streamResumable =\n submitOptions?.streamResumable ?? !!this.#runMetadataStorage;\n\n return client.runs.stream(usableThreadId!, assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: submitOptions?.multitaskStrategy,\n onCompletion: submitOptions?.onCompletion,\n onDisconnect:\n submitOptions?.onDisconnect ??\n (streamResumable ? \"continue\" : \"cancel\"),\n\n signal,\n\n checkpoint,\n streamMode,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n streamResumable,\n durability: submitOptions?.durability,\n onRunCreated: (params) => {\n callbackMeta = {\n run_id: params.run_id,\n thread_id: params.thread_id ?? usableThreadId!,\n };\n\n if (this.#runMetadataStorage) {\n rejoinKey = `lg:stream:${usableThreadId}`;\n this.#runMetadataStorage.setItem(rejoinKey, callbackMeta.run_id);\n }\n\n this.#options.onCreated?.(callbackMeta);\n },\n }) as AsyncGenerator<\n EventStreamEvent<StateType, UpdateType, CustomType>\n >;\n },\n {\n getMessages: (value: StateType) => this.#getMessages(value),\n setMessages: (current: StateType, messages: Message[]) =>\n this.#setMessages(current, messages),\n initialValues: this.historyValues,\n callbacks: this.#options,\n\n onSuccess: async () => {\n if (rejoinKey) this.#runMetadataStorage?.removeItem(rejoinKey);\n\n if (shouldRefetch && usableThreadId) {\n const newHistory = await this.#mutate(usableThreadId);\n const lastHead = newHistory?.at(0);\n if (lastHead) {\n this.#options.onFinish?.(lastHead, callbackMeta);\n return null;\n }\n } else if (\n this.#options.onFinish != null &&\n !onFinishRequiresThreadState(this.#options.onFinish)\n ) {\n this.#options.onFinish(\n undefined as unknown as ThreadState<StateType>,\n callbackMeta\n );\n }\n return undefined;\n },\n onError: (error) => {\n this.#options.onError?.(error, callbackMeta);\n submitOptions?.onError?.(error, callbackMeta);\n },\n onFinish: () => {\n this.#threadIdStreaming = null;\n },\n }\n );\n }\n\n #drainQueue(): void {\n if (!this.isLoading && !this.#submitting && this.pendingRuns.size > 0) {\n const next = this.pendingRuns.shift();\n if (next) {\n this.#submitting = true;\n void this.joinStream(next.id).finally(() => {\n this.#submitting = false;\n this.#drainQueue();\n });\n }\n }\n }\n\n /**\n * Trigger queue draining. Framework adapters should call this\n * when isLoading or queue size changes.\n */\n drainQueue(): void {\n this.#drainQueue();\n }\n\n /**\n * Submit input values with automatic queue management. If a stream is\n * already active, the run is enqueued (unless the multitask strategy\n * is `\"interrupt\"` or `\"rollback\"`, in which case the current run is\n * replaced). Queued runs are drained sequentially via {@link drainQueue}.\n *\n * @param values - The state values to send as run input.\n * @param submitOptions - Optional configuration for the run.\n * @returns The result of {@link submitDirect} if the run was started\n * immediately, or `void` if the run was enqueued.\n */\n async submit(\n values: StateType,\n submitOptions?: SubmitOptions<StateType, GetConfigurableType<Bag>>\n ): Promise<ReturnType<typeof this.submitDirect> | void> {\n if (this.stream.isLoading || this.#submitting) {\n const shouldAbort =\n submitOptions?.multitaskStrategy === \"interrupt\" ||\n submitOptions?.multitaskStrategy === \"rollback\";\n\n if (shouldAbort) {\n this.#submitting = true;\n try {\n await this.submitDirect(values, submitOptions);\n } finally {\n this.#submitting = false;\n }\n return;\n }\n\n let usableThreadId: string | undefined = this.#threadId;\n if (!usableThreadId && this.#threadIdPromise) {\n usableThreadId = await this.#threadIdPromise;\n }\n if (usableThreadId) {\n const client = this.#accessors.getClient();\n const assistantId = this.#accessors.getAssistantId();\n try {\n const run = await client.runs.create(usableThreadId, assistantId, {\n input: values as Record<string, unknown>,\n config: submitOptions?.config,\n context: submitOptions?.context,\n command: submitOptions?.command,\n interruptBefore: submitOptions?.interruptBefore,\n interruptAfter: submitOptions?.interruptAfter,\n metadata: submitOptions?.metadata,\n multitaskStrategy: \"enqueue\",\n streamResumable: true,\n streamSubgraphs: submitOptions?.streamSubgraphs,\n durability: submitOptions?.durability,\n });\n\n this.pendingRuns.add({\n id: run.run_id,\n values: values as Partial<StateType> | null | undefined,\n options: submitOptions,\n createdAt: new Date(run.created_at),\n });\n } catch (error) {\n this.#options.onError?.(error, undefined);\n submitOptions?.onError?.(error, undefined);\n }\n return;\n }\n }\n\n this.#submitting = true;\n const result = this.submitDirect(values, submitOptions);\n void Promise.resolve(result).finally(() => {\n this.#submitting = false;\n this.#drainQueue();\n });\n return result;\n }\n\n /**\n * Switch to a different thread (or clear the current thread).\n * Clears the active stream, cancels all queued runs on the previous\n * thread, fetches history for the new thread, and notifies the\n * {@link AnyStreamOptions.onThreadId | onThreadId} callback.\n *\n * @param newThreadId - The thread ID to switch to, or `null` to clear.\n */\n switchThread(newThreadId: string | null): void {\n const current = this.#threadId ?? null;\n if (newThreadId !== current) {\n const prevThreadId = this.#threadId;\n this.#threadId = newThreadId ?? undefined;\n this.#handledHeadlessToolInterruptIds.clear();\n this.stream.clear();\n\n const removed = this.pendingRuns.removeAll();\n if (prevThreadId && removed.length > 0) {\n const client = this.#accessors.getClient();\n void Promise.all(\n removed.map((e) => client.runs.cancel(prevThreadId, e.id))\n );\n }\n\n this.#fetchHistoryForThread(this.#threadId);\n\n if (newThreadId != null) {\n this.#options.onThreadId?.(newThreadId);\n }\n\n this.#notify();\n }\n }\n\n /**\n * Attempt to reconnect to a previously running stream.\n * Returns true if a reconnection was initiated.\n */\n tryReconnect(): boolean {\n if (this.#runMetadataStorage && this.#threadId) {\n const runId = this.#runMetadataStorage.getItem(\n `lg:stream:${this.#threadId}`\n );\n if (runId) {\n void this.joinStream(runId);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Whether reconnect-on-mount behaviour is enabled (i.e. run metadata\n * storage is available).\n */\n get shouldReconnect(): boolean {\n return !!this.#runMetadataStorage;\n }\n\n /**\n * Tear down the orchestrator: stop the active stream, remove all\n * internal subscriptions, and mark the instance as disposed.\n * After calling this method, the orchestrator should not be reused.\n */\n dispose(): void {\n this.#disposed = true;\n this.#streamUnsub?.();\n this.#queueUnsub?.();\n this.#streamUnsub = null;\n this.#queueUnsub = null;\n void this.stop().catch(() => undefined);\n }\n\n #flushPendingHeadlessToolInterrupts(\n values: Record<string, unknown> | null | undefined\n ): void {\n flushPendingHeadlessToolInterrupts(\n values,\n this.#options.tools,\n this.#handledHeadlessToolInterruptIds,\n {\n onTool: this.#options.onTool,\n defer: (run) => {\n void Promise.resolve().then(run);\n },\n resumeSubmit: (command) =>\n void this.submit(null as unknown as StateType, {\n multitaskStrategy: \"interrupt\",\n command,\n }),\n }\n );\n }\n}\n"],"mappings":"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"}