@langchain/langgraph-sdk 1.12.3 → 1.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/stream/handles/subagents.cjs +9 -2
- package/dist/client/stream/handles/subagents.cjs.map +1 -1
- package/dist/client/stream/handles/subagents.d.cts.map +1 -1
- package/dist/client/stream/handles/subagents.d.ts.map +1 -1
- package/dist/client/stream/handles/subagents.js +10 -3
- package/dist/client/stream/handles/subagents.js.map +1 -1
- package/dist/client/stream/handles/subgraphs.cjs +24 -2
- package/dist/client/stream/handles/subgraphs.cjs.map +1 -1
- package/dist/client/stream/handles/subgraphs.d.cts.map +1 -1
- package/dist/client/stream/handles/subgraphs.d.ts.map +1 -1
- package/dist/client/stream/handles/subgraphs.js +24 -3
- package/dist/client/stream/handles/subgraphs.js.map +1 -1
- package/dist/client/stream/index.cjs +17 -7
- package/dist/client/stream/index.cjs.map +1 -1
- package/dist/client/stream/index.d.cts.map +1 -1
- package/dist/client/stream/index.d.ts.map +1 -1
- package/dist/client/stream/index.js +17 -7
- package/dist/client/stream/index.js.map +1 -1
- package/dist/client/stream/messages.cjs +43 -0
- package/dist/client/stream/messages.cjs.map +1 -1
- package/dist/client/stream/messages.d.cts +8 -0
- package/dist/client/stream/messages.d.cts.map +1 -1
- package/dist/client/stream/messages.d.ts +8 -0
- package/dist/client/stream/messages.d.ts.map +1 -1
- package/dist/client/stream/messages.js +43 -0
- package/dist/client/stream/messages.js.map +1 -1
- package/dist/client/stream/transport/http.cjs +1 -12
- package/dist/client/stream/transport/http.cjs.map +1 -1
- package/dist/client/stream/transport/http.d.cts.map +1 -1
- package/dist/client/stream/transport/http.d.ts.map +1 -1
- package/dist/client/stream/transport/http.js +1 -12
- package/dist/client/stream/transport/http.js.map +1 -1
- package/dist/client/stream/transport/utils.cjs +12 -0
- package/dist/client/stream/transport/utils.cjs.map +1 -1
- package/dist/client/stream/transport/utils.js +12 -1
- package/dist/client/stream/transport/utils.js.map +1 -1
- package/dist/client/stream/transport/websocket.cjs +33 -3
- package/dist/client/stream/transport/websocket.cjs.map +1 -1
- package/dist/client/stream/transport/websocket.d.cts +4 -1
- package/dist/client/stream/transport/websocket.d.cts.map +1 -1
- package/dist/client/stream/transport/websocket.d.ts +4 -1
- package/dist/client/stream/transport/websocket.d.ts.map +1 -1
- package/dist/client/stream/transport/websocket.js +34 -4
- package/dist/client/stream/transport/websocket.js.map +1 -1
- package/dist/stream/controller.cjs +94 -3
- package/dist/stream/controller.cjs.map +1 -1
- package/dist/stream/controller.d.cts.map +1 -1
- package/dist/stream/controller.d.ts.map +1 -1
- package/dist/stream/controller.js +94 -3
- package/dist/stream/controller.js.map +1 -1
- package/dist/stream/discovery/namespace-from-history.cjs +1 -1
- package/dist/stream/discovery/namespace-from-history.cjs.map +1 -1
- package/dist/stream/discovery/namespace-from-history.js +1 -1
- package/dist/stream/discovery/namespace-from-history.js.map +1 -1
- package/dist/stream/lifecycle-loading-tracker.cjs +5 -0
- package/dist/stream/lifecycle-loading-tracker.cjs.map +1 -1
- package/dist/stream/lifecycle-loading-tracker.js +5 -0
- package/dist/stream/lifecycle-loading-tracker.js.map +1 -1
- package/dist/stream/projections/messages.cjs +45 -12
- package/dist/stream/projections/messages.cjs.map +1 -1
- package/dist/stream/projections/messages.js +45 -12
- package/dist/stream/projections/messages.js.map +1 -1
- package/dist/stream/root-message-projection.cjs +71 -8
- package/dist/stream/root-message-projection.cjs.map +1 -1
- package/dist/stream/root-message-projection.js +71 -8
- package/dist/stream/root-message-projection.js.map +1 -1
- package/dist/stream/submit-coordinator.cjs +7 -2
- package/dist/stream/submit-coordinator.cjs.map +1 -1
- package/dist/stream/submit-coordinator.js +7 -2
- package/dist/stream/submit-coordinator.js.map +1 -1
- package/dist/ui/manager.cjs +1 -1
- package/dist/ui/manager.cjs.map +1 -1
- package/dist/ui/manager.d.cts.map +1 -1
- package/dist/ui/manager.d.ts.map +1 -1
- package/dist/ui/manager.js +1 -1
- package/dist/ui/manager.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-coordinator.js","names":["#options","#rootStore","#queueAdapter","#getDisposed","#getCurrentThreadId","#setCurrentThreadId","#rememberSelfCreatedThreadId","#isSelfCreatedThreadId","#forgetSelfCreatedThreadId","#hydrate","#ensureThread","#startDeferredRootPump","#abandonDeferredRootPump","#waitForRootPumpReady","#awaitNextTerminal","#awaitResumedRunTerminal","#onSubmitStart","#onRunStart","#onRunCreated","#onRunCompleted","#onRunEnd","#beginOptimistic","#settleOptimistic","uuidv7","#runAbort","#scheduleQueueDrain"],"sources":["../../src/stream/submit-coordinator.ts"],"sourcesContent":["/**\n * Owns the run-submission lifecycle for a single\n * {@link StreamController}.\n *\n * # What this module is\n *\n * The {@link SubmitCoordinator} is the piece of the controller that\n * dispatches runs (`submit()`), enforces multitask strategies, queues\n * deferred submissions, races dispatch against terminal lifecycle\n * events, and surfaces errors back through the per-submit `onError`\n * callback and the root snapshot.\n *\n * Conceptually a submit looks like:\n *\n * 1. Optionally rebind to a different thread (`options.threadId`).\n * 2. Mint a thread id if one isn't bound yet.\n * 3. Wait for the controller's root pump to be ready (so the\n * transport is subscribed before the run is dispatched —\n * otherwise we could miss replayed events).\n * 4. Apply the {@link StreamSubmitOptions.multitaskStrategy} to\n * decide whether to abort, enqueue, reject, or proceed.\n * 5. Race the dispatch promise (`thread.submitRun()`) against the next root\n * terminal lifecycle event.\n * 6. Settle the resulting state (loading flag, error slot) and\n * drain the next queued submission, if any.\n *\n * # Why it lives in its own class\n *\n * The submit lifecycle is the most state-heavy part of the\n * controller — six promises, an abort controller, a queue, a\n * terminal-vs-command race, and bidirectional callback wiring with\n * the controller. Splitting it out keeps `controller.ts` focused on\n * subscription / projection wiring while letting the submit logic\n * evolve independently.\n *\n * # Why we race \"command\" against \"terminal\"\n *\n * For fast runs, the server's terminal lifecycle event can arrive\n * *before* the dispatch HTTP response has resolved. Racing the two\n * lets us detect terminal early and not block waiting for a now-stale\n * dispatch response. The dispatch response is still consumed (via\n * `.then(notifyCreated).catch(reportError)`) so `onCreated` still\n * fires and dispatch errors still surface through `onError`.\n *\n * # Queue semantics (`multitaskStrategy: \"enqueue\"`)\n *\n * When a run is already in flight, an `\"enqueue\"` submit is delegated to\n * a {@link QueueAdapter} instead of being handled inline.\n * `SubmitCoordinator` only owns *which* adapter gets built and feeding\n * it a dispatch callback (`onIdle`) once the active run settles.\n *\n * @see StreamController - The owner; injects every collaborator dep.\n */\nimport { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport type { ThreadStream } from \"../client/stream/index.js\";\nimport { bindThreadConfig } from \"./dispatch-config.js\";\nimport {\n EMPTY_QUEUE,\n type QueueAdapter,\n type ServerQueueCapability,\n type SubmissionQueueEntry,\n type SubmissionQueueSnapshot,\n} from \"./queue-adapter.js\";\nimport { AgentServerQueueAdapter } from \"./queue-adapter-agent-server.js\";\nimport { LocalQueueAdapter } from \"./queue-adapter-local.js\";\nimport { StreamStore } from \"./store.js\";\nimport type { OptimisticHandle } from \"./optimistic-input.js\";\nimport type {\n RootSnapshot,\n RunExecutionReason,\n StreamControllerOptions,\n StreamSubmitOptions,\n} from \"./types.js\";\n\nexport { EMPTY_QUEUE };\nexport type { SubmissionQueueEntry, SubmissionQueueSnapshot };\n\n/**\n * Result of awaiting the next root terminal lifecycle event. Mirrors\n * the three terminal lifecycle states the protocol surfaces, plus a\n * synthetic `\"aborted\"` for client-side cancellation.\n */\ntype TerminalResult = {\n event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n error?: string;\n};\n\nfunction terminalReason(event: TerminalResult[\"event\"]): RunExecutionReason {\n if (event === \"completed\") return \"success\";\n if (event === \"failed\") return \"error\";\n if (event === \"interrupted\") return \"interrupt\";\n return \"stopped\";\n}\n\n/** Validates `client.runs`'s shape; throws rather than falling back to local. */\nfunction assertServerQueueCapability(\n value: unknown\n): asserts value is ServerQueueCapability {\n const ok =\n typeof value === \"object\" &&\n value != null &&\n typeof (value as ServerQueueCapability).create === \"function\" &&\n typeof (value as ServerQueueCapability).list === \"function\" &&\n typeof (value as ServerQueueCapability).cancel === \"function\";\n if (!ok) {\n throw new Error(\n 'queue: \"server\" requires client.runs to implement create/list/cancel'\n );\n }\n}\n\n/**\n * Coordinates one controller's run-submission lifecycle.\n *\n * The constructor takes a bag of callbacks rather than a reference to\n * the parent {@link StreamController} on purpose:\n *\n * - It keeps the dependency surface explicit and testable — every\n * piece of controller state the submit lifecycle touches is one\n * of these closures.\n * - It avoids a cyclic dependency between controller and coordinator.\n * - Tests can construct one with stub callbacks and assert behavior\n * without mocking the entire controller.\n *\n * @typeParam StateType - Root state shape.\n * @typeParam InterruptType - Root interrupt payload shape.\n * @typeParam ConfigurableType - `config.configurable` shape accepted\n * by submit (usually `Record<string, unknown>`).\n */\nexport class SubmitCoordinator<\n StateType extends object = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Controller-level options forwarded into `submitRun` / callbacks. */\n readonly #options: StreamControllerOptions<StateType>;\n /** Root snapshot store; written for `isLoading`, `error`, `interrupts`. */\n readonly #rootStore: StreamStore<RootSnapshot<StateType, InterruptType>>;\n /** Pending submissions awaiting the active run to terminate. */\n /** Backs `\"enqueue\"`: local-only defer, or real durable runs when `queue: \"server\"`. */\n readonly #queueAdapter: QueueAdapter<StateType>;\n /** Probes the controller's `disposed` flag from deferred work. */\n readonly #getDisposed: () => boolean;\n /** Reads the controller's currently-bound thread id. */\n readonly #getCurrentThreadId: () => string | null;\n /** Updates the controller's thread id (used when minting a new id). */\n readonly #setCurrentThreadId: (threadId: string | null) => void;\n /** Records a thread id we created client-side so hydrate can skip a 404 round-trip. */\n readonly #rememberSelfCreatedThreadId: (threadId: string) => void;\n /** True when the id is pending server-side create (minted or hydrate 404). */\n readonly #isSelfCreatedThreadId: (threadId: string) => boolean;\n /** Drops a thread id from the self-created set once it's committed server-side. */\n readonly #forgetSelfCreatedThreadId: (threadId: string) => void;\n /** Triggers a hydrate on the controller (used by `options.threadId` rebinds). */\n readonly #hydrate: (threadId?: string | null) => Promise<void>;\n /** Lazily creates / returns the active {@link ThreadStream}. */\n readonly #ensureThread: (\n threadId: string,\n deferRootPump?: boolean\n ) => ThreadStream;\n /** Starts the previously-deferred root pump after a self-created thread commits. */\n readonly #startDeferredRootPump: () => void;\n /** Abandons a deferred root pump after a self-created dispatch fails. */\n readonly #abandonDeferredRootPump: () => void;\n /** Resolves once the controller's root subscription pump is up. */\n readonly #waitForRootPumpReady: () => Promise<void> | undefined;\n /** Resolves on the next root terminal lifecycle (or on abort). */\n readonly #awaitNextTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n /**\n * Resolves on the resumed run's terminal, skipping stale `interrupted`\n * events from the run being resumed (see {@link dispatchResume}).\n */\n readonly #awaitResumedRunTerminal: (\n signal: AbortSignal\n ) => Promise<TerminalResult>;\n /** Called once at the start of every {@link submit} invocation. */\n readonly #onSubmitStart: () => void;\n /** Marks that a local run dispatch is now active. */\n readonly #onRunStart: () => void;\n /** Records a server-accepted local run id and fires `onCreated`. */\n readonly #onRunCreated: (runId: string) => void;\n /** Fires `onCompleted` for the local run lifecycle. */\n readonly #onRunCompleted: (\n reason: RunExecutionReason,\n runId?: string\n ) => void;\n /** Marks the local run dispatch lifecycle as settled. */\n readonly #onRunEnd: () => void;\n /**\n * Apply a submit input optimistically before dispatch. Returns the\n * id-injected payload to dispatch plus a handle for terminal\n * reconciliation, or `undefined` when optimistic UI is disabled / no\n * echo applies (dispatch the raw input).\n */\n readonly #beginOptimistic: (\n input: unknown\n ) => { dispatchInput: unknown; handle: OptimisticHandle } | undefined;\n /** Reconcile optimistic state when a run terminates. */\n readonly #settleOptimistic: (\n handle: OptimisticHandle,\n event: TerminalResult[\"event\"]\n ) => void;\n\n /**\n * Active submission's abort controller. `undefined` between submits.\n *\n * Used both for `multitaskStrategy: \"rollback\"` (abort the previous\n * controller's signal) and `stop()` (abort the current one without\n * starting a new one).\n */\n #runAbort: AbortController | undefined;\n\n constructor(params: {\n options: StreamControllerOptions<StateType>;\n rootStore: StreamStore<RootSnapshot<StateType, InterruptType>>;\n queueStore: StreamStore<SubmissionQueueSnapshot<StateType>>;\n getDisposed: () => boolean;\n getCurrentThreadId: () => string | null;\n setCurrentThreadId: (threadId: string | null) => void;\n rememberSelfCreatedThreadId: (threadId: string) => void;\n isSelfCreatedThreadId: (threadId: string) => boolean;\n forgetSelfCreatedThreadId: (threadId: string) => void;\n hydrate: (threadId?: string | null) => Promise<void>;\n ensureThread: (threadId: string, deferRootPump?: boolean) => ThreadStream;\n startDeferredRootPump: () => void;\n abandonDeferredRootPump: () => void;\n waitForRootPumpReady: () => Promise<void> | undefined;\n awaitNextTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n awaitResumedRunTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n onSubmitStart?: () => void;\n onRunStart?: () => void;\n onRunCreated?: (runId: string) => void;\n onRunCompleted?: (reason: RunExecutionReason, runId?: string) => void;\n onRunEnd?: () => void;\n beginOptimistic?: (\n input: unknown\n ) => { dispatchInput: unknown; handle: OptimisticHandle } | undefined;\n settleOptimistic?: (\n handle: OptimisticHandle,\n event: TerminalResult[\"event\"]\n ) => void;\n }) {\n this.#options = params.options;\n this.#rootStore = params.rootStore;\n const onQueueError = (error: unknown) => {\n this.#rootStore.setState((state) => ({ ...state, error }));\n };\n // Custom transports don't get server-backed queueing at all: there's\n // nowhere on `AgentServerAdapter` to declare the capability. Chosen\n // once, here, for this coordinator's lifetime and never re-evaluated.\n const serverQueueEnabled =\n typeof params.options.transport !== \"object\" &&\n params.options.queue === \"server\";\n if (serverQueueEnabled) {\n assertServerQueueCapability(params.options.client.runs);\n }\n this.#queueAdapter = serverQueueEnabled\n ? new AgentServerQueueAdapter(\n params.options.client.runs,\n params.options.assistantId,\n params.queueStore,\n onQueueError,\n (threadId) => params.ensureThread(threadId, true) // deferRootPump: true, watching shouldn't force-start a root pump\n )\n : new LocalQueueAdapter(params.queueStore, onQueueError);\n this.#getDisposed = params.getDisposed;\n this.#getCurrentThreadId = params.getCurrentThreadId;\n this.#setCurrentThreadId = params.setCurrentThreadId;\n this.#rememberSelfCreatedThreadId = params.rememberSelfCreatedThreadId;\n this.#isSelfCreatedThreadId = params.isSelfCreatedThreadId;\n this.#forgetSelfCreatedThreadId = params.forgetSelfCreatedThreadId;\n this.#hydrate = params.hydrate;\n this.#ensureThread = params.ensureThread;\n this.#startDeferredRootPump = params.startDeferredRootPump;\n this.#abandonDeferredRootPump = params.abandonDeferredRootPump;\n this.#waitForRootPumpReady = params.waitForRootPumpReady;\n this.#awaitNextTerminal = params.awaitNextTerminal;\n this.#awaitResumedRunTerminal = params.awaitResumedRunTerminal;\n this.#onSubmitStart = params.onSubmitStart ?? (() => undefined);\n this.#onRunStart = params.onRunStart ?? (() => undefined);\n this.#onRunCreated = params.onRunCreated ?? (() => undefined);\n this.#onRunCompleted = params.onRunCompleted ?? (() => undefined);\n this.#onRunEnd = params.onRunEnd ?? (() => undefined);\n this.#beginOptimistic = params.beginOptimistic ?? (() => undefined);\n this.#settleOptimistic = params.settleOptimistic ?? (() => undefined);\n }\n\n /**\n * Submit input to the active thread.\n *\n * Honours {@link StreamSubmitOptions.multitaskStrategy}:\n *\n * - `\"rollback\"` (default): aborts any in-flight run and\n * dispatches immediately.\n * - `\"reject\"`: throws synchronously when a run is\n * already in flight.\n * - `\"enqueue\"`: defers via {@link QueueAdapter.enqueue};\n * resolves once accepted (durably, if server-backed), not on completion.\n * - `\"interrupt\"`: falls through to the default path\n *\n * Errors are routed through both the per-submit `onError` callback\n * and `rootStore.error`. Aborts (controller dispose / rollback) are\n * silently dropped.\n *\n * To resume a pending interrupt, use {@link StreamController.respond}\n * instead of `submit()`.\n *\n * @param input - Input payload for the run.\n * @param options - Per-submit options (config, metadata, callbacks,\n * strategy, etc).\n */\n async submit(\n input: unknown,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void> {\n if (this.#getDisposed()) return;\n\n // Per-submit thread override: rebind first so the rest of the\n // submit operates against the new thread.\n const overrideThreadId = options?.threadId;\n if (\n overrideThreadId !== undefined &&\n overrideThreadId !== this.#getCurrentThreadId()\n ) {\n await this.#hydrate(overrideThreadId);\n }\n\n // Self-created thread id path: mint client-side so the controller\n // (and Suspense boundaries) get a stable id even before the run\n // is dispatched.\n const wasSelfCreated = this.#getCurrentThreadId() == null;\n if (wasSelfCreated) {\n const threadId = uuidv7();\n this.#setCurrentThreadId(threadId);\n this.#rememberSelfCreatedThreadId(threadId);\n this.#options.onThreadId?.(threadId);\n this.#rootStore.setState((s) => ({\n ...s,\n threadId,\n }));\n }\n\n const currentThreadId = this.#getCurrentThreadId();\n if (currentThreadId == null) return;\n // For threads that don't exist server-side yet (just minted here,\n // or an externally-minted id that hydrate marked missing via 404)\n // we defer the persistent root SSE pump until after `submitRun` /\n // `respondInput` commits the thread. Opening the pump's\n // `subscription.subscribe` against a not-yet-existent thread row\n // either 404s or — on langgraph_api's in-mem runtime — joins a\n // dead subscription that delivers 0 bytes until idle reconnect.\n // The deferred path starts the pump after dispatch returns (see\n // `#startDeferredRootPump` calls below).\n const pendingServerCreate =\n wasSelfCreated || this.#isSelfCreatedThreadId(currentThreadId);\n const thread = this.#ensureThread(currentThreadId, pendingServerCreate);\n const activeThreadId = currentThreadId;\n\n const strategy = options?.multitaskStrategy ?? \"rollback\";\n // `wasSelfCreated` short-circuit: when this submit just minted a\n // brand-new thread id (the user clicked \"New Thread\"), the\n // strategy check shouldn't see a run on the *previous* thread as\n // a reason to enqueue. The previous run is on a thread the user\n // navigated away from; abandoning its client-side abort tracking\n // is correct (the server-side run continues independently).\n // Without this, `enqueue` would trap the new submission and\n // `submitRun` never fires for the new thread — leaving a freshly-\n // minted thread id committed to the URL but never to the server.\n // True for a run this client dispatched (#runAbort) or one it only\n // observed via the persistent lifecycle listener (started elsewhere —\n // another tab, a webhook, Slack).\n const hasActiveRun =\n !wasSelfCreated &&\n ((this.#runAbort != null && !this.#runAbort.signal.aborted) ||\n this.#rootStore.getSnapshot().isLoading);\n if (hasActiveRun && strategy === \"reject\") {\n throw new Error(\n \"submit() rejected: a run is already in flight and multitaskStrategy is 'reject'.\"\n );\n }\n if (hasActiveRun && strategy === \"enqueue\") {\n try {\n await this.#queueAdapter.enqueue(\n currentThreadId,\n (input ?? undefined) as Partial<StateType> | null | undefined,\n // QueueAdapter is generic only over StateType, not ConfigurableType.\n options as StreamSubmitOptions<StateType> | undefined\n );\n } catch (error) {\n // Already routed to rootStore.error by the adapter; must not reject.\n try {\n options?.onError?.(error);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n }\n return;\n }\n\n // Only once this submit will actually dispatch a command. Enqueue /\n // reject return above so they cannot reset the in-flight run's\n // interrupt replay barrier or drop events buffered for it.\n this.#onSubmitStart();\n\n // Rollback: abort the previous run before starting a new one.\n this.#runAbort?.abort();\n const abort = new AbortController();\n this.#runAbort = abort;\n\n // Claim the in-flight slot before awaiting the root pump so\n // concurrent `enqueue` submits in the same tick observe\n // `hasActiveRun` and land in {@link queueStore}.\n this.#rootStore.setState((s) => ({\n ...s,\n interrupts: [],\n interrupt: undefined,\n error: undefined,\n isLoading: true,\n }));\n\n // Declared before the try so the catch/finally can settle the\n // submit lifecycle (loading flag, abort slot, optimistic state)\n // even if optimistic preparation or the pump wait throws.\n let optimisticHandle: OptimisticHandle | undefined;\n let dispatchInput: unknown = input;\n let createdRunId: string | undefined;\n let pendingCompletionReason: RunExecutionReason | undefined;\n let completionNotified = false;\n let settleEvent: TerminalResult[\"event\"] | undefined;\n const notifyCompletion = (reason: RunExecutionReason): void => {\n if (completionNotified) return;\n if (createdRunId == null) {\n pendingCompletionReason = reason;\n return;\n }\n completionNotified = true;\n this.#onRunCompleted(reason, createdRunId);\n };\n const reportError = (error: unknown): void => {\n if (abort.signal.aborted) return;\n this.#rootStore.setState((s) => ({ ...s, error }));\n try {\n options?.onError?.(error);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n };\n\n try {\n // Apply the input optimistically *before* the first await so the\n // user's message (and any merged state) paints without waiting for\n // the server round-trip. Kept as the first statement in the try so\n // the synchronous paint still precedes the first `await`, while a\n // synchronous coercion failure (e.g. a malformed message entry)\n // settles the submit lifecycle through the catch/finally below —\n // exactly like a dispatch failure — instead of wedging `isLoading`\n // / `#runAbort` and stranding later enqueue/reject submits behind a\n // phantom in-flight run. Runs only on the dispatched path — an\n // `\"enqueue\"`d submission returns above and echoes when it drains,\n // keeping one optimistic batch bound to exactly one run lifecycle.\n // `dispatchInput` carries the minted ids the server must echo for\n // reconciliation, so the run is dispatched with it (not raw input).\n const prepared = this.#beginOptimistic(input);\n if (prepared != null) {\n optimisticHandle = prepared.handle;\n dispatchInput = prepared.dispatchInput;\n }\n\n // Wait for the root subscription to be live; otherwise the\n // dispatch could resolve before we're listening for events and\n // we'd miss the terminal that ends the run.\n await this.#waitForRootPumpReady();\n\n const boundConfig = bindThreadConfig(options?.config, currentThreadId);\n // Subscribe to the next terminal *before* dispatching so a fast\n // run's terminal can't race us.\n const terminalPromise = this.#awaitNextTerminal(abort.signal);\n this.#onRunStart();\n\n let terminalSettled = false;\n let terminal: TerminalResult | undefined;\n\n const commandPromise = thread.submitRun({\n input: dispatchInput ?? null,\n config: boundConfig,\n metadata: (options?.metadata ?? undefined) as Record<string, unknown>,\n forkFrom: options?.forkFrom,\n multitaskStrategy:\n options?.multitaskStrategy === \"enqueue\"\n ? \"enqueue\"\n : options?.multitaskStrategy,\n });\n // Start the deferred root pump *after* the dispatch HTTP\n // response lands — that's when the thread row exists server-\n // side. Doing it synchronously here would race the response\n // and the pump's `subscription.subscribe` would 404. Same\n // reason we drop the self-created flag only after dispatch:\n // future hydrates need the thread to exist before they fetch\n // state.\n //\n // Fire-and-forget: we don't want to gate Promise.race on this,\n // and `commandPromise.catch` is already handled below. A\n // dispatch failure means there's no thread to pump anyway.\n void commandPromise.then(\n () => {\n this.#startDeferredRootPump();\n this.#forgetSelfCreatedThreadId(activeThreadId);\n },\n () => {\n // Dispatch failed. Without abandoning, `#rootPumpDeferred`\n // stays armed and `selfCreatedThreadIds` still holds this\n // id — a retry submit would see `pendingServerCreate=true`\n // again but `#ensureThread` would early-return because\n // `#thread != null`, and the root pump would never start.\n // Tear down so the next submit re-runs `#ensureThread`\n // from scratch. Keep the self-created mark so the retry\n // still defers the pump (the server row was never created).\n if (pendingServerCreate) {\n this.#abandonDeferredRootPump();\n }\n }\n );\n const notifyCreated = (result: { run_id?: unknown }) => {\n if (typeof result.run_id !== \"string\") return;\n createdRunId = result.run_id;\n this.#onRunCreated(createdRunId);\n if (pendingCompletionReason != null) {\n notifyCompletion(pendingCompletionReason);\n }\n };\n const first = await Promise.race([\n terminalPromise.then((value) => ({\n type: \"terminal\" as const,\n value,\n })),\n commandPromise.then(\n (result) => ({ type: \"command\" as const, result }),\n (error) => ({ type: \"error\" as const, error })\n ),\n ]);\n if (first.type === \"error\") throw first.error;\n if (first.type === \"command\") {\n notifyCreated(first.result);\n } else {\n // Terminal landed first (very fast runs). Wait for the\n // dispatch response in the background so onCreated fires\n // and dispatch errors still surface.\n terminal = first.value;\n terminalSettled = true;\n void commandPromise.then(notifyCreated).catch((error) => {\n if (!terminalSettled) reportError(error);\n });\n }\n\n terminal ??= await terminalPromise;\n terminalSettled = true;\n settleEvent = terminal.event;\n if (terminal.event === \"failed\" && !abort.signal.aborted) {\n const runError = new Error(\n terminal.error ?? \"Run failed with no error message\"\n );\n this.#rootStore.setState((s) => ({ ...s, error: runError }));\n try {\n options?.onError?.(runError);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n }\n notifyCompletion(terminalReason(terminal.event));\n } catch (error) {\n if (!abort.signal.aborted) settleEvent = \"failed\";\n reportError(error);\n } finally {\n // Always settle loading and clear our slot of the abort\n // controller. Schedule queue drain on the next macrotask so any\n // late state updates from this run finish flushing first.\n this.#rootStore.setState((s) => ({ ...s, isLoading: false }));\n if (this.#runAbort === abort) this.#runAbort = undefined;\n // Reconcile optimistic state: flip pending messages to sent/failed\n // and roll back un-echoed non-message keys. `aborted` covers a\n // rollback-resubmit or `stop()` cancelling this run.\n if (optimisticHandle != null) {\n this.#settleOptimistic(\n optimisticHandle,\n abort.signal.aborted ? \"aborted\" : (settleEvent ?? \"failed\")\n );\n }\n this.#onRunEnd();\n this.#scheduleQueueDrain();\n }\n }\n\n /**\n * Schedules a queue-drain attempt on the next macrotask, once the\n * just-finished run's state has flushed. A no-op unless the queue\n * adapter is idle-driven (see {@link QueueAdapter.onIdle}) and no\n * other run is active.\n */\n #scheduleQueueDrain(): void {\n setTimeout(() => {\n if (this.#getDisposed()) return;\n if (this.#runAbort != null && !this.#runAbort.signal.aborted) return;\n if (this.#rootStore.getSnapshot().isLoading) return;\n\n this.#queueAdapter.onIdle?.((values, drainOptions) =>\n this.submit(\n values,\n drainOptions as StreamSubmitOptions<StateType, ConfigurableType>\n ).catch(() => {\n /* submit() already routes errors through the per-submit onError\n * hook and the root store; swallow here so a failing drain does\n * not surface as an unhandled rejection. */\n })\n );\n }, 0);\n }\n\n /**\n * Surface a *resumed* run's failure the same way {@link submit} surfaces\n * a fresh run's failure — by writing it to the reactive\n * {@link RootSnapshot.error} slot.\n *\n * `respond()` / `respondAll()` dispatch their `input.respond` command on\n * the controller directly (they target a specific interrupt, so they\n * cannot go through {@link submit}, which only does `run.start`). The\n * resumed run therefore never passed through the submit lifecycle that\n * populates `rootStore.error` — only the persistent lifecycle listener\n * observed it, and that listener drives `isLoading` alone. Without this,\n * a resumed run that fails (e.g. a missing model key surfaced after the\n * user approves an interrupt) would flip `isLoading` back to `false`\n * with `error` left untouched, so `stream.error`-driven UIs (error\n * banners, API-key retry prompts) would silently miss it.\n *\n * The `dispatch` thunk is awaited, so a dispatch failure rejects the\n * caller's `respond()` *and* lands in `rootStore.error`. The resumed\n * run's terminal is watched in the **background** so the returned promise\n * still settles on dispatch — preserving the resume command's\n * resolve-on-dispatch contract (and avoiding a hang when no terminal is\n * ever emitted, e.g. in unit tests).\n *\n * Reuses the shared {@link #runAbort} slot, so `stop()`, `dispose()`, and\n * a rollback `submit()` all cancel the terminal watch (no spurious error\n * on user-initiated cancel) and treat the resumed run as the active run.\n *\n * The terminal watch uses {@link #awaitResumedRunTerminal}, which skips\n * stale `interrupted` terminals from the run being resumed (they can reach\n * the pump after `input.requested` but before `respondInput` calls\n * `#prepareForNextRun`) and only accepts a later `interrupted` once a\n * root `running` lifecycle for the resumed run has been observed.\n *\n * @param dispatch - Sends the `input.respond` command (and marks the\n * targeted interrupt resolved). Invoked after the terminal watch is\n * armed.\n * @param optimisticHandle - Optional handle from an optimistic `update`\n * applied before dispatch (HITL \"push card into state + resume\"). Settled\n * on the resumed run's terminal — pending messages flip to `sent` and\n * un-echoed non-message keys roll back on failure — exactly like the\n * `submit()` optimistic lifecycle. A dispatch failure settles it `failed`.\n */\n async dispatchResume(\n dispatch: () => Promise<void>,\n optimisticHandle?: OptimisticHandle\n ): Promise<void> {\n if (this.#getDisposed()) return;\n\n // Same allowlist clear as submit(): a resumed run can pause on a\n // *new* interrupt id. Without this, the hydrate-window allowlist\n // still contains only the interrupt being answered and\n // `#recordRootInterrupt` drops the follow-on `input.requested`.\n this.#onSubmitStart();\n\n // Rollback any run still tracked as active (mirrors submit()), then\n // claim the in-flight slot so stop()/dispose()/a concurrent submit\n // cancels the terminal watch armed below.\n this.#runAbort?.abort();\n const abort = new AbortController();\n this.#runAbort = abort;\n\n // Optimistically clear a stale error from a previous run, matching\n // submit()'s reset, so the resume starts from a clean error slot.\n this.#rootStore.setState((s) =>\n s.error === undefined ? s : { ...s, error: undefined }\n );\n\n const reportError = (error: unknown): void => {\n if (abort.signal.aborted) return;\n this.#rootStore.setState((s) => ({ ...s, error }));\n };\n\n // Settle the optimistic `update` exactly once, whether the resumed run\n // terminates (success/failure/interrupt) or the dispatch itself fails.\n let optimisticSettled = false;\n const settleOptimisticOnce = (event: TerminalResult[\"event\"]): void => {\n if (optimisticSettled || optimisticHandle == null) return;\n optimisticSettled = true;\n this.#settleOptimistic(optimisticHandle, event);\n };\n\n // Subscribe to the resumed run's terminal *before* dispatching so a fast\n // `failed` can't race us. Unlike `#awaitNextTerminal`, the resume watcher\n // ignores stale `interrupted` events until root `running` is seen.\n // Watched in the background — we never gate the returned promise on the\n // resumed run's terminal.\n const terminalPromise = this.#awaitResumedRunTerminal(abort.signal);\n void terminalPromise.then((terminal) => {\n if (this.#runAbort === abort) this.#runAbort = undefined;\n if (terminal.event === \"failed\" && !abort.signal.aborted) {\n reportError(\n new Error(terminal.error ?? \"Run failed with no error message\")\n );\n }\n settleOptimisticOnce(abort.signal.aborted ? \"aborted\" : terminal.event);\n // Drain any submission enqueued while the resumed run was active.\n this.#scheduleQueueDrain();\n });\n\n try {\n await dispatch();\n } catch (error) {\n // The `input.respond` send itself failed, before any run started.\n reportError(error);\n settleOptimisticOnce(\"failed\");\n if (this.#runAbort === abort) this.#runAbort = undefined;\n throw error;\n }\n }\n\n /**\n * Abort the current run (if any) and force `isLoading=false`.\n *\n * Client-side only — server-side cancel is handled by\n * {@link StreamController.stop} before this is invoked.\n */\n async stop(): Promise<void> {\n this.abortActiveRun();\n this.#rootStore.setState((s) => ({ ...s, isLoading: false }));\n }\n\n /**\n * Abort the current run without forcing the loading flag down.\n *\n * Used by {@link StreamController.dispose}: disposal already tears\n * down the root store, so flipping `isLoading` here is unnecessary\n * and would race the dispose path.\n */\n abortActiveRun(): void {\n this.#runAbort?.abort();\n this.#runAbort = undefined;\n }\n\n /**\n * Populate the queue from whatever the configured adapter considers\n * the source of truth. No-op for `LocalQueueAdapter`; for the\n * server-backed adapter this is what makes pending runs created\n * before this page load (or by another tab/session) show up.\n * Fire-and-forget from the caller's side: the adapter manages its\n * own staleness guard against a rapid, repeated call for a newer\n * thread.\n */\n async hydrateQueue(threadId: string): Promise<void> {\n await this.#queueAdapter.hydrate(threadId);\n }\n\n /**\n * Public entry point for {@link #scheduleQueueDrain}. Called by the\n * controller when `isLoading` settles to `false` for a run this\n * coordinator never dispatched itself.\n */\n scheduleQueueDrainOnObservedIdle(): void {\n this.#scheduleQueueDrain();\n }\n\n /**\n * Cancel a queued submission by id.\n *\n * @param id - Client-side queue entry id to remove.\n * @returns `true` when the entry was found and dropped, `false` otherwise.\n */\n async cancelQueued(id: string): Promise<boolean> {\n return this.#queueAdapter.cancel(id);\n }\n\n /**\n * Drop every queued submission. Cancels the underlying server-side\n * runs too when server-backed; see `AgentServerQueueAdapter.clear`.\n */\n async clearQueue(): Promise<void> {\n await this.#queueAdapter.clear();\n }\n\n /**\n * Release whatever the queue adapter is watching. Called by\n * {@link StreamController} on thread rebind and on dispose, alongside\n * its own reset of the (still directly-owned, reactive) queue store.\n */\n detachQueue(): void {\n this.#queueAdapter.detach();\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"submit-coordinator.js","names":["#options","#rootStore","#queueAdapter","#getDisposed","#getCurrentThreadId","#setCurrentThreadId","#rememberSelfCreatedThreadId","#isSelfCreatedThreadId","#forgetSelfCreatedThreadId","#hydrate","#ensureThread","#startDeferredRootPump","#abandonDeferredRootPump","#waitForRootPumpReady","#awaitNextTerminal","#awaitResumedRunTerminal","#onSubmitStart","#onRunStart","#onRunCreated","#onRunStartReturned","#onRunCompleted","#onRunEnd","#beginOptimistic","#settleOptimistic","uuidv7","#runAbort","#scheduleQueueDrain"],"sources":["../../src/stream/submit-coordinator.ts"],"sourcesContent":["/**\n * Owns the run-submission lifecycle for a single\n * {@link StreamController}.\n *\n * # What this module is\n *\n * The {@link SubmitCoordinator} is the piece of the controller that\n * dispatches runs (`submit()`), enforces multitask strategies, queues\n * deferred submissions, races dispatch against terminal lifecycle\n * events, and surfaces errors back through the per-submit `onError`\n * callback and the root snapshot.\n *\n * Conceptually a submit looks like:\n *\n * 1. Optionally rebind to a different thread (`options.threadId`).\n * 2. Mint a thread id if one isn't bound yet.\n * 3. Wait for the controller's root pump to be ready (so the\n * transport is subscribed before the run is dispatched —\n * otherwise we could miss replayed events).\n * 4. Apply the {@link StreamSubmitOptions.multitaskStrategy} to\n * decide whether to abort, enqueue, reject, or proceed.\n * 5. Race the dispatch promise (`thread.submitRun()`) against the next root\n * terminal lifecycle event.\n * 6. Settle the resulting state (loading flag, error slot) and\n * drain the next queued submission, if any.\n *\n * # Why it lives in its own class\n *\n * The submit lifecycle is the most state-heavy part of the\n * controller — six promises, an abort controller, a queue, a\n * terminal-vs-command race, and bidirectional callback wiring with\n * the controller. Splitting it out keeps `controller.ts` focused on\n * subscription / projection wiring while letting the submit logic\n * evolve independently.\n *\n * # Why we race \"command\" against \"terminal\"\n *\n * For fast runs, the server's terminal lifecycle event can arrive\n * *before* the dispatch HTTP response has resolved. Racing the two\n * lets us detect terminal early and not block waiting for a now-stale\n * dispatch response. The dispatch response is still consumed (via\n * `.then(notifyCreated).catch(reportError)`) so `onCreated` still\n * fires and dispatch errors still surface through `onError`.\n *\n * # Queue semantics (`multitaskStrategy: \"enqueue\"`)\n *\n * When a run is already in flight, an `\"enqueue\"` submit is delegated to\n * a {@link QueueAdapter} instead of being handled inline.\n * `SubmitCoordinator` only owns *which* adapter gets built and feeding\n * it a dispatch callback (`onIdle`) once the active run settles.\n *\n * @see StreamController - The owner; injects every collaborator dep.\n */\nimport { v7 as uuidv7 } from \"@langchain/core/utils/uuid\";\nimport type { ThreadStream } from \"../client/stream/index.js\";\nimport { bindThreadConfig } from \"./dispatch-config.js\";\nimport {\n EMPTY_QUEUE,\n type QueueAdapter,\n type ServerQueueCapability,\n type SubmissionQueueEntry,\n type SubmissionQueueSnapshot,\n} from \"./queue-adapter.js\";\nimport { AgentServerQueueAdapter } from \"./queue-adapter-agent-server.js\";\nimport { LocalQueueAdapter } from \"./queue-adapter-local.js\";\nimport { StreamStore } from \"./store.js\";\nimport type { OptimisticHandle } from \"./optimistic-input.js\";\nimport type {\n RootSnapshot,\n RunExecutionReason,\n StreamControllerOptions,\n StreamSubmitOptions,\n} from \"./types.js\";\n\nexport { EMPTY_QUEUE };\nexport type { SubmissionQueueEntry, SubmissionQueueSnapshot };\n\n/**\n * Result of awaiting the next root terminal lifecycle event. Mirrors\n * the three terminal lifecycle states the protocol surfaces, plus a\n * synthetic `\"aborted\"` for client-side cancellation.\n */\ntype TerminalResult = {\n event: \"completed\" | \"failed\" | \"interrupted\" | \"aborted\";\n error?: string;\n};\n\nfunction terminalReason(event: TerminalResult[\"event\"]): RunExecutionReason {\n if (event === \"completed\") return \"success\";\n if (event === \"failed\") return \"error\";\n if (event === \"interrupted\") return \"interrupt\";\n return \"stopped\";\n}\n\n/** Validates `client.runs`'s shape; throws rather than falling back to local. */\nfunction assertServerQueueCapability(\n value: unknown\n): asserts value is ServerQueueCapability {\n const ok =\n typeof value === \"object\" &&\n value != null &&\n typeof (value as ServerQueueCapability).create === \"function\" &&\n typeof (value as ServerQueueCapability).list === \"function\" &&\n typeof (value as ServerQueueCapability).cancel === \"function\";\n if (!ok) {\n throw new Error(\n 'queue: \"server\" requires client.runs to implement create/list/cancel'\n );\n }\n}\n\n/**\n * Coordinates one controller's run-submission lifecycle.\n *\n * The constructor takes a bag of callbacks rather than a reference to\n * the parent {@link StreamController} on purpose:\n *\n * - It keeps the dependency surface explicit and testable — every\n * piece of controller state the submit lifecycle touches is one\n * of these closures.\n * - It avoids a cyclic dependency between controller and coordinator.\n * - Tests can construct one with stub callbacks and assert behavior\n * without mocking the entire controller.\n *\n * @typeParam StateType - Root state shape.\n * @typeParam InterruptType - Root interrupt payload shape.\n * @typeParam ConfigurableType - `config.configurable` shape accepted\n * by submit (usually `Record<string, unknown>`).\n */\nexport class SubmitCoordinator<\n StateType extends object = Record<string, unknown>,\n InterruptType = unknown,\n ConfigurableType extends object = Record<string, unknown>,\n> {\n /** Controller-level options forwarded into `submitRun` / callbacks. */\n readonly #options: StreamControllerOptions<StateType>;\n /** Root snapshot store; written for `isLoading`, `error`, `interrupts`. */\n readonly #rootStore: StreamStore<RootSnapshot<StateType, InterruptType>>;\n /** Pending submissions awaiting the active run to terminate. */\n /** Backs `\"enqueue\"`: local-only defer, or real durable runs when `queue: \"server\"`. */\n readonly #queueAdapter: QueueAdapter<StateType>;\n /** Probes the controller's `disposed` flag from deferred work. */\n readonly #getDisposed: () => boolean;\n /** Reads the controller's currently-bound thread id. */\n readonly #getCurrentThreadId: () => string | null;\n /** Updates the controller's thread id (used when minting a new id). */\n readonly #setCurrentThreadId: (threadId: string | null) => void;\n /** Records a thread id we created client-side so hydrate can skip a 404 round-trip. */\n readonly #rememberSelfCreatedThreadId: (threadId: string) => void;\n /** True when the id is pending server-side create (minted or hydrate 404). */\n readonly #isSelfCreatedThreadId: (threadId: string) => boolean;\n /** Drops a thread id from the self-created set once it's committed server-side. */\n readonly #forgetSelfCreatedThreadId: (threadId: string) => void;\n /** Triggers a hydrate on the controller (used by `options.threadId` rebinds). */\n readonly #hydrate: (threadId?: string | null) => Promise<void>;\n /** Lazily creates / returns the active {@link ThreadStream}. */\n readonly #ensureThread: (\n threadId: string,\n deferRootPump?: boolean\n ) => ThreadStream;\n /** Starts the previously-deferred root pump after a self-created thread commits. */\n readonly #startDeferredRootPump: () => void;\n /** Abandons a deferred root pump after a self-created dispatch fails. */\n readonly #abandonDeferredRootPump: () => void;\n /** Resolves once the controller's root subscription pump is up. */\n readonly #waitForRootPumpReady: () => Promise<void> | undefined;\n /** Resolves on the next root terminal lifecycle (or on abort). */\n readonly #awaitNextTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n /**\n * Resolves on the resumed run's terminal, skipping stale `interrupted`\n * events from the run being resumed (see {@link dispatchResume}).\n */\n readonly #awaitResumedRunTerminal: (\n signal: AbortSignal\n ) => Promise<TerminalResult>;\n /** Called once at the start of every {@link submit} invocation. */\n readonly #onSubmitStart: () => void;\n /** Marks that a local run dispatch is now active. */\n readonly #onRunStart: () => void;\n /** Records a server-accepted local run id and fires `onCreated`. */\n readonly #onRunCreated: (runId: string) => void;\n /** `run.start` answered for the current submit, with or without a run id. */\n readonly #onRunStartReturned: (runId: string | undefined) => void;\n /** Fires `onCompleted` for the local run lifecycle. */\n readonly #onRunCompleted: (\n reason: RunExecutionReason,\n runId?: string\n ) => void;\n /** Marks the local run dispatch lifecycle as settled. */\n readonly #onRunEnd: () => void;\n /**\n * Apply a submit input optimistically before dispatch. Returns the\n * id-injected payload to dispatch plus a handle for terminal\n * reconciliation, or `undefined` when optimistic UI is disabled / no\n * echo applies (dispatch the raw input).\n */\n readonly #beginOptimistic: (\n input: unknown\n ) => { dispatchInput: unknown; handle: OptimisticHandle } | undefined;\n /** Reconcile optimistic state when a run terminates. */\n readonly #settleOptimistic: (\n handle: OptimisticHandle,\n event: TerminalResult[\"event\"]\n ) => void;\n\n /**\n * Active submission's abort controller. `undefined` between submits.\n *\n * Used both for `multitaskStrategy: \"rollback\"` (abort the previous\n * controller's signal) and `stop()` (abort the current one without\n * starting a new one).\n */\n #runAbort: AbortController | undefined;\n\n constructor(params: {\n options: StreamControllerOptions<StateType>;\n rootStore: StreamStore<RootSnapshot<StateType, InterruptType>>;\n queueStore: StreamStore<SubmissionQueueSnapshot<StateType>>;\n getDisposed: () => boolean;\n getCurrentThreadId: () => string | null;\n setCurrentThreadId: (threadId: string | null) => void;\n rememberSelfCreatedThreadId: (threadId: string) => void;\n isSelfCreatedThreadId: (threadId: string) => boolean;\n forgetSelfCreatedThreadId: (threadId: string) => void;\n hydrate: (threadId?: string | null) => Promise<void>;\n ensureThread: (threadId: string, deferRootPump?: boolean) => ThreadStream;\n startDeferredRootPump: () => void;\n abandonDeferredRootPump: () => void;\n waitForRootPumpReady: () => Promise<void> | undefined;\n awaitNextTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n awaitResumedRunTerminal: (signal: AbortSignal) => Promise<TerminalResult>;\n onSubmitStart?: () => void;\n onRunStart?: () => void;\n onRunCreated?: (runId: string) => void;\n onRunStartReturned?: (runId: string | undefined) => void;\n onRunCompleted?: (reason: RunExecutionReason, runId?: string) => void;\n onRunEnd?: () => void;\n beginOptimistic?: (\n input: unknown\n ) => { dispatchInput: unknown; handle: OptimisticHandle } | undefined;\n settleOptimistic?: (\n handle: OptimisticHandle,\n event: TerminalResult[\"event\"]\n ) => void;\n }) {\n this.#options = params.options;\n this.#rootStore = params.rootStore;\n const onQueueError = (error: unknown) => {\n this.#rootStore.setState((state) => ({ ...state, error }));\n };\n // Custom transports don't get server-backed queueing at all: there's\n // nowhere on `AgentServerAdapter` to declare the capability. Chosen\n // once, here, for this coordinator's lifetime and never re-evaluated.\n const serverQueueEnabled =\n typeof params.options.transport !== \"object\" &&\n params.options.queue === \"server\";\n if (serverQueueEnabled) {\n assertServerQueueCapability(params.options.client.runs);\n }\n this.#queueAdapter = serverQueueEnabled\n ? new AgentServerQueueAdapter(\n params.options.client.runs,\n params.options.assistantId,\n params.queueStore,\n onQueueError,\n (threadId) => params.ensureThread(threadId, true) // deferRootPump: true, watching shouldn't force-start a root pump\n )\n : new LocalQueueAdapter(params.queueStore, onQueueError);\n this.#getDisposed = params.getDisposed;\n this.#getCurrentThreadId = params.getCurrentThreadId;\n this.#setCurrentThreadId = params.setCurrentThreadId;\n this.#rememberSelfCreatedThreadId = params.rememberSelfCreatedThreadId;\n this.#isSelfCreatedThreadId = params.isSelfCreatedThreadId;\n this.#forgetSelfCreatedThreadId = params.forgetSelfCreatedThreadId;\n this.#hydrate = params.hydrate;\n this.#ensureThread = params.ensureThread;\n this.#startDeferredRootPump = params.startDeferredRootPump;\n this.#abandonDeferredRootPump = params.abandonDeferredRootPump;\n this.#waitForRootPumpReady = params.waitForRootPumpReady;\n this.#awaitNextTerminal = params.awaitNextTerminal;\n this.#awaitResumedRunTerminal = params.awaitResumedRunTerminal;\n this.#onSubmitStart = params.onSubmitStart ?? (() => undefined);\n this.#onRunStart = params.onRunStart ?? (() => undefined);\n this.#onRunCreated = params.onRunCreated ?? (() => undefined);\n this.#onRunStartReturned = params.onRunStartReturned ?? (() => undefined);\n this.#onRunCompleted = params.onRunCompleted ?? (() => undefined);\n this.#onRunEnd = params.onRunEnd ?? (() => undefined);\n this.#beginOptimistic = params.beginOptimistic ?? (() => undefined);\n this.#settleOptimistic = params.settleOptimistic ?? (() => undefined);\n }\n\n /**\n * Submit input to the active thread.\n *\n * Honours {@link StreamSubmitOptions.multitaskStrategy}:\n *\n * - `\"rollback\"` (default): aborts any in-flight run and\n * dispatches immediately.\n * - `\"reject\"`: throws synchronously when a run is\n * already in flight.\n * - `\"enqueue\"`: defers via {@link QueueAdapter.enqueue};\n * resolves once accepted (durably, if server-backed), not on completion.\n * - `\"interrupt\"`: falls through to the default path\n *\n * Errors are routed through both the per-submit `onError` callback\n * and `rootStore.error`. Aborts (controller dispose / rollback) are\n * silently dropped.\n *\n * To resume a pending interrupt, use {@link StreamController.respond}\n * instead of `submit()`.\n *\n * @param input - Input payload for the run.\n * @param options - Per-submit options (config, metadata, callbacks,\n * strategy, etc).\n */\n async submit(\n input: unknown,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): Promise<void> {\n if (this.#getDisposed()) return;\n\n // Per-submit thread override: rebind first so the rest of the\n // submit operates against the new thread.\n const overrideThreadId = options?.threadId;\n if (\n overrideThreadId !== undefined &&\n overrideThreadId !== this.#getCurrentThreadId()\n ) {\n await this.#hydrate(overrideThreadId);\n }\n\n // Self-created thread id path: mint client-side so the controller\n // (and Suspense boundaries) get a stable id even before the run\n // is dispatched.\n const wasSelfCreated = this.#getCurrentThreadId() == null;\n if (wasSelfCreated) {\n const threadId = uuidv7();\n this.#setCurrentThreadId(threadId);\n this.#rememberSelfCreatedThreadId(threadId);\n this.#options.onThreadId?.(threadId);\n this.#rootStore.setState((s) => ({\n ...s,\n threadId,\n }));\n }\n\n const currentThreadId = this.#getCurrentThreadId();\n if (currentThreadId == null) return;\n // For threads that don't exist server-side yet (just minted here,\n // or an externally-minted id that hydrate marked missing via 404)\n // we defer the persistent root SSE pump until after `submitRun` /\n // `respondInput` commits the thread. Opening the pump's\n // `subscription.subscribe` against a not-yet-existent thread row\n // either 404s or — on langgraph_api's in-mem runtime — joins a\n // dead subscription that delivers 0 bytes until idle reconnect.\n // The deferred path starts the pump after dispatch returns (see\n // `#startDeferredRootPump` calls below).\n const pendingServerCreate =\n wasSelfCreated || this.#isSelfCreatedThreadId(currentThreadId);\n const thread = this.#ensureThread(currentThreadId, pendingServerCreate);\n const activeThreadId = currentThreadId;\n\n const strategy = options?.multitaskStrategy ?? \"rollback\";\n // `wasSelfCreated` short-circuit: when this submit just minted a\n // brand-new thread id (the user clicked \"New Thread\"), the\n // strategy check shouldn't see a run on the *previous* thread as\n // a reason to enqueue. The previous run is on a thread the user\n // navigated away from; abandoning its client-side abort tracking\n // is correct (the server-side run continues independently).\n // Without this, `enqueue` would trap the new submission and\n // `submitRun` never fires for the new thread — leaving a freshly-\n // minted thread id committed to the URL but never to the server.\n // True for a run this client dispatched (#runAbort) or one it only\n // observed via the persistent lifecycle listener (started elsewhere —\n // another tab, a webhook, Slack).\n const hasActiveRun =\n !wasSelfCreated &&\n ((this.#runAbort != null && !this.#runAbort.signal.aborted) ||\n this.#rootStore.getSnapshot().isLoading);\n if (hasActiveRun && strategy === \"reject\") {\n throw new Error(\n \"submit() rejected: a run is already in flight and multitaskStrategy is 'reject'.\"\n );\n }\n if (hasActiveRun && strategy === \"enqueue\") {\n try {\n await this.#queueAdapter.enqueue(\n currentThreadId,\n (input ?? undefined) as Partial<StateType> | null | undefined,\n // QueueAdapter is generic only over StateType, not ConfigurableType.\n options as StreamSubmitOptions<StateType> | undefined\n );\n } catch (error) {\n // Already routed to rootStore.error by the adapter; must not reject.\n try {\n options?.onError?.(error);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n }\n return;\n }\n\n // Only once this submit will actually dispatch a command. Enqueue /\n // reject return above so they cannot reset the in-flight run's\n // interrupt replay barrier or drop events buffered for it.\n this.#onSubmitStart();\n\n // Rollback: abort the previous run before starting a new one.\n this.#runAbort?.abort();\n const abort = new AbortController();\n this.#runAbort = abort;\n\n // Claim the in-flight slot before awaiting the root pump so\n // concurrent `enqueue` submits in the same tick observe\n // `hasActiveRun` and land in {@link queueStore}.\n this.#rootStore.setState((s) => ({\n ...s,\n interrupts: [],\n interrupt: undefined,\n error: undefined,\n isLoading: true,\n }));\n\n // Declared before the try so the catch/finally can settle the\n // submit lifecycle (loading flag, abort slot, optimistic state)\n // even if optimistic preparation or the pump wait throws.\n let optimisticHandle: OptimisticHandle | undefined;\n let dispatchInput: unknown = input;\n let createdRunId: string | undefined;\n let pendingCompletionReason: RunExecutionReason | undefined;\n let completionNotified = false;\n let settleEvent: TerminalResult[\"event\"] | undefined;\n const notifyCompletion = (reason: RunExecutionReason): void => {\n if (completionNotified) return;\n if (createdRunId == null) {\n pendingCompletionReason = reason;\n return;\n }\n completionNotified = true;\n this.#onRunCompleted(reason, createdRunId);\n };\n const reportError = (error: unknown): void => {\n if (abort.signal.aborted) return;\n this.#rootStore.setState((s) => ({ ...s, error }));\n try {\n options?.onError?.(error);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n };\n\n try {\n // Apply the input optimistically *before* the first await so the\n // user's message (and any merged state) paints without waiting for\n // the server round-trip. Kept as the first statement in the try so\n // the synchronous paint still precedes the first `await`, while a\n // synchronous coercion failure (e.g. a malformed message entry)\n // settles the submit lifecycle through the catch/finally below —\n // exactly like a dispatch failure — instead of wedging `isLoading`\n // / `#runAbort` and stranding later enqueue/reject submits behind a\n // phantom in-flight run. Runs only on the dispatched path — an\n // `\"enqueue\"`d submission returns above and echoes when it drains,\n // keeping one optimistic batch bound to exactly one run lifecycle.\n // `dispatchInput` carries the minted ids the server must echo for\n // reconciliation, so the run is dispatched with it (not raw input).\n const prepared = this.#beginOptimistic(input);\n if (prepared != null) {\n optimisticHandle = prepared.handle;\n dispatchInput = prepared.dispatchInput;\n }\n\n // Wait for the root subscription to be live; otherwise the\n // dispatch could resolve before we're listening for events and\n // we'd miss the terminal that ends the run.\n await this.#waitForRootPumpReady();\n\n const boundConfig = bindThreadConfig(options?.config, currentThreadId);\n // Subscribe to the next terminal *before* dispatching so a fast\n // run's terminal can't race us.\n const terminalPromise = this.#awaitNextTerminal(abort.signal);\n this.#onRunStart();\n\n let terminalSettled = false;\n let terminal: TerminalResult | undefined;\n\n const commandPromise = thread.submitRun({\n input: dispatchInput ?? null,\n config: boundConfig,\n metadata: (options?.metadata ?? undefined) as Record<string, unknown>,\n forkFrom: options?.forkFrom,\n multitaskStrategy:\n options?.multitaskStrategy === \"enqueue\"\n ? \"enqueue\"\n : options?.multitaskStrategy,\n });\n // Start the deferred root pump *after* the dispatch HTTP\n // response lands — that's when the thread row exists server-\n // side. Doing it synchronously here would race the response\n // and the pump's `subscription.subscribe` would 404. Same\n // reason we drop the self-created flag only after dispatch:\n // future hydrates need the thread to exist before they fetch\n // state.\n //\n // Fire-and-forget: we don't want to gate Promise.race on this,\n // and `commandPromise.catch` is already handled below. A\n // dispatch failure means there's no thread to pump anyway.\n void commandPromise.then(\n () => {\n this.#startDeferredRootPump();\n this.#forgetSelfCreatedThreadId(activeThreadId);\n },\n () => {\n // Dispatch failed. Without abandoning, `#rootPumpDeferred`\n // stays armed and `selfCreatedThreadIds` still holds this\n // id — a retry submit would see `pendingServerCreate=true`\n // again but `#ensureThread` would early-return because\n // `#thread != null`, and the root pump would never start.\n // Tear down so the next submit re-runs `#ensureThread`\n // from scratch. Keep the self-created mark so the retry\n // still defers the pump (the server row was never created).\n if (pendingServerCreate) {\n this.#abandonDeferredRootPump();\n }\n }\n );\n const notifyCreated = (result: { run_id?: unknown }) => {\n const runId =\n typeof result.run_id === \"string\" ? result.run_id : undefined;\n if (!abort.signal.aborted) this.#onRunStartReturned(runId);\n if (runId == null) return;\n createdRunId = runId;\n this.#onRunCreated(createdRunId);\n if (pendingCompletionReason != null) {\n notifyCompletion(pendingCompletionReason);\n }\n };\n const first = await Promise.race([\n terminalPromise.then((value) => ({\n type: \"terminal\" as const,\n value,\n })),\n commandPromise.then(\n (result) => ({ type: \"command\" as const, result }),\n (error) => ({ type: \"error\" as const, error })\n ),\n ]);\n if (first.type === \"error\") throw first.error;\n if (first.type === \"command\") {\n notifyCreated(first.result);\n } else {\n // Terminal landed first (very fast runs). Wait for the\n // dispatch response in the background so onCreated fires\n // and dispatch errors still surface.\n terminal = first.value;\n terminalSettled = true;\n void commandPromise.then(notifyCreated).catch((error) => {\n if (!terminalSettled) reportError(error);\n });\n }\n\n terminal ??= await terminalPromise;\n terminalSettled = true;\n settleEvent = terminal.event;\n if (terminal.event === \"failed\" && !abort.signal.aborted) {\n const runError = new Error(\n terminal.error ?? \"Run failed with no error message\"\n );\n this.#rootStore.setState((s) => ({ ...s, error: runError }));\n try {\n options?.onError?.(runError);\n } catch {\n /* caller-supplied callback errors must not crash the submit */\n }\n }\n notifyCompletion(terminalReason(terminal.event));\n } catch (error) {\n if (!abort.signal.aborted) settleEvent = \"failed\";\n reportError(error);\n } finally {\n // Always settle loading and clear our slot of the abort\n // controller. Schedule queue drain on the next macrotask so any\n // late state updates from this run finish flushing first.\n this.#rootStore.setState((s) => ({ ...s, isLoading: false }));\n if (this.#runAbort === abort) this.#runAbort = undefined;\n // Reconcile optimistic state: flip pending messages to sent/failed\n // and roll back un-echoed non-message keys. `aborted` covers a\n // rollback-resubmit or `stop()` cancelling this run.\n if (optimisticHandle != null) {\n this.#settleOptimistic(\n optimisticHandle,\n abort.signal.aborted ? \"aborted\" : (settleEvent ?? \"failed\")\n );\n }\n this.#onRunEnd();\n this.#scheduleQueueDrain();\n }\n }\n\n /**\n * Schedules a queue-drain attempt on the next macrotask, once the\n * just-finished run's state has flushed. A no-op unless the queue\n * adapter is idle-driven (see {@link QueueAdapter.onIdle}) and no\n * other run is active.\n */\n #scheduleQueueDrain(): void {\n setTimeout(() => {\n if (this.#getDisposed()) return;\n if (this.#runAbort != null && !this.#runAbort.signal.aborted) return;\n if (this.#rootStore.getSnapshot().isLoading) return;\n\n this.#queueAdapter.onIdle?.((values, drainOptions) =>\n this.submit(\n values,\n drainOptions as StreamSubmitOptions<StateType, ConfigurableType>\n ).catch(() => {\n /* submit() already routes errors through the per-submit onError\n * hook and the root store; swallow here so a failing drain does\n * not surface as an unhandled rejection. */\n })\n );\n }, 0);\n }\n\n /**\n * Surface a *resumed* run's failure the same way {@link submit} surfaces\n * a fresh run's failure — by writing it to the reactive\n * {@link RootSnapshot.error} slot.\n *\n * `respond()` / `respondAll()` dispatch their `input.respond` command on\n * the controller directly (they target a specific interrupt, so they\n * cannot go through {@link submit}, which only does `run.start`). The\n * resumed run therefore never passed through the submit lifecycle that\n * populates `rootStore.error` — only the persistent lifecycle listener\n * observed it, and that listener drives `isLoading` alone. Without this,\n * a resumed run that fails (e.g. a missing model key surfaced after the\n * user approves an interrupt) would flip `isLoading` back to `false`\n * with `error` left untouched, so `stream.error`-driven UIs (error\n * banners, API-key retry prompts) would silently miss it.\n *\n * The `dispatch` thunk is awaited, so a dispatch failure rejects the\n * caller's `respond()` *and* lands in `rootStore.error`. The resumed\n * run's terminal is watched in the **background** so the returned promise\n * still settles on dispatch — preserving the resume command's\n * resolve-on-dispatch contract (and avoiding a hang when no terminal is\n * ever emitted, e.g. in unit tests).\n *\n * Reuses the shared {@link #runAbort} slot, so `stop()`, `dispose()`, and\n * a rollback `submit()` all cancel the terminal watch (no spurious error\n * on user-initiated cancel) and treat the resumed run as the active run.\n *\n * The terminal watch uses {@link #awaitResumedRunTerminal}, which skips\n * stale `interrupted` terminals from the run being resumed (they can reach\n * the pump after `input.requested` but before `respondInput` calls\n * `#prepareForNextRun`) and only accepts a later `interrupted` once a\n * root `running` lifecycle for the resumed run has been observed.\n *\n * @param dispatch - Sends the `input.respond` command (and marks the\n * targeted interrupt resolved). Invoked after the terminal watch is\n * armed.\n * @param optimisticHandle - Optional handle from an optimistic `update`\n * applied before dispatch (HITL \"push card into state + resume\"). Settled\n * on the resumed run's terminal — pending messages flip to `sent` and\n * un-echoed non-message keys roll back on failure — exactly like the\n * `submit()` optimistic lifecycle. A dispatch failure settles it `failed`.\n */\n async dispatchResume(\n dispatch: () => Promise<void>,\n optimisticHandle?: OptimisticHandle\n ): Promise<void> {\n if (this.#getDisposed()) return;\n\n // Same allowlist clear as submit(): a resumed run can pause on a\n // *new* interrupt id. Without this, the hydrate-window allowlist\n // still contains only the interrupt being answered and\n // `#recordRootInterrupt` drops the follow-on `input.requested`.\n this.#onSubmitStart();\n\n // Rollback any run still tracked as active (mirrors submit()), then\n // claim the in-flight slot so stop()/dispose()/a concurrent submit\n // cancels the terminal watch armed below.\n this.#runAbort?.abort();\n const abort = new AbortController();\n this.#runAbort = abort;\n\n // Optimistically clear a stale error from a previous run, matching\n // submit()'s reset, so the resume starts from a clean error slot.\n this.#rootStore.setState((s) =>\n s.error === undefined ? s : { ...s, error: undefined }\n );\n\n const reportError = (error: unknown): void => {\n if (abort.signal.aborted) return;\n this.#rootStore.setState((s) => ({ ...s, error }));\n };\n\n // Settle the optimistic `update` exactly once, whether the resumed run\n // terminates (success/failure/interrupt) or the dispatch itself fails.\n let optimisticSettled = false;\n const settleOptimisticOnce = (event: TerminalResult[\"event\"]): void => {\n if (optimisticSettled || optimisticHandle == null) return;\n optimisticSettled = true;\n this.#settleOptimistic(optimisticHandle, event);\n };\n\n // Subscribe to the resumed run's terminal *before* dispatching so a fast\n // `failed` can't race us. Unlike `#awaitNextTerminal`, the resume watcher\n // ignores stale `interrupted` events until root `running` is seen.\n // Watched in the background — we never gate the returned promise on the\n // resumed run's terminal.\n const terminalPromise = this.#awaitResumedRunTerminal(abort.signal);\n void terminalPromise.then((terminal) => {\n if (this.#runAbort === abort) this.#runAbort = undefined;\n if (terminal.event === \"failed\" && !abort.signal.aborted) {\n reportError(\n new Error(terminal.error ?? \"Run failed with no error message\")\n );\n }\n settleOptimisticOnce(abort.signal.aborted ? \"aborted\" : terminal.event);\n // Drain any submission enqueued while the resumed run was active.\n this.#scheduleQueueDrain();\n });\n\n try {\n await dispatch();\n } catch (error) {\n // The `input.respond` send itself failed, before any run started.\n reportError(error);\n settleOptimisticOnce(\"failed\");\n if (this.#runAbort === abort) this.#runAbort = undefined;\n throw error;\n }\n }\n\n /**\n * Abort the current run (if any) and force `isLoading=false`.\n *\n * Client-side only — server-side cancel is handled by\n * {@link StreamController.stop} before this is invoked.\n */\n async stop(): Promise<void> {\n this.abortActiveRun();\n this.#rootStore.setState((s) => ({ ...s, isLoading: false }));\n }\n\n /**\n * Abort the current run without forcing the loading flag down.\n *\n * Used by {@link StreamController.dispose}: disposal already tears\n * down the root store, so flipping `isLoading` here is unnecessary\n * and would race the dispose path.\n */\n abortActiveRun(): void {\n this.#runAbort?.abort();\n this.#runAbort = undefined;\n }\n\n /**\n * Populate the queue from whatever the configured adapter considers\n * the source of truth. No-op for `LocalQueueAdapter`; for the\n * server-backed adapter this is what makes pending runs created\n * before this page load (or by another tab/session) show up.\n * Fire-and-forget from the caller's side: the adapter manages its\n * own staleness guard against a rapid, repeated call for a newer\n * thread.\n */\n async hydrateQueue(threadId: string): Promise<void> {\n await this.#queueAdapter.hydrate(threadId);\n }\n\n /**\n * Public entry point for {@link #scheduleQueueDrain}. Called by the\n * controller when `isLoading` settles to `false` for a run this\n * coordinator never dispatched itself.\n */\n scheduleQueueDrainOnObservedIdle(): void {\n this.#scheduleQueueDrain();\n }\n\n /**\n * Cancel a queued submission by id.\n *\n * @param id - Client-side queue entry id to remove.\n * @returns `true` when the entry was found and dropped, `false` otherwise.\n */\n async cancelQueued(id: string): Promise<boolean> {\n return this.#queueAdapter.cancel(id);\n }\n\n /**\n * Drop every queued submission. Cancels the underlying server-side\n * runs too when server-backed; see `AgentServerQueueAdapter.clear`.\n */\n async clearQueue(): Promise<void> {\n await this.#queueAdapter.clear();\n }\n\n /**\n * Release whatever the queue adapter is watching. Called by\n * {@link StreamController} on thread rebind and on dispose, alongside\n * its own reset of the (still directly-owned, reactive) queue store.\n */\n detachQueue(): void {\n this.#queueAdapter.detach();\n }\n}\n"],"mappings":"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"}
|
package/dist/ui/manager.cjs
CHANGED
|
@@ -200,7 +200,7 @@ var StreamManager = class {
|
|
|
200
200
|
if (!hasUnmappedToolCalls()) break;
|
|
201
201
|
const { tasks } = checkpoint;
|
|
202
202
|
if (!tasks || tasks.length === 0) continue;
|
|
203
|
-
const pushTasks = tasks.filter((t) => Array.isArray(t.path) && t.path[0] === "__pregel_push" && typeof t.path[1] === "number" && typeof t.id === "string" && typeof t.name === "string");
|
|
203
|
+
const pushTasks = tasks.filter((t) => Array.isArray(t.path) && t.path[0] === "__pregel_push" && typeof t.path[1] === "number" && t.path.length <= 3 && typeof t.id === "string" && typeof t.name === "string");
|
|
204
204
|
if (pushTasks.length === 0) continue;
|
|
205
205
|
/**
|
|
206
206
|
* Find the AI message with subagent tool calls to align by Send index.
|
package/dist/ui/manager.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.cjs","names":["toMessageDict","SubagentManager","StreamError","isSubagentNamespace","extractToolCallIdFromNamespace"],"sources":["../../src/ui/manager.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\n\nimport { DEFAULT_MESSAGES_KEY } from \"../stream/constants.js\";\nimport type {\n CheckpointsStreamEvent,\n CustomStreamEvent,\n DebugStreamEvent,\n ErrorStreamEvent,\n EventsStreamEvent,\n FeedbackStreamEvent,\n MessagesTupleStreamEvent,\n MetadataStreamEvent,\n TasksStreamEvent,\n ToolsStreamEvent,\n UpdatesStreamEvent,\n ValuesStreamEvent,\n} from \"../types.stream.js\";\nimport { MessageTupleManager, toMessageDict } from \"./messages.js\";\nimport { StreamError } from \"./errors.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { BagTemplate } from \"../types.template.js\";\nimport {\n SubagentManager,\n extractToolCallIdFromNamespace,\n isSubagentNamespace,\n} from \"./subagents.js\";\nimport type { SubagentStreamInterface } from \"./types.js\";\n\n/**\n * Special ID used by LangGraph's messagesStateReducer to signal\n * that all messages should be removed from the state.\n */\nexport const REMOVE_ALL_MESSAGES = \"__remove_all__\";\n\ntype GetUpdateType<\n Bag extends BagTemplate,\n StateType extends Record<string, unknown>,\n> = Bag extends { UpdateType: unknown }\n ? Bag[\"UpdateType\"]\n : Partial<StateType>;\n\ntype GetCustomEventType<Bag extends BagTemplate> = Bag extends {\n CustomEventType: unknown;\n}\n ? Bag[\"CustomEventType\"]\n : unknown;\n\ntype EventStreamMap<StateType, UpdateType, CustomType> = {\n values: ValuesStreamEvent<StateType>;\n updates: UpdatesStreamEvent<UpdateType>;\n custom: CustomStreamEvent<CustomType>;\n debug: DebugStreamEvent;\n messages: MessagesTupleStreamEvent;\n events: EventsStreamEvent;\n metadata: MetadataStreamEvent;\n checkpoints: CheckpointsStreamEvent<StateType>;\n tasks: TasksStreamEvent<StateType, UpdateType>;\n error: ErrorStreamEvent;\n feedback: FeedbackStreamEvent;\n tools: ToolsStreamEvent;\n};\n\nexport type EventStreamEvent<StateType, UpdateType, CustomType> =\n EventStreamMap<StateType, UpdateType, CustomType>[keyof EventStreamMap<\n StateType,\n UpdateType,\n CustomType\n >];\n\ninterface StreamManagerEventCallbacks<\n StateType extends Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n> {\n onUpdateEvent?: (\n data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>[\"data\"],\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n onCustomEvent?: (\n data: GetCustomEventType<Bag>,\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n onMetadataEvent?: (data: MetadataStreamEvent[\"data\"]) => void;\n onLangChainEvent?: (data: EventsStreamEvent[\"data\"]) => void;\n onDebugEvent?: (\n data: DebugStreamEvent[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onCheckpointEvent?: (\n data: CheckpointsStreamEvent<StateType>[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onTaskEvent?: (\n data: TasksStreamEvent<StateType, GetUpdateType<Bag, StateType>>[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onToolEvent?: (\n data: ToolsStreamEvent[\"data\"],\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n}\n\n/**\n * Options for StreamManager constructor.\n */\nexport interface StreamManagerOptions {\n /**\n * Throttle the stream updates.\n * If a number is provided, updates are throttled to the given milliseconds.\n * If `true`, updates are batched in a single macrotask.\n * If `false`, updates are not throttled.\n */\n throttle: number | boolean;\n\n /**\n * Tool names that indicate subagent invocation.\n *\n * When an AI message contains tool calls with these names, they are\n * automatically tracked as subagent executions. This enables the\n * `subagents`, `activeSubagents`, `getSubagent()`, and `getSubagentsByType()`\n * properties on the stream.\n *\n * @default [\"task\"]\n *\n * @example\n * ```typescript\n * // Track both \"task\" and \"delegate\" as subagent tools\n * subagentToolNames: [\"task\", \"delegate\", \"spawn_agent\"]\n * ```\n */\n subagentToolNames?: string[];\n\n /**\n * Filter out messages from subagent streams in the main messages array.\n *\n * When enabled, messages from subagraph executions (those with a `tools:` namespace)\n * are excluded from `stream.messages`. Instead, these messages are tracked\n * per-subagent and accessible via `stream.subagents.get(id).messages`.\n *\n * This is useful for deep agent architectures where you want to display\n * the main conversation separately from subagent activity.\n *\n * @default false\n *\n * @example\n * ```typescript\n * const stream = useStream({\n * assistantId: \"my-agent\",\n * filterSubagentMessages: true,\n * });\n *\n * // Main thread messages only (no subagent messages)\n * stream.messages\n *\n * // Access subagent messages individually\n * stream.subagents.get(\"call_xyz\").messages\n * ```\n */\n filterSubagentMessages?: boolean;\n\n /**\n * Converts a @langchain/core BaseMessage to the desired output format.\n *\n * Defaults to `toMessageDict` which produces plain Message objects.\n * Framework SDKs pass `toMessageClass` (identity) to keep class instances.\n */\n toMessage?: (chunk: BaseMessage) => Message | BaseMessage;\n}\n\nexport class StreamManager<\n StateType extends Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n> {\n private abortRef = new AbortController();\n\n private messages: MessageTupleManager;\n\n private subagentManager: SubagentManager;\n\n private listeners = new Set<() => void>();\n\n private throttle: number | boolean;\n\n private filterSubagentMessages: boolean;\n\n private toMessage: (chunk: BaseMessage) => Message | BaseMessage;\n\n private queue: Promise<unknown> = Promise.resolve();\n\n private queueSize: number = 0;\n\n private state: {\n isLoading: boolean;\n values: [values: StateType, kind: \"stream\" | \"stop\"] | null;\n error: unknown;\n /** Version counter to force React re-renders on subagent changes */\n version: number;\n };\n\n constructor(messages: MessageTupleManager, options: StreamManagerOptions) {\n this.messages = messages;\n this.state = {\n isLoading: false,\n values: null,\n error: undefined,\n version: 0,\n };\n this.throttle = options.throttle;\n this.filterSubagentMessages = options.filterSubagentMessages ?? false;\n this.toMessage = options.toMessage ?? toMessageDict;\n this.subagentManager = new SubagentManager({\n subagentToolNames: options.subagentToolNames,\n onSubagentChange: () => this.bumpVersion(),\n toMessage: this.toMessage,\n });\n }\n\n /**\n * Increment version counter to trigger React re-renders.\n * Called when subagent state changes.\n */\n private bumpVersion = () => {\n this.state = { ...this.state, version: this.state.version + 1 };\n this.notifyListeners();\n };\n\n /**\n * Get all subagents as a Map.\n */\n getSubagents(): Map<string, SubagentStreamInterface> {\n return this.subagentManager.getSubagents();\n }\n\n /**\n * Get all currently running subagents.\n */\n getActiveSubagents(): SubagentStreamInterface[] {\n return this.subagentManager.getActiveSubagents();\n }\n\n /**\n * Get a specific subagent by tool call ID.\n */\n getSubagent(toolCallId: string): SubagentStreamInterface | undefined {\n return this.subagentManager.getSubagent(toolCallId);\n }\n\n /**\n * Get all subagents of a specific type.\n */\n getSubagentsByType(type: string): SubagentStreamInterface[] {\n return this.subagentManager.getSubagentsByType(type);\n }\n\n /**\n * Get all subagents triggered by a specific AI message.\n */\n getSubagentsByMessage(messageId: string): SubagentStreamInterface[] {\n return this.subagentManager.getSubagentsByMessage(messageId);\n }\n\n /**\n * Reconstruct subagent state from historical messages.\n *\n * This method should be called when loading thread history to restore\n * subagent visualization after:\n * - Page refresh (when stream has already completed)\n * - Loading thread history\n * - Navigating between threads\n *\n * @param messages - Array of messages from thread history\n * @param options - Optional configuration\n * @param options.skipIfPopulated - If true, skip reconstruction if subagents already exist\n */\n reconstructSubagents(\n messages: Message[],\n options?: { skipIfPopulated?: boolean }\n ): void {\n this.subagentManager.reconstructFromMessages(messages, options);\n }\n\n /**\n * Fetch and restore internal messages for reconstructed subagents from their\n * subgraph checkpoints. Should be called after `reconstructSubagents` to\n * restore the full subagent conversation after a page refresh.\n *\n * Subagent messages are persisted in the LangGraph checkpointer under a\n * subgraph-specific `checkpoint_ns` (e.g. `tools:<uuid>`). This method\n * discovers the correct namespace by inspecting the main thread's intermediate\n * history checkpoints, where each pending task's `checkpoint.checkpoint_ns`\n * identifies the subgraph. Tasks are matched to tool calls by their Send index\n * (`task.path[1]`), which corresponds to the order of tool calls in the AI\n * message — no deepagent-specific metadata required.\n *\n * @param threads - Client with a `getHistory` method (e.g. `client.threads`)\n * @param threadId - The parent thread ID\n * @param options - Optional configuration\n * @param options.messagesKey - Key in state values containing messages (default: \"messages\")\n * @param options.signal - AbortSignal to cancel in-flight requests on effect cleanup\n */\n async fetchSubagentHistory(\n threads: {\n getHistory<V extends Record<string, unknown>>(\n threadId: string,\n options?: {\n limit?: number;\n checkpoint?: { checkpoint_ns?: string };\n signal?: AbortSignal;\n }\n ): Promise<\n Array<{\n values: V;\n tasks?: Array<{\n id: string;\n name: string;\n path?: unknown[];\n checkpoint?: { checkpoint_ns?: string } | null;\n }>;\n }>\n >;\n },\n threadId: string,\n options?: {\n messagesKey?: string;\n historyLimit?: number;\n signal?: AbortSignal;\n }\n ): Promise<void> {\n const messagesKey = options?.messagesKey ?? DEFAULT_MESSAGES_KEY;\n const signal = options?.signal;\n\n /**\n * Bail immediately if already cancelled (React Strict Mode cleanup)\n */\n if (signal?.aborted) {\n return;\n }\n\n /**\n * Only fetch for subagents that have no messages (reconstructed from history)\n */\n const toFetch = [...this.subagentManager.getSubagents().entries()].filter(\n ([, s]) => s.messages.length === 0\n );\n\n /**\n * Bail immediately if there are no subagents to fetch\n */\n if (toFetch.length === 0) {\n return;\n }\n\n /**\n * Step 1: Discover subgraph namespaces from intermediate history\n *\n * When LangGraph dispatches parallel tool calls (v2 mode), each is a\n * separate Send task with a unique UUID-based checkpoint_ns. The intermediate\n * history checkpoints record these as `tasks[i]` where:\n * - `tasks[i].checkpoint.checkpoint_ns` = \"tools:<uuid>\" for each subgraph\n * - `tasks[i].path = [\"__pregel_push\", sendIndex]` matches tool_calls order\n *\n * By matching task Send index → tool_call position in the AI message we can\n * derive the subgraph namespace for every tool call without any external\n * metadata on the ToolMessage itself.\n */\n const toolCallIdToNamespace = new Map<string, string>();\n\n try {\n /**\n * Fetch enough history to include the intermediate checkpoint where\n * tool-call tasks were pending (typically within the last 10 checkpoints).\n */\n const mainHistory = await threads.getHistory<Record<string, unknown>>(\n threadId,\n { limit: options?.historyLimit ?? 20, signal }\n );\n\n /**\n * Phase 1: Direct mapping across ALL checkpoints (preferred).\n *\n * When a completed checkpoint contains task results, each task.result\n * has a ToolMessage whose tool_call_id directly and unambiguously maps\n * the task to the LLM tool call that triggered it. This is more robust\n * than positional alignment: it works even when a step mixes subagent\n * tool calls with other tool calls, and requires no assumptions about\n * the ordering of tasks vs tool_calls.\n *\n * We collect these direct mappings across the entire history before\n * attempting any positional fallback. Otherwise a more recent checkpoint\n * whose task is still pending (e.g. an interrupted run) could produce a\n * positional guess and stop the scan before reaching the older checkpoint\n * that actually holds the correct, completed mapping.\n *\n * LangGraph v2 dispatches each parallel tool call as a separate PUSH\n * task (\"__pregel_push\"). The subgraph checkpoint_ns is constructed as\n * `task.name + \":\" + task.id`, mirroring algo.ts:\n * taskCheckpointNamespace = checkpointNamespace + \":\" + taskId\n * where checkpointNamespace = task.name for root-level tasks.\n *\n * task.checkpoint is always null for completed tasks, so we derive the\n * namespace from task.name + task.id rather than task.checkpoint.checkpoint_ns.\n */\n for (const checkpoint of mainHistory) {\n const { tasks } = checkpoint;\n if (!tasks || tasks.length === 0) {\n continue;\n }\n\n for (const task of tasks) {\n if (\n !Array.isArray(task.path) ||\n task.path[0] !== \"__pregel_push\" ||\n typeof task.id !== \"string\" ||\n typeof task.name !== \"string\"\n ) {\n continue;\n }\n\n /**\n * Read tool_call_id directly from the task's result ToolMessage.\n */\n const resultMessages = (\n task as unknown as { result?: { messages?: unknown[] } }\n ).result?.messages;\n\n if (!Array.isArray(resultMessages)) {\n continue;\n }\n\n for (const msg of resultMessages) {\n const m = msg as Record<string, unknown>;\n if (\n m.type === \"tool\" &&\n typeof m.tool_call_id === \"string\" &&\n toFetch.some(([id]) => id === m.tool_call_id) &&\n !toolCallIdToNamespace.has(m.tool_call_id)\n ) {\n toolCallIdToNamespace.set(\n m.tool_call_id,\n `${task.name}:${task.id}`\n );\n }\n }\n }\n }\n\n /**\n * Phase 2: Positional fallback, applied ONLY to tool calls that Phase 1\n * could not resolve.\n *\n * This covers checkpoints whose task results are not yet populated (tasks\n * still pending — the live or just-interrupted case). We align push tasks\n * to the subagent tool calls of the triggering AI message by Send index\n * (task.path[1]). Restricting this to still-unmapped tool calls guarantees\n * a correct direct mapping from Phase 1 is never overwritten by a guess.\n */\n const hasUnmappedToolCalls = () =>\n toFetch.some(([id]) => !toolCallIdToNamespace.has(id));\n\n if (hasUnmappedToolCalls()) {\n for (const checkpoint of mainHistory) {\n if (!hasUnmappedToolCalls()) break;\n\n const { tasks } = checkpoint;\n if (!tasks || tasks.length === 0) {\n continue;\n }\n\n const pushTasks = tasks.filter(\n (t) =>\n Array.isArray(t.path) &&\n t.path[0] === \"__pregel_push\" &&\n typeof t.path[1] === \"number\" &&\n typeof t.id === \"string\" &&\n typeof t.name === \"string\"\n );\n if (pushTasks.length === 0) continue;\n\n /**\n * Find the AI message with subagent tool calls to align by Send index.\n */\n const msgs = checkpoint.values[messagesKey];\n if (!Array.isArray(msgs)) continue;\n\n let aiMessage: Record<string, unknown> | undefined;\n for (let i = msgs.length - 1; i >= 0; i -= 1) {\n const m = msgs[i] as Record<string, unknown>;\n if (\n m.type === \"ai\" &&\n Array.isArray(m.tool_calls) &&\n m.tool_calls.length > 0 &&\n (m.tool_calls as Array<{ name: string }>).some((tc) =>\n this.subagentManager.isSubagentToolCall(tc.name)\n )\n ) {\n aiMessage = m;\n break;\n }\n }\n if (!aiMessage) {\n continue;\n }\n\n /**\n * Only consider subagent tool calls from the AI message — not all tool\n * calls. This ensures regular tool calls (searchWeb, queryDatabase, etc.)\n * are never mistaken for subagents even when they appear in the same step.\n */\n const subagentToolCalls = (\n aiMessage.tool_calls as Array<{ id?: string; name: string }>\n ).filter((tc) => this.subagentManager.isSubagentToolCall(tc.name));\n\n if (subagentToolCalls.length === 0) {\n continue;\n }\n\n /**\n * Sort push tasks by Send index (path[1]) to align with tool_calls order\n */\n const sorted = [...pushTasks].sort((a, b) => {\n const ai = Array.isArray(a.path) ? (a.path[1] as number) : 0;\n const bi = Array.isArray(b.path) ? (b.path[1] as number) : 0;\n return ai - bi;\n });\n\n for (\n let i = 0;\n i < sorted.length && i < subagentToolCalls.length;\n i += 1\n ) {\n const tc = subagentToolCalls[i];\n const task = sorted[i];\n if (\n tc?.id &&\n task.id &&\n task.name &&\n toFetch.some(([id]) => id === tc.id) &&\n !toolCallIdToNamespace.has(tc.id)\n ) {\n toolCallIdToNamespace.set(tc.id, `${task.name}:${task.id}`);\n }\n }\n }\n }\n } catch {\n /**\n * Non-fatal: fall back to subagent.namespace below\n */\n }\n\n /**\n * Step 2: Fetch each subagent's conversation from its subgraph checkpoint\n */\n await Promise.all(\n toFetch.map(async ([toolCallId, subagent]) => {\n /**\n * Priority order for the subgraph checkpoint_ns:\n * 1. Derived from main thread's intermediate task list (preferred, no coupling)\n * 2. Already on the subagent's namespace (e.g. populated during streaming)\n * 3. Skip — we cannot reliably identify the namespace\n */\n const checkpointNs =\n toolCallIdToNamespace.get(toolCallId) ??\n (subagent.namespace.length > 0\n ? subagent.namespace.join(\"|\")\n : undefined);\n\n if (!checkpointNs) return;\n\n try {\n const history = await threads.getHistory<Record<string, unknown>>(\n threadId,\n {\n checkpoint: { checkpoint_ns: checkpointNs },\n limit: 1,\n signal,\n }\n );\n\n /**\n * If the HTTP request was cancelled mid-flight the getHistory call\n * would have thrown an AbortError (caught below). If we reach here the\n * fetch completed successfully, so always process the result.\n */\n const latestState = history[0];\n if (!latestState?.values) return;\n\n const messages = latestState.values[messagesKey];\n if (!Array.isArray(messages) || messages.length === 0) return;\n\n /**\n * Normalize messages: promote tool_calls from additional_kwargs to top\n * level when the checkpointer serialized them in the legacy format.\n */\n const normalizedMessages = messages.map((msg) => {\n const m = msg as Record<string, unknown>;\n if (\n m.type === \"ai\" &&\n (!m.tool_calls || (m.tool_calls as unknown[]).length === 0)\n ) {\n const ak = m.additional_kwargs as\n | Record<string, unknown>\n | undefined;\n const legacy = ak?.tool_calls;\n if (Array.isArray(legacy) && legacy.length > 0) {\n return { ...m, tool_calls: legacy };\n }\n }\n return m;\n });\n\n this.subagentManager.updateSubagentFromSubgraphState(\n toolCallId,\n normalizedMessages as Message[],\n latestState.values\n );\n } catch {\n /**\n * Ignore AbortError and other transient errors\n */\n }\n })\n );\n }\n\n /**\n * Check if any subagents are currently tracked.\n */\n hasSubagents(): boolean {\n return this.subagentManager.hasSubagents();\n }\n\n private setState = (newState: Partial<typeof this.state>) => {\n this.state = { ...this.state, ...newState };\n this.notifyListeners();\n };\n\n private notifyListeners = () => {\n this.listeners.forEach((listener) => listener());\n };\n\n subscribe = (listener: () => void): (() => void) => {\n if (this.throttle === false) {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n const timeoutMs = this.throttle === true ? 0 : this.throttle;\n let timeoutId: NodeJS.Timeout | number | undefined;\n\n const throttledListener = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n clearTimeout(timeoutId);\n listener();\n }, timeoutMs);\n };\n\n this.listeners.add(throttledListener);\n return () => {\n clearTimeout(timeoutId);\n this.listeners.delete(throttledListener);\n };\n };\n\n getSnapshot = () => this.state;\n\n get isLoading() {\n return this.state.isLoading;\n }\n\n get values() {\n return this.state.values?.[0] ?? null;\n }\n\n get error() {\n return this.state.error;\n }\n\n setStreamValues = (\n values:\n | (StateType | null)\n | ((prev: StateType | null, kind: \"stream\" | \"stop\") => StateType | null),\n kind: \"stream\" | \"stop\" = \"stream\"\n ) => {\n if (typeof values === \"function\") {\n const [prevValues, prevKind] = this.state.values ?? [null, \"stream\"];\n const nextValues = values(prevValues, prevKind);\n this.setState({ values: nextValues != null ? [nextValues, kind] : null });\n } else {\n const nextValues = values != null ? [values, kind] : null;\n this.setState({ values: nextValues as [StateType, \"stream\" | \"stop\"] });\n }\n };\n\n private getMutateFn = (kind: \"stream\" | \"stop\", historyValues: StateType) => {\n return (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => {\n const stateValues = (this.state.values ?? [null, \"stream\"])[0];\n const prev = {\n ...historyValues,\n ...stateValues,\n };\n const next = typeof update === \"function\" ? update(prev) : update;\n this.setStreamValues({ ...prev, ...next }, kind);\n };\n };\n\n private matchEventType = <\n T extends keyof EventStreamMap<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >,\n >(\n expected: T,\n actual: EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[\"event\"],\n _data: EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[\"data\"]\n ): _data is EventStreamMap<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[T][\"data\"] => {\n return expected === actual || actual.startsWith(`${expected}|`);\n };\n\n protected enqueue = async (\n action: (\n signal: AbortSignal\n ) => Promise<\n AsyncGenerator<\n EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >\n >\n >,\n options: {\n getMessages: (values: StateType) => Message[];\n\n setMessages: (current: StateType, messages: Message[]) => StateType;\n\n initialValues: StateType;\n\n callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n onSuccess: () =>\n | StateType\n | null\n | undefined\n | void\n | Promise<StateType | null | undefined | void>;\n\n onError: (error: unknown) => void | Promise<void>;\n\n onFinish?: () => void;\n }\n ) => {\n try {\n this.queueSize = Math.max(0, this.queueSize - 1);\n this.setState({ isLoading: true, error: undefined });\n this.abortRef = new AbortController();\n\n const run = await action(this.abortRef.signal);\n let clearedPreviousInterrupts = false;\n\n let streamError: StreamError | undefined;\n for await (const { event, data } of run) {\n if (event === \"error\") {\n streamError = new StreamError(data);\n break;\n }\n\n const namespace = event.includes(\"|\")\n ? event.split(\"|\").slice(1)\n : undefined;\n\n const mutate = this.getMutateFn(\"stream\", options.initialValues);\n\n if (event === \"metadata\") options.callbacks.onMetadataEvent?.(data);\n if (event === \"events\") options.callbacks.onLangChainEvent?.(data);\n\n if (this.matchEventType(\"updates\", event, data)) {\n options.callbacks.onUpdateEvent?.(data, { namespace, mutate });\n\n // Track subagent streaming updates from subgraph namespaces\n // Mark the subagent as running when we receive updates\n // The actual message content is handled via addMessageToSubagent\n if (namespace && isSubagentNamespace(namespace)) {\n const namespaceId = extractToolCallIdFromNamespace(namespace);\n if (namespaceId && this.filterSubagentMessages) {\n this.subagentManager.markRunningFromNamespace(\n namespaceId,\n namespace\n );\n }\n }\n\n // Also register subagents from main agent updates (tool_calls in messages)\n // AND process tool results to complete subagents\n // This is needed because tool_calls often appear complete in updates\n // before they appear in the messages stream\n if (!namespace || !isSubagentNamespace(namespace)) {\n const updateData = data as Record<string, unknown>;\n for (const nodeData of Object.values(updateData)) {\n if (\n nodeData &&\n typeof nodeData === \"object\" &&\n \"messages\" in nodeData\n ) {\n const { messages } = nodeData as { messages: unknown[] };\n if (Array.isArray(messages)) {\n for (const msg of messages) {\n if (!msg || typeof msg !== \"object\") continue;\n const msgObj = msg as Record<string, unknown>;\n\n // Register subagents from AI messages with tool_calls\n if (\n msgObj.type === \"ai\" &&\n \"tool_calls\" in msgObj &&\n Array.isArray(msgObj.tool_calls)\n ) {\n this.subagentManager.registerFromToolCalls(\n msgObj.tool_calls as Array<{\n id?: string;\n name: string;\n args: Record<string, unknown> | string;\n }>,\n msgObj.id as string | undefined\n );\n }\n\n // Complete subagents from tool messages (task results)\n if (\n msgObj.type === \"tool\" &&\n \"tool_call_id\" in msgObj &&\n typeof msgObj.tool_call_id === \"string\"\n ) {\n const content =\n typeof msgObj.content === \"string\"\n ? msgObj.content\n : JSON.stringify(msgObj.content);\n const status =\n \"status\" in msgObj && msgObj.status === \"error\"\n ? \"error\"\n : \"success\";\n this.subagentManager.processToolMessage(\n msgObj.tool_call_id,\n content,\n status\n );\n }\n }\n }\n }\n }\n }\n }\n\n if (this.matchEventType(\"custom\", event, data)) {\n options.callbacks.onCustomEvent?.(data, { namespace, mutate });\n }\n\n if (this.matchEventType(\"checkpoints\", event, data)) {\n options.callbacks.onCheckpointEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"tasks\", event, data)) {\n options.callbacks.onTaskEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"debug\", event, data)) {\n options.callbacks.onDebugEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"tools\", event, data)) {\n options.callbacks.onToolEvent?.(data, { namespace, mutate });\n }\n\n // Handle values events - use startsWith to match both \"values\" and \"values|tools:xxx\"\n if (event === \"values\" || event.startsWith(\"values|\")) {\n // Check if this is a subgraph values event (for namespace mapping and values)\n if (namespace && isSubagentNamespace(namespace)) {\n const namespaceId = extractToolCallIdFromNamespace(namespace);\n if (namespaceId && this.filterSubagentMessages) {\n const valuesData = data as Record<string, unknown>;\n\n // Try to establish namespace mapping from the initial human message\n const messages = valuesData.messages as unknown[];\n if (Array.isArray(messages) && messages.length > 0) {\n const firstMsg = messages[0] as Record<string, unknown>;\n if (\n firstMsg?.type === \"human\" &&\n typeof firstMsg?.content === \"string\"\n ) {\n this.subagentManager.matchSubgraphToSubagent(\n namespaceId,\n firstMsg.content\n );\n }\n }\n\n // Update the subagent's values with the full state\n this.subagentManager.updateSubagentValues(\n namespaceId,\n valuesData\n );\n }\n } else {\n if (!clearedPreviousInterrupts) {\n // Clear stale __interrupt__ from the previous run once the new\n // stream starts delivering main values. This avoids carrying\n // resumed interrupts forward while still preserving the previous\n // interrupt state if the new stream fails before any values\n // arrive.\n this.setStreamValues((prev) => {\n if (prev && \"__interrupt__\" in prev) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { __interrupt__, ...rest } = prev;\n return rest as StateType;\n }\n return prev;\n });\n clearedPreviousInterrupts = true;\n }\n\n if (data && typeof data === \"object\" && \"__interrupt__\" in data) {\n // When parallel branches each raise an interrupt, the backend\n // may stream separate values events per branch. We accumulate\n // the __interrupt__ arrays so none are lost, but still honor an\n // explicit empty array as \"clear interrupts\".\n const interruptData = data as Partial<StateType> & {\n __interrupt__?: Array<{ id?: string }>;\n };\n this.setStreamValues((prev) => {\n const prevInterrupts = (\n prev as\n | (StateType & { __interrupt__?: Array<{ id?: string }> })\n | null\n )?.__interrupt__;\n\n let interrupts = interruptData.__interrupt__;\n if (Array.isArray(interrupts)) {\n if (interrupts.length === 0) {\n interrupts = [];\n } else if (Array.isArray(prevInterrupts)) {\n const mergedInterrupts = [...prevInterrupts];\n const existingIds = new Set(\n prevInterrupts.map((i) => i.id).filter((id) => id != null)\n );\n for (const interrupt of interrupts) {\n if (interrupt.id != null) {\n if (existingIds.has(interrupt.id)) continue;\n existingIds.add(interrupt.id);\n }\n mergedInterrupts.push(interrupt);\n }\n interrupts = mergedInterrupts;\n }\n }\n\n return {\n ...prev,\n __interrupt__: interrupts,\n } as unknown as StateType;\n });\n } else {\n // Non-interrupt values events must not wipe accumulated\n // __interrupt__ state. Preserve it when the incoming data\n // does not carry its own __interrupt__ field.\n this.setStreamValues((prev) => {\n if (\n prev &&\n \"__interrupt__\" in prev &&\n Array.isArray((prev as Record<string, unknown>).__interrupt__)\n ) {\n return {\n ...(data as StateType),\n __interrupt__: (prev as Record<string, unknown>)\n .__interrupt__,\n } as StateType;\n }\n return data as StateType;\n });\n }\n }\n }\n\n if (this.matchEventType(\"messages\", event, data)) {\n const [serialized, metadata] = data;\n\n // Check if this message is from a subagent namespace\n const eventCheckpointNs =\n namespace && isSubagentNamespace(namespace) ? namespace : undefined;\n const rawCheckpointNs =\n (metadata?.langgraph_checkpoint_ns as string | undefined) ||\n (metadata?.checkpoint_ns as string | undefined);\n const checkpointNs: string[] | undefined =\n eventCheckpointNs ??\n (typeof rawCheckpointNs === \"string\"\n ? rawCheckpointNs.split(\"|\")\n : undefined);\n const isFromSubagent = isSubagentNamespace(checkpointNs);\n const toolCallId = isFromSubagent\n ? extractToolCallIdFromNamespace(checkpointNs)\n : undefined;\n\n // If filtering is enabled and this is a subagent message,\n // add it to the subagent's messages instead of the main stream\n if (this.filterSubagentMessages && isFromSubagent && toolCallId) {\n // Add to subagent's message list\n this.subagentManager.addMessageToSubagent(\n toolCallId,\n serialized,\n metadata\n );\n continue;\n }\n\n const messageId = this.messages.add(serialized, metadata);\n if (!messageId) {\n console.warn(\n \"Failed to add message to manager, no message ID found\"\n );\n continue;\n }\n\n this.setStreamValues((streamValues) => {\n const values = {\n ...options.initialValues,\n ...streamValues,\n };\n\n // Assumption: we're concatenating the message\n let messages = options.getMessages(values).slice();\n const { chunk, index } =\n this.messages.get(messageId, messages.length) ?? {};\n\n if (!chunk || index == null) return values;\n if (chunk.getType() === \"remove\") {\n // Check for special REMOVE_ALL_MESSAGES sentinel\n if (chunk.id === REMOVE_ALL_MESSAGES) {\n // Clear all messages when __remove_all__ is received\n messages = [];\n } else {\n messages.splice(index, 1);\n }\n } else {\n const msgDict = this.toMessage(chunk) as Message;\n messages[index] = msgDict;\n\n // Track subagents from AI messages with tool calls (main agent only)\n if (\n !isFromSubagent &&\n msgDict.type === \"ai\" &&\n \"tool_calls\" in msgDict &&\n Array.isArray(msgDict.tool_calls)\n ) {\n this.subagentManager.registerFromToolCalls(\n msgDict.tool_calls,\n msgDict.id as string | undefined\n );\n }\n\n // Complete subagents when tool messages arrive (main agent only)\n if (\n !isFromSubagent &&\n msgDict.type === \"tool\" &&\n \"tool_call_id\" in msgDict\n ) {\n const tcId = msgDict.tool_call_id as string;\n const content =\n typeof msgDict.content === \"string\"\n ? msgDict.content\n : JSON.stringify(msgDict.content);\n const status =\n \"status\" in msgDict && msgDict.status === \"error\"\n ? \"error\"\n : \"success\";\n this.subagentManager.processToolMessage(tcId, content, status);\n }\n }\n\n return options.setMessages(values, messages);\n });\n }\n }\n\n if (streamError != null) throw streamError;\n\n // Skip onSuccess when the stream was aborted (e.g., by multitask interrupt).\n // This avoids unnecessary HTTP calls (like history fetching) that would\n // delay the next queued stream from starting.\n if (!this.abortRef.signal.aborted) {\n const values = await options.onSuccess?.();\n if (typeof values !== \"undefined\" && this.queueSize === 0) {\n this.setStreamValues(values);\n }\n }\n } catch (error) {\n if (\n !(\n error instanceof Error && // eslint-disable-line no-instanceof/no-instanceof\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n )\n ) {\n console.error(error);\n this.setState({ error });\n await options.onError?.(error);\n }\n } finally {\n this.setState({ isLoading: false });\n this.abortRef = new AbortController();\n options.onFinish?.();\n }\n };\n\n start = async (\n action: (\n signal: AbortSignal\n ) => Promise<\n AsyncGenerator<\n EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >\n >\n >,\n options: {\n getMessages: (values: StateType) => Message[];\n\n setMessages: (current: StateType, messages: Message[]) => StateType;\n\n initialValues: StateType;\n\n callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n onSuccess: () =>\n | StateType\n | null\n | undefined\n | void\n | Promise<StateType | null | undefined | void>;\n\n onError: (error: unknown) => void | Promise<void>;\n\n onFinish?: () => void;\n },\n startOptions?: {\n /**\n * If true, abort any currently running stream before starting this one.\n * Used for multitask_strategy: \"interrupt\" and \"rollback\" to unblock\n * the queue so the new run request can proceed immediately.\n */\n abortPrevious?: boolean;\n }\n ): Promise<void> => {\n if (startOptions?.abortPrevious) {\n this.abortRef.abort();\n }\n this.queueSize += 1;\n const queued = this.queue.then(() => this.enqueue(action, options));\n this.queue = queued;\n await queued;\n };\n\n stop = async (\n historyValues: StateType,\n options: {\n onStop?: (options: {\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }) => void;\n }\n ): Promise<void> => {\n this.abortRef.abort();\n this.abortRef = new AbortController();\n\n options.onStop?.({ mutate: this.getMutateFn(\"stop\", historyValues) });\n };\n\n clear = () => {\n // Cancel any running streams\n this.abortRef.abort();\n this.abortRef = new AbortController();\n\n // Set the stream state to null\n this.setState({ error: undefined, values: null, isLoading: false });\n\n // Clear any pending messages\n this.messages.clear();\n\n // Clear subagent state\n this.subagentManager.clear();\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"manager.cjs","names":["toMessageDict","SubagentManager","StreamError","isSubagentNamespace","extractToolCallIdFromNamespace"],"sources":["../../src/ui/manager.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\n\nimport { DEFAULT_MESSAGES_KEY } from \"../stream/constants.js\";\nimport type {\n CheckpointsStreamEvent,\n CustomStreamEvent,\n DebugStreamEvent,\n ErrorStreamEvent,\n EventsStreamEvent,\n FeedbackStreamEvent,\n MessagesTupleStreamEvent,\n MetadataStreamEvent,\n TasksStreamEvent,\n ToolsStreamEvent,\n UpdatesStreamEvent,\n ValuesStreamEvent,\n} from \"../types.stream.js\";\nimport { MessageTupleManager, toMessageDict } from \"./messages.js\";\nimport { StreamError } from \"./errors.js\";\nimport type { Message } from \"../types.messages.js\";\nimport type { BagTemplate } from \"../types.template.js\";\nimport {\n SubagentManager,\n extractToolCallIdFromNamespace,\n isSubagentNamespace,\n} from \"./subagents.js\";\nimport type { SubagentStreamInterface } from \"./types.js\";\n\n/**\n * Special ID used by LangGraph's messagesStateReducer to signal\n * that all messages should be removed from the state.\n */\nexport const REMOVE_ALL_MESSAGES = \"__remove_all__\";\n\ntype GetUpdateType<\n Bag extends BagTemplate,\n StateType extends Record<string, unknown>,\n> = Bag extends { UpdateType: unknown }\n ? Bag[\"UpdateType\"]\n : Partial<StateType>;\n\ntype GetCustomEventType<Bag extends BagTemplate> = Bag extends {\n CustomEventType: unknown;\n}\n ? Bag[\"CustomEventType\"]\n : unknown;\n\ntype EventStreamMap<StateType, UpdateType, CustomType> = {\n values: ValuesStreamEvent<StateType>;\n updates: UpdatesStreamEvent<UpdateType>;\n custom: CustomStreamEvent<CustomType>;\n debug: DebugStreamEvent;\n messages: MessagesTupleStreamEvent;\n events: EventsStreamEvent;\n metadata: MetadataStreamEvent;\n checkpoints: CheckpointsStreamEvent<StateType>;\n tasks: TasksStreamEvent<StateType, UpdateType>;\n error: ErrorStreamEvent;\n feedback: FeedbackStreamEvent;\n tools: ToolsStreamEvent;\n};\n\nexport type EventStreamEvent<StateType, UpdateType, CustomType> =\n EventStreamMap<StateType, UpdateType, CustomType>[keyof EventStreamMap<\n StateType,\n UpdateType,\n CustomType\n >];\n\ninterface StreamManagerEventCallbacks<\n StateType extends Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n> {\n onUpdateEvent?: (\n data: UpdatesStreamEvent<GetUpdateType<Bag, StateType>>[\"data\"],\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n onCustomEvent?: (\n data: GetCustomEventType<Bag>,\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n onMetadataEvent?: (data: MetadataStreamEvent[\"data\"]) => void;\n onLangChainEvent?: (data: EventsStreamEvent[\"data\"]) => void;\n onDebugEvent?: (\n data: DebugStreamEvent[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onCheckpointEvent?: (\n data: CheckpointsStreamEvent<StateType>[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onTaskEvent?: (\n data: TasksStreamEvent<StateType, GetUpdateType<Bag, StateType>>[\"data\"],\n options: { namespace: string[] | undefined }\n ) => void;\n onToolEvent?: (\n data: ToolsStreamEvent[\"data\"],\n options: {\n namespace: string[] | undefined;\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }\n ) => void;\n}\n\n/**\n * Options for StreamManager constructor.\n */\nexport interface StreamManagerOptions {\n /**\n * Throttle the stream updates.\n * If a number is provided, updates are throttled to the given milliseconds.\n * If `true`, updates are batched in a single macrotask.\n * If `false`, updates are not throttled.\n */\n throttle: number | boolean;\n\n /**\n * Tool names that indicate subagent invocation.\n *\n * When an AI message contains tool calls with these names, they are\n * automatically tracked as subagent executions. This enables the\n * `subagents`, `activeSubagents`, `getSubagent()`, and `getSubagentsByType()`\n * properties on the stream.\n *\n * @default [\"task\"]\n *\n * @example\n * ```typescript\n * // Track both \"task\" and \"delegate\" as subagent tools\n * subagentToolNames: [\"task\", \"delegate\", \"spawn_agent\"]\n * ```\n */\n subagentToolNames?: string[];\n\n /**\n * Filter out messages from subagent streams in the main messages array.\n *\n * When enabled, messages from subagraph executions (those with a `tools:` namespace)\n * are excluded from `stream.messages`. Instead, these messages are tracked\n * per-subagent and accessible via `stream.subagents.get(id).messages`.\n *\n * This is useful for deep agent architectures where you want to display\n * the main conversation separately from subagent activity.\n *\n * @default false\n *\n * @example\n * ```typescript\n * const stream = useStream({\n * assistantId: \"my-agent\",\n * filterSubagentMessages: true,\n * });\n *\n * // Main thread messages only (no subagent messages)\n * stream.messages\n *\n * // Access subagent messages individually\n * stream.subagents.get(\"call_xyz\").messages\n * ```\n */\n filterSubagentMessages?: boolean;\n\n /**\n * Converts a @langchain/core BaseMessage to the desired output format.\n *\n * Defaults to `toMessageDict` which produces plain Message objects.\n * Framework SDKs pass `toMessageClass` (identity) to keep class instances.\n */\n toMessage?: (chunk: BaseMessage) => Message | BaseMessage;\n}\n\nexport class StreamManager<\n StateType extends Record<string, unknown>,\n Bag extends BagTemplate = BagTemplate,\n> {\n private abortRef = new AbortController();\n\n private messages: MessageTupleManager;\n\n private subagentManager: SubagentManager;\n\n private listeners = new Set<() => void>();\n\n private throttle: number | boolean;\n\n private filterSubagentMessages: boolean;\n\n private toMessage: (chunk: BaseMessage) => Message | BaseMessage;\n\n private queue: Promise<unknown> = Promise.resolve();\n\n private queueSize: number = 0;\n\n private state: {\n isLoading: boolean;\n values: [values: StateType, kind: \"stream\" | \"stop\"] | null;\n error: unknown;\n /** Version counter to force React re-renders on subagent changes */\n version: number;\n };\n\n constructor(messages: MessageTupleManager, options: StreamManagerOptions) {\n this.messages = messages;\n this.state = {\n isLoading: false,\n values: null,\n error: undefined,\n version: 0,\n };\n this.throttle = options.throttle;\n this.filterSubagentMessages = options.filterSubagentMessages ?? false;\n this.toMessage = options.toMessage ?? toMessageDict;\n this.subagentManager = new SubagentManager({\n subagentToolNames: options.subagentToolNames,\n onSubagentChange: () => this.bumpVersion(),\n toMessage: this.toMessage,\n });\n }\n\n /**\n * Increment version counter to trigger React re-renders.\n * Called when subagent state changes.\n */\n private bumpVersion = () => {\n this.state = { ...this.state, version: this.state.version + 1 };\n this.notifyListeners();\n };\n\n /**\n * Get all subagents as a Map.\n */\n getSubagents(): Map<string, SubagentStreamInterface> {\n return this.subagentManager.getSubagents();\n }\n\n /**\n * Get all currently running subagents.\n */\n getActiveSubagents(): SubagentStreamInterface[] {\n return this.subagentManager.getActiveSubagents();\n }\n\n /**\n * Get a specific subagent by tool call ID.\n */\n getSubagent(toolCallId: string): SubagentStreamInterface | undefined {\n return this.subagentManager.getSubagent(toolCallId);\n }\n\n /**\n * Get all subagents of a specific type.\n */\n getSubagentsByType(type: string): SubagentStreamInterface[] {\n return this.subagentManager.getSubagentsByType(type);\n }\n\n /**\n * Get all subagents triggered by a specific AI message.\n */\n getSubagentsByMessage(messageId: string): SubagentStreamInterface[] {\n return this.subagentManager.getSubagentsByMessage(messageId);\n }\n\n /**\n * Reconstruct subagent state from historical messages.\n *\n * This method should be called when loading thread history to restore\n * subagent visualization after:\n * - Page refresh (when stream has already completed)\n * - Loading thread history\n * - Navigating between threads\n *\n * @param messages - Array of messages from thread history\n * @param options - Optional configuration\n * @param options.skipIfPopulated - If true, skip reconstruction if subagents already exist\n */\n reconstructSubagents(\n messages: Message[],\n options?: { skipIfPopulated?: boolean }\n ): void {\n this.subagentManager.reconstructFromMessages(messages, options);\n }\n\n /**\n * Fetch and restore internal messages for reconstructed subagents from their\n * subgraph checkpoints. Should be called after `reconstructSubagents` to\n * restore the full subagent conversation after a page refresh.\n *\n * Subagent messages are persisted in the LangGraph checkpointer under a\n * subgraph-specific `checkpoint_ns` (e.g. `tools:<uuid>`). This method\n * discovers the correct namespace by inspecting the main thread's intermediate\n * history checkpoints, where each pending task's `checkpoint.checkpoint_ns`\n * identifies the subgraph. Tasks are matched to tool calls by their Send index\n * (`task.path[1]`), which corresponds to the order of tool calls in the AI\n * message — no deepagent-specific metadata required.\n *\n * @param threads - Client with a `getHistory` method (e.g. `client.threads`)\n * @param threadId - The parent thread ID\n * @param options - Optional configuration\n * @param options.messagesKey - Key in state values containing messages (default: \"messages\")\n * @param options.signal - AbortSignal to cancel in-flight requests on effect cleanup\n */\n async fetchSubagentHistory(\n threads: {\n getHistory<V extends Record<string, unknown>>(\n threadId: string,\n options?: {\n limit?: number;\n checkpoint?: { checkpoint_ns?: string };\n signal?: AbortSignal;\n }\n ): Promise<\n Array<{\n values: V;\n tasks?: Array<{\n id: string;\n name: string;\n path?: unknown[];\n checkpoint?: { checkpoint_ns?: string } | null;\n }>;\n }>\n >;\n },\n threadId: string,\n options?: {\n messagesKey?: string;\n historyLimit?: number;\n signal?: AbortSignal;\n }\n ): Promise<void> {\n const messagesKey = options?.messagesKey ?? DEFAULT_MESSAGES_KEY;\n const signal = options?.signal;\n\n /**\n * Bail immediately if already cancelled (React Strict Mode cleanup)\n */\n if (signal?.aborted) {\n return;\n }\n\n /**\n * Only fetch for subagents that have no messages (reconstructed from history)\n */\n const toFetch = [...this.subagentManager.getSubagents().entries()].filter(\n ([, s]) => s.messages.length === 0\n );\n\n /**\n * Bail immediately if there are no subagents to fetch\n */\n if (toFetch.length === 0) {\n return;\n }\n\n /**\n * Step 1: Discover subgraph namespaces from intermediate history\n *\n * When LangGraph dispatches parallel tool calls (v2 mode), each is a\n * separate Send task with a unique UUID-based checkpoint_ns. The intermediate\n * history checkpoints record these as `tasks[i]` where:\n * - `tasks[i].checkpoint.checkpoint_ns` = \"tools:<uuid>\" for each subgraph\n * - `tasks[i].path = [\"__pregel_push\", sendIndex]` matches tool_calls order\n *\n * By matching task Send index → tool_call position in the AI message we can\n * derive the subgraph namespace for every tool call without any external\n * metadata on the ToolMessage itself.\n */\n const toolCallIdToNamespace = new Map<string, string>();\n\n try {\n /**\n * Fetch enough history to include the intermediate checkpoint where\n * tool-call tasks were pending (typically within the last 10 checkpoints).\n */\n const mainHistory = await threads.getHistory<Record<string, unknown>>(\n threadId,\n { limit: options?.historyLimit ?? 20, signal }\n );\n\n /**\n * Phase 1: Direct mapping across ALL checkpoints (preferred).\n *\n * When a completed checkpoint contains task results, each task.result\n * has a ToolMessage whose tool_call_id directly and unambiguously maps\n * the task to the LLM tool call that triggered it. This is more robust\n * than positional alignment: it works even when a step mixes subagent\n * tool calls with other tool calls, and requires no assumptions about\n * the ordering of tasks vs tool_calls.\n *\n * We collect these direct mappings across the entire history before\n * attempting any positional fallback. Otherwise a more recent checkpoint\n * whose task is still pending (e.g. an interrupted run) could produce a\n * positional guess and stop the scan before reaching the older checkpoint\n * that actually holds the correct, completed mapping.\n *\n * LangGraph v2 dispatches each parallel tool call as a separate PUSH\n * task (\"__pregel_push\"). The subgraph checkpoint_ns is constructed as\n * `task.name + \":\" + task.id`, mirroring algo.ts:\n * taskCheckpointNamespace = checkpointNamespace + \":\" + taskId\n * where checkpointNamespace = task.name for root-level tasks.\n *\n * task.checkpoint is always null for completed tasks, so we derive the\n * namespace from task.name + task.id rather than task.checkpoint.checkpoint_ns.\n */\n for (const checkpoint of mainHistory) {\n const { tasks } = checkpoint;\n if (!tasks || tasks.length === 0) {\n continue;\n }\n\n for (const task of tasks) {\n if (\n !Array.isArray(task.path) ||\n task.path[0] !== \"__pregel_push\" ||\n typeof task.id !== \"string\" ||\n typeof task.name !== \"string\"\n ) {\n continue;\n }\n\n /**\n * Read tool_call_id directly from the task's result ToolMessage.\n */\n const resultMessages = (\n task as unknown as { result?: { messages?: unknown[] } }\n ).result?.messages;\n\n if (!Array.isArray(resultMessages)) {\n continue;\n }\n\n for (const msg of resultMessages) {\n const m = msg as Record<string, unknown>;\n if (\n m.type === \"tool\" &&\n typeof m.tool_call_id === \"string\" &&\n toFetch.some(([id]) => id === m.tool_call_id) &&\n !toolCallIdToNamespace.has(m.tool_call_id)\n ) {\n toolCallIdToNamespace.set(\n m.tool_call_id,\n `${task.name}:${task.id}`\n );\n }\n }\n }\n }\n\n /**\n * Phase 2: Positional fallback, applied ONLY to tool calls that Phase 1\n * could not resolve.\n *\n * This covers checkpoints whose task results are not yet populated (tasks\n * still pending — the live or just-interrupted case). We align push tasks\n * to the subagent tool calls of the triggering AI message by Send index\n * (task.path[1]). Restricting this to still-unmapped tool calls guarantees\n * a correct direct mapping from Phase 1 is never overwritten by a guess.\n */\n const hasUnmappedToolCalls = () =>\n toFetch.some(([id]) => !toolCallIdToNamespace.has(id));\n\n if (hasUnmappedToolCalls()) {\n for (const checkpoint of mainHistory) {\n if (!hasUnmappedToolCalls()) break;\n\n const { tasks } = checkpoint;\n if (!tasks || tasks.length === 0) {\n continue;\n }\n\n const pushTasks = tasks.filter(\n (t) =>\n Array.isArray(t.path) &&\n t.path[0] === \"__pregel_push\" &&\n typeof t.path[1] === \"number\" &&\n // Send tasks are `[PUSH, i]` (legacy JS servers) or\n // `[PUSH, i, false]` (aligned with Python); longer paths are\n // error handlers of failed Sends (`[PUSH, i, false,\n // \"node_error_handler\", false]`) and must not be mistaken for\n // a second Send at the same index.\n t.path.length <= 3 &&\n typeof t.id === \"string\" &&\n typeof t.name === \"string\"\n );\n if (pushTasks.length === 0) continue;\n\n /**\n * Find the AI message with subagent tool calls to align by Send index.\n */\n const msgs = checkpoint.values[messagesKey];\n if (!Array.isArray(msgs)) continue;\n\n let aiMessage: Record<string, unknown> | undefined;\n for (let i = msgs.length - 1; i >= 0; i -= 1) {\n const m = msgs[i] as Record<string, unknown>;\n if (\n m.type === \"ai\" &&\n Array.isArray(m.tool_calls) &&\n m.tool_calls.length > 0 &&\n (m.tool_calls as Array<{ name: string }>).some((tc) =>\n this.subagentManager.isSubagentToolCall(tc.name)\n )\n ) {\n aiMessage = m;\n break;\n }\n }\n if (!aiMessage) {\n continue;\n }\n\n /**\n * Only consider subagent tool calls from the AI message — not all tool\n * calls. This ensures regular tool calls (searchWeb, queryDatabase, etc.)\n * are never mistaken for subagents even when they appear in the same step.\n */\n const subagentToolCalls = (\n aiMessage.tool_calls as Array<{ id?: string; name: string }>\n ).filter((tc) => this.subagentManager.isSubagentToolCall(tc.name));\n\n if (subagentToolCalls.length === 0) {\n continue;\n }\n\n /**\n * Sort push tasks by Send index (path[1]) to align with tool_calls order\n */\n const sorted = [...pushTasks].sort((a, b) => {\n const ai = Array.isArray(a.path) ? (a.path[1] as number) : 0;\n const bi = Array.isArray(b.path) ? (b.path[1] as number) : 0;\n return ai - bi;\n });\n\n for (\n let i = 0;\n i < sorted.length && i < subagentToolCalls.length;\n i += 1\n ) {\n const tc = subagentToolCalls[i];\n const task = sorted[i];\n if (\n tc?.id &&\n task.id &&\n task.name &&\n toFetch.some(([id]) => id === tc.id) &&\n !toolCallIdToNamespace.has(tc.id)\n ) {\n toolCallIdToNamespace.set(tc.id, `${task.name}:${task.id}`);\n }\n }\n }\n }\n } catch {\n /**\n * Non-fatal: fall back to subagent.namespace below\n */\n }\n\n /**\n * Step 2: Fetch each subagent's conversation from its subgraph checkpoint\n */\n await Promise.all(\n toFetch.map(async ([toolCallId, subagent]) => {\n /**\n * Priority order for the subgraph checkpoint_ns:\n * 1. Derived from main thread's intermediate task list (preferred, no coupling)\n * 2. Already on the subagent's namespace (e.g. populated during streaming)\n * 3. Skip — we cannot reliably identify the namespace\n */\n const checkpointNs =\n toolCallIdToNamespace.get(toolCallId) ??\n (subagent.namespace.length > 0\n ? subagent.namespace.join(\"|\")\n : undefined);\n\n if (!checkpointNs) return;\n\n try {\n const history = await threads.getHistory<Record<string, unknown>>(\n threadId,\n {\n checkpoint: { checkpoint_ns: checkpointNs },\n limit: 1,\n signal,\n }\n );\n\n /**\n * If the HTTP request was cancelled mid-flight the getHistory call\n * would have thrown an AbortError (caught below). If we reach here the\n * fetch completed successfully, so always process the result.\n */\n const latestState = history[0];\n if (!latestState?.values) return;\n\n const messages = latestState.values[messagesKey];\n if (!Array.isArray(messages) || messages.length === 0) return;\n\n /**\n * Normalize messages: promote tool_calls from additional_kwargs to top\n * level when the checkpointer serialized them in the legacy format.\n */\n const normalizedMessages = messages.map((msg) => {\n const m = msg as Record<string, unknown>;\n if (\n m.type === \"ai\" &&\n (!m.tool_calls || (m.tool_calls as unknown[]).length === 0)\n ) {\n const ak = m.additional_kwargs as\n | Record<string, unknown>\n | undefined;\n const legacy = ak?.tool_calls;\n if (Array.isArray(legacy) && legacy.length > 0) {\n return { ...m, tool_calls: legacy };\n }\n }\n return m;\n });\n\n this.subagentManager.updateSubagentFromSubgraphState(\n toolCallId,\n normalizedMessages as Message[],\n latestState.values\n );\n } catch {\n /**\n * Ignore AbortError and other transient errors\n */\n }\n })\n );\n }\n\n /**\n * Check if any subagents are currently tracked.\n */\n hasSubagents(): boolean {\n return this.subagentManager.hasSubagents();\n }\n\n private setState = (newState: Partial<typeof this.state>) => {\n this.state = { ...this.state, ...newState };\n this.notifyListeners();\n };\n\n private notifyListeners = () => {\n this.listeners.forEach((listener) => listener());\n };\n\n subscribe = (listener: () => void): (() => void) => {\n if (this.throttle === false) {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n const timeoutMs = this.throttle === true ? 0 : this.throttle;\n let timeoutId: NodeJS.Timeout | number | undefined;\n\n const throttledListener = () => {\n clearTimeout(timeoutId);\n timeoutId = setTimeout(() => {\n clearTimeout(timeoutId);\n listener();\n }, timeoutMs);\n };\n\n this.listeners.add(throttledListener);\n return () => {\n clearTimeout(timeoutId);\n this.listeners.delete(throttledListener);\n };\n };\n\n getSnapshot = () => this.state;\n\n get isLoading() {\n return this.state.isLoading;\n }\n\n get values() {\n return this.state.values?.[0] ?? null;\n }\n\n get error() {\n return this.state.error;\n }\n\n setStreamValues = (\n values:\n | (StateType | null)\n | ((prev: StateType | null, kind: \"stream\" | \"stop\") => StateType | null),\n kind: \"stream\" | \"stop\" = \"stream\"\n ) => {\n if (typeof values === \"function\") {\n const [prevValues, prevKind] = this.state.values ?? [null, \"stream\"];\n const nextValues = values(prevValues, prevKind);\n this.setState({ values: nextValues != null ? [nextValues, kind] : null });\n } else {\n const nextValues = values != null ? [values, kind] : null;\n this.setState({ values: nextValues as [StateType, \"stream\" | \"stop\"] });\n }\n };\n\n private getMutateFn = (kind: \"stream\" | \"stop\", historyValues: StateType) => {\n return (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => {\n const stateValues = (this.state.values ?? [null, \"stream\"])[0];\n const prev = {\n ...historyValues,\n ...stateValues,\n };\n const next = typeof update === \"function\" ? update(prev) : update;\n this.setStreamValues({ ...prev, ...next }, kind);\n };\n };\n\n private matchEventType = <\n T extends keyof EventStreamMap<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >,\n >(\n expected: T,\n actual: EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[\"event\"],\n _data: EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[\"data\"]\n ): _data is EventStreamMap<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >[T][\"data\"] => {\n return expected === actual || actual.startsWith(`${expected}|`);\n };\n\n protected enqueue = async (\n action: (\n signal: AbortSignal\n ) => Promise<\n AsyncGenerator<\n EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >\n >\n >,\n options: {\n getMessages: (values: StateType) => Message[];\n\n setMessages: (current: StateType, messages: Message[]) => StateType;\n\n initialValues: StateType;\n\n callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n onSuccess: () =>\n | StateType\n | null\n | undefined\n | void\n | Promise<StateType | null | undefined | void>;\n\n onError: (error: unknown) => void | Promise<void>;\n\n onFinish?: () => void;\n }\n ) => {\n try {\n this.queueSize = Math.max(0, this.queueSize - 1);\n this.setState({ isLoading: true, error: undefined });\n this.abortRef = new AbortController();\n\n const run = await action(this.abortRef.signal);\n let clearedPreviousInterrupts = false;\n\n let streamError: StreamError | undefined;\n for await (const { event, data } of run) {\n if (event === \"error\") {\n streamError = new StreamError(data);\n break;\n }\n\n const namespace = event.includes(\"|\")\n ? event.split(\"|\").slice(1)\n : undefined;\n\n const mutate = this.getMutateFn(\"stream\", options.initialValues);\n\n if (event === \"metadata\") options.callbacks.onMetadataEvent?.(data);\n if (event === \"events\") options.callbacks.onLangChainEvent?.(data);\n\n if (this.matchEventType(\"updates\", event, data)) {\n options.callbacks.onUpdateEvent?.(data, { namespace, mutate });\n\n // Track subagent streaming updates from subgraph namespaces\n // Mark the subagent as running when we receive updates\n // The actual message content is handled via addMessageToSubagent\n if (namespace && isSubagentNamespace(namespace)) {\n const namespaceId = extractToolCallIdFromNamespace(namespace);\n if (namespaceId && this.filterSubagentMessages) {\n this.subagentManager.markRunningFromNamespace(\n namespaceId,\n namespace\n );\n }\n }\n\n // Also register subagents from main agent updates (tool_calls in messages)\n // AND process tool results to complete subagents\n // This is needed because tool_calls often appear complete in updates\n // before they appear in the messages stream\n if (!namespace || !isSubagentNamespace(namespace)) {\n const updateData = data as Record<string, unknown>;\n for (const nodeData of Object.values(updateData)) {\n if (\n nodeData &&\n typeof nodeData === \"object\" &&\n \"messages\" in nodeData\n ) {\n const { messages } = nodeData as { messages: unknown[] };\n if (Array.isArray(messages)) {\n for (const msg of messages) {\n if (!msg || typeof msg !== \"object\") continue;\n const msgObj = msg as Record<string, unknown>;\n\n // Register subagents from AI messages with tool_calls\n if (\n msgObj.type === \"ai\" &&\n \"tool_calls\" in msgObj &&\n Array.isArray(msgObj.tool_calls)\n ) {\n this.subagentManager.registerFromToolCalls(\n msgObj.tool_calls as Array<{\n id?: string;\n name: string;\n args: Record<string, unknown> | string;\n }>,\n msgObj.id as string | undefined\n );\n }\n\n // Complete subagents from tool messages (task results)\n if (\n msgObj.type === \"tool\" &&\n \"tool_call_id\" in msgObj &&\n typeof msgObj.tool_call_id === \"string\"\n ) {\n const content =\n typeof msgObj.content === \"string\"\n ? msgObj.content\n : JSON.stringify(msgObj.content);\n const status =\n \"status\" in msgObj && msgObj.status === \"error\"\n ? \"error\"\n : \"success\";\n this.subagentManager.processToolMessage(\n msgObj.tool_call_id,\n content,\n status\n );\n }\n }\n }\n }\n }\n }\n }\n\n if (this.matchEventType(\"custom\", event, data)) {\n options.callbacks.onCustomEvent?.(data, { namespace, mutate });\n }\n\n if (this.matchEventType(\"checkpoints\", event, data)) {\n options.callbacks.onCheckpointEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"tasks\", event, data)) {\n options.callbacks.onTaskEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"debug\", event, data)) {\n options.callbacks.onDebugEvent?.(data, { namespace });\n }\n\n if (this.matchEventType(\"tools\", event, data)) {\n options.callbacks.onToolEvent?.(data, { namespace, mutate });\n }\n\n // Handle values events - use startsWith to match both \"values\" and \"values|tools:xxx\"\n if (event === \"values\" || event.startsWith(\"values|\")) {\n // Check if this is a subgraph values event (for namespace mapping and values)\n if (namespace && isSubagentNamespace(namespace)) {\n const namespaceId = extractToolCallIdFromNamespace(namespace);\n if (namespaceId && this.filterSubagentMessages) {\n const valuesData = data as Record<string, unknown>;\n\n // Try to establish namespace mapping from the initial human message\n const messages = valuesData.messages as unknown[];\n if (Array.isArray(messages) && messages.length > 0) {\n const firstMsg = messages[0] as Record<string, unknown>;\n if (\n firstMsg?.type === \"human\" &&\n typeof firstMsg?.content === \"string\"\n ) {\n this.subagentManager.matchSubgraphToSubagent(\n namespaceId,\n firstMsg.content\n );\n }\n }\n\n // Update the subagent's values with the full state\n this.subagentManager.updateSubagentValues(\n namespaceId,\n valuesData\n );\n }\n } else {\n if (!clearedPreviousInterrupts) {\n // Clear stale __interrupt__ from the previous run once the new\n // stream starts delivering main values. This avoids carrying\n // resumed interrupts forward while still preserving the previous\n // interrupt state if the new stream fails before any values\n // arrive.\n this.setStreamValues((prev) => {\n if (prev && \"__interrupt__\" in prev) {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { __interrupt__, ...rest } = prev;\n return rest as StateType;\n }\n return prev;\n });\n clearedPreviousInterrupts = true;\n }\n\n if (data && typeof data === \"object\" && \"__interrupt__\" in data) {\n // When parallel branches each raise an interrupt, the backend\n // may stream separate values events per branch. We accumulate\n // the __interrupt__ arrays so none are lost, but still honor an\n // explicit empty array as \"clear interrupts\".\n const interruptData = data as Partial<StateType> & {\n __interrupt__?: Array<{ id?: string }>;\n };\n this.setStreamValues((prev) => {\n const prevInterrupts = (\n prev as\n | (StateType & { __interrupt__?: Array<{ id?: string }> })\n | null\n )?.__interrupt__;\n\n let interrupts = interruptData.__interrupt__;\n if (Array.isArray(interrupts)) {\n if (interrupts.length === 0) {\n interrupts = [];\n } else if (Array.isArray(prevInterrupts)) {\n const mergedInterrupts = [...prevInterrupts];\n const existingIds = new Set(\n prevInterrupts.map((i) => i.id).filter((id) => id != null)\n );\n for (const interrupt of interrupts) {\n if (interrupt.id != null) {\n if (existingIds.has(interrupt.id)) continue;\n existingIds.add(interrupt.id);\n }\n mergedInterrupts.push(interrupt);\n }\n interrupts = mergedInterrupts;\n }\n }\n\n return {\n ...prev,\n __interrupt__: interrupts,\n } as unknown as StateType;\n });\n } else {\n // Non-interrupt values events must not wipe accumulated\n // __interrupt__ state. Preserve it when the incoming data\n // does not carry its own __interrupt__ field.\n this.setStreamValues((prev) => {\n if (\n prev &&\n \"__interrupt__\" in prev &&\n Array.isArray((prev as Record<string, unknown>).__interrupt__)\n ) {\n return {\n ...(data as StateType),\n __interrupt__: (prev as Record<string, unknown>)\n .__interrupt__,\n } as StateType;\n }\n return data as StateType;\n });\n }\n }\n }\n\n if (this.matchEventType(\"messages\", event, data)) {\n const [serialized, metadata] = data;\n\n // Check if this message is from a subagent namespace\n const eventCheckpointNs =\n namespace && isSubagentNamespace(namespace) ? namespace : undefined;\n const rawCheckpointNs =\n (metadata?.langgraph_checkpoint_ns as string | undefined) ||\n (metadata?.checkpoint_ns as string | undefined);\n const checkpointNs: string[] | undefined =\n eventCheckpointNs ??\n (typeof rawCheckpointNs === \"string\"\n ? rawCheckpointNs.split(\"|\")\n : undefined);\n const isFromSubagent = isSubagentNamespace(checkpointNs);\n const toolCallId = isFromSubagent\n ? extractToolCallIdFromNamespace(checkpointNs)\n : undefined;\n\n // If filtering is enabled and this is a subagent message,\n // add it to the subagent's messages instead of the main stream\n if (this.filterSubagentMessages && isFromSubagent && toolCallId) {\n // Add to subagent's message list\n this.subagentManager.addMessageToSubagent(\n toolCallId,\n serialized,\n metadata\n );\n continue;\n }\n\n const messageId = this.messages.add(serialized, metadata);\n if (!messageId) {\n console.warn(\n \"Failed to add message to manager, no message ID found\"\n );\n continue;\n }\n\n this.setStreamValues((streamValues) => {\n const values = {\n ...options.initialValues,\n ...streamValues,\n };\n\n // Assumption: we're concatenating the message\n let messages = options.getMessages(values).slice();\n const { chunk, index } =\n this.messages.get(messageId, messages.length) ?? {};\n\n if (!chunk || index == null) return values;\n if (chunk.getType() === \"remove\") {\n // Check for special REMOVE_ALL_MESSAGES sentinel\n if (chunk.id === REMOVE_ALL_MESSAGES) {\n // Clear all messages when __remove_all__ is received\n messages = [];\n } else {\n messages.splice(index, 1);\n }\n } else {\n const msgDict = this.toMessage(chunk) as Message;\n messages[index] = msgDict;\n\n // Track subagents from AI messages with tool calls (main agent only)\n if (\n !isFromSubagent &&\n msgDict.type === \"ai\" &&\n \"tool_calls\" in msgDict &&\n Array.isArray(msgDict.tool_calls)\n ) {\n this.subagentManager.registerFromToolCalls(\n msgDict.tool_calls,\n msgDict.id as string | undefined\n );\n }\n\n // Complete subagents when tool messages arrive (main agent only)\n if (\n !isFromSubagent &&\n msgDict.type === \"tool\" &&\n \"tool_call_id\" in msgDict\n ) {\n const tcId = msgDict.tool_call_id as string;\n const content =\n typeof msgDict.content === \"string\"\n ? msgDict.content\n : JSON.stringify(msgDict.content);\n const status =\n \"status\" in msgDict && msgDict.status === \"error\"\n ? \"error\"\n : \"success\";\n this.subagentManager.processToolMessage(tcId, content, status);\n }\n }\n\n return options.setMessages(values, messages);\n });\n }\n }\n\n if (streamError != null) throw streamError;\n\n // Skip onSuccess when the stream was aborted (e.g., by multitask interrupt).\n // This avoids unnecessary HTTP calls (like history fetching) that would\n // delay the next queued stream from starting.\n if (!this.abortRef.signal.aborted) {\n const values = await options.onSuccess?.();\n if (typeof values !== \"undefined\" && this.queueSize === 0) {\n this.setStreamValues(values);\n }\n }\n } catch (error) {\n if (\n !(\n error instanceof Error && // eslint-disable-line no-instanceof/no-instanceof\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n )\n ) {\n console.error(error);\n this.setState({ error });\n await options.onError?.(error);\n }\n } finally {\n this.setState({ isLoading: false });\n this.abortRef = new AbortController();\n options.onFinish?.();\n }\n };\n\n start = async (\n action: (\n signal: AbortSignal\n ) => Promise<\n AsyncGenerator<\n EventStreamEvent<\n StateType,\n GetUpdateType<Bag, StateType>,\n GetCustomEventType<Bag>\n >\n >\n >,\n options: {\n getMessages: (values: StateType) => Message[];\n\n setMessages: (current: StateType, messages: Message[]) => StateType;\n\n initialValues: StateType;\n\n callbacks: StreamManagerEventCallbacks<StateType, Bag>;\n\n onSuccess: () =>\n | StateType\n | null\n | undefined\n | void\n | Promise<StateType | null | undefined | void>;\n\n onError: (error: unknown) => void | Promise<void>;\n\n onFinish?: () => void;\n },\n startOptions?: {\n /**\n * If true, abort any currently running stream before starting this one.\n * Used for multitask_strategy: \"interrupt\" and \"rollback\" to unblock\n * the queue so the new run request can proceed immediately.\n */\n abortPrevious?: boolean;\n }\n ): Promise<void> => {\n if (startOptions?.abortPrevious) {\n this.abortRef.abort();\n }\n this.queueSize += 1;\n const queued = this.queue.then(() => this.enqueue(action, options));\n this.queue = queued;\n await queued;\n };\n\n stop = async (\n historyValues: StateType,\n options: {\n onStop?: (options: {\n mutate: (\n update: Partial<StateType> | ((prev: StateType) => Partial<StateType>)\n ) => void;\n }) => void;\n }\n ): Promise<void> => {\n this.abortRef.abort();\n this.abortRef = new AbortController();\n\n options.onStop?.({ mutate: this.getMutateFn(\"stop\", historyValues) });\n };\n\n clear = () => {\n // Cancel any running streams\n this.abortRef.abort();\n this.abortRef = new AbortController();\n\n // Set the stream state to null\n this.setState({ error: undefined, values: null, isLoading: false });\n\n // Clear any pending messages\n this.messages.clear();\n\n // Clear subagent state\n this.subagentManager.clear();\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.cts","names":[],"sources":["../../src/ui/manager.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"manager.d.cts","names":[],"sources":["../../src/ui/manager.ts"],"mappings":"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"}
|
package/dist/ui/manager.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","names":[],"sources":["../../src/ui/manager.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"manager.d.ts","names":[],"sources":["../../src/ui/manager.ts"],"mappings":"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"}
|
package/dist/ui/manager.js
CHANGED
|
@@ -200,7 +200,7 @@ var StreamManager = class {
|
|
|
200
200
|
if (!hasUnmappedToolCalls()) break;
|
|
201
201
|
const { tasks } = checkpoint;
|
|
202
202
|
if (!tasks || tasks.length === 0) continue;
|
|
203
|
-
const pushTasks = tasks.filter((t) => Array.isArray(t.path) && t.path[0] === "__pregel_push" && typeof t.path[1] === "number" && typeof t.id === "string" && typeof t.name === "string");
|
|
203
|
+
const pushTasks = tasks.filter((t) => Array.isArray(t.path) && t.path[0] === "__pregel_push" && typeof t.path[1] === "number" && t.path.length <= 3 && typeof t.id === "string" && typeof t.name === "string");
|
|
204
204
|
if (pushTasks.length === 0) continue;
|
|
205
205
|
/**
|
|
206
206
|
* Find the AI message with subagent tool calls to align by Send index.
|