@langchain/langgraph-sdk 1.9.4 → 1.9.6
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/base.cjs.map +1 -1
- package/dist/client/base.d.cts +37 -0
- package/dist/client/base.d.cts.map +1 -1
- package/dist/client/base.d.ts +37 -0
- package/dist/client/base.d.ts.map +1 -1
- package/dist/client/base.js.map +1 -1
- package/dist/client/index.d.cts +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client/stream/handles/index.d.ts +1 -1
- package/dist/client/stream/handles/subagents.cjs +1 -1
- package/dist/client/stream/handles/subagents.cjs.map +1 -1
- package/dist/client/stream/handles/subagents.d.cts +2 -2
- package/dist/client/stream/handles/subagents.d.cts.map +1 -1
- package/dist/client/stream/handles/subagents.d.ts +2 -2
- package/dist/client/stream/handles/subagents.d.ts.map +1 -1
- package/dist/client/stream/handles/subagents.js +2 -2
- package/dist/client/stream/handles/subagents.js.map +1 -1
- package/dist/client/stream/handles/subgraphs.cjs +1 -1
- package/dist/client/stream/handles/subgraphs.cjs.map +1 -1
- package/dist/client/stream/handles/subgraphs.d.cts +2 -2
- package/dist/client/stream/handles/subgraphs.d.cts.map +1 -1
- package/dist/client/stream/handles/subgraphs.d.ts +2 -2
- package/dist/client/stream/handles/subgraphs.d.ts.map +1 -1
- package/dist/client/stream/handles/subgraphs.js +2 -2
- package/dist/client/stream/handles/subgraphs.js.map +1 -1
- package/dist/client/stream/handles/tools.cjs +124 -52
- package/dist/client/stream/handles/tools.cjs.map +1 -1
- package/dist/client/stream/handles/tools.d.cts +59 -13
- package/dist/client/stream/handles/tools.d.cts.map +1 -1
- package/dist/client/stream/handles/tools.d.ts +59 -13
- package/dist/client/stream/handles/tools.d.ts.map +1 -1
- package/dist/client/stream/handles/tools.js +122 -53
- package/dist/client/stream/handles/tools.js.map +1 -1
- package/dist/client/stream/index.cjs +13 -5
- package/dist/client/stream/index.cjs.map +1 -1
- package/dist/client/stream/index.d.cts +3 -3
- package/dist/client/stream/index.d.cts.map +1 -1
- package/dist/client/stream/index.d.ts +3 -3
- package/dist/client/stream/index.d.ts.map +1 -1
- package/dist/client/stream/index.js +14 -6
- package/dist/client/stream/index.js.map +1 -1
- package/dist/headless-tools.cjs +131 -4
- package/dist/headless-tools.cjs.map +1 -1
- package/dist/headless-tools.d.cts +9 -1
- package/dist/headless-tools.d.cts.map +1 -1
- package/dist/headless-tools.d.ts +9 -1
- package/dist/headless-tools.d.ts.map +1 -1
- package/dist/headless-tools.js +129 -5
- package/dist/headless-tools.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/stream/controller.cjs +77 -16
- package/dist/stream/controller.cjs.map +1 -1
- package/dist/stream/controller.d.cts +3 -1
- package/dist/stream/controller.d.cts.map +1 -1
- package/dist/stream/controller.d.ts +3 -1
- package/dist/stream/controller.d.ts.map +1 -1
- package/dist/stream/controller.js +78 -17
- package/dist/stream/controller.js.map +1 -1
- package/dist/stream/discovery/subagents.cjs +13 -0
- package/dist/stream/discovery/subagents.cjs.map +1 -1
- package/dist/stream/discovery/subagents.d.cts +5 -0
- package/dist/stream/discovery/subagents.d.cts.map +1 -1
- package/dist/stream/discovery/subagents.d.ts +5 -0
- package/dist/stream/discovery/subagents.d.ts.map +1 -1
- package/dist/stream/discovery/subagents.js +13 -0
- package/dist/stream/discovery/subagents.js.map +1 -1
- package/dist/stream/discovery/subgraphs.cjs +13 -0
- package/dist/stream/discovery/subgraphs.cjs.map +1 -1
- package/dist/stream/discovery/subgraphs.d.cts +5 -0
- package/dist/stream/discovery/subgraphs.d.cts.map +1 -1
- package/dist/stream/discovery/subgraphs.d.ts +5 -0
- package/dist/stream/discovery/subgraphs.d.ts.map +1 -1
- package/dist/stream/discovery/subgraphs.js +13 -0
- package/dist/stream/discovery/subgraphs.js.map +1 -1
- package/dist/stream/index.cjs +3 -0
- package/dist/stream/index.d.cts +5 -5
- package/dist/stream/index.d.ts +5 -5
- package/dist/stream/index.js +2 -1
- package/dist/stream/lifecycle-loading-tracker.cjs +1 -1
- package/dist/stream/lifecycle-loading-tracker.cjs.map +1 -1
- package/dist/stream/lifecycle-loading-tracker.js +1 -1
- package/dist/stream/lifecycle-loading-tracker.js.map +1 -1
- package/dist/stream/projections/tool-calls.cjs.map +1 -1
- package/dist/stream/projections/tool-calls.js.map +1 -1
- package/dist/stream/submit-coordinator.cjs +47 -16
- package/dist/stream/submit-coordinator.cjs.map +1 -1
- package/dist/stream/submit-coordinator.d.cts.map +1 -1
- package/dist/stream/submit-coordinator.d.ts.map +1 -1
- package/dist/stream/submit-coordinator.js +47 -16
- package/dist/stream/submit-coordinator.js.map +1 -1
- package/dist/stream/tool-calls.cjs +39 -2
- package/dist/stream/tool-calls.cjs.map +1 -1
- package/dist/stream/tool-calls.js +38 -3
- package/dist/stream/tool-calls.js.map +1 -1
- package/dist/stream/types-inference.d.cts +65 -7
- package/dist/stream/types-inference.d.cts.map +1 -1
- package/dist/stream/types-inference.d.ts +65 -7
- package/dist/stream/types-inference.d.ts.map +1 -1
- package/dist/stream/types.d.cts +42 -23
- package/dist/stream/types.d.cts.map +1 -1
- package/dist/stream/types.d.ts +42 -23
- package/dist/stream/types.d.ts.map +1 -1
- package/dist/types.messages.d.cts +38 -1
- package/dist/types.messages.d.cts.map +1 -1
- package/dist/types.messages.d.ts +38 -1
- package/dist/types.messages.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"submit-coordinator.js","names":["#options","#rootStore","#queueStore","#getDisposed","#getCurrentThreadId","#setCurrentThreadId","#rememberSelfCreatedThreadId","#forgetSelfCreatedThreadId","#hydrate","#ensureThread","#startDeferredRootPump","#abandonDeferredRootPump","#waitForRootPumpReady","#awaitNextTerminal","#latestUnresolvedInterrupt","#markInterruptResolved","#onSubmitStart","uuidv7","#runAbort","#enqueueSubmission","#drainQueue"],"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()` or\n * `thread.respondInput()` for resumes) 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 recorded\n * into {@link queueStore} and the call returns immediately. After the\n * active run terminates, `#drainQueue` schedules the head of the\n * queue as a fresh submit on the next macrotask. Each drained\n * submission has its own `multitaskStrategy` cleared so it doesn't\n * recursively re-enqueue.\n *\n * @see StreamController - The owner; injects every collaborator dep.\n */\nimport { v7 as uuidv7 } from \"uuid\";\nimport type { ThreadStream } from \"../client/stream/index.js\";\nimport { StreamStore } from \"./store.js\";\nimport type {\n RootSnapshot,\n StreamControllerOptions,\n StreamSubmitOptions,\n} from \"./types.js\";\n\n/**\n * Pointer to a pending root protocol interrupt. Used to target\n * `respondInput` for resume submissions.\n */\ninterface ResolvedInterrupt {\n interruptId: string;\n namespace: string[];\n}\n\n/**\n * Result of awaiting the next root terminal lifecycle event. Mirrors\n * the four 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\n/**\n * Queued submission entry mirrored from the server-side run queue.\n *\n * Surfaces the deferred submission to UI consumers via\n * {@link StreamController.queueStore}.\n */\nexport interface SubmissionQueueEntry<\n StateType extends object = Record<string, unknown>,\n> {\n /** Stable id minted on enqueue (uuidv7 — sortable by creation time). */\n readonly id: string;\n /** Original submit input, narrowed to the partial state shape. */\n readonly values: Partial<StateType> | null | undefined;\n /** Original submit options, minus the strategy slot which is reset on drain. */\n readonly options?: StreamSubmitOptions<StateType>;\n /** Wall-clock timestamp at enqueue. */\n readonly createdAt: Date;\n}\n\n/**\n * Read-only snapshot of the queue. The queue store hands this out\n * directly; consumers must not mutate the array.\n */\nexport type SubmissionQueueSnapshot<\n StateType extends object = Record<string, unknown>,\n> = ReadonlyArray<SubmissionQueueEntry<StateType>>;\n\n/**\n * Frozen empty queue value used as the initial / cleared snapshot.\n *\n * Reusing one frozen reference keeps store identity stable across\n * empty resets, so React's `useSyncExternalStore` doesn't think the\n * queue changed when it actually didn't.\n */\nexport const EMPTY_QUEUE: SubmissionQueueSnapshot<never> = Object.freeze([]);\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 readonly #queueStore: StreamStore<SubmissionQueueSnapshot<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 /** 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 /** Returns the most recent unresolved root interrupt, for resumes. */\n readonly #latestUnresolvedInterrupt: () => ResolvedInterrupt | null;\n /** Marks an interrupt id as resolved so it isn't re-targeted. */\n readonly #markInterruptResolved: (interruptId: string) => void;\n /** Called once at the start of every {@link submit} invocation. */\n readonly #onSubmitStart: () => 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 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 latestUnresolvedInterrupt: () => ResolvedInterrupt | null;\n markInterruptResolved: (interruptId: string) => void;\n onSubmitStart?: () => void;\n }) {\n this.#options = params.options;\n this.#rootStore = params.rootStore;\n this.#queueStore = params.queueStore;\n this.#getDisposed = params.getDisposed;\n this.#getCurrentThreadId = params.getCurrentThreadId;\n this.#setCurrentThreadId = params.setCurrentThreadId;\n this.#rememberSelfCreatedThreadId = params.rememberSelfCreatedThreadId;\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.#latestUnresolvedInterrupt = params.latestUnresolvedInterrupt;\n this.#markInterruptResolved = params.markInterruptResolved;\n this.#onSubmitStart = params.onSubmitStart ?? (() => undefined);\n }\n\n /**\n * Submit input or a resume command 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 #enqueueSubmission};\n * the call returns without dispatching.\n * - `\"interrupt\"` — falls through to the default path\n * (server-side cancellation lands with roadmap A0.3).\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 * @param input - Input payload, or `null`/`undefined` for no input\n * (typical for resume commands).\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 this.#onSubmitStart();\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 client-self-created threads we defer the persistent root SSE\n // pump until after `submitRun` / `respondInput` commits the thread\n // server-side. Opening the pump's `subscription.subscribe` against\n // a not-yet-existent thread row produces a `404: Thread not found`\n // protocol error that strands lifecycle / messages events for the\n // first run. The deferred path starts the pump after dispatch\n // returns (see `#startDeferredRootPump` calls below).\n const thread = this.#ensureThread(currentThreadId, wasSelfCreated);\n const activeThreadId = currentThreadId;\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 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 const hasActiveRun =\n !wasSelfCreated &&\n this.#runAbort != null &&\n !this.#runAbort.signal.aborted;\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 this.#enqueueSubmission(input, options);\n return;\n }\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 const resumeCommand = options?.command?.resume;\n const isResume = resumeCommand !== undefined;\n\n // Optimistically clear interrupts/error and flip loading. The\n // root pump's lifecycle listener will re-flip these as the run\n // terminates.\n this.#rootStore.setState((s) => ({\n ...s,\n interrupts: [],\n interrupt: undefined,\n error: undefined,\n isLoading: true,\n }));\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\n let terminalSettled = false;\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 let terminal: TerminalResult | undefined;\n\n if (isResume) {\n const target = this.#latestUnresolvedInterrupt();\n if (target == null) {\n throw new Error(\n \"submit({ command: { resume } }) called but no pending protocol interrupt is available.\"\n );\n }\n const commandPromise = thread.respondInput({\n namespace: target.namespace,\n interrupt_id: target.interruptId,\n response: resumeCommand,\n config: boundConfig,\n metadata: options?.metadata,\n });\n // Defer the pump start until the dispatch HTTP response\n // lands — see the analogous block in the non-resume path\n // below for the rationale (thread row not committed\n // synchronously). For a resume the thread exists already\n // (it must, since `latestUnresolvedInterrupt()` was non-null),\n // so `#startDeferredRootPump` is typically a no-op here, but\n // we keep the same shape to avoid a future regression.\n //\n // Asymmetry with the non-resume path: we don't call\n // `#forgetSelfCreatedThreadId` because a resume implies the\n // thread already committed, so the self-created marker was\n // already cleared on the original submit. Same reason we\n // don't call `#abandonDeferredRootPump` on failure here.\n void commandPromise.then(\n () => this.#startDeferredRootPump(),\n () => {}\n );\n // Mark resolved synchronously: even if the response races and\n // the command settles after the terminal, we don't want to\n // re-target this same interrupt on the next submit.\n this.#markInterruptResolved(target.interruptId);\n const first = await Promise.race([\n terminalPromise.then((value) => ({\n type: \"terminal\" as const,\n value,\n })),\n commandPromise.then(\n () => ({ type: \"command\" as const }),\n (error) => ({ type: \"error\" as const, error })\n ),\n ]);\n if (first.type === \"error\") throw first.error;\n if (first.type === \"terminal\") {\n terminal = first.value;\n terminalSettled = true;\n // Stale command response — surface as error only if it\n // arrives with a real failure (not just our own abort).\n void commandPromise.catch((error) => {\n if (!terminalSettled) reportError(error);\n });\n }\n } else {\n const commandPromise = thread.submitRun({\n input: input ?? 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 `wasSelfCreated=false`\n // (currentThreadId is no longer null), `#ensureThread`\n // would early-return because `#thread != null`, and the\n // root pump would never start. Tear down so the next\n // submit re-runs `#ensureThread` from scratch.\n if (wasSelfCreated) {\n this.#abandonDeferredRootPump();\n this.#forgetSelfCreatedThreadId(activeThreadId);\n }\n }\n );\n const notifyCreated = (result: { run_id?: unknown }) => {\n this.#options.onCreated?.({\n run_id: result.run_id as string,\n thread_id: activeThreadId,\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\n terminal ??= await terminalPromise;\n terminalSettled = true;\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 } catch (error) {\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 setTimeout(() => this.#drainQueue(), 0);\n }\n }\n\n /**\n * Abort the current run (if any) and force `isLoading=false`.\n *\n * Does NOT issue a server-side cancel — that lands with roadmap\n * A0.3. Today this is a client-side stop only: subsequent events\n * for the aborted run are ignored by the controller's pump because\n * the abort signal is the same one `#awaitNextTerminal` is wired\n * to.\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 * 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 const current = this.#queueStore.getSnapshot();\n const next = current.filter((entry) => entry.id !== id);\n if (next.length === current.length) return false;\n this.#queueStore.setState(() => next);\n return true;\n }\n\n /**\n * Drop every queued submission. Server-side cancel arrives with A0.3.\n */\n async clearQueue(): Promise<void> {\n this.#queueStore.setState(\n () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n );\n }\n\n /**\n * Append a submission to the queue without dispatching.\n *\n * The drained submission is later run via {@link #drainQueue} after\n * the active run terminates.\n */\n #enqueueSubmission(\n input: unknown,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): void {\n const entry: SubmissionQueueEntry<StateType> = {\n id: uuidv7(),\n values: (input ?? undefined) as Partial<StateType> | null | undefined,\n options: options as StreamSubmitOptions<StateType> | undefined,\n createdAt: new Date(),\n };\n this.#queueStore.setState((current) => [...current, entry]);\n }\n\n /**\n * Drain the head of the queue if no run is active.\n *\n * Called from the `finally` block of `submit()` on the next\n * macrotask (so the just-finished run's state flushes first).\n * Strips the strategy off the dequeued options to prevent infinite\n * re-enqueueing.\n */\n #drainQueue(): void {\n if (this.#getDisposed()) return;\n if (this.#runAbort != null && !this.#runAbort.signal.aborted) return;\n const current = this.#queueStore.getSnapshot();\n if (current.length === 0) return;\n const [next, ...rest] = current;\n this.#queueStore.setState(() => rest);\n const nextOptions: StreamSubmitOptions<StateType, ConfigurableType> = {\n ...((next.options ?? {}) as StreamSubmitOptions<\n StateType,\n ConfigurableType\n >),\n multitaskStrategy: undefined,\n };\n void this.submit(next.values, nextOptions).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}\n\n/**\n * Merge `thread_id` into a user-supplied `config.configurable` blob.\n *\n * The platform expects `config.configurable.thread_id` on every run\n * dispatch; we set it last so user-supplied values can't accidentally\n * override the active thread id (which would route the run to a\n * different thread).\n */\nfunction bindThreadConfig(\n config: unknown,\n threadId: string\n): Record<string, unknown> {\n const base =\n config != null && typeof config === \"object\"\n ? (config as Record<string, unknown>)\n : {};\n const configurable =\n base.configurable != null && typeof base.configurable === \"object\"\n ? (base.configurable as Record<string, unknown>)\n : {};\n return {\n ...base,\n configurable: {\n ...configurable,\n thread_id: threadId,\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"submit-coordinator.js","names":["#options","#rootStore","#queueStore","#getDisposed","#getCurrentThreadId","#setCurrentThreadId","#rememberSelfCreatedThreadId","#forgetSelfCreatedThreadId","#hydrate","#ensureThread","#startDeferredRootPump","#abandonDeferredRootPump","#waitForRootPumpReady","#awaitNextTerminal","#buildResumeRunInput","#markInterruptResolved","#onSubmitStart","#onRunStart","#onRunCreated","#onRunCompleted","#onRunEnd","uuidv7","#runAbort","#enqueueSubmission","#drainQueue"],"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()` or\n * `thread.submitRun()` for resumes) 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 recorded\n * into {@link queueStore} and the call returns immediately. After the\n * active run terminates, `#drainQueue` schedules the head of the\n * queue as a fresh submit on the next macrotask. Each drained\n * submission has its own `multitaskStrategy` cleared so it doesn't\n * recursively re-enqueue.\n *\n * @see StreamController - The owner; injects every collaborator dep.\n */\nimport { v7 as uuidv7 } from \"uuid\";\nimport type { ThreadStream } from \"../client/stream/index.js\";\nimport { StreamStore } from \"./store.js\";\nimport type {\n RootSnapshot,\n RunExecutionReason,\n StreamControllerOptions,\n StreamSubmitOptions,\n} from \"./types.js\";\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/**\n * Queued submission entry mirrored from the server-side run queue.\n *\n * Surfaces the deferred submission to UI consumers via\n * {@link StreamController.queueStore}.\n */\nexport interface SubmissionQueueEntry<\n StateType extends object = Record<string, unknown>,\n> {\n /** Stable id minted on enqueue (uuidv7 — sortable by creation time). */\n readonly id: string;\n /** Original submit input, narrowed to the partial state shape. */\n readonly values: Partial<StateType> | null | undefined;\n /** Original submit options, minus the strategy slot which is reset on drain. */\n readonly options?: StreamSubmitOptions<StateType>;\n /** Wall-clock timestamp at enqueue. */\n readonly createdAt: Date;\n}\n\n/**\n * Read-only snapshot of the queue. The queue store hands this out\n * directly; consumers must not mutate the array.\n */\nexport type SubmissionQueueSnapshot<\n StateType extends object = Record<string, unknown>,\n> = ReadonlyArray<SubmissionQueueEntry<StateType>>;\n\n/**\n * Frozen empty queue value used as the initial / cleared snapshot.\n *\n * Reusing one frozen reference keeps store identity stable across\n * empty resets, so React's `useSyncExternalStore` doesn't think the\n * queue changed when it actually didn't.\n */\nexport const EMPTY_QUEUE: SubmissionQueueSnapshot<never> = Object.freeze([]);\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 readonly #queueStore: StreamStore<SubmissionQueueSnapshot<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 /** 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 /** Builds interrupt-id keyed `run.start` input from `command.resume`. */\n readonly #buildResumeRunInput: (\n resume: unknown\n ) => Record<string, unknown> | null;\n /** Marks an interrupt id as resolved so it isn't re-targeted. */\n readonly #markInterruptResolved: (interruptId: string) => void;\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 /**\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 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 buildResumeRunInput: (resume: unknown) => Record<string, unknown> | null;\n markInterruptResolved: (interruptId: string) => void;\n onSubmitStart?: () => void;\n onRunStart?: () => void;\n onRunCreated?: (runId: string) => void;\n onRunCompleted?: (reason: RunExecutionReason, runId?: string) => void;\n onRunEnd?: () => void;\n }) {\n this.#options = params.options;\n this.#rootStore = params.rootStore;\n this.#queueStore = params.queueStore;\n this.#getDisposed = params.getDisposed;\n this.#getCurrentThreadId = params.getCurrentThreadId;\n this.#setCurrentThreadId = params.setCurrentThreadId;\n this.#rememberSelfCreatedThreadId = params.rememberSelfCreatedThreadId;\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.#buildResumeRunInput = params.buildResumeRunInput;\n this.#markInterruptResolved = params.markInterruptResolved;\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 }\n\n /**\n * Submit input or a resume command 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 #enqueueSubmission};\n * the call returns without dispatching.\n * - `\"interrupt\"` — falls through to the default path\n * (server-side cancellation lands with roadmap A0.3).\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 * @param input - Input payload, or `null`/`undefined` for no input\n * (typical for resume commands).\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 this.#onSubmitStart();\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 client-self-created threads we defer the persistent root SSE\n // pump until after `submitRun` / `respondInput` commits the thread\n // server-side. Opening the pump's `subscription.subscribe` against\n // a not-yet-existent thread row produces a `404: Thread not found`\n // protocol error that strands lifecycle / messages events for the\n // first run. The deferred path starts the pump after dispatch\n // returns (see `#startDeferredRootPump` calls below).\n const thread = this.#ensureThread(currentThreadId, wasSelfCreated);\n const activeThreadId = currentThreadId;\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 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 const hasActiveRun =\n !wasSelfCreated &&\n this.#runAbort != null &&\n !this.#runAbort.signal.aborted;\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 this.#enqueueSubmission(input, options);\n return;\n }\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 const resumeCommand = options?.command?.resume;\n const isResume = resumeCommand !== undefined;\n\n // Optimistically clear interrupts/error and flip loading. The\n // root pump's lifecycle listener will re-flip these as the run\n // terminates.\n this.#rootStore.setState((s) => ({\n ...s,\n interrupts: [],\n interrupt: undefined,\n error: undefined,\n isLoading: true,\n }));\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 createdRunId: string | undefined;\n let pendingCompletionReason: RunExecutionReason | undefined;\n let completionNotified = false;\n const notifyCompletion = (reason: RunExecutionReason): void => {\n if (completionNotified) return;\n if (!isResume && 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 let terminal: TerminalResult | undefined;\n\n if (isResume) {\n const resumeInput = this.#buildResumeRunInput(resumeCommand);\n if (resumeInput == null) {\n throw new Error(\n \"submit({ command: { resume } }) called but no pending protocol interrupt is available.\"\n );\n }\n const commandPromise = thread.submitRun({\n input: resumeInput,\n config: boundConfig,\n metadata: (options?.metadata ?? undefined) as Record<string, unknown>,\n });\n // Defer the pump start until the dispatch HTTP response\n // lands — see the analogous block in the non-resume path\n // below for the rationale (thread row not committed\n // synchronously). For a resume the thread exists already\n // (it must, since `buildResumeRunInput()` was non-null),\n // so `#startDeferredRootPump` is typically a no-op here, but\n // we keep the same shape to avoid a future regression.\n //\n // Asymmetry with the non-resume path: we don't call\n // `#forgetSelfCreatedThreadId` because a resume implies the\n // thread already committed, so the self-created marker was\n // already cleared on the original submit. Same reason we\n // don't call `#abandonDeferredRootPump` on failure here.\n void commandPromise.then(\n () => this.#startDeferredRootPump(),\n () => {}\n );\n // Mark resolved synchronously: even if the response races and\n // the command settles after the terminal, we don't want to\n // re-target these interrupts on the next submit.\n for (const interruptId of Object.keys(resumeInput)) {\n this.#markInterruptResolved(interruptId);\n }\n const first = await Promise.race([\n terminalPromise.then((value) => ({\n type: \"terminal\" as const,\n value,\n })),\n commandPromise.then(\n () => ({ type: \"command\" as const }),\n (error) => ({ type: \"error\" as const, error })\n ),\n ]);\n if (first.type === \"error\") throw first.error;\n if (first.type === \"terminal\") {\n terminal = first.value;\n terminalSettled = true;\n // Stale command response — surface as error only if it\n // arrives with a real failure (not just our own abort).\n void commandPromise.catch((error) => {\n if (!terminalSettled) reportError(error);\n });\n }\n } else {\n const commandPromise = thread.submitRun({\n input: input ?? 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 `wasSelfCreated=false`\n // (currentThreadId is no longer null), `#ensureThread`\n // would early-return because `#thread != null`, and the\n // root pump would never start. Tear down so the next\n // submit re-runs `#ensureThread` from scratch.\n if (wasSelfCreated) {\n this.#abandonDeferredRootPump();\n this.#forgetSelfCreatedThreadId(activeThreadId);\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\n terminal ??= await terminalPromise;\n terminalSettled = true;\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 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 this.#onRunEnd();\n setTimeout(() => this.#drainQueue(), 0);\n }\n }\n\n /**\n * Abort the current run (if any) and force `isLoading=false`.\n *\n * Does NOT issue a server-side cancel — that lands with roadmap\n * A0.3. Today this is a client-side stop only: subsequent events\n * for the aborted run are ignored by the controller's pump because\n * the abort signal is the same one `#awaitNextTerminal` is wired\n * to.\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 * 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 const current = this.#queueStore.getSnapshot();\n const next = current.filter((entry) => entry.id !== id);\n if (next.length === current.length) return false;\n this.#queueStore.setState(() => next);\n return true;\n }\n\n /**\n * Drop every queued submission. Server-side cancel arrives with A0.3.\n */\n async clearQueue(): Promise<void> {\n this.#queueStore.setState(\n () => EMPTY_QUEUE as SubmissionQueueSnapshot<StateType>\n );\n }\n\n /**\n * Append a submission to the queue without dispatching.\n *\n * The drained submission is later run via {@link #drainQueue} after\n * the active run terminates.\n */\n #enqueueSubmission(\n input: unknown,\n options?: StreamSubmitOptions<StateType, ConfigurableType>\n ): void {\n const entry: SubmissionQueueEntry<StateType> = {\n id: uuidv7(),\n values: (input ?? undefined) as Partial<StateType> | null | undefined,\n options: options as StreamSubmitOptions<StateType> | undefined,\n createdAt: new Date(),\n };\n this.#queueStore.setState((current) => [...current, entry]);\n }\n\n /**\n * Drain the head of the queue if no run is active.\n *\n * Called from the `finally` block of `submit()` on the next\n * macrotask (so the just-finished run's state flushes first).\n * Strips the strategy off the dequeued options to prevent infinite\n * re-enqueueing.\n */\n #drainQueue(): void {\n if (this.#getDisposed()) return;\n if (this.#runAbort != null && !this.#runAbort.signal.aborted) return;\n const current = this.#queueStore.getSnapshot();\n if (current.length === 0) return;\n const [next, ...rest] = current;\n this.#queueStore.setState(() => rest);\n const nextOptions: StreamSubmitOptions<StateType, ConfigurableType> = {\n ...((next.options ?? {}) as StreamSubmitOptions<\n StateType,\n ConfigurableType\n >),\n multitaskStrategy: undefined,\n };\n void this.submit(next.values, nextOptions).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}\n\n/**\n * Merge `thread_id` into a user-supplied `config.configurable` blob.\n *\n * The platform expects `config.configurable.thread_id` on every run\n * dispatch; we set it last so user-supplied values can't accidentally\n * override the active thread id (which would route the run to a\n * different thread).\n */\nfunction bindThreadConfig(\n config: unknown,\n threadId: string\n): Record<string, unknown> {\n const base =\n config != null && typeof config === \"object\"\n ? (config as Record<string, unknown>)\n : {};\n const configurable =\n base.configurable != null && typeof base.configurable === \"object\"\n ? (base.configurable as Record<string, unknown>)\n : {};\n return {\n ...base,\n configurable: {\n ...configurable,\n thread_id: threadId,\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,15 +1,52 @@
|
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_tools = require("../client/stream/handles/tools.cjs");
|
|
3
|
+
let _langchain_core_messages = require("@langchain/core/messages");
|
|
1
4
|
//#region src/stream/tool-calls.ts
|
|
2
5
|
/**
|
|
3
6
|
* Insert or replace an assembled tool call by call id.
|
|
7
|
+
*
|
|
8
|
+
* ToolCallAssembler mutates its active handle in place as `tool-finished` /
|
|
9
|
+
* `tool-error` events arrive. Publish a fresh object here so framework
|
|
10
|
+
* adapters that pass individual tool calls as props (notably Vue's shallow
|
|
11
|
+
* prop tracking) observe status/output changes.
|
|
4
12
|
*/
|
|
5
13
|
function upsertToolCall(current, next) {
|
|
14
|
+
const snapshot = { ...next };
|
|
6
15
|
const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);
|
|
7
|
-
if (idx < 0) return [...current,
|
|
16
|
+
if (idx < 0) return [...current, snapshot];
|
|
8
17
|
const updated = current.slice();
|
|
9
|
-
updated[idx] =
|
|
18
|
+
updated[idx] = snapshot;
|
|
10
19
|
return updated;
|
|
11
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Backfill unfinished tool-call handles from authoritative ToolMessages in a
|
|
23
|
+
* values snapshot. This covers headless tools whose graph state contains the
|
|
24
|
+
* result even when the `tools` channel omits a matching `tool-finished` event.
|
|
25
|
+
*/
|
|
26
|
+
function reconcileToolCallsFromMessages(toolCalls, messages) {
|
|
27
|
+
let updated;
|
|
28
|
+
for (const message of messages) {
|
|
29
|
+
if (!_langchain_core_messages.ToolMessage.isInstance(message)) continue;
|
|
30
|
+
const callId = message.tool_call_id;
|
|
31
|
+
if (typeof callId !== "string" || callId.length === 0) continue;
|
|
32
|
+
const currentToolCalls = updated ?? toolCalls;
|
|
33
|
+
const idx = currentToolCalls.findIndex((toolCall) => toolCall.callId === callId);
|
|
34
|
+
if (idx < 0) continue;
|
|
35
|
+
const current = currentToolCalls[idx];
|
|
36
|
+
if (current.status === "finished" && current.output != null) continue;
|
|
37
|
+
const output = require_tools.parseToolOutput(message.content);
|
|
38
|
+
if (output == null) continue;
|
|
39
|
+
updated = upsertToolCall(currentToolCalls, {
|
|
40
|
+
...current,
|
|
41
|
+
output,
|
|
42
|
+
status: "finished",
|
|
43
|
+
error: void 0
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return updated ?? toolCalls;
|
|
47
|
+
}
|
|
12
48
|
//#endregion
|
|
49
|
+
exports.reconcileToolCallsFromMessages = reconcileToolCallsFromMessages;
|
|
13
50
|
exports.upsertToolCall = upsertToolCall;
|
|
14
51
|
|
|
15
52
|
//# sourceMappingURL=tool-calls.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-calls.cjs","names":[],"sources":["../../src/stream/tool-calls.ts"],"sourcesContent":["import type { AssembledToolCall } from \"../client/stream/handles/tools.js\";\n\n/**\n * Insert or replace an assembled tool call by call id.\n */\nexport function upsertToolCall(\n current: readonly AssembledToolCall[],\n next: AssembledToolCall\n): AssembledToolCall[] {\n const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);\n if (idx < 0) return [...current,
|
|
1
|
+
{"version":3,"file":"tool-calls.cjs","names":["ToolMessage","parseToolOutput"],"sources":["../../src/stream/tool-calls.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { AssembledToolCall } from \"../client/stream/handles/tools.js\";\nimport { parseToolOutput } from \"../client/stream/handles/tools.js\";\n\n/**\n * Insert or replace an assembled tool call by call id.\n *\n * ToolCallAssembler mutates its active handle in place as `tool-finished` /\n * `tool-error` events arrive. Publish a fresh object here so framework\n * adapters that pass individual tool calls as props (notably Vue's shallow\n * prop tracking) observe status/output changes.\n */\nexport function upsertToolCall(\n current: readonly AssembledToolCall[],\n next: AssembledToolCall\n): AssembledToolCall[] {\n const snapshot = { ...next };\n const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);\n if (idx < 0) return [...current, snapshot];\n const updated = current.slice();\n updated[idx] = snapshot;\n return updated;\n}\n\n/**\n * Backfill unfinished tool-call handles from authoritative ToolMessages in a\n * values snapshot. This covers headless tools whose graph state contains the\n * result even when the `tools` channel omits a matching `tool-finished` event.\n */\nexport function reconcileToolCallsFromMessages(\n toolCalls: readonly AssembledToolCall[],\n messages: readonly BaseMessage[]\n): AssembledToolCall[] {\n let updated: AssembledToolCall[] | undefined;\n for (const message of messages) {\n if (!ToolMessage.isInstance(message)) continue;\n const callId = message.tool_call_id;\n if (typeof callId !== \"string\" || callId.length === 0) continue;\n\n const currentToolCalls = updated ?? toolCalls;\n const idx = currentToolCalls.findIndex(\n (toolCall) => toolCall.callId === callId\n );\n if (idx < 0) continue;\n\n const current = currentToolCalls[idx];\n if (current.status === \"finished\" && current.output != null) continue;\n\n const output = parseToolOutput(message.content);\n if (output == null) continue;\n\n updated = upsertToolCall(currentToolCalls, {\n ...current,\n output,\n status: \"finished\",\n error: undefined,\n });\n }\n return updated ?? (toolCalls as AssembledToolCall[]);\n}\n"],"mappings":";;;;;;;;;;;;AAaA,SAAgB,eACd,SACA,MACqB;CACrB,MAAM,WAAW,EAAE,GAAG,MAAM;CAC5B,MAAM,MAAM,QAAQ,WAAW,aAAa,SAAS,WAAW,KAAK,OAAO;AAC5E,KAAI,MAAM,EAAG,QAAO,CAAC,GAAG,SAAS,SAAS;CAC1C,MAAM,UAAU,QAAQ,OAAO;AAC/B,SAAQ,OAAO;AACf,QAAO;;;;;;;AAQT,SAAgB,+BACd,WACA,UACqB;CACrB,IAAI;AACJ,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,CAACA,yBAAAA,YAAY,WAAW,QAAQ,CAAE;EACtC,MAAM,SAAS,QAAQ;AACvB,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,EAAG;EAEvD,MAAM,mBAAmB,WAAW;EACpC,MAAM,MAAM,iBAAiB,WAC1B,aAAa,SAAS,WAAW,OACnC;AACD,MAAI,MAAM,EAAG;EAEb,MAAM,UAAU,iBAAiB;AACjC,MAAI,QAAQ,WAAW,cAAc,QAAQ,UAAU,KAAM;EAE7D,MAAM,SAASC,cAAAA,gBAAgB,QAAQ,QAAQ;AAC/C,MAAI,UAAU,KAAM;AAEpB,YAAU,eAAe,kBAAkB;GACzC,GAAG;GACH;GACA,QAAQ;GACR,OAAO,KAAA;GACR,CAAC;;AAEJ,QAAO,WAAY"}
|
|
@@ -1,15 +1,50 @@
|
|
|
1
|
+
import { parseToolOutput } from "../client/stream/handles/tools.js";
|
|
2
|
+
import { ToolMessage } from "@langchain/core/messages";
|
|
1
3
|
//#region src/stream/tool-calls.ts
|
|
2
4
|
/**
|
|
3
5
|
* Insert or replace an assembled tool call by call id.
|
|
6
|
+
*
|
|
7
|
+
* ToolCallAssembler mutates its active handle in place as `tool-finished` /
|
|
8
|
+
* `tool-error` events arrive. Publish a fresh object here so framework
|
|
9
|
+
* adapters that pass individual tool calls as props (notably Vue's shallow
|
|
10
|
+
* prop tracking) observe status/output changes.
|
|
4
11
|
*/
|
|
5
12
|
function upsertToolCall(current, next) {
|
|
13
|
+
const snapshot = { ...next };
|
|
6
14
|
const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);
|
|
7
|
-
if (idx < 0) return [...current,
|
|
15
|
+
if (idx < 0) return [...current, snapshot];
|
|
8
16
|
const updated = current.slice();
|
|
9
|
-
updated[idx] =
|
|
17
|
+
updated[idx] = snapshot;
|
|
10
18
|
return updated;
|
|
11
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Backfill unfinished tool-call handles from authoritative ToolMessages in a
|
|
22
|
+
* values snapshot. This covers headless tools whose graph state contains the
|
|
23
|
+
* result even when the `tools` channel omits a matching `tool-finished` event.
|
|
24
|
+
*/
|
|
25
|
+
function reconcileToolCallsFromMessages(toolCalls, messages) {
|
|
26
|
+
let updated;
|
|
27
|
+
for (const message of messages) {
|
|
28
|
+
if (!ToolMessage.isInstance(message)) continue;
|
|
29
|
+
const callId = message.tool_call_id;
|
|
30
|
+
if (typeof callId !== "string" || callId.length === 0) continue;
|
|
31
|
+
const currentToolCalls = updated ?? toolCalls;
|
|
32
|
+
const idx = currentToolCalls.findIndex((toolCall) => toolCall.callId === callId);
|
|
33
|
+
if (idx < 0) continue;
|
|
34
|
+
const current = currentToolCalls[idx];
|
|
35
|
+
if (current.status === "finished" && current.output != null) continue;
|
|
36
|
+
const output = parseToolOutput(message.content);
|
|
37
|
+
if (output == null) continue;
|
|
38
|
+
updated = upsertToolCall(currentToolCalls, {
|
|
39
|
+
...current,
|
|
40
|
+
output,
|
|
41
|
+
status: "finished",
|
|
42
|
+
error: void 0
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return updated ?? toolCalls;
|
|
46
|
+
}
|
|
12
47
|
//#endregion
|
|
13
|
-
export { upsertToolCall };
|
|
48
|
+
export { reconcileToolCallsFromMessages, upsertToolCall };
|
|
14
49
|
|
|
15
50
|
//# sourceMappingURL=tool-calls.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-calls.js","names":[],"sources":["../../src/stream/tool-calls.ts"],"sourcesContent":["import type { AssembledToolCall } from \"../client/stream/handles/tools.js\";\n\n/**\n * Insert or replace an assembled tool call by call id.\n */\nexport function upsertToolCall(\n current: readonly AssembledToolCall[],\n next: AssembledToolCall\n): AssembledToolCall[] {\n const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);\n if (idx < 0) return [...current,
|
|
1
|
+
{"version":3,"file":"tool-calls.js","names":[],"sources":["../../src/stream/tool-calls.ts"],"sourcesContent":["import type { BaseMessage } from \"@langchain/core/messages\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport type { AssembledToolCall } from \"../client/stream/handles/tools.js\";\nimport { parseToolOutput } from \"../client/stream/handles/tools.js\";\n\n/**\n * Insert or replace an assembled tool call by call id.\n *\n * ToolCallAssembler mutates its active handle in place as `tool-finished` /\n * `tool-error` events arrive. Publish a fresh object here so framework\n * adapters that pass individual tool calls as props (notably Vue's shallow\n * prop tracking) observe status/output changes.\n */\nexport function upsertToolCall(\n current: readonly AssembledToolCall[],\n next: AssembledToolCall\n): AssembledToolCall[] {\n const snapshot = { ...next };\n const idx = current.findIndex((toolCall) => toolCall.callId === next.callId);\n if (idx < 0) return [...current, snapshot];\n const updated = current.slice();\n updated[idx] = snapshot;\n return updated;\n}\n\n/**\n * Backfill unfinished tool-call handles from authoritative ToolMessages in a\n * values snapshot. This covers headless tools whose graph state contains the\n * result even when the `tools` channel omits a matching `tool-finished` event.\n */\nexport function reconcileToolCallsFromMessages(\n toolCalls: readonly AssembledToolCall[],\n messages: readonly BaseMessage[]\n): AssembledToolCall[] {\n let updated: AssembledToolCall[] | undefined;\n for (const message of messages) {\n if (!ToolMessage.isInstance(message)) continue;\n const callId = message.tool_call_id;\n if (typeof callId !== \"string\" || callId.length === 0) continue;\n\n const currentToolCalls = updated ?? toolCalls;\n const idx = currentToolCalls.findIndex(\n (toolCall) => toolCall.callId === callId\n );\n if (idx < 0) continue;\n\n const current = currentToolCalls[idx];\n if (current.status === \"finished\" && current.output != null) continue;\n\n const output = parseToolOutput(message.content);\n if (output == null) continue;\n\n updated = upsertToolCall(currentToolCalls, {\n ...current,\n output,\n status: \"finished\",\n error: undefined,\n });\n }\n return updated ?? (toolCalls as AssembledToolCall[]);\n}\n"],"mappings":";;;;;;;;;;;AAaA,SAAgB,eACd,SACA,MACqB;CACrB,MAAM,WAAW,EAAE,GAAG,MAAM;CAC5B,MAAM,MAAM,QAAQ,WAAW,aAAa,SAAS,WAAW,KAAK,OAAO;AAC5E,KAAI,MAAM,EAAG,QAAO,CAAC,GAAG,SAAS,SAAS;CAC1C,MAAM,UAAU,QAAQ,OAAO;AAC/B,SAAQ,OAAO;AACf,QAAO;;;;;;;AAQT,SAAgB,+BACd,WACA,UACqB;CACrB,IAAI;AACJ,MAAK,MAAM,WAAW,UAAU;AAC9B,MAAI,CAAC,YAAY,WAAW,QAAQ,CAAE;EACtC,MAAM,SAAS,QAAQ;AACvB,MAAI,OAAO,WAAW,YAAY,OAAO,WAAW,EAAG;EAEvD,MAAM,mBAAmB,WAAW;EACpC,MAAM,MAAM,iBAAiB,WAC1B,aAAa,SAAS,WAAW,OACnC;AACD,MAAI,MAAM,EAAG;EAEb,MAAM,UAAU,iBAAiB;AACjC,MAAI,QAAQ,WAAW,cAAc,QAAQ,UAAU,KAAM;EAE7D,MAAM,SAAS,gBAAgB,QAAQ,QAAQ;AAC/C,MAAI,UAAU,KAAM;AAEpB,YAAU,eAAe,kBAAkB;GACzC,GAAG;GACH;GACA,QAAQ;GACR,OAAO,KAAA;GACR,CAAC;;AAEJ,QAAO,WAAY"}
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
-
import { DefaultToolCall, ToolCallFromTool } from "../types.messages.cjs";
|
|
1
|
+
import { DefaultToolCall, InferToolOutput, ToolCallFromTool } from "../types.messages.cjs";
|
|
2
|
+
import { AssembledToolCall } from "../client/stream/handles/tools.cjs";
|
|
2
3
|
import { AgentTypeConfigLike, CompiledSubAgentLike, DeepAgentTypeConfigLike, DefaultSubagentStates, ExtractAgentConfig, ExtractDeepAgentConfig, ExtractSubAgentMiddleware, InferAgentToolCalls, InferDeepAgentSubagents, InferSubagentByName, InferSubagentNames, InferSubagentState, IsAgentLike, IsDeepAgentLike, SubAgentLike, SubagentStateMap, SubagentToolCall } from "../ui/types.cjs";
|
|
3
4
|
import { InferBag, InferNodeNames, InferStateType as InferStateType$1, InferSubagentStates as InferSubagentStates$1, InferToolCalls as InferToolCalls$1 } from "../ui/stream/index.cjs";
|
|
4
5
|
import { BaseMessage } from "@langchain/core/messages";
|
|
5
6
|
|
|
6
7
|
//#region src/stream/types-inference.d.ts
|
|
8
|
+
/** @internal Map a {@link ToolCallFromTool} message shape to {@link AssembledToolCall}. */
|
|
9
|
+
type AssembledToolCallFromToolCall<TCall extends {
|
|
10
|
+
name: string;
|
|
11
|
+
args: Record<string, unknown>;
|
|
12
|
+
}, TOutput = unknown> = TCall extends {
|
|
13
|
+
name: infer N;
|
|
14
|
+
args: infer A;
|
|
15
|
+
} ? N extends string ? A extends Record<string, any> ? AssembledToolCall<N, A, TOutput> : never : never : never;
|
|
16
|
+
/**
|
|
17
|
+
* Infer the streaming {@link AssembledToolCall} handle for a single
|
|
18
|
+
* LangChain tool.
|
|
19
|
+
*
|
|
20
|
+
* Parallel to {@link ToolCallFromTool} for message-level tool calls —
|
|
21
|
+
* use this when a component receives one entry from `stream.toolCalls`
|
|
22
|
+
* and you know which tool definition it came from.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const searchWeb = tool(/* ... *\/);
|
|
27
|
+
*
|
|
28
|
+
* function SearchWebCall({ toolCall }: {
|
|
29
|
+
* toolCall: AssembledToolCallFromTool<typeof searchWeb>;
|
|
30
|
+
* }) {
|
|
31
|
+
* // toolCall.name is "search_web", args/input are schema-inferred
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* v1 framework packages (`@langchain/react`, `@langchain/vue`, etc.) re-export
|
|
35
|
+
* this type as {@link ToolCallFromTool}. {@link AssembledToolCall.output} is
|
|
36
|
+
* `null` until the call succeeds; use {@link status} / {@link error} for UI.
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
type AssembledToolCallFromTool<T> = AssembledToolCallFromToolCall<ToolCallFromTool<T>, InferToolOutput<T>>;
|
|
40
|
+
/** @internal Resolve a tool definition's registered name. */
|
|
41
|
+
type ToolNameOf<T> = T extends {
|
|
42
|
+
name: infer N extends string;
|
|
43
|
+
} ? N : T extends {
|
|
44
|
+
tool: {
|
|
45
|
+
name: infer N extends string;
|
|
46
|
+
};
|
|
47
|
+
} ? N : never;
|
|
48
|
+
/** @internal Look up the return type of a tool in a tuple by its `name`. */
|
|
49
|
+
type MatchedToolOutput<Tools extends readonly unknown[], N extends string> = Tools extends readonly [infer First, ...infer Rest] ? ToolNameOf<First> extends N ? InferToolOutput<First> : MatchedToolOutput<Rest, N> : unknown;
|
|
50
|
+
/**
|
|
51
|
+
* @internal Bridge a message-level tool-call shape from {@link InferToolCallsFromUi}
|
|
52
|
+
* to a streaming {@link AssembledToolCall}, resolving `output` from the agent's
|
|
53
|
+
* declared tool list.
|
|
54
|
+
*/
|
|
55
|
+
type AssembledFromMessageToolCall<TC extends {
|
|
56
|
+
name: string;
|
|
57
|
+
args: Record<string, unknown>;
|
|
58
|
+
}, Tools extends readonly unknown[]> = TC extends {
|
|
59
|
+
name: infer N;
|
|
60
|
+
} ? N extends string ? AssembledToolCallFromToolCall<TC, MatchedToolOutput<Tools, N>> : AssembledToolCall : AssembledToolCall;
|
|
7
61
|
/**
|
|
8
62
|
* Unwrap the state shape from a compiled graph, a create-agent brand,
|
|
9
63
|
* or a plain type. Used by `useStream<T>()` to resolve `T = typeof
|
|
@@ -16,13 +70,17 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
16
70
|
*/
|
|
17
71
|
type InferStateType<T> = InferStateType$1<T>;
|
|
18
72
|
/**
|
|
19
|
-
* Infer the discriminated union of
|
|
20
|
-
*
|
|
21
|
-
*
|
|
73
|
+
* Infer the discriminated union of {@link AssembledToolCall} handles
|
|
74
|
+
* from an agent brand, an array of LangChain tools, or fall back to the
|
|
75
|
+
* untyped default handle.
|
|
22
76
|
*
|
|
23
|
-
*
|
|
77
|
+
* Pass `typeof agent` or `typeof tools` and narrow on `name` / `args`
|
|
78
|
+
* (aliases for `input`) in tool-call UI components.
|
|
24
79
|
*/
|
|
25
|
-
type InferToolCalls<T> = T extends readonly unknown[] ?
|
|
80
|
+
type InferToolCalls<T> = T extends readonly unknown[] ? AssembledToolCallFromTool<T[number]> : ExtractAgentConfig<T>["Tools"] extends infer Tools extends readonly unknown[] ? InferToolCalls$1<T> extends infer TC ? TC extends {
|
|
81
|
+
name: string;
|
|
82
|
+
args: Record<string, unknown>;
|
|
83
|
+
} ? AssembledFromMessageToolCall<TC, Tools> : AssembledToolCall : AssembledToolCall : AssembledToolCall;
|
|
26
84
|
/**
|
|
27
85
|
* Infer the subagent → state map from a DeepAgent brand. Non-brands
|
|
28
86
|
* collapse to {@link DefaultSubagentStates}.
|
|
@@ -39,5 +97,5 @@ type InferSubagentStates<T> = InferSubagentStates$1<T>;
|
|
|
39
97
|
*/
|
|
40
98
|
type WidenUpdateMessages<T> = T extends Record<string, unknown> ? { [K in keyof T]: K extends "messages" ? T[K] | BaseMessage | BaseMessage[] : T[K] } : T;
|
|
41
99
|
//#endregion
|
|
42
|
-
export { InferStateType, InferSubagentStates, InferToolCalls, WidenUpdateMessages };
|
|
100
|
+
export { AssembledToolCallFromTool, InferStateType, InferSubagentStates, InferToolCalls, WidenUpdateMessages };
|
|
43
101
|
//# sourceMappingURL=types-inference.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-inference.d.cts","names":[],"sources":["../../src/stream/types-inference.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"types-inference.d.cts","names":[],"sources":["../../src/stream/types-inference.ts"],"mappings":";;;;;;;;KA8CK,6BAAA;EACa,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,wBAElC,KAAA;EAAgB,IAAA;EAAe,IAAA;AAAA,IAC/B,CAAA,kBAEE,CAAA,SAAU,MAAA,gBACR,iBAAA,CAAkB,CAAA,EAAG,CAAA,EAAG,OAAA;;;;;;;;;;;;;;;AA4BhC;;;;;;;;;KAAY,yBAAA,MAA+B,6BAAA,CACzC,gBAAA,CAAiB,CAAA,GACjB,eAAA,CAAgB,CAAA;;KAIb,UAAA,MAAgB,CAAA;EAAY,IAAA;AAAA,IAC7B,CAAA,GACA,CAAA;EAAY,IAAA;IAAQ,IAAA;EAAA;AAAA,IAClB,CAAA;AANJ;AAAA,KAUG,iBAAA,uDAGD,KAAA,iDACA,UAAA,CAAW,KAAA,UAAe,CAAA,GACxB,eAAA,CAAgB,KAAA,IAChB,iBAAA,CAAkB,IAAA,EAAM,CAAA;;;;;;KAQzB,4BAAA;EACU,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,uCAE/B,EAAA;EAAa,IAAA;AAAA,IACb,CAAA,kBACE,6BAAA,CAA8B,EAAA,EAAI,iBAAA,CAAkB,KAAA,EAAO,CAAA,KAC3D,iBAAA,GACF,iBAAA;;;;AAzBG;;;;;;;KAqCK,cAAA,MAAoB,gBAAA,CAAqB,CAAA;;;;;;;;;KAUzC,cAAA,MAAoB,CAAA,8BAC5B,yBAAA,CAA0B,CAAA,YAC1B,kBAAA,CAAmB,CAAA,4DAEjB,gBAAA,CAAqB,CAAA,qBACnB,EAAA;EAAa,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,IAC/B,4BAAA,CAA6B,EAAA,EAAI,KAAA,IACjC,iBAAA,GACF,iBAAA,GACF,iBAAA;;;;;KAMM,mBAAA,MAAyB,qBAAA,CAA0B,CAAA;;;;;AApDhC;;;;;KA+DnB,mBAAA,MACV,CAAA,SAAU,MAAA,kCAEQ,CAAA,GAAI,CAAA,sBACZ,CAAA,CAAE,CAAA,IAAK,WAAA,GAAc,WAAA,KACrB,CAAA,CAAE,CAAA,MAER,CAAA"}
|
|
@@ -1,9 +1,63 @@
|
|
|
1
|
-
import { DefaultToolCall, ToolCallFromTool } from "../types.messages.js";
|
|
1
|
+
import { DefaultToolCall, InferToolOutput, ToolCallFromTool } from "../types.messages.js";
|
|
2
|
+
import { AssembledToolCall } from "../client/stream/handles/tools.js";
|
|
2
3
|
import { AgentTypeConfigLike, CompiledSubAgentLike, DeepAgentTypeConfigLike, DefaultSubagentStates, ExtractAgentConfig, ExtractDeepAgentConfig, ExtractSubAgentMiddleware, InferAgentToolCalls, InferDeepAgentSubagents, InferSubagentByName, InferSubagentNames, InferSubagentState, IsAgentLike, IsDeepAgentLike, SubAgentLike, SubagentStateMap, SubagentToolCall } from "../ui/types.js";
|
|
3
4
|
import { InferBag, InferNodeNames, InferStateType as InferStateType$1, InferSubagentStates as InferSubagentStates$1, InferToolCalls as InferToolCalls$1 } from "../ui/stream/index.js";
|
|
4
5
|
import { BaseMessage } from "@langchain/core/messages";
|
|
5
6
|
|
|
6
7
|
//#region src/stream/types-inference.d.ts
|
|
8
|
+
/** @internal Map a {@link ToolCallFromTool} message shape to {@link AssembledToolCall}. */
|
|
9
|
+
type AssembledToolCallFromToolCall<TCall extends {
|
|
10
|
+
name: string;
|
|
11
|
+
args: Record<string, unknown>;
|
|
12
|
+
}, TOutput = unknown> = TCall extends {
|
|
13
|
+
name: infer N;
|
|
14
|
+
args: infer A;
|
|
15
|
+
} ? N extends string ? A extends Record<string, any> ? AssembledToolCall<N, A, TOutput> : never : never : never;
|
|
16
|
+
/**
|
|
17
|
+
* Infer the streaming {@link AssembledToolCall} handle for a single
|
|
18
|
+
* LangChain tool.
|
|
19
|
+
*
|
|
20
|
+
* Parallel to {@link ToolCallFromTool} for message-level tool calls —
|
|
21
|
+
* use this when a component receives one entry from `stream.toolCalls`
|
|
22
|
+
* and you know which tool definition it came from.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const searchWeb = tool(/* ... *\/);
|
|
27
|
+
*
|
|
28
|
+
* function SearchWebCall({ toolCall }: {
|
|
29
|
+
* toolCall: AssembledToolCallFromTool<typeof searchWeb>;
|
|
30
|
+
* }) {
|
|
31
|
+
* // toolCall.name is "search_web", args/input are schema-inferred
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* v1 framework packages (`@langchain/react`, `@langchain/vue`, etc.) re-export
|
|
35
|
+
* this type as {@link ToolCallFromTool}. {@link AssembledToolCall.output} is
|
|
36
|
+
* `null` until the call succeeds; use {@link status} / {@link error} for UI.
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
type AssembledToolCallFromTool<T> = AssembledToolCallFromToolCall<ToolCallFromTool<T>, InferToolOutput<T>>;
|
|
40
|
+
/** @internal Resolve a tool definition's registered name. */
|
|
41
|
+
type ToolNameOf<T> = T extends {
|
|
42
|
+
name: infer N extends string;
|
|
43
|
+
} ? N : T extends {
|
|
44
|
+
tool: {
|
|
45
|
+
name: infer N extends string;
|
|
46
|
+
};
|
|
47
|
+
} ? N : never;
|
|
48
|
+
/** @internal Look up the return type of a tool in a tuple by its `name`. */
|
|
49
|
+
type MatchedToolOutput<Tools extends readonly unknown[], N extends string> = Tools extends readonly [infer First, ...infer Rest] ? ToolNameOf<First> extends N ? InferToolOutput<First> : MatchedToolOutput<Rest, N> : unknown;
|
|
50
|
+
/**
|
|
51
|
+
* @internal Bridge a message-level tool-call shape from {@link InferToolCallsFromUi}
|
|
52
|
+
* to a streaming {@link AssembledToolCall}, resolving `output` from the agent's
|
|
53
|
+
* declared tool list.
|
|
54
|
+
*/
|
|
55
|
+
type AssembledFromMessageToolCall<TC extends {
|
|
56
|
+
name: string;
|
|
57
|
+
args: Record<string, unknown>;
|
|
58
|
+
}, Tools extends readonly unknown[]> = TC extends {
|
|
59
|
+
name: infer N;
|
|
60
|
+
} ? N extends string ? AssembledToolCallFromToolCall<TC, MatchedToolOutput<Tools, N>> : AssembledToolCall : AssembledToolCall;
|
|
7
61
|
/**
|
|
8
62
|
* Unwrap the state shape from a compiled graph, a create-agent brand,
|
|
9
63
|
* or a plain type. Used by `useStream<T>()` to resolve `T = typeof
|
|
@@ -16,13 +70,17 @@ import { BaseMessage } from "@langchain/core/messages";
|
|
|
16
70
|
*/
|
|
17
71
|
type InferStateType<T> = InferStateType$1<T>;
|
|
18
72
|
/**
|
|
19
|
-
* Infer the discriminated union of
|
|
20
|
-
*
|
|
21
|
-
*
|
|
73
|
+
* Infer the discriminated union of {@link AssembledToolCall} handles
|
|
74
|
+
* from an agent brand, an array of LangChain tools, or fall back to the
|
|
75
|
+
* untyped default handle.
|
|
22
76
|
*
|
|
23
|
-
*
|
|
77
|
+
* Pass `typeof agent` or `typeof tools` and narrow on `name` / `args`
|
|
78
|
+
* (aliases for `input`) in tool-call UI components.
|
|
24
79
|
*/
|
|
25
|
-
type InferToolCalls<T> = T extends readonly unknown[] ?
|
|
80
|
+
type InferToolCalls<T> = T extends readonly unknown[] ? AssembledToolCallFromTool<T[number]> : ExtractAgentConfig<T>["Tools"] extends infer Tools extends readonly unknown[] ? InferToolCalls$1<T> extends infer TC ? TC extends {
|
|
81
|
+
name: string;
|
|
82
|
+
args: Record<string, unknown>;
|
|
83
|
+
} ? AssembledFromMessageToolCall<TC, Tools> : AssembledToolCall : AssembledToolCall : AssembledToolCall;
|
|
26
84
|
/**
|
|
27
85
|
* Infer the subagent → state map from a DeepAgent brand. Non-brands
|
|
28
86
|
* collapse to {@link DefaultSubagentStates}.
|
|
@@ -39,5 +97,5 @@ type InferSubagentStates<T> = InferSubagentStates$1<T>;
|
|
|
39
97
|
*/
|
|
40
98
|
type WidenUpdateMessages<T> = T extends Record<string, unknown> ? { [K in keyof T]: K extends "messages" ? T[K] | BaseMessage | BaseMessage[] : T[K] } : T;
|
|
41
99
|
//#endregion
|
|
42
|
-
export { InferStateType, InferSubagentStates, InferToolCalls, WidenUpdateMessages };
|
|
100
|
+
export { AssembledToolCallFromTool, InferStateType, InferSubagentStates, InferToolCalls, WidenUpdateMessages };
|
|
43
101
|
//# sourceMappingURL=types-inference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-inference.d.ts","names":[],"sources":["../../src/stream/types-inference.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"types-inference.d.ts","names":[],"sources":["../../src/stream/types-inference.ts"],"mappings":";;;;;;;;KA8CK,6BAAA;EACa,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,wBAElC,KAAA;EAAgB,IAAA;EAAe,IAAA;AAAA,IAC/B,CAAA,kBAEE,CAAA,SAAU,MAAA,gBACR,iBAAA,CAAkB,CAAA,EAAG,CAAA,EAAG,OAAA;;;;;;;;;;;;;;;AA4BhC;;;;;;;;;KAAY,yBAAA,MAA+B,6BAAA,CACzC,gBAAA,CAAiB,CAAA,GACjB,eAAA,CAAgB,CAAA;;KAIb,UAAA,MAAgB,CAAA;EAAY,IAAA;AAAA,IAC7B,CAAA,GACA,CAAA;EAAY,IAAA;IAAQ,IAAA;EAAA;AAAA,IAClB,CAAA;AANJ;AAAA,KAUG,iBAAA,uDAGD,KAAA,iDACA,UAAA,CAAW,KAAA,UAAe,CAAA,GACxB,eAAA,CAAgB,KAAA,IAChB,iBAAA,CAAkB,IAAA,EAAM,CAAA;;;;;;KAQzB,4BAAA;EACU,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,uCAE/B,EAAA;EAAa,IAAA;AAAA,IACb,CAAA,kBACE,6BAAA,CAA8B,EAAA,EAAI,iBAAA,CAAkB,KAAA,EAAO,CAAA,KAC3D,iBAAA,GACF,iBAAA;;;;AAzBG;;;;;;;KAqCK,cAAA,MAAoB,gBAAA,CAAqB,CAAA;;;;;;;;;KAUzC,cAAA,MAAoB,CAAA,8BAC5B,yBAAA,CAA0B,CAAA,YAC1B,kBAAA,CAAmB,CAAA,4DAEjB,gBAAA,CAAqB,CAAA,qBACnB,EAAA;EAAa,IAAA;EAAc,IAAA,EAAM,MAAA;AAAA,IAC/B,4BAAA,CAA6B,EAAA,EAAI,KAAA,IACjC,iBAAA,GACF,iBAAA,GACF,iBAAA;;;;;KAMM,mBAAA,MAAyB,qBAAA,CAA0B,CAAA;;;;;AApDhC;;;;;KA+DnB,mBAAA,MACV,CAAA,SAAU,MAAA,kCAEQ,CAAA,GAAI,CAAA,sBACZ,CAAA,CAAE,CAAA,IAAK,WAAA,GAAc,WAAA,KACrB,CAAA,CAAE,CAAA,MAER,CAAA"}
|
package/dist/stream/types.d.cts
CHANGED
|
@@ -6,27 +6,40 @@ import { ThreadStreamOptions } from "../client/stream/types.cjs";
|
|
|
6
6
|
import { ThreadStream } from "../client/stream/index.cjs";
|
|
7
7
|
import { Client } from "../client/index.cjs";
|
|
8
8
|
import { AnyHeadlessToolImplementation, OnToolCallback } from "../headless-tools.cjs";
|
|
9
|
-
import { InferStateType } from "./types-inference.cjs";
|
|
10
9
|
import { StreamStore } from "./store.cjs";
|
|
11
10
|
import { Channel, Event as Event$1 } from "@langchain/protocol";
|
|
12
11
|
import { BaseMessage as BaseMessage$1 } from "@langchain/core/messages";
|
|
13
12
|
|
|
14
13
|
//#region src/stream/types.d.ts
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
/** Why a run's active streaming phase ended. */
|
|
15
|
+
type RunExecutionReason = /** The run reached the protocol `completed` lifecycle event. */"success" /** The run reached the protocol `failed` lifecycle event. */ | "error" /** The run paused on a protocol `interrupted` lifecycle event. */ | "interrupt" /** The run was stopped by a client-side abort. */ | "stopped";
|
|
16
|
+
/** Payload for run-start callbacks. */
|
|
17
|
+
interface RunExecutionInfo {
|
|
18
|
+
runId: string;
|
|
19
|
+
}
|
|
20
|
+
/** Payload for run-end callbacks. */
|
|
21
|
+
interface RunCompletedInfo extends Omit<RunExecutionInfo, "runId"> {
|
|
22
|
+
/** Omitted when re-attaching to an in-flight run without local dispatch. */
|
|
23
|
+
runId?: string;
|
|
24
|
+
/** Why the active streaming phase ended. */
|
|
25
|
+
reason: RunExecutionReason;
|
|
26
|
+
}
|
|
22
27
|
/** Options common to both transport branches of framework `useStream` APIs. */
|
|
23
28
|
interface UseStreamCommonOptions<StateType extends object, ThreadIdType = string | null> {
|
|
24
29
|
threadId?: ThreadIdType;
|
|
25
30
|
onThreadId?: (threadId: string) => void;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Convenience callback fired when this hook instance's run is accepted
|
|
33
|
+
* by the server. Prefer `stream.isLoading` for UI; use this for
|
|
34
|
+
* imperative run-execution side effects.
|
|
35
|
+
*/
|
|
36
|
+
onCreated?: (info: RunExecutionInfo) => void;
|
|
37
|
+
/**
|
|
38
|
+
* Convenience callback fired when a run's active streaming phase ends.
|
|
39
|
+
* `runId` may be omitted for re-attached in-flight runs because no local
|
|
40
|
+
* dispatch response was observed.
|
|
41
|
+
*/
|
|
42
|
+
onCompleted?: (info: RunCompletedInfo) => void;
|
|
30
43
|
initialValues?: StateType;
|
|
31
44
|
/** State key holding the message array. Defaults to `"messages"`. */
|
|
32
45
|
messagesKey?: string;
|
|
@@ -138,9 +151,8 @@ interface StreamControllerOptions<StateType extends object = Record<string, unkn
|
|
|
138
151
|
/**
|
|
139
152
|
* How the controller talks to the agent server. Accepts either a
|
|
140
153
|
* built-in transport string (`"sse"` / `"websocket"`) or a custom
|
|
141
|
-
* {@link
|
|
142
|
-
*
|
|
143
|
-
* `client.threads.stream({ transport })`.
|
|
154
|
+
* {@link AgentServerAdapter} that bypasses the built-in factories
|
|
155
|
+
* entirely. Forwarded to `client.threads.stream({ transport })`.
|
|
144
156
|
*/
|
|
145
157
|
transport?: ThreadStreamOptions["transport"];
|
|
146
158
|
/** Optional `fetch` override forwarded to the built-in SSE transport. */
|
|
@@ -149,11 +161,18 @@ interface StreamControllerOptions<StateType extends object = Record<string, unkn
|
|
|
149
161
|
webSocketFactory?: (url: string) => WebSocket;
|
|
150
162
|
/** Called when a thread id is first produced (new-thread submits). */
|
|
151
163
|
onThreadId?: (threadId: string) => void;
|
|
152
|
-
/**
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Convenience callback fired when this hook instance's run is accepted
|
|
166
|
+
* by the server. Prefer `root.isLoading` for UI; use this for
|
|
167
|
+
* imperative run-execution side effects.
|
|
168
|
+
*/
|
|
169
|
+
onCreated?: (info: RunExecutionInfo) => void;
|
|
170
|
+
/**
|
|
171
|
+
* Convenience callback fired when a run's active streaming phase ends.
|
|
172
|
+
* `runId` may be omitted for re-attached in-flight runs because no local
|
|
173
|
+
* dispatch response was observed.
|
|
174
|
+
*/
|
|
175
|
+
onCompleted?: (info: RunCompletedInfo) => void;
|
|
157
176
|
/** Initial state for `root.values` before hydration lands. */
|
|
158
177
|
initialValues?: StateType;
|
|
159
178
|
/** Key inside `values` that holds the message array. Defaults to `"messages"`. */
|
|
@@ -170,8 +189,8 @@ interface StreamSubmitOptions<StateType extends object = Record<string, unknown>
|
|
|
170
189
|
/**
|
|
171
190
|
* Command shape widened to the v1 surface + protocol-v2 additions.
|
|
172
191
|
*
|
|
173
|
-
* - `resume` — dispatches to `thread.
|
|
174
|
-
*
|
|
192
|
+
* - `resume` — dispatches to `thread.submitRun` with interrupt-id keyed
|
|
193
|
+
* `input` (single or batched `Command({ resume })`).
|
|
175
194
|
* - `goto` — routes execution to a specific node (planned, forwarded
|
|
176
195
|
* via `/run.start` metadata).
|
|
177
196
|
* - `update` — merges a partial state update into the thread's
|
|
@@ -350,5 +369,5 @@ interface AcquiredProjection<T> {
|
|
|
350
369
|
release(): void;
|
|
351
370
|
}
|
|
352
371
|
//#endregion
|
|
353
|
-
export { AcquiredProjection, AgentServerOptions, CustomAdapterOptions, ProjectionRuntime, ProjectionSpec, RootEventBus, RootSnapshot,
|
|
372
|
+
export { AcquiredProjection, AgentServerOptions, CustomAdapterOptions, ProjectionRuntime, ProjectionSpec, RootEventBus, RootSnapshot, RunCompletedInfo, RunExecutionInfo, RunExecutionReason, StreamControllerOptions, StreamSubmitOptions, SubagentDiscoverySnapshot, SubgraphDiscoverySnapshot, Target, UseStreamCommonOptions, UseStreamOptions };
|
|
354
373
|
//# sourceMappingURL=types.d.cts.map
|