UNPKG

@langchain/langgraph

Version:
1 lines 25.1 kB
{"version":3,"file":"runner.cjs","names":["isGraphInterrupt","isGraphBubbleUp","isGraphDrained","combineAbortSignals","patchConfigurable","CONFIG_KEY_ABORT_SIGNALS","_runWithRetry","CONFIG_KEY_CALL","INTERRUPT","RESUME","ERROR","ERROR_SOURCE_NODE","NO_WRITES","CONFIG_KEY_SCRATCHPAD","Call","RETURN"],"sources":["../../src/pregel/runner.ts"],"sourcesContent":["import { PendingWrite } from \"@langchain/langgraph-checkpoint\";\nimport {\n Call,\n PregelAbortSignals,\n PregelExecutableTask,\n PregelScratchpad,\n} from \"./types.js\";\nimport {\n CachePolicy,\n combineAbortSignals,\n patchConfigurable,\n RetryPolicy,\n TimeoutPolicy,\n} from \"./utils/index.js\";\nimport {\n CONFIG_KEY_SCRATCHPAD,\n ERROR,\n ERROR_SOURCE_NODE,\n INTERRUPT,\n RESUME,\n NO_WRITES,\n TAG_HIDDEN,\n RETURN,\n CONFIG_KEY_CALL,\n CONFIG_KEY_ABORT_SIGNALS,\n} from \"../constants.js\";\nimport {\n GraphBubbleUp,\n isGraphBubbleUp,\n isGraphDrained,\n isGraphInterrupt,\n} from \"../errors.js\";\nimport { _runWithRetry, SettledPregelTask } from \"./retry.js\";\nimport { PregelLoop } from \"./loop.js\";\n\nconst PROMISE_ADDED_SYMBOL = Symbol.for(\"promiseAdded\");\n\nfunction createPromiseBarrier() {\n const barrier: {\n next: () => void;\n wait: Promise<unknown>;\n } = {\n next: () => void 0,\n wait: Promise.resolve(PROMISE_ADDED_SYMBOL),\n };\n\n function waitHandler(resolve: (value: typeof PROMISE_ADDED_SYMBOL) => void) {\n barrier.next = () => {\n barrier.wait = new Promise(waitHandler);\n resolve(PROMISE_ADDED_SYMBOL);\n };\n }\n barrier.wait = new Promise(waitHandler);\n return barrier;\n}\n\n/**\n * Options for the {@link PregelRunner#tick} method.\n */\nexport type TickOptions = {\n /**\n * The deadline before which all tasks must be completed.\n */\n timeout?: number;\n\n /**\n * An optional {@link AbortSignal} to cancel processing of tasks.\n */\n signal?: AbortSignal;\n\n /**\n * The {@link RetryPolicy} to use for the tick.\n */\n retryPolicy?: RetryPolicy;\n\n /**\n * An optional callback to be called after all task writes are completed.\n */\n onStepWrite?: (step: number, writes: PendingWrite[]) => void;\n\n /**\n * The maximum number of tasks to execute concurrently.\n */\n maxConcurrency?: number;\n};\n\n/**\n * Responsible for handling task execution on each tick of the {@link PregelLoop}.\n */\nexport class PregelRunner {\n private nodeFinished?: (id: string) => void;\n\n private loop: PregelLoop;\n\n /**\n * Exceptions already routed to a node-level error handler. Consulted when\n * deciding whether a failed task should abort the run.\n */\n private handledExceptions = new WeakSet<Error>();\n\n /**\n * Construct a new PregelRunner, which executes tasks from the provided PregelLoop.\n * @param loop - The PregelLoop that produces tasks for this runner to execute.\n */\n constructor({\n loop,\n nodeFinished,\n }: {\n loop: PregelLoop;\n nodeFinished?: (id: string) => void;\n }) {\n this.loop = loop;\n this.nodeFinished = nodeFinished;\n }\n\n /**\n * Execute tasks from the current step of the PregelLoop.\n *\n * Note: this method does NOT call {@link PregelLoop}#tick. That must be handled externally.\n * @param options - Options for the execution.\n */\n async tick(options: TickOptions = {}) {\n const { timeout, retryPolicy, onStepWrite, maxConcurrency } = options;\n\n const nodeErrors: Set<Error> = new Set();\n let graphBubbleUp: GraphBubbleUp | undefined;\n\n const exceptionSignalController = new AbortController();\n const exceptionSignal = exceptionSignalController.signal;\n const stepTimeoutSignal = timeout\n ? AbortSignal.timeout(timeout)\n : undefined;\n\n const allTasks = Object.values(this.loop.tasks);\n const pendingTasks = allTasks.filter((t) => t.writes.length === 0);\n\n const { signals, disposeCombinedSignal } = this._initializeAbortSignals({\n exceptionSignal,\n stepTimeoutSignal,\n signal: options.signal,\n });\n\n const taskStream = this._executeTasksWithRetry(pendingTasks, {\n signals,\n retryPolicy,\n maxConcurrency,\n });\n\n for await (const { task, error, signalAborted } of taskStream) {\n this._commit(task, error);\n if (error !== undefined && this.handledExceptions.has(error)) {\n // Routed to a node-level error handler in this tick; provenance is\n // checkpointed and the error must not abort the run.\n continue;\n }\n if (isGraphInterrupt(error)) {\n graphBubbleUp = error;\n } else if (isGraphBubbleUp(error) && !isGraphInterrupt(graphBubbleUp)) {\n graphBubbleUp = error;\n } else if (error && (nodeErrors.size === 0 || !signalAborted)) {\n /*\n * The goal here is to capture the exception that causes the graph to terminate early. In\n * theory it's possible for multiple nodes to throw, so this also handles the edge case of\n * capturing concurrent exceptions thrown before the node saw an abort. This is checked via\n * the signalAborted flag, which records the state of the abort signal at the time the node\n * execution finished.\n *\n * There is a case however where one node throws some error causing us to trigger an abort,\n * which then causes other concurrently executing nodes to throw their own AbortErrors. In\n * this case we don't care about reporting the abort errors thrown by the other nodes,\n * because they don't tell the user anything about what caused the graph execution to\n * terminate early, so we ignore them (and any other errors that occur after the node sees\n * an abort signal).\n */\n exceptionSignalController.abort();\n nodeErrors.add(error);\n }\n }\n\n disposeCombinedSignal?.();\n\n onStepWrite?.(this.loop.step, allTasks.map((task) => task.writes).flat());\n\n if (nodeErrors.size === 1) {\n throw Array.from(nodeErrors)[0];\n } else if (nodeErrors.size > 1) {\n throw new AggregateError(\n Array.from(nodeErrors),\n `Multiple errors occurred during superstep ${this.loop.step}. See the \"errors\" field of this exception for more details.`\n );\n }\n\n if (isGraphInterrupt(graphBubbleUp)) {\n throw graphBubbleUp;\n }\n\n // A cooperative drain raised by a subgraph bubbles up through the parent\n // loop (even when the parent is the top graph) so the parent stops at this\n // boundary and its checkpoint can be resumed later.\n if (isGraphDrained(graphBubbleUp)) {\n throw graphBubbleUp;\n }\n\n if (isGraphBubbleUp(graphBubbleUp) && this.loop.isNested) {\n throw graphBubbleUp;\n }\n }\n\n /**\n * Initializes the current AbortSignals for the PregelRunner, handling the various ways that\n * AbortSignals must be chained together so that the PregelLoop can be interrupted if necessary\n * while still allowing nodes to gracefully exit.\n *\n * This method must only be called once per PregelRunner#tick. It has the side effect of updating\n * the PregelLoop#config with the new AbortSignals so they may be propagated correctly to future\n * ticks and subgraph calls.\n *\n * @param options - Options for the initialization.\n * @returns The current abort signals.\n * @internal\n */\n private _initializeAbortSignals({\n exceptionSignal,\n stepTimeoutSignal,\n signal,\n }: {\n exceptionSignal: AbortSignal;\n stepTimeoutSignal?: AbortSignal;\n signal?: AbortSignal;\n }): { signals: PregelAbortSignals; disposeCombinedSignal?: () => void } {\n const previousSignals = (this.loop.config.configurable?.[\n CONFIG_KEY_ABORT_SIGNALS\n ] ?? {}) as PregelAbortSignals;\n\n // We always inherit the external abort signal from AsyncLocalStorage,\n // since that's the only way the signal is inherited by the subgraph calls.\n const externalAbortSignal = previousSignals.externalAbortSignal ?? signal;\n\n // inherit the step timeout signal from parent graph\n const timeoutAbortSignal =\n stepTimeoutSignal ?? previousSignals.timeoutAbortSignal;\n\n const { signal: composedAbortSignal, dispose: disposeCombinedSignal } =\n combineAbortSignals(\n externalAbortSignal,\n timeoutAbortSignal,\n exceptionSignal\n );\n\n const signals: PregelAbortSignals = {\n externalAbortSignal,\n timeoutAbortSignal,\n composedAbortSignal,\n };\n\n this.loop.config = patchConfigurable(this.loop.config, {\n [CONFIG_KEY_ABORT_SIGNALS]: signals,\n });\n\n return { signals, disposeCombinedSignal };\n }\n\n /**\n * Concurrently executes tasks with the requested retry policy, yielding a {@link SettledPregelTask} for each task as it completes.\n * @param tasks - The tasks to execute.\n * @param options - Options for the execution.\n */\n private async *_executeTasksWithRetry(\n tasks: PregelExecutableTask<string, string>[],\n options?: {\n signals?: PregelAbortSignals;\n retryPolicy?: RetryPolicy;\n maxConcurrency?: number;\n }\n ): AsyncGenerator<SettledPregelTask> {\n const { retryPolicy, maxConcurrency, signals } = options ?? {};\n\n const barrier = createPromiseBarrier();\n const executingTasksMap: Record<\n string,\n Promise<{\n task: PregelExecutableTask<string, string>;\n result?: unknown;\n error?: Error;\n }>\n > = {};\n\n const thisCall = {\n executingTasksMap,\n barrier,\n retryPolicy,\n scheduleTask: async (\n task: PregelExecutableTask<string, string>,\n writeIdx: number,\n call?: Call\n ) => this.loop.acceptPush(task, writeIdx, call),\n };\n\n if (signals?.composedAbortSignal?.aborted) {\n // note: don't use throwIfAborted here because it throws a DOMException,\n // which isn't consistent with how we throw on abort below.\n throw new Error(\"Abort\");\n }\n\n let startedTasksCount = 0;\n\n let listener: (() => void) | undefined;\n const timeoutOrCancelSignal = combineAbortSignals(\n signals?.externalAbortSignal,\n signals?.timeoutAbortSignal\n );\n\n const abortPromise = timeoutOrCancelSignal.signal\n ? new Promise<never>((_resolve, reject) => {\n listener = () => reject(new Error(\"Abort\"));\n timeoutOrCancelSignal.signal?.addEventListener(\"abort\", listener, {\n once: true,\n });\n })\n : undefined;\n\n while (\n (startedTasksCount === 0 || Object.keys(executingTasksMap).length > 0) &&\n tasks.length\n ) {\n for (\n ;\n Object.values(executingTasksMap).length <\n (maxConcurrency ?? tasks.length) && startedTasksCount < tasks.length;\n startedTasksCount += 1\n ) {\n const task = tasks[startedTasksCount];\n\n executingTasksMap[task.id] = _runWithRetry(\n task,\n retryPolicy,\n { [CONFIG_KEY_CALL]: call?.bind(thisCall, this, task) },\n signals?.composedAbortSignal\n ).catch((error) => {\n return {\n task,\n error,\n signalAborted: signals?.composedAbortSignal?.aborted,\n };\n });\n }\n\n const settledTask = await Promise.race([\n ...Object.values(executingTasksMap),\n ...(abortPromise ? [abortPromise] : []),\n barrier.wait,\n ]);\n\n if (settledTask === PROMISE_ADDED_SYMBOL) {\n continue;\n }\n\n const settled = settledTask as SettledPregelTask;\n const { task: settledPregelTask, error: settledError } = settled;\n\n // If the task failed (after exhausting its retry policy) and the node has\n // a registered error handler, schedule that handler to run within this\n // same tick instead of aborting the run. GraphBubbleUp errors (e.g.\n // interrupts / parent commands) are never routed to error handlers.\n if (\n settledError !== undefined &&\n !isGraphBubbleUp(settledError) &&\n !this.loop.isErrorHandlerNode(String(settledPregelTask.name)) &&\n this.loop.getErrorHandlerNode(String(settledPregelTask.name)) !==\n undefined\n ) {\n const handlerTask = this.loop.scheduleErrorHandler(\n settledPregelTask,\n settledError\n );\n if (handlerTask !== undefined) {\n executingTasksMap[handlerTask.id] = _runWithRetry(\n handlerTask,\n retryPolicy,\n { [CONFIG_KEY_CALL]: call?.bind(thisCall, this, handlerTask) },\n signals?.composedAbortSignal\n ).catch((error) => {\n return {\n task: handlerTask,\n error,\n signalAborted: signals?.composedAbortSignal?.aborted,\n };\n });\n barrier.next();\n }\n }\n\n yield settled;\n\n if (listener != null) {\n timeoutOrCancelSignal.signal?.removeEventListener(\"abort\", listener);\n timeoutOrCancelSignal.dispose?.();\n }\n\n delete executingTasksMap[(settledTask as SettledPregelTask).task.id];\n }\n }\n\n /**\n * Whether a failed task should record {@link ERROR_SOURCE_NODE} provenance.\n */\n private _shouldRouteToErrorHandler(\n task: PregelExecutableTask<string, string>\n ): boolean {\n const name = String(task.name);\n if (this.loop.isErrorHandlerNode(name)) {\n return false;\n }\n return this.loop.getErrorHandlerNode(name) !== undefined;\n }\n\n /**\n * Determines what writes to apply based on whether the task completed successfully, and what type of error occurred.\n *\n * Throws an error if the error is a {@link GraphBubbleUp} error and {@link PregelLoop}#isNested is true.\n *\n * @param task - The task to commit.\n * @param error - The error that occurred, if any.\n */\n private _commit(task: PregelExecutableTask<string, string>, error?: Error) {\n if (error !== undefined) {\n if (isGraphInterrupt(error)) {\n if (error.interrupts.length) {\n const interrupts: PendingWrite<string>[] = error.interrupts.map(\n (interrupt) => [INTERRUPT, interrupt]\n );\n const resumes = task.writes.filter((w) => w[0] === RESUME);\n if (resumes.length) {\n interrupts.push(...resumes);\n }\n this.loop.putWrites(task.id, interrupts);\n }\n } else if (isGraphDrained(error)) {\n // Cooperative drain bubbled up from a subgraph. Leave the task\n // uncommitted (unless it already produced writes) so it is\n // re-executed when the parent run resumes.\n if (task.writes.length) {\n this.loop.putWrites(task.id, task.writes);\n }\n } else if (isGraphBubbleUp(error) && task.writes.length) {\n this.loop.putWrites(task.id, task.writes);\n } else {\n task.writes.push([ERROR, { message: error.message, name: error.name }]);\n if (this._shouldRouteToErrorHandler(task)) {\n task.writes.push([ERROR_SOURCE_NODE, String(task.name)]);\n this.handledExceptions.add(error);\n }\n this.loop.putWrites(task.id, task.writes);\n }\n } else {\n if (\n this.nodeFinished &&\n (task.config?.tags == null || !task.config.tags.includes(TAG_HIDDEN))\n ) {\n this.nodeFinished(String(task.name));\n }\n\n if (task.writes.length === 0) {\n // Add no writes marker\n task.writes.push([NO_WRITES, null]);\n }\n\n // Save task writes to checkpointer\n this.loop.putWrites(task.id, task.writes);\n }\n }\n}\n\nasync function call(\n this: {\n executingTasksMap: Record<\n string,\n Promise<{\n task: PregelExecutableTask<string, string>;\n result?: unknown;\n error?: Error;\n }>\n >;\n\n barrier: {\n next: () => void;\n wait: Promise<unknown>;\n };\n\n retryPolicy?: RetryPolicy;\n\n scheduleTask: (\n task: PregelExecutableTask<string, string>,\n writeIdx: number,\n call?: Call\n ) => Promise<PregelExecutableTask<string, string> | void>;\n },\n runner: PregelRunner,\n task: PregelExecutableTask<string, string>,\n func: (...args: unknown[]) => unknown | Promise<unknown>,\n name: string,\n input: unknown,\n options: {\n retry?: RetryPolicy;\n cache?: CachePolicy;\n timeout?: TimeoutPolicy;\n callbacks?: unknown;\n } = {}\n): Promise<unknown> {\n // Schedule PUSH tasks, collect promises\n const scratchpad = task.config?.configurable?.[CONFIG_KEY_SCRATCHPAD] as\n | PregelScratchpad<unknown>\n | undefined;\n\n if (!scratchpad) {\n throw new Error(\n `BUG: No scratchpad found on task ${task.name}__${task.id}`\n );\n }\n\n const cnt = scratchpad.callCounter;\n scratchpad.callCounter += 1;\n\n // schedule the next task, if the callback returns one\n const wcall = new Call({\n func,\n name,\n input,\n cache: options.cache,\n retry: options.retry,\n timeout: options.timeout,\n callbacks: options.callbacks,\n });\n const nextTask = await this.scheduleTask(task, cnt, wcall);\n if (!nextTask) return undefined;\n\n // Check if this task is already running\n const existingPromise = this.executingTasksMap[nextTask.id];\n\n if (existingPromise !== undefined) {\n // If the parent task was retried, the next task might already be running\n return existingPromise;\n }\n\n if (nextTask.writes.length > 0) {\n // If it already ran, return the result\n const returns = nextTask.writes.filter(([c]) => c === RETURN);\n const errors = nextTask.writes.filter(([c]) => c === ERROR);\n\n if (returns.length > 0) {\n // Task completed successfully\n if (returns.length === 1) return Promise.resolve(returns[0][1]);\n\n // should be unreachable\n throw new Error(\n `BUG: multiple returns found for task ${nextTask.name}__${nextTask.id}`\n );\n }\n\n if (errors.length > 0) {\n // Task failed\n if (errors.length === 1) {\n const errorValue = errors[0][1];\n const error =\n // eslint-disable-next-line no-instanceof/no-instanceof\n errorValue instanceof Error\n ? errorValue\n : new Error(String(errorValue));\n\n return Promise.reject(error);\n }\n\n // the only way this should happen is if the task executes multiple times and writes aren't cleared\n throw new Error(\n `BUG: multiple errors found for task ${nextTask.name}__${nextTask.id}`\n );\n }\n\n return undefined;\n } else {\n // Schedule the next task with retry\n const prom = _runWithRetry<string, string>(nextTask, options.retry, {\n [CONFIG_KEY_CALL]: call.bind(this, runner, nextTask),\n });\n\n this.executingTasksMap[nextTask.id] = prom;\n this.barrier.next();\n\n return prom.then(({ result, error }) => {\n if (error) return Promise.reject(error);\n return result;\n });\n }\n}\n"],"mappings":"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"}