@langchain/langgraph 1.4.12 → 1.4.14
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/func/index.cjs.map +1 -1
- package/dist/func/index.js.map +1 -1
- package/dist/graph/message.cjs +7 -4
- package/dist/graph/message.cjs.map +1 -1
- package/dist/graph/message.d.cts.map +1 -1
- package/dist/graph/message.d.ts.map +1 -1
- package/dist/graph/message.js +7 -4
- package/dist/graph/message.js.map +1 -1
- package/dist/pregel/messages-v2.cjs +6 -0
- package/dist/pregel/messages-v2.cjs.map +1 -1
- package/dist/pregel/messages-v2.js +6 -0
- package/dist/pregel/messages-v2.js.map +1 -1
- package/dist/pregel/utils/config.cjs +3 -2
- package/dist/pregel/utils/config.cjs.map +1 -1
- package/dist/pregel/utils/config.d.cts.map +1 -1
- package/dist/pregel/utils/config.d.ts.map +1 -1
- package/dist/pregel/utils/config.js +3 -2
- package/dist/pregel/utils/config.js.map +1 -1
- package/package.json +7 -7
package/dist/func/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["coerceTimeoutPolicy","isAsyncGeneratorFunction","isGeneratorFunction","call","getRunnableForEntrypoint","RunnableCallable","PregelNode","START","ChannelWrite","END","PASSTHROUGH","PREVIOUS","TAG_HIDDEN","Pregel","EphemeralValue","LastValue","AsyncLocalStorageProviderSingleton","CONFIG_KEY_PREVIOUS_STATE"],"sources":["../../src/func/index.ts"],"sourcesContent":["import {\n BaseCache,\n BaseCheckpointSaver,\n BaseStore,\n} from \"@langchain/langgraph-checkpoint\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { Pregel } from \"../pregel/index.js\";\nimport { PregelNode } from \"../pregel/read.js\";\nimport {\n CONFIG_KEY_PREVIOUS_STATE,\n END,\n PREVIOUS,\n START,\n TAG_HIDDEN,\n} from \"../constants.js\";\nimport { EphemeralValue } from \"../channels/ephemeral_value.js\";\nimport { call, getRunnableForEntrypoint } from \"../pregel/call.js\";\nimport type {\n CachePolicy,\n RetryPolicy,\n TimeoutPolicy,\n} from \"../pregel/utils/index.js\";\nimport { coerceTimeoutPolicy } from \"../pregel/utils/index.js\";\nimport { LastValue } from \"../channels/last_value.js\";\nimport {\n EntrypointFinal,\n EntrypointReturnT,\n EntrypointFinalSaveT,\n EntrypointFunc,\n TaskFunc,\n} from \"./types.js\";\nimport { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\nimport {\n RunnableCallable,\n isAsyncGeneratorFunction,\n isGeneratorFunction,\n} from \"../utils.js\";\nimport { ChannelWrite, PASSTHROUGH } from \"../pregel/write.js\";\n\n/**\n * Options for the {@link task} function\n */\nexport interface TaskOptions {\n /**\n * The name of the task, analogous to the node name in {@link StateGraph}.\n */\n name: string;\n /**\n * The retry policy for the task. Configures how many times and under what conditions\n * the task should be retried if it fails.\n */\n retry?: RetryPolicy;\n\n /**\n * The cache policy for the task. Configures how the task should be cached.\n */\n cachePolicy?: CachePolicy;\n\n /**\n * Maximum duration for a single attempt of this task. Accepts a number of\n * milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised and the task's\n * retry policy (if any) decides whether to retry.\n */\n timeout?: number | TimeoutPolicy;\n}\n\n/**\n * Define a LangGraph task using the `task` function.\n *\n * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.\n * A task can be called like a regular function with the following differences:\n *\n * - When a checkpointer is enabled, the function inputs and outputs must be serializable.\n * - The wrapped function can only be called from within an entrypoint or StateGraph.\n * - Calling the function produces a promise. This makes it easy to parallelize tasks.\n *\n * @typeParam ArgsT - The type of arguments the task function accepts\n * @typeParam OutputT - The type of value the task function returns\n * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task\n * @param func - The function that executes this task\n * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise\n *\n * @example basic example\n * ```typescript\n * const addOne = task(\"add\", async (a: number) => a + 1);\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n *\n * // Call the entrypoint\n * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]\n * ```\n *\n * @example using a retry policy\n * ```typescript\n * const addOne = task({\n * name: \"add\",\n * retry: { maxAttempts: 3 }\n * },\n * async (a: number) => a + 1\n * );\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n * ```\n * @category Functional API\n */\nexport function task<ArgsT extends unknown[], OutputT>(\n optionsOrName: TaskOptions | string,\n func: TaskFunc<ArgsT, OutputT>\n): (...args: ArgsT) => Promise<OutputT> {\n const options =\n typeof optionsOrName === \"string\"\n ? {\n name: optionsOrName,\n retry: undefined,\n cachePolicy: undefined,\n timeout: undefined,\n }\n : optionsOrName;\n\n const { name, retry } = options;\n const timeout = coerceTimeoutPolicy(options.timeout);\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as tasks. For streaming responses, use config.write.\"\n );\n }\n\n const cachePolicy =\n options.cachePolicy ??\n // `cache` was mistakingly used as an alias for `cachePolicy` in v0.3.x,\n // TODO: remove in 1.x\n (\"cache\" in options ? (options.cache as CachePolicy) : undefined);\n\n let cache: CachePolicy | undefined;\n if (typeof cachePolicy === \"boolean\") {\n cache = cachePolicy ? {} : undefined;\n } else {\n cache = cachePolicy;\n }\n\n return (...args: ArgsT) => {\n return call({ func, name, retry, cache, timeout }, ...args);\n };\n}\n\n/**\n * Options for the {@link entrypoint} function\n */\nexport type EntrypointOptions = {\n /**\n * The name of the {@link entrypoint}, analogous to the node name in {@link StateGraph}.\n * This name is used for logging, debugging, and checkpoint identification.\n */\n name: string;\n /**\n * The checkpointer for the {@link entrypoint}. Used to save and restore state between\n * invocations of the workflow.\n */\n checkpointer?: BaseCheckpointSaver;\n /**\n * The store for the {@link entrypoint}. Used to persist data across workflow runs.\n */\n store?: BaseStore;\n\n /**\n * The cache for the {@link entrypoint}. Used to cache values between workflow runs.\n */\n cache?: BaseCache;\n\n /**\n * Maximum duration for a single attempt of this entrypoint. Accepts a number\n * of milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised.\n */\n timeout?: number | TimeoutPolicy;\n};\n\n/**\n * Type declaration for the entrypoint function with its properties\n * @category Functional API\n */\nexport interface EntrypointFunction {\n <InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n ): Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>,\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n },\n Record<string, unknown>,\n InputT,\n EntrypointReturnT<OutputT>,\n // Because the update type is an return type union of tasks + entrypoint,\n // thus we can't type it properly.\n any, // eslint-disable-line @typescript-eslint/no-explicit-any\n Awaited<EntrypointReturnT<OutputT>>\n >;\n\n /**\n * A helper utility for use with the functional API that returns a value to the caller,\n * as well as a separate state value to persist to the checkpoint. This allows workflows\n * to maintain state between runs while returning different values to the caller.\n *\n * @typeParam ValueT - The type of the value to return to the caller\n * @typeParam SaveT - The type of the state to save to the checkpoint\n * @param options.value - The value to return to the caller\n * @param options.save - The value to save to the checkpoint\n * @returns An object with the value and save properties\n *\n * @example\n * ```typescript\n * return entrypoint.final({\n * value: \"result for caller\",\n * save: { counter: currentCount + 1 }\n * });\n * ```\n */\n final<ValueT, SaveT>(options: {\n value?: ValueT;\n save?: SaveT;\n }): EntrypointFinal<ValueT, SaveT>;\n}\n\n/**\n * Define a LangGraph workflow using the `entrypoint` function.\n *\n * ### Function signature\n *\n * The wrapped function must accept at most **two parameters**. The first parameter\n * is the input to the function. The second (optional) parameter is a\n * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to\n * the function, you can pass them as an object.\n *\n * ### Helper functions\n *\n * #### Streaming\n * To write data to the \"custom\" stream, use the {@link getWriter} function, or the\n * {@link LangGraphRunnableConfig.writer} property.\n *\n * #### State management\n * The {@link getPreviousState} function can be used to access the previous state\n * that was returned from the last invocation of the entrypoint on the same thread id.\n *\n * If you wish to save state other than the return value, you can use the\n * {@link entrypoint.final} function.\n *\n * @typeParam InputT - The type of input the entrypoint accepts\n * @typeParam OutputT - The type of output the entrypoint produces\n * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint\n * @param func - The function that executes this entrypoint\n * @returns A {@link Pregel} instance that can be run to execute the workflow\n *\n * @example Using entrypoint and tasks\n * ```typescript\n * import { task, entrypoint } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n * import { interrupt, Command } from \"@langchain/langgraph\";\n *\n * const composeEssay = task(\"compose\", async (topic: string) => {\n * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation\n * return `An essay about ${topic}`;\n * });\n *\n * const reviewWorkflow = entrypoint({\n * name: \"review\",\n * checkpointer: new MemorySaver()\n * }, async (topic: string) => {\n * const essay = await composeEssay(topic);\n * const humanReview = await interrupt({\n * question: \"Please provide a review\",\n * essay\n * });\n * return {\n * essay,\n * review: humanReview\n * };\n * });\n *\n * // Example configuration for the workflow\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * // Topic for the essay\n * const topic = \"cats\";\n *\n * // Stream the workflow to generate the essay and await human review\n * for await (const result of reviewWorkflow.stream(topic, config)) {\n * console.log(result);\n * }\n *\n * // Example human review provided after the interrupt\n * const humanReview = \"This essay is great.\";\n *\n * // Resume the workflow with the provided human review\n * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {\n * console.log(result);\n * }\n * ```\n *\n * @example Accessing the previous return value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const accumulator = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (input: string) => {\n * const previous = getPreviousState<number>();\n * return previous !== undefined ? `${previous } ${input}` : input;\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n * await accumulator.invoke(\"hello\", config); // returns \"hello\"\n * await accumulator.invoke(\"world\", config); // returns \"hello world\"\n * ```\n *\n * @example Using entrypoint.final to save a value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const myWorkflow = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (num: number) => {\n * const previous = getPreviousState<number>();\n *\n * // This will return the previous value to the caller, saving\n * // 2 * num to the checkpoint, which will be used in the next invocation\n * // for the `previous` parameter.\n * return entrypoint.final({\n * value: previous ?? 0,\n * save: 2 * num\n * });\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * await myWorkflow.invoke(3, config); // 0 (previous was undefined)\n * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)\n * ```\n * @category Functional API\n */\nexport const entrypoint = function entrypoint<InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n) {\n const { name, checkpointer, store, cache } =\n typeof optionsOrName === \"string\"\n ? { name: optionsOrName, checkpointer: undefined, store: undefined }\n : optionsOrName;\n const timeout = coerceTimeoutPolicy(\n typeof optionsOrName === \"string\" ? undefined : optionsOrName.timeout\n );\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as entrypoints. For streaming responses, use config.write.\"\n );\n }\n const streamMode = \"updates\";\n const bound = getRunnableForEntrypoint(name, func);\n\n // Helper to check if a value is an EntrypointFinal\n function isEntrypointFinal(\n value: unknown\n ): value is EntrypointFinal<unknown, unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__lg_type\" in value &&\n value.__lg_type === \"__pregel_final\"\n );\n }\n\n // Helper function to pluck the return value from EntrypointFinal or passthrough\n const pluckReturnValue = new RunnableCallable({\n name: \"pluckReturnValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.value : value;\n },\n });\n\n // Helper function to pluck the save value from EntrypointFinal or passthrough\n const pluckSaveValue = new RunnableCallable({\n name: \"pluckSaveValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.save : value;\n },\n });\n\n const entrypointNode = new PregelNode<InputT, EntrypointReturnT<OutputT>>({\n bound,\n triggers: [START],\n channels: [START],\n timeout,\n writers: [\n new ChannelWrite(\n [\n { channel: END, value: PASSTHROUGH, mapper: pluckReturnValue },\n { channel: PREVIOUS, value: PASSTHROUGH, mapper: pluckSaveValue },\n ],\n [TAG_HIDDEN]\n ),\n ],\n });\n\n return new Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>, // node types\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n }, // channel types\n Record<string, unknown>, // configurable types\n InputT, // input type\n EntrypointReturnT<OutputT> // output type\n >({\n name,\n checkpointer,\n nodes: {\n [name]: entrypointNode,\n },\n channels: {\n [START]: new EphemeralValue<InputT>(),\n [END]: new LastValue<EntrypointReturnT<OutputT>>(),\n [PREVIOUS]: new LastValue<EntrypointFinalSaveT<OutputT>>(),\n },\n inputChannels: START,\n outputChannels: END,\n streamChannels: END,\n streamMode,\n store,\n cache,\n });\n} as EntrypointFunction;\n\n// documented by the EntrypointFunction interface\nentrypoint.final = function final<ValueT, SaveT>({\n value,\n save,\n}: {\n value?: ValueT;\n save?: SaveT;\n}): EntrypointFinal<ValueT, SaveT> {\n return { value, save, __lg_type: \"__pregel_final\" };\n};\n\n/**\n * A helper utility function for use with the functional API that returns the previous\n * state from the checkpoint from the last invocation of the current thread.\n *\n * This function allows workflows to access state that was saved in previous runs\n * using {@link entrypoint.final}.\n *\n * @typeParam StateT - The type of the state that was previously saved\n * @returns The previous saved state from the last invocation of the current thread\n *\n * @example\n * ```typescript\n * const previousState = getPreviousState<{ counter: number }>();\n * const newCount = (previousState?.counter ?? 0) + 1;\n * ```\n * @category Functional API\n */\nexport function getPreviousState<StateT>(): StateT {\n const config: LangGraphRunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n return config.configurable?.[CONFIG_KEY_PREVIOUS_STATE] as StateT;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["coerceTimeoutPolicy","isAsyncGeneratorFunction","isGeneratorFunction","call","getRunnableForEntrypoint","RunnableCallable","PregelNode","START","ChannelWrite","END","PASSTHROUGH","PREVIOUS","TAG_HIDDEN","Pregel","EphemeralValue","LastValue","AsyncLocalStorageProviderSingleton","CONFIG_KEY_PREVIOUS_STATE"],"sources":["../../src/func/index.ts"],"sourcesContent":["import {\n BaseCache,\n BaseCheckpointSaver,\n BaseStore,\n} from \"@langchain/langgraph-checkpoint\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { Pregel } from \"../pregel/index.js\";\nimport { PregelNode } from \"../pregel/read.js\";\nimport {\n CONFIG_KEY_PREVIOUS_STATE,\n END,\n PREVIOUS,\n START,\n TAG_HIDDEN,\n} from \"../constants.js\";\nimport { EphemeralValue } from \"../channels/ephemeral_value.js\";\nimport { call, getRunnableForEntrypoint } from \"../pregel/call.js\";\nimport type {\n CachePolicy,\n RetryPolicy,\n TimeoutPolicy,\n} from \"../pregel/utils/index.js\";\nimport { coerceTimeoutPolicy } from \"../pregel/utils/index.js\";\nimport { LastValue } from \"../channels/last_value.js\";\nimport {\n EntrypointFinal,\n EntrypointReturnT,\n EntrypointFinalSaveT,\n EntrypointFunc,\n TaskFunc,\n} from \"./types.js\";\nimport { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\nimport {\n RunnableCallable,\n isAsyncGeneratorFunction,\n isGeneratorFunction,\n} from \"../utils.js\";\nimport { ChannelWrite, PASSTHROUGH } from \"../pregel/write.js\";\n\n/**\n * Options for the {@link task} function\n */\nexport interface TaskOptions {\n /**\n * The name of the task, analogous to the node name in {@link StateGraph}.\n */\n name: string;\n /**\n * The retry policy for the task. Configures how many times and under what conditions\n * the task should be retried if it fails.\n */\n retry?: RetryPolicy;\n\n /**\n * The cache policy for the task. Configures how the task should be cached.\n */\n cachePolicy?: CachePolicy;\n\n /**\n * Maximum duration for a single attempt of this task. Accepts a number of\n * milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised and the task's\n * retry policy (if any) decides whether to retry.\n */\n timeout?: number | TimeoutPolicy;\n}\n\n/**\n * Define a LangGraph task using the `task` function.\n *\n * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.\n * A task can be called like a regular function with the following differences:\n *\n * - When a checkpointer is enabled, the function inputs and outputs must be serializable.\n * - The wrapped function can only be called from within an entrypoint or StateGraph.\n * - Calling the function produces a promise. This makes it easy to parallelize tasks.\n *\n * @typeParam ArgsT - The type of arguments the task function accepts\n * @typeParam OutputT - The type of value the task function returns\n * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task\n * @param func - The function that executes this task\n * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise\n *\n * @example basic example\n * ```typescript\n * const addOne = task(\"add\", async (a: number) => a + 1);\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n *\n * // Call the entrypoint\n * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]\n * ```\n *\n * @example using a retry policy\n * ```typescript\n * const addOne = task({\n * name: \"add\",\n * retry: { maxAttempts: 3 }\n * },\n * async (a: number) => a + 1\n * );\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n * ```\n * @category Functional API\n */\nexport function task<ArgsT extends unknown[], OutputT>(\n optionsOrName: TaskOptions | string,\n func: TaskFunc<ArgsT, OutputT>\n): (...args: ArgsT) => Promise<OutputT> {\n const options =\n typeof optionsOrName === \"string\"\n ? {\n name: optionsOrName,\n retry: undefined,\n cachePolicy: undefined,\n timeout: undefined,\n }\n : optionsOrName;\n\n const { name, retry } = options;\n const timeout = coerceTimeoutPolicy(options.timeout);\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as tasks. For streaming responses, use config.write.\"\n );\n }\n\n const cachePolicy =\n options.cachePolicy ??\n // `cache` was mistakenly used as an alias for `cachePolicy` in v0.3.x,\n // TODO: remove in 1.x\n (\"cache\" in options ? (options.cache as CachePolicy) : undefined);\n\n let cache: CachePolicy | undefined;\n if (typeof cachePolicy === \"boolean\") {\n cache = cachePolicy ? {} : undefined;\n } else {\n cache = cachePolicy;\n }\n\n return (...args: ArgsT) => {\n return call({ func, name, retry, cache, timeout }, ...args);\n };\n}\n\n/**\n * Options for the {@link entrypoint} function\n */\nexport type EntrypointOptions = {\n /**\n * The name of the {@link entrypoint}, analogous to the node name in {@link StateGraph}.\n * This name is used for logging, debugging, and checkpoint identification.\n */\n name: string;\n /**\n * The checkpointer for the {@link entrypoint}. Used to save and restore state between\n * invocations of the workflow.\n */\n checkpointer?: BaseCheckpointSaver;\n /**\n * The store for the {@link entrypoint}. Used to persist data across workflow runs.\n */\n store?: BaseStore;\n\n /**\n * The cache for the {@link entrypoint}. Used to cache values between workflow runs.\n */\n cache?: BaseCache;\n\n /**\n * Maximum duration for a single attempt of this entrypoint. Accepts a number\n * of milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised.\n */\n timeout?: number | TimeoutPolicy;\n};\n\n/**\n * Type declaration for the entrypoint function with its properties\n * @category Functional API\n */\nexport interface EntrypointFunction {\n <InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n ): Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>,\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n },\n Record<string, unknown>,\n InputT,\n EntrypointReturnT<OutputT>,\n // Because the update type is an return type union of tasks + entrypoint,\n // thus we can't type it properly.\n any, // eslint-disable-line @typescript-eslint/no-explicit-any\n Awaited<EntrypointReturnT<OutputT>>\n >;\n\n /**\n * A helper utility for use with the functional API that returns a value to the caller,\n * as well as a separate state value to persist to the checkpoint. This allows workflows\n * to maintain state between runs while returning different values to the caller.\n *\n * @typeParam ValueT - The type of the value to return to the caller\n * @typeParam SaveT - The type of the state to save to the checkpoint\n * @param options.value - The value to return to the caller\n * @param options.save - The value to save to the checkpoint\n * @returns An object with the value and save properties\n *\n * @example\n * ```typescript\n * return entrypoint.final({\n * value: \"result for caller\",\n * save: { counter: currentCount + 1 }\n * });\n * ```\n */\n final<ValueT, SaveT>(options: {\n value?: ValueT;\n save?: SaveT;\n }): EntrypointFinal<ValueT, SaveT>;\n}\n\n/**\n * Define a LangGraph workflow using the `entrypoint` function.\n *\n * ### Function signature\n *\n * The wrapped function must accept at most **two parameters**. The first parameter\n * is the input to the function. The second (optional) parameter is a\n * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to\n * the function, you can pass them as an object.\n *\n * ### Helper functions\n *\n * #### Streaming\n * To write data to the \"custom\" stream, use the {@link getWriter} function, or the\n * {@link LangGraphRunnableConfig.writer} property.\n *\n * #### State management\n * The {@link getPreviousState} function can be used to access the previous state\n * that was returned from the last invocation of the entrypoint on the same thread id.\n *\n * If you wish to save state other than the return value, you can use the\n * {@link entrypoint.final} function.\n *\n * @typeParam InputT - The type of input the entrypoint accepts\n * @typeParam OutputT - The type of output the entrypoint produces\n * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint\n * @param func - The function that executes this entrypoint\n * @returns A {@link Pregel} instance that can be run to execute the workflow\n *\n * @example Using entrypoint and tasks\n * ```typescript\n * import { task, entrypoint } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n * import { interrupt, Command } from \"@langchain/langgraph\";\n *\n * const composeEssay = task(\"compose\", async (topic: string) => {\n * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation\n * return `An essay about ${topic}`;\n * });\n *\n * const reviewWorkflow = entrypoint({\n * name: \"review\",\n * checkpointer: new MemorySaver()\n * }, async (topic: string) => {\n * const essay = await composeEssay(topic);\n * const humanReview = await interrupt({\n * question: \"Please provide a review\",\n * essay\n * });\n * return {\n * essay,\n * review: humanReview\n * };\n * });\n *\n * // Example configuration for the workflow\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * // Topic for the essay\n * const topic = \"cats\";\n *\n * // Stream the workflow to generate the essay and await human review\n * for await (const result of reviewWorkflow.stream(topic, config)) {\n * console.log(result);\n * }\n *\n * // Example human review provided after the interrupt\n * const humanReview = \"This essay is great.\";\n *\n * // Resume the workflow with the provided human review\n * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {\n * console.log(result);\n * }\n * ```\n *\n * @example Accessing the previous return value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const accumulator = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (input: string) => {\n * const previous = getPreviousState<number>();\n * return previous !== undefined ? `${previous } ${input}` : input;\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n * await accumulator.invoke(\"hello\", config); // returns \"hello\"\n * await accumulator.invoke(\"world\", config); // returns \"hello world\"\n * ```\n *\n * @example Using entrypoint.final to save a value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const myWorkflow = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (num: number) => {\n * const previous = getPreviousState<number>();\n *\n * // This will return the previous value to the caller, saving\n * // 2 * num to the checkpoint, which will be used in the next invocation\n * // for the `previous` parameter.\n * return entrypoint.final({\n * value: previous ?? 0,\n * save: 2 * num\n * });\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * await myWorkflow.invoke(3, config); // 0 (previous was undefined)\n * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)\n * ```\n * @category Functional API\n */\nexport const entrypoint = function entrypoint<InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n) {\n const { name, checkpointer, store, cache } =\n typeof optionsOrName === \"string\"\n ? { name: optionsOrName, checkpointer: undefined, store: undefined }\n : optionsOrName;\n const timeout = coerceTimeoutPolicy(\n typeof optionsOrName === \"string\" ? undefined : optionsOrName.timeout\n );\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as entrypoints. For streaming responses, use config.write.\"\n );\n }\n const streamMode = \"updates\";\n const bound = getRunnableForEntrypoint(name, func);\n\n // Helper to check if a value is an EntrypointFinal\n function isEntrypointFinal(\n value: unknown\n ): value is EntrypointFinal<unknown, unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__lg_type\" in value &&\n value.__lg_type === \"__pregel_final\"\n );\n }\n\n // Helper function to pluck the return value from EntrypointFinal or passthrough\n const pluckReturnValue = new RunnableCallable({\n name: \"pluckReturnValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.value : value;\n },\n });\n\n // Helper function to pluck the save value from EntrypointFinal or passthrough\n const pluckSaveValue = new RunnableCallable({\n name: \"pluckSaveValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.save : value;\n },\n });\n\n const entrypointNode = new PregelNode<InputT, EntrypointReturnT<OutputT>>({\n bound,\n triggers: [START],\n channels: [START],\n timeout,\n writers: [\n new ChannelWrite(\n [\n { channel: END, value: PASSTHROUGH, mapper: pluckReturnValue },\n { channel: PREVIOUS, value: PASSTHROUGH, mapper: pluckSaveValue },\n ],\n [TAG_HIDDEN]\n ),\n ],\n });\n\n return new Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>, // node types\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n }, // channel types\n Record<string, unknown>, // configurable types\n InputT, // input type\n EntrypointReturnT<OutputT> // output type\n >({\n name,\n checkpointer,\n nodes: {\n [name]: entrypointNode,\n },\n channels: {\n [START]: new EphemeralValue<InputT>(),\n [END]: new LastValue<EntrypointReturnT<OutputT>>(),\n [PREVIOUS]: new LastValue<EntrypointFinalSaveT<OutputT>>(),\n },\n inputChannels: START,\n outputChannels: END,\n streamChannels: END,\n streamMode,\n store,\n cache,\n });\n} as EntrypointFunction;\n\n// documented by the EntrypointFunction interface\nentrypoint.final = function final<ValueT, SaveT>({\n value,\n save,\n}: {\n value?: ValueT;\n save?: SaveT;\n}): EntrypointFinal<ValueT, SaveT> {\n return { value, save, __lg_type: \"__pregel_final\" };\n};\n\n/**\n * A helper utility function for use with the functional API that returns the previous\n * state from the checkpoint from the last invocation of the current thread.\n *\n * This function allows workflows to access state that was saved in previous runs\n * using {@link entrypoint.final}.\n *\n * @typeParam StateT - The type of the state that was previously saved\n * @returns The previous saved state from the last invocation of the current thread\n *\n * @example\n * ```typescript\n * const previousState = getPreviousState<{ counter: number }>();\n * const newCount = (previousState?.counter ?? 0) + 1;\n * ```\n * @category Functional API\n */\nexport function getPreviousState<StateT>(): StateT {\n const config: LangGraphRunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n return config.configurable?.[CONFIG_KEY_PREVIOUS_STATE] as StateT;\n}\n"],"mappings":"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"}
|
package/dist/func/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/func/index.ts"],"sourcesContent":["import {\n BaseCache,\n BaseCheckpointSaver,\n BaseStore,\n} from \"@langchain/langgraph-checkpoint\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { Pregel } from \"../pregel/index.js\";\nimport { PregelNode } from \"../pregel/read.js\";\nimport {\n CONFIG_KEY_PREVIOUS_STATE,\n END,\n PREVIOUS,\n START,\n TAG_HIDDEN,\n} from \"../constants.js\";\nimport { EphemeralValue } from \"../channels/ephemeral_value.js\";\nimport { call, getRunnableForEntrypoint } from \"../pregel/call.js\";\nimport type {\n CachePolicy,\n RetryPolicy,\n TimeoutPolicy,\n} from \"../pregel/utils/index.js\";\nimport { coerceTimeoutPolicy } from \"../pregel/utils/index.js\";\nimport { LastValue } from \"../channels/last_value.js\";\nimport {\n EntrypointFinal,\n EntrypointReturnT,\n EntrypointFinalSaveT,\n EntrypointFunc,\n TaskFunc,\n} from \"./types.js\";\nimport { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\nimport {\n RunnableCallable,\n isAsyncGeneratorFunction,\n isGeneratorFunction,\n} from \"../utils.js\";\nimport { ChannelWrite, PASSTHROUGH } from \"../pregel/write.js\";\n\n/**\n * Options for the {@link task} function\n */\nexport interface TaskOptions {\n /**\n * The name of the task, analogous to the node name in {@link StateGraph}.\n */\n name: string;\n /**\n * The retry policy for the task. Configures how many times and under what conditions\n * the task should be retried if it fails.\n */\n retry?: RetryPolicy;\n\n /**\n * The cache policy for the task. Configures how the task should be cached.\n */\n cachePolicy?: CachePolicy;\n\n /**\n * Maximum duration for a single attempt of this task. Accepts a number of\n * milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised and the task's\n * retry policy (if any) decides whether to retry.\n */\n timeout?: number | TimeoutPolicy;\n}\n\n/**\n * Define a LangGraph task using the `task` function.\n *\n * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.\n * A task can be called like a regular function with the following differences:\n *\n * - When a checkpointer is enabled, the function inputs and outputs must be serializable.\n * - The wrapped function can only be called from within an entrypoint or StateGraph.\n * - Calling the function produces a promise. This makes it easy to parallelize tasks.\n *\n * @typeParam ArgsT - The type of arguments the task function accepts\n * @typeParam OutputT - The type of value the task function returns\n * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task\n * @param func - The function that executes this task\n * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise\n *\n * @example basic example\n * ```typescript\n * const addOne = task(\"add\", async (a: number) => a + 1);\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n *\n * // Call the entrypoint\n * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]\n * ```\n *\n * @example using a retry policy\n * ```typescript\n * const addOne = task({\n * name: \"add\",\n * retry: { maxAttempts: 3 }\n * },\n * async (a: number) => a + 1\n * );\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n * ```\n * @category Functional API\n */\nexport function task<ArgsT extends unknown[], OutputT>(\n optionsOrName: TaskOptions | string,\n func: TaskFunc<ArgsT, OutputT>\n): (...args: ArgsT) => Promise<OutputT> {\n const options =\n typeof optionsOrName === \"string\"\n ? {\n name: optionsOrName,\n retry: undefined,\n cachePolicy: undefined,\n timeout: undefined,\n }\n : optionsOrName;\n\n const { name, retry } = options;\n const timeout = coerceTimeoutPolicy(options.timeout);\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as tasks. For streaming responses, use config.write.\"\n );\n }\n\n const cachePolicy =\n options.cachePolicy ??\n // `cache` was mistakingly used as an alias for `cachePolicy` in v0.3.x,\n // TODO: remove in 1.x\n (\"cache\" in options ? (options.cache as CachePolicy) : undefined);\n\n let cache: CachePolicy | undefined;\n if (typeof cachePolicy === \"boolean\") {\n cache = cachePolicy ? {} : undefined;\n } else {\n cache = cachePolicy;\n }\n\n return (...args: ArgsT) => {\n return call({ func, name, retry, cache, timeout }, ...args);\n };\n}\n\n/**\n * Options for the {@link entrypoint} function\n */\nexport type EntrypointOptions = {\n /**\n * The name of the {@link entrypoint}, analogous to the node name in {@link StateGraph}.\n * This name is used for logging, debugging, and checkpoint identification.\n */\n name: string;\n /**\n * The checkpointer for the {@link entrypoint}. Used to save and restore state between\n * invocations of the workflow.\n */\n checkpointer?: BaseCheckpointSaver;\n /**\n * The store for the {@link entrypoint}. Used to persist data across workflow runs.\n */\n store?: BaseStore;\n\n /**\n * The cache for the {@link entrypoint}. Used to cache values between workflow runs.\n */\n cache?: BaseCache;\n\n /**\n * Maximum duration for a single attempt of this entrypoint. Accepts a number\n * of milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised.\n */\n timeout?: number | TimeoutPolicy;\n};\n\n/**\n * Type declaration for the entrypoint function with its properties\n * @category Functional API\n */\nexport interface EntrypointFunction {\n <InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n ): Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>,\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n },\n Record<string, unknown>,\n InputT,\n EntrypointReturnT<OutputT>,\n // Because the update type is an return type union of tasks + entrypoint,\n // thus we can't type it properly.\n any, // eslint-disable-line @typescript-eslint/no-explicit-any\n Awaited<EntrypointReturnT<OutputT>>\n >;\n\n /**\n * A helper utility for use with the functional API that returns a value to the caller,\n * as well as a separate state value to persist to the checkpoint. This allows workflows\n * to maintain state between runs while returning different values to the caller.\n *\n * @typeParam ValueT - The type of the value to return to the caller\n * @typeParam SaveT - The type of the state to save to the checkpoint\n * @param options.value - The value to return to the caller\n * @param options.save - The value to save to the checkpoint\n * @returns An object with the value and save properties\n *\n * @example\n * ```typescript\n * return entrypoint.final({\n * value: \"result for caller\",\n * save: { counter: currentCount + 1 }\n * });\n * ```\n */\n final<ValueT, SaveT>(options: {\n value?: ValueT;\n save?: SaveT;\n }): EntrypointFinal<ValueT, SaveT>;\n}\n\n/**\n * Define a LangGraph workflow using the `entrypoint` function.\n *\n * ### Function signature\n *\n * The wrapped function must accept at most **two parameters**. The first parameter\n * is the input to the function. The second (optional) parameter is a\n * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to\n * the function, you can pass them as an object.\n *\n * ### Helper functions\n *\n * #### Streaming\n * To write data to the \"custom\" stream, use the {@link getWriter} function, or the\n * {@link LangGraphRunnableConfig.writer} property.\n *\n * #### State management\n * The {@link getPreviousState} function can be used to access the previous state\n * that was returned from the last invocation of the entrypoint on the same thread id.\n *\n * If you wish to save state other than the return value, you can use the\n * {@link entrypoint.final} function.\n *\n * @typeParam InputT - The type of input the entrypoint accepts\n * @typeParam OutputT - The type of output the entrypoint produces\n * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint\n * @param func - The function that executes this entrypoint\n * @returns A {@link Pregel} instance that can be run to execute the workflow\n *\n * @example Using entrypoint and tasks\n * ```typescript\n * import { task, entrypoint } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n * import { interrupt, Command } from \"@langchain/langgraph\";\n *\n * const composeEssay = task(\"compose\", async (topic: string) => {\n * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation\n * return `An essay about ${topic}`;\n * });\n *\n * const reviewWorkflow = entrypoint({\n * name: \"review\",\n * checkpointer: new MemorySaver()\n * }, async (topic: string) => {\n * const essay = await composeEssay(topic);\n * const humanReview = await interrupt({\n * question: \"Please provide a review\",\n * essay\n * });\n * return {\n * essay,\n * review: humanReview\n * };\n * });\n *\n * // Example configuration for the workflow\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * // Topic for the essay\n * const topic = \"cats\";\n *\n * // Stream the workflow to generate the essay and await human review\n * for await (const result of reviewWorkflow.stream(topic, config)) {\n * console.log(result);\n * }\n *\n * // Example human review provided after the interrupt\n * const humanReview = \"This essay is great.\";\n *\n * // Resume the workflow with the provided human review\n * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {\n * console.log(result);\n * }\n * ```\n *\n * @example Accessing the previous return value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const accumulator = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (input: string) => {\n * const previous = getPreviousState<number>();\n * return previous !== undefined ? `${previous } ${input}` : input;\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n * await accumulator.invoke(\"hello\", config); // returns \"hello\"\n * await accumulator.invoke(\"world\", config); // returns \"hello world\"\n * ```\n *\n * @example Using entrypoint.final to save a value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const myWorkflow = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (num: number) => {\n * const previous = getPreviousState<number>();\n *\n * // This will return the previous value to the caller, saving\n * // 2 * num to the checkpoint, which will be used in the next invocation\n * // for the `previous` parameter.\n * return entrypoint.final({\n * value: previous ?? 0,\n * save: 2 * num\n * });\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * await myWorkflow.invoke(3, config); // 0 (previous was undefined)\n * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)\n * ```\n * @category Functional API\n */\nexport const entrypoint = function entrypoint<InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n) {\n const { name, checkpointer, store, cache } =\n typeof optionsOrName === \"string\"\n ? { name: optionsOrName, checkpointer: undefined, store: undefined }\n : optionsOrName;\n const timeout = coerceTimeoutPolicy(\n typeof optionsOrName === \"string\" ? undefined : optionsOrName.timeout\n );\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as entrypoints. For streaming responses, use config.write.\"\n );\n }\n const streamMode = \"updates\";\n const bound = getRunnableForEntrypoint(name, func);\n\n // Helper to check if a value is an EntrypointFinal\n function isEntrypointFinal(\n value: unknown\n ): value is EntrypointFinal<unknown, unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__lg_type\" in value &&\n value.__lg_type === \"__pregel_final\"\n );\n }\n\n // Helper function to pluck the return value from EntrypointFinal or passthrough\n const pluckReturnValue = new RunnableCallable({\n name: \"pluckReturnValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.value : value;\n },\n });\n\n // Helper function to pluck the save value from EntrypointFinal or passthrough\n const pluckSaveValue = new RunnableCallable({\n name: \"pluckSaveValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.save : value;\n },\n });\n\n const entrypointNode = new PregelNode<InputT, EntrypointReturnT<OutputT>>({\n bound,\n triggers: [START],\n channels: [START],\n timeout,\n writers: [\n new ChannelWrite(\n [\n { channel: END, value: PASSTHROUGH, mapper: pluckReturnValue },\n { channel: PREVIOUS, value: PASSTHROUGH, mapper: pluckSaveValue },\n ],\n [TAG_HIDDEN]\n ),\n ],\n });\n\n return new Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>, // node types\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n }, // channel types\n Record<string, unknown>, // configurable types\n InputT, // input type\n EntrypointReturnT<OutputT> // output type\n >({\n name,\n checkpointer,\n nodes: {\n [name]: entrypointNode,\n },\n channels: {\n [START]: new EphemeralValue<InputT>(),\n [END]: new LastValue<EntrypointReturnT<OutputT>>(),\n [PREVIOUS]: new LastValue<EntrypointFinalSaveT<OutputT>>(),\n },\n inputChannels: START,\n outputChannels: END,\n streamChannels: END,\n streamMode,\n store,\n cache,\n });\n} as EntrypointFunction;\n\n// documented by the EntrypointFunction interface\nentrypoint.final = function final<ValueT, SaveT>({\n value,\n save,\n}: {\n value?: ValueT;\n save?: SaveT;\n}): EntrypointFinal<ValueT, SaveT> {\n return { value, save, __lg_type: \"__pregel_final\" };\n};\n\n/**\n * A helper utility function for use with the functional API that returns the previous\n * state from the checkpoint from the last invocation of the current thread.\n *\n * This function allows workflows to access state that was saved in previous runs\n * using {@link entrypoint.final}.\n *\n * @typeParam StateT - The type of the state that was previously saved\n * @returns The previous saved state from the last invocation of the current thread\n *\n * @example\n * ```typescript\n * const previousState = getPreviousState<{ counter: number }>();\n * const newCount = (previousState?.counter ?? 0) + 1;\n * ```\n * @category Functional API\n */\nexport function getPreviousState<StateT>(): StateT {\n const config: LangGraphRunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n return config.configurable?.[CONFIG_KEY_PREVIOUS_STATE] as StateT;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkHA,SAAgB,KACd,eACA,MACsC;CACtC,MAAM,UACJ,OAAO,kBAAkB,WACrB;EACE,MAAM;EACN,OAAO,KAAA;EACP,aAAa,KAAA;EACb,SAAS,KAAA;EACV,GACD;CAEN,MAAM,EAAE,MAAM,UAAU;CACxB,MAAM,UAAU,oBAAoB,QAAQ,QAAQ;AACpD,KAAI,yBAAyB,KAAK,IAAI,oBAAoB,KAAK,CAC7D,OAAM,IAAI,MACR,iFACD;CAGH,MAAM,cACJ,QAAQ,gBAGP,WAAW,UAAW,QAAQ,QAAwB,KAAA;CAEzD,IAAI;AACJ,KAAI,OAAO,gBAAgB,UACzB,SAAQ,cAAc,EAAE,GAAG,KAAA;KAE3B,SAAQ;AAGV,SAAQ,GAAG,SAAgB;AACzB,SAAO,KAAK;GAAE;GAAM;GAAM;GAAO;GAAO;GAAS,EAAE,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyN/D,MAAa,aAAa,SAAS,WACjC,eACA,MACA;CACA,MAAM,EAAE,MAAM,cAAc,OAAO,UACjC,OAAO,kBAAkB,WACrB;EAAE,MAAM;EAAe,cAAc,KAAA;EAAW,OAAO,KAAA;EAAW,GAClE;CACN,MAAM,UAAU,oBACd,OAAO,kBAAkB,WAAW,KAAA,IAAY,cAAc,QAC/D;AACD,KAAI,yBAAyB,KAAK,IAAI,oBAAoB,KAAK,CAC7D,OAAM,IAAI,MACR,uFACD;CAEH,MAAM,aAAa;CACnB,MAAM,QAAQ,yBAAyB,MAAM,KAAK;CAGlD,SAAS,kBACP,OAC4C;AAC5C,SACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACf,MAAM,cAAc;;CAKxB,MAAM,mBAAmB,IAAI,iBAAiB;EAC5C,MAAM;EACN,OAAO,UAAmB;AACxB,UAAO,kBAAkB,MAAM,GAAG,MAAM,QAAQ;;EAEnD,CAAC;CAGF,MAAM,iBAAiB,IAAI,iBAAiB;EAC1C,MAAM;EACN,OAAO,UAAmB;AACxB,UAAO,kBAAkB,MAAM,GAAG,MAAM,OAAO;;EAElD,CAAC;CAEF,MAAM,iBAAiB,IAAI,WAA+C;EACxE;EACA,UAAU,CAAC,MAAM;EACjB,UAAU,CAAC,MAAM;EACjB;EACA,SAAS,CACP,IAAI,aACF,CACE;GAAE,SAAS;GAAK,OAAO;GAAa,QAAQ;GAAkB,EAC9D;GAAE,SAAS;GAAU,OAAO;GAAa,QAAQ;GAAgB,CAClE,EACD,CAAC,WAAW,CACb,CACF;EACF,CAAC;AAEF,QAAO,IAAI,OAUT;EACA;EACA;EACA,OAAO,GACJ,OAAO,gBACT;EACD,UAAU;IACP,QAAQ,IAAI,gBAAwB;IACpC,MAAM,IAAI,WAAuC;IACjD,WAAW,IAAI,WAA0C;GAC3D;EACD,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB;EACA;EACA;EACD,CAAC;;AAIJ,WAAW,QAAQ,SAAS,MAAqB,EAC/C,OACA,QAIiC;AACjC,QAAO;EAAE;EAAO;EAAM,WAAW;EAAkB;;;;;;;;;;;;;;;;;;;AAoBrD,SAAgB,mBAAmC;AAGjD,QADE,mCAAmC,mBAAmB,CAC1C,eAAe"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/func/index.ts"],"sourcesContent":["import {\n BaseCache,\n BaseCheckpointSaver,\n BaseStore,\n} from \"@langchain/langgraph-checkpoint\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { Pregel } from \"../pregel/index.js\";\nimport { PregelNode } from \"../pregel/read.js\";\nimport {\n CONFIG_KEY_PREVIOUS_STATE,\n END,\n PREVIOUS,\n START,\n TAG_HIDDEN,\n} from \"../constants.js\";\nimport { EphemeralValue } from \"../channels/ephemeral_value.js\";\nimport { call, getRunnableForEntrypoint } from \"../pregel/call.js\";\nimport type {\n CachePolicy,\n RetryPolicy,\n TimeoutPolicy,\n} from \"../pregel/utils/index.js\";\nimport { coerceTimeoutPolicy } from \"../pregel/utils/index.js\";\nimport { LastValue } from \"../channels/last_value.js\";\nimport {\n EntrypointFinal,\n EntrypointReturnT,\n EntrypointFinalSaveT,\n EntrypointFunc,\n TaskFunc,\n} from \"./types.js\";\nimport { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\nimport {\n RunnableCallable,\n isAsyncGeneratorFunction,\n isGeneratorFunction,\n} from \"../utils.js\";\nimport { ChannelWrite, PASSTHROUGH } from \"../pregel/write.js\";\n\n/**\n * Options for the {@link task} function\n */\nexport interface TaskOptions {\n /**\n * The name of the task, analogous to the node name in {@link StateGraph}.\n */\n name: string;\n /**\n * The retry policy for the task. Configures how many times and under what conditions\n * the task should be retried if it fails.\n */\n retry?: RetryPolicy;\n\n /**\n * The cache policy for the task. Configures how the task should be cached.\n */\n cachePolicy?: CachePolicy;\n\n /**\n * Maximum duration for a single attempt of this task. Accepts a number of\n * milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised and the task's\n * retry policy (if any) decides whether to retry.\n */\n timeout?: number | TimeoutPolicy;\n}\n\n/**\n * Define a LangGraph task using the `task` function.\n *\n * Tasks can only be called from within an {@link entrypoint} or from within a StateGraph.\n * A task can be called like a regular function with the following differences:\n *\n * - When a checkpointer is enabled, the function inputs and outputs must be serializable.\n * - The wrapped function can only be called from within an entrypoint or StateGraph.\n * - Calling the function produces a promise. This makes it easy to parallelize tasks.\n *\n * @typeParam ArgsT - The type of arguments the task function accepts\n * @typeParam OutputT - The type of value the task function returns\n * @param optionsOrName - Either an {@link TaskOptions} object, or a string for the name of the task\n * @param func - The function that executes this task\n * @returns A proxy function that accepts the same arguments as the original and always returns the result as a Promise\n *\n * @example basic example\n * ```typescript\n * const addOne = task(\"add\", async (a: number) => a + 1);\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n *\n * // Call the entrypoint\n * await workflow.invoke([1, 2, 3]); // Returns [2, 3, 4]\n * ```\n *\n * @example using a retry policy\n * ```typescript\n * const addOne = task({\n * name: \"add\",\n * retry: { maxAttempts: 3 }\n * },\n * async (a: number) => a + 1\n * );\n *\n * const workflow = entrypoint(\"example\", async (numbers: number[]) => {\n * const promises = numbers.map(n => addOne(n));\n * const results = await Promise.all(promises);\n * return results;\n * });\n * ```\n * @category Functional API\n */\nexport function task<ArgsT extends unknown[], OutputT>(\n optionsOrName: TaskOptions | string,\n func: TaskFunc<ArgsT, OutputT>\n): (...args: ArgsT) => Promise<OutputT> {\n const options =\n typeof optionsOrName === \"string\"\n ? {\n name: optionsOrName,\n retry: undefined,\n cachePolicy: undefined,\n timeout: undefined,\n }\n : optionsOrName;\n\n const { name, retry } = options;\n const timeout = coerceTimeoutPolicy(options.timeout);\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as tasks. For streaming responses, use config.write.\"\n );\n }\n\n const cachePolicy =\n options.cachePolicy ??\n // `cache` was mistakenly used as an alias for `cachePolicy` in v0.3.x,\n // TODO: remove in 1.x\n (\"cache\" in options ? (options.cache as CachePolicy) : undefined);\n\n let cache: CachePolicy | undefined;\n if (typeof cachePolicy === \"boolean\") {\n cache = cachePolicy ? {} : undefined;\n } else {\n cache = cachePolicy;\n }\n\n return (...args: ArgsT) => {\n return call({ func, name, retry, cache, timeout }, ...args);\n };\n}\n\n/**\n * Options for the {@link entrypoint} function\n */\nexport type EntrypointOptions = {\n /**\n * The name of the {@link entrypoint}, analogous to the node name in {@link StateGraph}.\n * This name is used for logging, debugging, and checkpoint identification.\n */\n name: string;\n /**\n * The checkpointer for the {@link entrypoint}. Used to save and restore state between\n * invocations of the workflow.\n */\n checkpointer?: BaseCheckpointSaver;\n /**\n * The store for the {@link entrypoint}. Used to persist data across workflow runs.\n */\n store?: BaseStore;\n\n /**\n * The cache for the {@link entrypoint}. Used to cache values between workflow runs.\n */\n cache?: BaseCache;\n\n /**\n * Maximum duration for a single attempt of this entrypoint. Accepts a number\n * of milliseconds (a hard wall-clock cap) or a {@link TimeoutPolicy} for finer\n * control. When exceeded, a {@link NodeTimeoutError} is raised.\n */\n timeout?: number | TimeoutPolicy;\n};\n\n/**\n * Type declaration for the entrypoint function with its properties\n * @category Functional API\n */\nexport interface EntrypointFunction {\n <InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n ): Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>,\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n },\n Record<string, unknown>,\n InputT,\n EntrypointReturnT<OutputT>,\n // Because the update type is an return type union of tasks + entrypoint,\n // thus we can't type it properly.\n any, // eslint-disable-line @typescript-eslint/no-explicit-any\n Awaited<EntrypointReturnT<OutputT>>\n >;\n\n /**\n * A helper utility for use with the functional API that returns a value to the caller,\n * as well as a separate state value to persist to the checkpoint. This allows workflows\n * to maintain state between runs while returning different values to the caller.\n *\n * @typeParam ValueT - The type of the value to return to the caller\n * @typeParam SaveT - The type of the state to save to the checkpoint\n * @param options.value - The value to return to the caller\n * @param options.save - The value to save to the checkpoint\n * @returns An object with the value and save properties\n *\n * @example\n * ```typescript\n * return entrypoint.final({\n * value: \"result for caller\",\n * save: { counter: currentCount + 1 }\n * });\n * ```\n */\n final<ValueT, SaveT>(options: {\n value?: ValueT;\n save?: SaveT;\n }): EntrypointFinal<ValueT, SaveT>;\n}\n\n/**\n * Define a LangGraph workflow using the `entrypoint` function.\n *\n * ### Function signature\n *\n * The wrapped function must accept at most **two parameters**. The first parameter\n * is the input to the function. The second (optional) parameter is a\n * {@link LangGraphRunnableConfig} object. If you wish to pass multiple parameters to\n * the function, you can pass them as an object.\n *\n * ### Helper functions\n *\n * #### Streaming\n * To write data to the \"custom\" stream, use the {@link getWriter} function, or the\n * {@link LangGraphRunnableConfig.writer} property.\n *\n * #### State management\n * The {@link getPreviousState} function can be used to access the previous state\n * that was returned from the last invocation of the entrypoint on the same thread id.\n *\n * If you wish to save state other than the return value, you can use the\n * {@link entrypoint.final} function.\n *\n * @typeParam InputT - The type of input the entrypoint accepts\n * @typeParam OutputT - The type of output the entrypoint produces\n * @param optionsOrName - Either an {@link EntrypointOptions} object, or a string for the name of the entrypoint\n * @param func - The function that executes this entrypoint\n * @returns A {@link Pregel} instance that can be run to execute the workflow\n *\n * @example Using entrypoint and tasks\n * ```typescript\n * import { task, entrypoint } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n * import { interrupt, Command } from \"@langchain/langgraph\";\n *\n * const composeEssay = task(\"compose\", async (topic: string) => {\n * await new Promise(r => setTimeout(r, 1000)); // Simulate slow operation\n * return `An essay about ${topic}`;\n * });\n *\n * const reviewWorkflow = entrypoint({\n * name: \"review\",\n * checkpointer: new MemorySaver()\n * }, async (topic: string) => {\n * const essay = await composeEssay(topic);\n * const humanReview = await interrupt({\n * question: \"Please provide a review\",\n * essay\n * });\n * return {\n * essay,\n * review: humanReview\n * };\n * });\n *\n * // Example configuration for the workflow\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * // Topic for the essay\n * const topic = \"cats\";\n *\n * // Stream the workflow to generate the essay and await human review\n * for await (const result of reviewWorkflow.stream(topic, config)) {\n * console.log(result);\n * }\n *\n * // Example human review provided after the interrupt\n * const humanReview = \"This essay is great.\";\n *\n * // Resume the workflow with the provided human review\n * for await (const result of reviewWorkflow.stream(new Command({ resume: humanReview }), config)) {\n * console.log(result);\n * }\n * ```\n *\n * @example Accessing the previous return value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const accumulator = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (input: string) => {\n * const previous = getPreviousState<number>();\n * return previous !== undefined ? `${previous } ${input}` : input;\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n * await accumulator.invoke(\"hello\", config); // returns \"hello\"\n * await accumulator.invoke(\"world\", config); // returns \"hello world\"\n * ```\n *\n * @example Using entrypoint.final to save a value\n * ```typescript\n * import { entrypoint, getPreviousState } from \"@langchain/langgraph\";\n * import { MemorySaver } from \"@langchain/langgraph-checkpoint\";\n *\n * const myWorkflow = entrypoint({\n * name: \"accumulator\",\n * checkpointer: new MemorySaver()\n * }, async (num: number) => {\n * const previous = getPreviousState<number>();\n *\n * // This will return the previous value to the caller, saving\n * // 2 * num to the checkpoint, which will be used in the next invocation\n * // for the `previous` parameter.\n * return entrypoint.final({\n * value: previous ?? 0,\n * save: 2 * num\n * });\n * });\n *\n * const config = {\n * configurable: {\n * thread_id: \"some_thread\"\n * }\n * };\n *\n * await myWorkflow.invoke(3, config); // 0 (previous was undefined)\n * await myWorkflow.invoke(1, config); // 6 (previous was 3 * 2 from the previous invocation)\n * ```\n * @category Functional API\n */\nexport const entrypoint = function entrypoint<InputT, OutputT>(\n optionsOrName: EntrypointOptions | string,\n func: EntrypointFunc<InputT, OutputT>\n) {\n const { name, checkpointer, store, cache } =\n typeof optionsOrName === \"string\"\n ? { name: optionsOrName, checkpointer: undefined, store: undefined }\n : optionsOrName;\n const timeout = coerceTimeoutPolicy(\n typeof optionsOrName === \"string\" ? undefined : optionsOrName.timeout\n );\n if (isAsyncGeneratorFunction(func) || isGeneratorFunction(func)) {\n throw new Error(\n \"Generators are disallowed as entrypoints. For streaming responses, use config.write.\"\n );\n }\n const streamMode = \"updates\";\n const bound = getRunnableForEntrypoint(name, func);\n\n // Helper to check if a value is an EntrypointFinal\n function isEntrypointFinal(\n value: unknown\n ): value is EntrypointFinal<unknown, unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"__lg_type\" in value &&\n value.__lg_type === \"__pregel_final\"\n );\n }\n\n // Helper function to pluck the return value from EntrypointFinal or passthrough\n const pluckReturnValue = new RunnableCallable({\n name: \"pluckReturnValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.value : value;\n },\n });\n\n // Helper function to pluck the save value from EntrypointFinal or passthrough\n const pluckSaveValue = new RunnableCallable({\n name: \"pluckSaveValue\",\n func: (value: unknown) => {\n return isEntrypointFinal(value) ? value.save : value;\n },\n });\n\n const entrypointNode = new PregelNode<InputT, EntrypointReturnT<OutputT>>({\n bound,\n triggers: [START],\n channels: [START],\n timeout,\n writers: [\n new ChannelWrite(\n [\n { channel: END, value: PASSTHROUGH, mapper: pluckReturnValue },\n { channel: PREVIOUS, value: PASSTHROUGH, mapper: pluckSaveValue },\n ],\n [TAG_HIDDEN]\n ),\n ],\n });\n\n return new Pregel<\n Record<string, PregelNode<InputT, EntrypointReturnT<OutputT>>>, // node types\n {\n [START]: EphemeralValue<InputT>;\n [END]: LastValue<EntrypointReturnT<OutputT>>;\n [PREVIOUS]: LastValue<EntrypointFinalSaveT<OutputT>>;\n }, // channel types\n Record<string, unknown>, // configurable types\n InputT, // input type\n EntrypointReturnT<OutputT> // output type\n >({\n name,\n checkpointer,\n nodes: {\n [name]: entrypointNode,\n },\n channels: {\n [START]: new EphemeralValue<InputT>(),\n [END]: new LastValue<EntrypointReturnT<OutputT>>(),\n [PREVIOUS]: new LastValue<EntrypointFinalSaveT<OutputT>>(),\n },\n inputChannels: START,\n outputChannels: END,\n streamChannels: END,\n streamMode,\n store,\n cache,\n });\n} as EntrypointFunction;\n\n// documented by the EntrypointFunction interface\nentrypoint.final = function final<ValueT, SaveT>({\n value,\n save,\n}: {\n value?: ValueT;\n save?: SaveT;\n}): EntrypointFinal<ValueT, SaveT> {\n return { value, save, __lg_type: \"__pregel_final\" };\n};\n\n/**\n * A helper utility function for use with the functional API that returns the previous\n * state from the checkpoint from the last invocation of the current thread.\n *\n * This function allows workflows to access state that was saved in previous runs\n * using {@link entrypoint.final}.\n *\n * @typeParam StateT - The type of the state that was previously saved\n * @returns The previous saved state from the last invocation of the current thread\n *\n * @example\n * ```typescript\n * const previousState = getPreviousState<{ counter: number }>();\n * const newCount = (previousState?.counter ?? 0) + 1;\n * ```\n * @category Functional API\n */\nexport function getPreviousState<StateT>(): StateT {\n const config: LangGraphRunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n return config.configurable?.[CONFIG_KEY_PREVIOUS_STATE] as StateT;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkHA,SAAgB,KACd,eACA,MACsC;CACtC,MAAM,UACJ,OAAO,kBAAkB,WACrB;EACE,MAAM;EACN,OAAO,KAAA;EACP,aAAa,KAAA;EACb,SAAS,KAAA;EACV,GACD;CAEN,MAAM,EAAE,MAAM,UAAU;CACxB,MAAM,UAAU,oBAAoB,QAAQ,QAAQ;AACpD,KAAI,yBAAyB,KAAK,IAAI,oBAAoB,KAAK,CAC7D,OAAM,IAAI,MACR,iFACD;CAGH,MAAM,cACJ,QAAQ,gBAGP,WAAW,UAAW,QAAQ,QAAwB,KAAA;CAEzD,IAAI;AACJ,KAAI,OAAO,gBAAgB,UACzB,SAAQ,cAAc,EAAE,GAAG,KAAA;KAE3B,SAAQ;AAGV,SAAQ,GAAG,SAAgB;AACzB,SAAO,KAAK;GAAE;GAAM;GAAM;GAAO;GAAO;GAAS,EAAE,GAAG,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyN/D,MAAa,aAAa,SAAS,WACjC,eACA,MACA;CACA,MAAM,EAAE,MAAM,cAAc,OAAO,UACjC,OAAO,kBAAkB,WACrB;EAAE,MAAM;EAAe,cAAc,KAAA;EAAW,OAAO,KAAA;EAAW,GAClE;CACN,MAAM,UAAU,oBACd,OAAO,kBAAkB,WAAW,KAAA,IAAY,cAAc,QAC/D;AACD,KAAI,yBAAyB,KAAK,IAAI,oBAAoB,KAAK,CAC7D,OAAM,IAAI,MACR,uFACD;CAEH,MAAM,aAAa;CACnB,MAAM,QAAQ,yBAAyB,MAAM,KAAK;CAGlD,SAAS,kBACP,OAC4C;AAC5C,SACE,OAAO,UAAU,YACjB,UAAU,QACV,eAAe,SACf,MAAM,cAAc;;CAKxB,MAAM,mBAAmB,IAAI,iBAAiB;EAC5C,MAAM;EACN,OAAO,UAAmB;AACxB,UAAO,kBAAkB,MAAM,GAAG,MAAM,QAAQ;;EAEnD,CAAC;CAGF,MAAM,iBAAiB,IAAI,iBAAiB;EAC1C,MAAM;EACN,OAAO,UAAmB;AACxB,UAAO,kBAAkB,MAAM,GAAG,MAAM,OAAO;;EAElD,CAAC;CAEF,MAAM,iBAAiB,IAAI,WAA+C;EACxE;EACA,UAAU,CAAC,MAAM;EACjB,UAAU,CAAC,MAAM;EACjB;EACA,SAAS,CACP,IAAI,aACF,CACE;GAAE,SAAS;GAAK,OAAO;GAAa,QAAQ;GAAkB,EAC9D;GAAE,SAAS;GAAU,OAAO;GAAa,QAAQ;GAAgB,CAClE,EACD,CAAC,WAAW,CACb,CACF;EACF,CAAC;AAEF,QAAO,IAAI,OAUT;EACA;EACA;EACA,OAAO,GACJ,OAAO,gBACT;EACD,UAAU;IACP,QAAQ,IAAI,gBAAwB;IACpC,MAAM,IAAI,WAAuC;IACjD,WAAW,IAAI,WAA0C;GAC3D;EACD,eAAe;EACf,gBAAgB;EAChB,gBAAgB;EAChB;EACA;EACA;EACD,CAAC;;AAIJ,WAAW,QAAQ,SAAS,MAAqB,EAC/C,OACA,QAIiC;AACjC,QAAO;EAAE;EAAO;EAAM,WAAW;EAAkB;;;;;;;;;;;;;;;;;;;AAoBrD,SAAgB,mBAAmC;AAGjD,QADE,mCAAmC,mBAAmB,CAC1C,eAAe"}
|
package/dist/graph/message.cjs
CHANGED
|
@@ -31,15 +31,18 @@ function pushMessage(message, options) {
|
|
|
31
31
|
if (userStateKey === null) stateKey = void 0;
|
|
32
32
|
const validMessage = (0, _langchain_core_messages.coerceMessageLikeToMessage)(message);
|
|
33
33
|
if (!validMessage.id) throw new Error("Message ID is required.");
|
|
34
|
-
const
|
|
34
|
+
const callbacks = (() => {
|
|
35
35
|
if (Array.isArray(config.callbacks)) return config.callbacks;
|
|
36
36
|
if (typeof config.callbacks !== "undefined") return config.callbacks.handlers;
|
|
37
37
|
return [];
|
|
38
|
-
})()
|
|
39
|
-
|
|
38
|
+
})();
|
|
39
|
+
const messagesHandler = callbacks.find((cb) => "name" in cb && cb.name === "StreamMessagesHandler");
|
|
40
|
+
const protocolMessagesHandler = callbacks.find((cb) => "name" in cb && cb.name === "StreamProtocolMessagesHandler");
|
|
41
|
+
if (messagesHandler || protocolMessagesHandler) {
|
|
40
42
|
const metadata = config.metadata ?? {};
|
|
41
43
|
const namespace = (metadata.langgraph_checkpoint_ns ?? "").split("|");
|
|
42
|
-
messagesHandler._emit([namespace, metadata], validMessage, void 0, false);
|
|
44
|
+
if (messagesHandler) messagesHandler._emit([namespace, metadata], validMessage, void 0, false);
|
|
45
|
+
else if (protocolMessagesHandler) protocolMessagesHandler.emitFinalMessage([namespace, metadata], validMessage, void 0, false);
|
|
43
46
|
}
|
|
44
47
|
if (stateKey) config.configurable?.__pregel_send?.([[stateKey, validMessage]]);
|
|
45
48
|
return validMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.cjs","names":["StateGraph","messagesStateReducer","ensureLangGraphConfig"],"sources":["../../src/graph/message.ts"],"sourcesContent":["import {\n BaseMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from \"@langchain/core/messages\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { StateGraph } from \"./state.js\";\nimport { ensureLangGraphConfig } from \"../pregel/utils/config.js\";\nimport type { StreamMessagesHandler } from \"../pregel/messages.js\";\nimport { messagesStateReducer, type Messages } from \"./messages_reducer.js\";\n\n/** @ignore */\nexport class MessageGraph extends StateGraph<\n BaseMessage[],\n BaseMessage[],\n Messages\n> {\n constructor() {\n super({\n channels: {\n __root__: {\n reducer: messagesStateReducer,\n default: () => [],\n },\n },\n });\n }\n}\n\n/**\n * Manually push a message to a message stream.\n *\n * This is useful when you need to push a manually created message before the node\n * has finished executing.\n *\n * When a message is pushed, it will be automatically persisted to the state after the node has finished executing.\n * To disable persisting, set `options.stateKey` to `null`.\n *\n * @param message The message to push. The message must have an ID set, otherwise an error will be thrown.\n * @param options RunnableConfig / Runtime coming from node context.\n */\nexport function pushMessage(\n message: BaseMessage | BaseMessageLike,\n options?: RunnableConfig & {\n /**\n * The key of the state to push the message to. Set to `null` to avoid persisting.\n * @default \"messages\"\n */\n stateKey?: string | null;\n }\n) {\n const { stateKey: userStateKey, ...userConfig } = options ?? {};\n const config = ensureLangGraphConfig(userConfig);\n\n let stateKey: string | undefined = userStateKey ?? \"messages\";\n if (userStateKey === null) stateKey = undefined;\n\n // coerce to message\n const validMessage = coerceMessageLikeToMessage(message);\n if (!validMessage.id) throw new Error(\"Message ID is required.\");\n\n const callbacks = (() => {\n if (Array.isArray(config.callbacks)) {\n return config.callbacks;\n }\n\n if (typeof config.callbacks !== \"undefined\") {\n return config.callbacks.handlers;\n }\n\n return [];\n })();\n\n const messagesHandler = callbacks.find(\n (cb): cb is StreamMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamMessagesHandler\"\n );\n\n if (messagesHandler) {\n const metadata = config.metadata ?? {};\n const namespace = (\n (metadata.langgraph_checkpoint_ns ?? \"\") as string\n ).split(\"|\");\n\n messagesHandler._emit(\n
|
|
1
|
+
{"version":3,"file":"message.cjs","names":["StateGraph","messagesStateReducer","ensureLangGraphConfig"],"sources":["../../src/graph/message.ts"],"sourcesContent":["import {\n BaseMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from \"@langchain/core/messages\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { StateGraph } from \"./state.js\";\nimport { ensureLangGraphConfig } from \"../pregel/utils/config.js\";\nimport type { StreamMessagesHandler } from \"../pregel/messages.js\";\nimport type { StreamProtocolMessagesHandler } from \"../pregel/messages-v2.js\";\nimport { messagesStateReducer, type Messages } from \"./messages_reducer.js\";\n\n/** @ignore */\nexport class MessageGraph extends StateGraph<\n BaseMessage[],\n BaseMessage[],\n Messages\n> {\n constructor() {\n super({\n channels: {\n __root__: {\n reducer: messagesStateReducer,\n default: () => [],\n },\n },\n });\n }\n}\n\n/**\n * Manually push a message to a message stream.\n *\n * This is useful when you need to push a manually created message before the node\n * has finished executing.\n *\n * When a message is pushed, it will be automatically persisted to the state after the node has finished executing.\n * To disable persisting, set `options.stateKey` to `null`.\n *\n * @param message The message to push. The message must have an ID set, otherwise an error will be thrown.\n * @param options RunnableConfig / Runtime coming from node context.\n */\nexport function pushMessage(\n message: BaseMessage | BaseMessageLike,\n options?: RunnableConfig & {\n /**\n * The key of the state to push the message to. Set to `null` to avoid persisting.\n * @default \"messages\"\n */\n stateKey?: string | null;\n }\n) {\n const { stateKey: userStateKey, ...userConfig } = options ?? {};\n const config = ensureLangGraphConfig(userConfig);\n\n let stateKey: string | undefined = userStateKey ?? \"messages\";\n if (userStateKey === null) stateKey = undefined;\n\n // coerce to message\n const validMessage = coerceMessageLikeToMessage(message);\n if (!validMessage.id) throw new Error(\"Message ID is required.\");\n\n const callbacks = (() => {\n if (Array.isArray(config.callbacks)) {\n return config.callbacks;\n }\n\n if (typeof config.callbacks !== \"undefined\") {\n return config.callbacks.handlers;\n }\n\n return [];\n })();\n\n const messagesHandler = callbacks.find(\n (cb): cb is StreamMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamMessagesHandler\"\n );\n const protocolMessagesHandler = callbacks.find(\n (cb): cb is StreamProtocolMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamProtocolMessagesHandler\"\n );\n\n if (messagesHandler || protocolMessagesHandler) {\n const metadata = config.metadata ?? {};\n const namespace = (\n (metadata.langgraph_checkpoint_ns ?? \"\") as string\n ).split(\"|\");\n\n if (messagesHandler) {\n messagesHandler._emit(\n [namespace, metadata],\n validMessage,\n undefined,\n false\n );\n } else if (protocolMessagesHandler) {\n // streamEvents v3 registers StreamProtocolMessagesHandler instead of\n // StreamMessagesHandler; without this branch, pushed messages are\n // silently absent from the live `messages` channel and only surface in\n // state at node end. else-if: the handlers are mutually exclusive per\n // stream, and a single emission path avoids double emits if a caller\n // ever registers both.\n protocolMessagesHandler.emitFinalMessage(\n [namespace, metadata],\n validMessage,\n undefined,\n false\n );\n }\n }\n\n if (stateKey) {\n config.configurable?.__pregel_send?.([[stateKey, validMessage]]);\n }\n\n return validMessage;\n}\n"],"mappings":";;;;;;AAaA,IAAa,eAAb,cAAkCA,cAAAA,WAIhC;CACA,cAAc;AACZ,QAAM,EACJ,UAAU,EACR,UAAU;GACR,SAASC,yBAAAA;GACT,eAAe,EAAE;GAClB,EACF,EACF,CAAC;;;;;;;;;;;;;;;AAgBN,SAAgB,YACd,SACA,SAOA;CACA,MAAM,EAAE,UAAU,cAAc,GAAG,eAAe,WAAW,EAAE;CAC/D,MAAM,SAASC,eAAAA,sBAAsB,WAAW;CAEhD,IAAI,WAA+B,gBAAgB;AACnD,KAAI,iBAAiB,KAAM,YAAW,KAAA;CAGtC,MAAM,gBAAA,GAAA,yBAAA,4BAA0C,QAAQ;AACxD,KAAI,CAAC,aAAa,GAAI,OAAM,IAAI,MAAM,0BAA0B;CAEhE,MAAM,mBAAmB;AACvB,MAAI,MAAM,QAAQ,OAAO,UAAU,CACjC,QAAO,OAAO;AAGhB,MAAI,OAAO,OAAO,cAAc,YAC9B,QAAO,OAAO,UAAU;AAG1B,SAAO,EAAE;KACP;CAEJ,MAAM,kBAAkB,UAAU,MAC/B,OACC,UAAU,MAAM,GAAG,SAAS,wBAC/B;CACD,MAAM,0BAA0B,UAAU,MACvC,OACC,UAAU,MAAM,GAAG,SAAS,gCAC/B;AAED,KAAI,mBAAmB,yBAAyB;EAC9C,MAAM,WAAW,OAAO,YAAY,EAAE;EACtC,MAAM,aACH,SAAS,2BAA2B,IACrC,MAAM,IAAI;AAEZ,MAAI,gBACF,iBAAgB,MACd,CAAC,WAAW,SAAS,EACrB,cACA,KAAA,GACA,MACD;WACQ,wBAOT,yBAAwB,iBACtB,CAAC,WAAW,SAAS,EACrB,cACA,KAAA,GACA,MACD;;AAIL,KAAI,SACF,QAAO,cAAc,gBAAgB,CAAC,CAAC,UAAU,aAAa,CAAC,CAAC;AAGlE,QAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.cts","names":[],"sources":["../../src/graph/message.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"message.d.cts","names":[],"sources":["../../src/graph/message.ts"],"mappings":";;;;;;;;cAaa,YAAA,SAAqB,UAAA,CAChC,WAAA,IACA,WAAA,IACA,QAAA;EAEA,WAAA,CAAA;AAAA;;;;;;;;;;;;;iBAwBc,WAAA,CACd,OAAA,EAAS,WAAA,GAAc,eAAA,EACvB,OAAA,GAAU,cAAA;EA1BV;;AAwBF;;EAOI,QAAA;AAAA,IACD,WAAA,CAAA,yBAAA,CAAA,gBAAA,CANuB,yBAAA,CAMvB,cAAA,GAAA,yBAAA,CAAA,WAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.d.ts","names":[],"sources":["../../src/graph/message.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"message.d.ts","names":[],"sources":["../../src/graph/message.ts"],"mappings":";;;;;;;;cAaa,YAAA,SAAqB,UAAA,CAChC,WAAA,IACA,WAAA,IACA,QAAA;EAEA,WAAA,CAAA;AAAA;;;;;;;;;;;;;iBAwBc,WAAA,CACd,OAAA,EAAS,WAAA,GAAc,eAAA,EACvB,OAAA,GAAU,cAAA;EA1BV;;AAwBF;;EAOI,QAAA;AAAA,IACD,WAAA,CAAA,yBAAA,CAAA,gBAAA,CANuB,yBAAA,CAMvB,cAAA,GAAA,yBAAA,CAAA,WAAA"}
|
package/dist/graph/message.js
CHANGED
|
@@ -31,15 +31,18 @@ function pushMessage(message, options) {
|
|
|
31
31
|
if (userStateKey === null) stateKey = void 0;
|
|
32
32
|
const validMessage = coerceMessageLikeToMessage(message);
|
|
33
33
|
if (!validMessage.id) throw new Error("Message ID is required.");
|
|
34
|
-
const
|
|
34
|
+
const callbacks = (() => {
|
|
35
35
|
if (Array.isArray(config.callbacks)) return config.callbacks;
|
|
36
36
|
if (typeof config.callbacks !== "undefined") return config.callbacks.handlers;
|
|
37
37
|
return [];
|
|
38
|
-
})()
|
|
39
|
-
|
|
38
|
+
})();
|
|
39
|
+
const messagesHandler = callbacks.find((cb) => "name" in cb && cb.name === "StreamMessagesHandler");
|
|
40
|
+
const protocolMessagesHandler = callbacks.find((cb) => "name" in cb && cb.name === "StreamProtocolMessagesHandler");
|
|
41
|
+
if (messagesHandler || protocolMessagesHandler) {
|
|
40
42
|
const metadata = config.metadata ?? {};
|
|
41
43
|
const namespace = (metadata.langgraph_checkpoint_ns ?? "").split("|");
|
|
42
|
-
messagesHandler._emit([namespace, metadata], validMessage, void 0, false);
|
|
44
|
+
if (messagesHandler) messagesHandler._emit([namespace, metadata], validMessage, void 0, false);
|
|
45
|
+
else if (protocolMessagesHandler) protocolMessagesHandler.emitFinalMessage([namespace, metadata], validMessage, void 0, false);
|
|
43
46
|
}
|
|
44
47
|
if (stateKey) config.configurable?.__pregel_send?.([[stateKey, validMessage]]);
|
|
45
48
|
return validMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message.js","names":[],"sources":["../../src/graph/message.ts"],"sourcesContent":["import {\n BaseMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from \"@langchain/core/messages\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { StateGraph } from \"./state.js\";\nimport { ensureLangGraphConfig } from \"../pregel/utils/config.js\";\nimport type { StreamMessagesHandler } from \"../pregel/messages.js\";\nimport { messagesStateReducer, type Messages } from \"./messages_reducer.js\";\n\n/** @ignore */\nexport class MessageGraph extends StateGraph<\n BaseMessage[],\n BaseMessage[],\n Messages\n> {\n constructor() {\n super({\n channels: {\n __root__: {\n reducer: messagesStateReducer,\n default: () => [],\n },\n },\n });\n }\n}\n\n/**\n * Manually push a message to a message stream.\n *\n * This is useful when you need to push a manually created message before the node\n * has finished executing.\n *\n * When a message is pushed, it will be automatically persisted to the state after the node has finished executing.\n * To disable persisting, set `options.stateKey` to `null`.\n *\n * @param message The message to push. The message must have an ID set, otherwise an error will be thrown.\n * @param options RunnableConfig / Runtime coming from node context.\n */\nexport function pushMessage(\n message: BaseMessage | BaseMessageLike,\n options?: RunnableConfig & {\n /**\n * The key of the state to push the message to. Set to `null` to avoid persisting.\n * @default \"messages\"\n */\n stateKey?: string | null;\n }\n) {\n const { stateKey: userStateKey, ...userConfig } = options ?? {};\n const config = ensureLangGraphConfig(userConfig);\n\n let stateKey: string | undefined = userStateKey ?? \"messages\";\n if (userStateKey === null) stateKey = undefined;\n\n // coerce to message\n const validMessage = coerceMessageLikeToMessage(message);\n if (!validMessage.id) throw new Error(\"Message ID is required.\");\n\n const callbacks = (() => {\n if (Array.isArray(config.callbacks)) {\n return config.callbacks;\n }\n\n if (typeof config.callbacks !== \"undefined\") {\n return config.callbacks.handlers;\n }\n\n return [];\n })();\n\n const messagesHandler = callbacks.find(\n (cb): cb is StreamMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamMessagesHandler\"\n );\n\n if (messagesHandler) {\n const metadata = config.metadata ?? {};\n const namespace = (\n (metadata.langgraph_checkpoint_ns ?? \"\") as string\n ).split(\"|\");\n\n messagesHandler._emit(\n
|
|
1
|
+
{"version":3,"file":"message.js","names":[],"sources":["../../src/graph/message.ts"],"sourcesContent":["import {\n BaseMessage,\n BaseMessageLike,\n coerceMessageLikeToMessage,\n} from \"@langchain/core/messages\";\nimport type { RunnableConfig } from \"@langchain/core/runnables\";\nimport { StateGraph } from \"./state.js\";\nimport { ensureLangGraphConfig } from \"../pregel/utils/config.js\";\nimport type { StreamMessagesHandler } from \"../pregel/messages.js\";\nimport type { StreamProtocolMessagesHandler } from \"../pregel/messages-v2.js\";\nimport { messagesStateReducer, type Messages } from \"./messages_reducer.js\";\n\n/** @ignore */\nexport class MessageGraph extends StateGraph<\n BaseMessage[],\n BaseMessage[],\n Messages\n> {\n constructor() {\n super({\n channels: {\n __root__: {\n reducer: messagesStateReducer,\n default: () => [],\n },\n },\n });\n }\n}\n\n/**\n * Manually push a message to a message stream.\n *\n * This is useful when you need to push a manually created message before the node\n * has finished executing.\n *\n * When a message is pushed, it will be automatically persisted to the state after the node has finished executing.\n * To disable persisting, set `options.stateKey` to `null`.\n *\n * @param message The message to push. The message must have an ID set, otherwise an error will be thrown.\n * @param options RunnableConfig / Runtime coming from node context.\n */\nexport function pushMessage(\n message: BaseMessage | BaseMessageLike,\n options?: RunnableConfig & {\n /**\n * The key of the state to push the message to. Set to `null` to avoid persisting.\n * @default \"messages\"\n */\n stateKey?: string | null;\n }\n) {\n const { stateKey: userStateKey, ...userConfig } = options ?? {};\n const config = ensureLangGraphConfig(userConfig);\n\n let stateKey: string | undefined = userStateKey ?? \"messages\";\n if (userStateKey === null) stateKey = undefined;\n\n // coerce to message\n const validMessage = coerceMessageLikeToMessage(message);\n if (!validMessage.id) throw new Error(\"Message ID is required.\");\n\n const callbacks = (() => {\n if (Array.isArray(config.callbacks)) {\n return config.callbacks;\n }\n\n if (typeof config.callbacks !== \"undefined\") {\n return config.callbacks.handlers;\n }\n\n return [];\n })();\n\n const messagesHandler = callbacks.find(\n (cb): cb is StreamMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamMessagesHandler\"\n );\n const protocolMessagesHandler = callbacks.find(\n (cb): cb is StreamProtocolMessagesHandler =>\n \"name\" in cb && cb.name === \"StreamProtocolMessagesHandler\"\n );\n\n if (messagesHandler || protocolMessagesHandler) {\n const metadata = config.metadata ?? {};\n const namespace = (\n (metadata.langgraph_checkpoint_ns ?? \"\") as string\n ).split(\"|\");\n\n if (messagesHandler) {\n messagesHandler._emit(\n [namespace, metadata],\n validMessage,\n undefined,\n false\n );\n } else if (protocolMessagesHandler) {\n // streamEvents v3 registers StreamProtocolMessagesHandler instead of\n // StreamMessagesHandler; without this branch, pushed messages are\n // silently absent from the live `messages` channel and only surface in\n // state at node end. else-if: the handlers are mutually exclusive per\n // stream, and a single emission path avoids double emits if a caller\n // ever registers both.\n protocolMessagesHandler.emitFinalMessage(\n [namespace, metadata],\n validMessage,\n undefined,\n false\n );\n }\n }\n\n if (stateKey) {\n config.configurable?.__pregel_send?.([[stateKey, validMessage]]);\n }\n\n return validMessage;\n}\n"],"mappings":";;;;;;AAaA,IAAa,eAAb,cAAkC,WAIhC;CACA,cAAc;AACZ,QAAM,EACJ,UAAU,EACR,UAAU;GACR,SAAS;GACT,eAAe,EAAE;GAClB,EACF,EACF,CAAC;;;;;;;;;;;;;;;AAgBN,SAAgB,YACd,SACA,SAOA;CACA,MAAM,EAAE,UAAU,cAAc,GAAG,eAAe,WAAW,EAAE;CAC/D,MAAM,SAAS,sBAAsB,WAAW;CAEhD,IAAI,WAA+B,gBAAgB;AACnD,KAAI,iBAAiB,KAAM,YAAW,KAAA;CAGtC,MAAM,eAAe,2BAA2B,QAAQ;AACxD,KAAI,CAAC,aAAa,GAAI,OAAM,IAAI,MAAM,0BAA0B;CAEhE,MAAM,mBAAmB;AACvB,MAAI,MAAM,QAAQ,OAAO,UAAU,CACjC,QAAO,OAAO;AAGhB,MAAI,OAAO,OAAO,cAAc,YAC9B,QAAO,OAAO,UAAU;AAG1B,SAAO,EAAE;KACP;CAEJ,MAAM,kBAAkB,UAAU,MAC/B,OACC,UAAU,MAAM,GAAG,SAAS,wBAC/B;CACD,MAAM,0BAA0B,UAAU,MACvC,OACC,UAAU,MAAM,GAAG,SAAS,gCAC/B;AAED,KAAI,mBAAmB,yBAAyB;EAC9C,MAAM,WAAW,OAAO,YAAY,EAAE;EACtC,MAAM,aACH,SAAS,2BAA2B,IACrC,MAAM,IAAI;AAEZ,MAAI,gBACF,iBAAgB,MACd,CAAC,WAAW,SAAS,EACrB,cACA,KAAA,GACA,MACD;WACQ,wBAOT,yBAAwB,iBACtB,CAAC,WAAW,SAAS,EACrB,cACA,KAAA,GACA,MACD;;AAIL,KAAI,SACF,QAAO,cAAc,gBAAgB,CAAC,CAAC,UAAU,aAAa,CAAC,CAAC;AAGlE,QAAO"}
|
|
@@ -112,6 +112,12 @@ var StreamProtocolMessagesHandler = class extends _langchain_core_callbacks_base
|
|
|
112
112
|
[data, metadata]
|
|
113
113
|
]);
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Emit a complete message as protocol events (message-start, content
|
|
117
|
+
* blocks, message-finish). Public so `pushMessage` can deliver manually
|
|
118
|
+
* created messages when this handler is registered (streamEvents v3),
|
|
119
|
+
* mirroring `StreamMessagesHandler._emit` on the classic path.
|
|
120
|
+
*/
|
|
115
121
|
emitFinalMessage(meta, message, runId, dedupe = false) {
|
|
116
122
|
const existingId = message.id ?? (runId != null ? this.stableMessageIdMap[runId] : void 0);
|
|
117
123
|
if (dedupe && existingId != null && this.seen[existingId] !== void 0) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-v2.cjs","names":["BaseCallbackHandler","ToolMessage","BaseMessage","BaseMessageChunk"],"sources":["../../src/pregel/messages-v2.ts"],"sourcesContent":["import { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport {\n BaseMessage,\n ToolMessage,\n BaseMessageChunk,\n} from \"@langchain/core/messages\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { ChatGeneration, LLMResult } from \"@langchain/core/outputs\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { ChainValues } from \"@langchain/core/utils/types\";\n\nimport { TAG_HIDDEN, TAG_NOSTREAM } from \"../constants.js\";\nimport { StreamChunk } from \"./stream.js\";\n\ntype Meta = [string[], Record<string, unknown>];\ntype CompatibleContentBlock = { type: string; [key: string]: unknown };\n\nfunction getResponseMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"response_metadata\" in message &&\n typeof message.response_metadata === \"object\" &&\n message.response_metadata != null\n ) {\n return message.response_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getUsageMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"usage_metadata\" in message &&\n typeof message.usage_metadata === \"object\" &&\n message.usage_metadata != null\n ) {\n return message.usage_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction startBlockFor(block: CompatibleContentBlock): CompatibleContentBlock {\n switch (block.type) {\n case \"text\":\n return { type: \"text\", text: \"\" };\n case \"reasoning\":\n return { type: \"reasoning\", reasoning: \"\" };\n case \"tool_call\":\n case \"tool_call_chunk\":\n return {\n type: \"tool_call_chunk\",\n ...(block.id != null ? { id: block.id } : {}),\n ...(block.name != null ? { name: block.name } : {}),\n args: \"\",\n };\n default:\n return block;\n }\n}\n\nfunction deltaFor(\n block: CompatibleContentBlock\n): ChatModelStreamEvent | undefined {\n switch (block.type) {\n case \"text\": {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n return text.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"text-delta\", text },\n }\n : undefined;\n }\n case \"reasoning\": {\n const reasoning =\n typeof block.reasoning === \"string\" ? block.reasoning : \"\";\n return reasoning.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"reasoning-delta\", reasoning },\n }\n : undefined;\n }\n case \"tool_call_chunk\":\n return {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: {\n type: \"block-delta\",\n fields: { ...block, type: \"tool_call_chunk\" },\n },\n };\n default:\n return undefined;\n }\n}\n\n/**\n * A callback handler that implements protocol-native stream_mode=messages.\n *\n * LangChain Core owns chat model content-block event construction. This handler\n * only captures LangGraph metadata, forwards Core events to the Pregel messages\n * channel, and emits a small non-streaming fallback for models that cannot\n * produce stream events.\n */\nexport class StreamProtocolMessagesHandler extends BaseCallbackHandler {\n name = \"StreamProtocolMessagesHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n metadatas: Record<string, Meta | undefined> = {};\n\n seen: Record<string, BaseMessage | true> = {};\n\n streamedRunIds = new Set<string>();\n\n stableMessageIdMap: Record<string, string> = {};\n\n lc_prefer_chat_model_stream_events = true;\n\n // Dispatch this handler's callbacks inline rather than on LangChain's\n // background callback queue. The handler's only side effect is a synchronous\n // `push()` onto the run's stream, so running it inline guarantees those\n // pushes happen *during* the model/chain call — while the stream is still\n // open — instead of after the Pregel loop has returned and sealed the\n // stream. Background dispatch let a model/tool call in a nested or parallel\n // task flush its `messages` chunk after close, where `push()` silently drops\n // it; this surfaced as empty per-message streams (`sub.messages`) for\n // subagents dispatched in parallel from a single tools step.\n awaitHandlers = true;\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n private normalizeMessageId(message: BaseMessage, runId: string | undefined) {\n let messageId = message.id;\n\n if (runId != null) {\n if (ToolMessage.isInstance(message)) {\n messageId ??= `run-${runId}-tool-${message.tool_call_id}`;\n } else {\n if (messageId == null || messageId === `run-${runId}`) {\n messageId =\n this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;\n }\n this.stableMessageIdMap[runId] ??= messageId;\n }\n }\n\n if (messageId !== message.id) {\n // eslint-disable-next-line no-param-reassign\n message.id = messageId;\n // eslint-disable-next-line no-param-reassign\n message.lc_kwargs.id = messageId;\n }\n\n if (message.id != null) this.seen[message.id] = message;\n return message.id;\n }\n\n private emit(meta: Meta, data: ChatModelStreamEvent, runId?: string) {\n const metadata = runId != null ? { ...meta[1], run_id: runId } : meta[1];\n this.streamFn([meta[0], \"messages\", [data, metadata]]);\n }\n\n private emitFinalMessage(\n meta: Meta,\n message: BaseMessage,\n runId: string | undefined,\n dedupe = false\n ) {\n const existingId =\n message.id ??\n (runId != null ? this.stableMessageIdMap[runId] : undefined);\n if (dedupe && existingId != null && this.seen[existingId] !== undefined) {\n return;\n }\n\n const messageId = this.normalizeMessageId(message, runId);\n const role =\n message.type === \"human\"\n ? \"human\"\n : message.type === \"system\"\n ? \"system\"\n : message.type === \"tool\"\n ? \"tool\"\n : \"ai\";\n const toolCallId =\n role === \"tool\" && ToolMessage.isInstance(message)\n ? message.tool_call_id\n : undefined;\n\n this.emit(\n meta,\n {\n event: \"message-start\",\n ...(messageId != null ? { id: messageId } : {}),\n ...(role !== \"ai\" ? ({ role } as Record<string, unknown>) : {}),\n ...(typeof toolCallId === \"string\"\n ? ({ tool_call_id: toolCallId } as Record<string, unknown>)\n : {}),\n } as ChatModelStreamEvent,\n runId\n );\n\n const contentBlocks: CompatibleContentBlock[] = Array.isArray(\n message.content\n )\n ? (message.content as CompatibleContentBlock[])\n : typeof message.content === \"string\" && message.content.length > 0\n ? [{ type: \"text\", text: message.content }]\n : [];\n\n contentBlocks.forEach((block, offset) => {\n const index = typeof block.index === \"number\" ? block.index : offset;\n this.emit(\n meta,\n {\n event: \"content-block-start\",\n index,\n content: startBlockFor(block),\n },\n runId\n );\n const delta = deltaFor({ ...block, index });\n if (delta != null) {\n this.emit(meta, delta, runId);\n }\n this.emit(\n meta,\n {\n event: \"content-block-finish\",\n index,\n content: block,\n },\n runId\n );\n });\n\n this.emit(\n meta,\n {\n event: \"message-finish\",\n ...(getUsageMetadata(message) != null\n ? { usage: getUsageMetadata(message) }\n : {}),\n ...(getResponseMetadata(message) != null\n ? { responseMetadata: getResponseMetadata(message) }\n : {}),\n },\n runId\n );\n }\n\n handleChatModelStart(\n _llm: Serialized,\n _messages: BaseMessage[][],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ) {\n if (\n metadata &&\n (!tags || (!tags.includes(TAG_NOSTREAM) && !tags.includes(\"nostream\")))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n }\n }\n\n handleLLMNewToken() {\n // Core v2 stream events are forwarded via handleChatModelStreamEvent.\n }\n\n handleChatModelStreamEvent(event: ChatModelStreamEvent, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n let forwarded = event;\n if (event.event === \"message-start\") {\n this.streamedRunIds.add(runId);\n const id = event.id ?? `run-${runId}`;\n this.seen[id] = true;\n this.stableMessageIdMap[runId] ??= id;\n if (event.id == null) {\n forwarded = { ...event, id };\n }\n }\n\n this.emit(meta, forwarded, runId);\n }\n\n handleLLMEnd(output: LLMResult, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n const chatGeneration = output.generations?.[0]?.[0] as ChatGeneration;\n const message = BaseMessage.isInstance(chatGeneration?.message)\n ? chatGeneration.message\n : undefined;\n\n if (message != null) {\n if (this.streamedRunIds.has(runId)) {\n const messageId = this.normalizeMessageId(message, runId);\n if (messageId != null) this.seen[messageId] = message;\n } else {\n this.emitFinalMessage(meta, message, runId, true);\n }\n }\n\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleLLMError(_err: any, runId: string) {\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n handleChainStart(\n _chain: Serialized,\n inputs: ChainValues,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runType?: string,\n name?: string\n ) {\n if (\n metadata !== undefined &&\n name === metadata.langgraph_node &&\n (tags === undefined || !tags.includes(TAG_HIDDEN))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n\n if (typeof inputs === \"object\") {\n for (const value of Object.values(inputs)) {\n if (\n (BaseMessage.isInstance(value) ||\n BaseMessageChunk.isInstance(value)) &&\n value.id !== undefined\n ) {\n this.seen[value.id] = value;\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (\n (BaseMessage.isInstance(item) ||\n BaseMessageChunk.isInstance(item)) &&\n item.id !== undefined\n ) {\n this.seen[item.id] = item;\n }\n }\n }\n }\n }\n }\n }\n\n handleChainEnd(outputs: ChainValues, runId: string) {\n const meta = this.metadatas[runId];\n delete this.metadatas[runId];\n if (meta === undefined) return;\n\n const emitMessage = (value: unknown) => {\n if (BaseMessage.isInstance(value) && !ToolMessage.isInstance(value)) {\n this.emitFinalMessage(meta, value, runId, true);\n }\n };\n\n if (BaseMessage.isInstance(outputs)) {\n emitMessage(outputs);\n } else if (Array.isArray(outputs)) {\n for (const value of outputs) emitMessage(value);\n } else if (outputs != null && typeof outputs === \"object\") {\n for (const value of Object.values(outputs)) {\n if (Array.isArray(value)) {\n for (const item of value) emitMessage(item);\n } else {\n emitMessage(value);\n }\n }\n }\n\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleChainError(_err: any, runId: string) {\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages-v2.cjs","names":["BaseCallbackHandler","ToolMessage","BaseMessage","BaseMessageChunk"],"sources":["../../src/pregel/messages-v2.ts"],"sourcesContent":["import { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport {\n BaseMessage,\n ToolMessage,\n BaseMessageChunk,\n} from \"@langchain/core/messages\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { ChatGeneration, LLMResult } from \"@langchain/core/outputs\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { ChainValues } from \"@langchain/core/utils/types\";\n\nimport { TAG_HIDDEN, TAG_NOSTREAM } from \"../constants.js\";\nimport { StreamChunk } from \"./stream.js\";\n\ntype Meta = [string[], Record<string, unknown>];\ntype CompatibleContentBlock = { type: string; [key: string]: unknown };\n\nfunction getResponseMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"response_metadata\" in message &&\n typeof message.response_metadata === \"object\" &&\n message.response_metadata != null\n ) {\n return message.response_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getUsageMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"usage_metadata\" in message &&\n typeof message.usage_metadata === \"object\" &&\n message.usage_metadata != null\n ) {\n return message.usage_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction startBlockFor(block: CompatibleContentBlock): CompatibleContentBlock {\n switch (block.type) {\n case \"text\":\n return { type: \"text\", text: \"\" };\n case \"reasoning\":\n return { type: \"reasoning\", reasoning: \"\" };\n case \"tool_call\":\n case \"tool_call_chunk\":\n return {\n type: \"tool_call_chunk\",\n ...(block.id != null ? { id: block.id } : {}),\n ...(block.name != null ? { name: block.name } : {}),\n args: \"\",\n };\n default:\n return block;\n }\n}\n\nfunction deltaFor(\n block: CompatibleContentBlock\n): ChatModelStreamEvent | undefined {\n switch (block.type) {\n case \"text\": {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n return text.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"text-delta\", text },\n }\n : undefined;\n }\n case \"reasoning\": {\n const reasoning =\n typeof block.reasoning === \"string\" ? block.reasoning : \"\";\n return reasoning.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"reasoning-delta\", reasoning },\n }\n : undefined;\n }\n case \"tool_call_chunk\":\n return {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: {\n type: \"block-delta\",\n fields: { ...block, type: \"tool_call_chunk\" },\n },\n };\n default:\n return undefined;\n }\n}\n\n/**\n * A callback handler that implements protocol-native stream_mode=messages.\n *\n * LangChain Core owns chat model content-block event construction. This handler\n * only captures LangGraph metadata, forwards Core events to the Pregel messages\n * channel, and emits a small non-streaming fallback for models that cannot\n * produce stream events.\n */\nexport class StreamProtocolMessagesHandler extends BaseCallbackHandler {\n name = \"StreamProtocolMessagesHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n metadatas: Record<string, Meta | undefined> = {};\n\n seen: Record<string, BaseMessage | true> = {};\n\n streamedRunIds = new Set<string>();\n\n stableMessageIdMap: Record<string, string> = {};\n\n lc_prefer_chat_model_stream_events = true;\n\n // Dispatch this handler's callbacks inline rather than on LangChain's\n // background callback queue. The handler's only side effect is a synchronous\n // `push()` onto the run's stream, so running it inline guarantees those\n // pushes happen *during* the model/chain call — while the stream is still\n // open — instead of after the Pregel loop has returned and sealed the\n // stream. Background dispatch let a model/tool call in a nested or parallel\n // task flush its `messages` chunk after close, where `push()` silently drops\n // it; this surfaced as empty per-message streams (`sub.messages`) for\n // subagents dispatched in parallel from a single tools step.\n awaitHandlers = true;\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n private normalizeMessageId(message: BaseMessage, runId: string | undefined) {\n let messageId = message.id;\n\n if (runId != null) {\n if (ToolMessage.isInstance(message)) {\n messageId ??= `run-${runId}-tool-${message.tool_call_id}`;\n } else {\n if (messageId == null || messageId === `run-${runId}`) {\n messageId =\n this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;\n }\n this.stableMessageIdMap[runId] ??= messageId;\n }\n }\n\n if (messageId !== message.id) {\n // eslint-disable-next-line no-param-reassign\n message.id = messageId;\n // eslint-disable-next-line no-param-reassign\n message.lc_kwargs.id = messageId;\n }\n\n if (message.id != null) this.seen[message.id] = message;\n return message.id;\n }\n\n private emit(meta: Meta, data: ChatModelStreamEvent, runId?: string) {\n const metadata = runId != null ? { ...meta[1], run_id: runId } : meta[1];\n this.streamFn([meta[0], \"messages\", [data, metadata]]);\n }\n\n /**\n * Emit a complete message as protocol events (message-start, content\n * blocks, message-finish). Public so `pushMessage` can deliver manually\n * created messages when this handler is registered (streamEvents v3),\n * mirroring `StreamMessagesHandler._emit` on the classic path.\n */\n emitFinalMessage(\n meta: Meta,\n message: BaseMessage,\n runId: string | undefined,\n dedupe = false\n ) {\n const existingId =\n message.id ??\n (runId != null ? this.stableMessageIdMap[runId] : undefined);\n if (dedupe && existingId != null && this.seen[existingId] !== undefined) {\n return;\n }\n\n const messageId = this.normalizeMessageId(message, runId);\n const role =\n message.type === \"human\"\n ? \"human\"\n : message.type === \"system\"\n ? \"system\"\n : message.type === \"tool\"\n ? \"tool\"\n : \"ai\";\n const toolCallId =\n role === \"tool\" && ToolMessage.isInstance(message)\n ? message.tool_call_id\n : undefined;\n\n this.emit(\n meta,\n {\n event: \"message-start\",\n ...(messageId != null ? { id: messageId } : {}),\n ...(role !== \"ai\" ? ({ role } as Record<string, unknown>) : {}),\n ...(typeof toolCallId === \"string\"\n ? ({ tool_call_id: toolCallId } as Record<string, unknown>)\n : {}),\n } as ChatModelStreamEvent,\n runId\n );\n\n const contentBlocks: CompatibleContentBlock[] = Array.isArray(\n message.content\n )\n ? (message.content as CompatibleContentBlock[])\n : typeof message.content === \"string\" && message.content.length > 0\n ? [{ type: \"text\", text: message.content }]\n : [];\n\n contentBlocks.forEach((block, offset) => {\n const index = typeof block.index === \"number\" ? block.index : offset;\n this.emit(\n meta,\n {\n event: \"content-block-start\",\n index,\n content: startBlockFor(block),\n },\n runId\n );\n const delta = deltaFor({ ...block, index });\n if (delta != null) {\n this.emit(meta, delta, runId);\n }\n this.emit(\n meta,\n {\n event: \"content-block-finish\",\n index,\n content: block,\n },\n runId\n );\n });\n\n this.emit(\n meta,\n {\n event: \"message-finish\",\n ...(getUsageMetadata(message) != null\n ? { usage: getUsageMetadata(message) }\n : {}),\n ...(getResponseMetadata(message) != null\n ? { responseMetadata: getResponseMetadata(message) }\n : {}),\n },\n runId\n );\n }\n\n handleChatModelStart(\n _llm: Serialized,\n _messages: BaseMessage[][],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ) {\n if (\n metadata &&\n (!tags || (!tags.includes(TAG_NOSTREAM) && !tags.includes(\"nostream\")))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n }\n }\n\n handleLLMNewToken() {\n // Core v2 stream events are forwarded via handleChatModelStreamEvent.\n }\n\n handleChatModelStreamEvent(event: ChatModelStreamEvent, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n let forwarded = event;\n if (event.event === \"message-start\") {\n this.streamedRunIds.add(runId);\n const id = event.id ?? `run-${runId}`;\n this.seen[id] = true;\n this.stableMessageIdMap[runId] ??= id;\n if (event.id == null) {\n forwarded = { ...event, id };\n }\n }\n\n this.emit(meta, forwarded, runId);\n }\n\n handleLLMEnd(output: LLMResult, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n const chatGeneration = output.generations?.[0]?.[0] as ChatGeneration;\n const message = BaseMessage.isInstance(chatGeneration?.message)\n ? chatGeneration.message\n : undefined;\n\n if (message != null) {\n if (this.streamedRunIds.has(runId)) {\n const messageId = this.normalizeMessageId(message, runId);\n if (messageId != null) this.seen[messageId] = message;\n } else {\n this.emitFinalMessage(meta, message, runId, true);\n }\n }\n\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleLLMError(_err: any, runId: string) {\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n handleChainStart(\n _chain: Serialized,\n inputs: ChainValues,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runType?: string,\n name?: string\n ) {\n if (\n metadata !== undefined &&\n name === metadata.langgraph_node &&\n (tags === undefined || !tags.includes(TAG_HIDDEN))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n\n if (typeof inputs === \"object\") {\n for (const value of Object.values(inputs)) {\n if (\n (BaseMessage.isInstance(value) ||\n BaseMessageChunk.isInstance(value)) &&\n value.id !== undefined\n ) {\n this.seen[value.id] = value;\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (\n (BaseMessage.isInstance(item) ||\n BaseMessageChunk.isInstance(item)) &&\n item.id !== undefined\n ) {\n this.seen[item.id] = item;\n }\n }\n }\n }\n }\n }\n }\n\n handleChainEnd(outputs: ChainValues, runId: string) {\n const meta = this.metadatas[runId];\n delete this.metadatas[runId];\n if (meta === undefined) return;\n\n const emitMessage = (value: unknown) => {\n if (BaseMessage.isInstance(value) && !ToolMessage.isInstance(value)) {\n this.emitFinalMessage(meta, value, runId, true);\n }\n };\n\n if (BaseMessage.isInstance(outputs)) {\n emitMessage(outputs);\n } else if (Array.isArray(outputs)) {\n for (const value of outputs) emitMessage(value);\n } else if (outputs != null && typeof outputs === \"object\") {\n for (const value of Object.values(outputs)) {\n if (Array.isArray(value)) {\n for (const item of value) emitMessage(item);\n } else {\n emitMessage(value);\n }\n }\n }\n\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleChainError(_err: any, runId: string) {\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n}\n"],"mappings":"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"}
|
|
@@ -112,6 +112,12 @@ var StreamProtocolMessagesHandler = class extends BaseCallbackHandler {
|
|
|
112
112
|
[data, metadata]
|
|
113
113
|
]);
|
|
114
114
|
}
|
|
115
|
+
/**
|
|
116
|
+
* Emit a complete message as protocol events (message-start, content
|
|
117
|
+
* blocks, message-finish). Public so `pushMessage` can deliver manually
|
|
118
|
+
* created messages when this handler is registered (streamEvents v3),
|
|
119
|
+
* mirroring `StreamMessagesHandler._emit` on the classic path.
|
|
120
|
+
*/
|
|
115
121
|
emitFinalMessage(meta, message, runId, dedupe = false) {
|
|
116
122
|
const existingId = message.id ?? (runId != null ? this.stableMessageIdMap[runId] : void 0);
|
|
117
123
|
if (dedupe && existingId != null && this.seen[existingId] !== void 0) return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages-v2.js","names":[],"sources":["../../src/pregel/messages-v2.ts"],"sourcesContent":["import { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport {\n BaseMessage,\n ToolMessage,\n BaseMessageChunk,\n} from \"@langchain/core/messages\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { ChatGeneration, LLMResult } from \"@langchain/core/outputs\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { ChainValues } from \"@langchain/core/utils/types\";\n\nimport { TAG_HIDDEN, TAG_NOSTREAM } from \"../constants.js\";\nimport { StreamChunk } from \"./stream.js\";\n\ntype Meta = [string[], Record<string, unknown>];\ntype CompatibleContentBlock = { type: string; [key: string]: unknown };\n\nfunction getResponseMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"response_metadata\" in message &&\n typeof message.response_metadata === \"object\" &&\n message.response_metadata != null\n ) {\n return message.response_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getUsageMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"usage_metadata\" in message &&\n typeof message.usage_metadata === \"object\" &&\n message.usage_metadata != null\n ) {\n return message.usage_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction startBlockFor(block: CompatibleContentBlock): CompatibleContentBlock {\n switch (block.type) {\n case \"text\":\n return { type: \"text\", text: \"\" };\n case \"reasoning\":\n return { type: \"reasoning\", reasoning: \"\" };\n case \"tool_call\":\n case \"tool_call_chunk\":\n return {\n type: \"tool_call_chunk\",\n ...(block.id != null ? { id: block.id } : {}),\n ...(block.name != null ? { name: block.name } : {}),\n args: \"\",\n };\n default:\n return block;\n }\n}\n\nfunction deltaFor(\n block: CompatibleContentBlock\n): ChatModelStreamEvent | undefined {\n switch (block.type) {\n case \"text\": {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n return text.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"text-delta\", text },\n }\n : undefined;\n }\n case \"reasoning\": {\n const reasoning =\n typeof block.reasoning === \"string\" ? block.reasoning : \"\";\n return reasoning.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"reasoning-delta\", reasoning },\n }\n : undefined;\n }\n case \"tool_call_chunk\":\n return {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: {\n type: \"block-delta\",\n fields: { ...block, type: \"tool_call_chunk\" },\n },\n };\n default:\n return undefined;\n }\n}\n\n/**\n * A callback handler that implements protocol-native stream_mode=messages.\n *\n * LangChain Core owns chat model content-block event construction. This handler\n * only captures LangGraph metadata, forwards Core events to the Pregel messages\n * channel, and emits a small non-streaming fallback for models that cannot\n * produce stream events.\n */\nexport class StreamProtocolMessagesHandler extends BaseCallbackHandler {\n name = \"StreamProtocolMessagesHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n metadatas: Record<string, Meta | undefined> = {};\n\n seen: Record<string, BaseMessage | true> = {};\n\n streamedRunIds = new Set<string>();\n\n stableMessageIdMap: Record<string, string> = {};\n\n lc_prefer_chat_model_stream_events = true;\n\n // Dispatch this handler's callbacks inline rather than on LangChain's\n // background callback queue. The handler's only side effect is a synchronous\n // `push()` onto the run's stream, so running it inline guarantees those\n // pushes happen *during* the model/chain call — while the stream is still\n // open — instead of after the Pregel loop has returned and sealed the\n // stream. Background dispatch let a model/tool call in a nested or parallel\n // task flush its `messages` chunk after close, where `push()` silently drops\n // it; this surfaced as empty per-message streams (`sub.messages`) for\n // subagents dispatched in parallel from a single tools step.\n awaitHandlers = true;\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n private normalizeMessageId(message: BaseMessage, runId: string | undefined) {\n let messageId = message.id;\n\n if (runId != null) {\n if (ToolMessage.isInstance(message)) {\n messageId ??= `run-${runId}-tool-${message.tool_call_id}`;\n } else {\n if (messageId == null || messageId === `run-${runId}`) {\n messageId =\n this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;\n }\n this.stableMessageIdMap[runId] ??= messageId;\n }\n }\n\n if (messageId !== message.id) {\n // eslint-disable-next-line no-param-reassign\n message.id = messageId;\n // eslint-disable-next-line no-param-reassign\n message.lc_kwargs.id = messageId;\n }\n\n if (message.id != null) this.seen[message.id] = message;\n return message.id;\n }\n\n private emit(meta: Meta, data: ChatModelStreamEvent, runId?: string) {\n const metadata = runId != null ? { ...meta[1], run_id: runId } : meta[1];\n this.streamFn([meta[0], \"messages\", [data, metadata]]);\n }\n\n private emitFinalMessage(\n meta: Meta,\n message: BaseMessage,\n runId: string | undefined,\n dedupe = false\n ) {\n const existingId =\n message.id ??\n (runId != null ? this.stableMessageIdMap[runId] : undefined);\n if (dedupe && existingId != null && this.seen[existingId] !== undefined) {\n return;\n }\n\n const messageId = this.normalizeMessageId(message, runId);\n const role =\n message.type === \"human\"\n ? \"human\"\n : message.type === \"system\"\n ? \"system\"\n : message.type === \"tool\"\n ? \"tool\"\n : \"ai\";\n const toolCallId =\n role === \"tool\" && ToolMessage.isInstance(message)\n ? message.tool_call_id\n : undefined;\n\n this.emit(\n meta,\n {\n event: \"message-start\",\n ...(messageId != null ? { id: messageId } : {}),\n ...(role !== \"ai\" ? ({ role } as Record<string, unknown>) : {}),\n ...(typeof toolCallId === \"string\"\n ? ({ tool_call_id: toolCallId } as Record<string, unknown>)\n : {}),\n } as ChatModelStreamEvent,\n runId\n );\n\n const contentBlocks: CompatibleContentBlock[] = Array.isArray(\n message.content\n )\n ? (message.content as CompatibleContentBlock[])\n : typeof message.content === \"string\" && message.content.length > 0\n ? [{ type: \"text\", text: message.content }]\n : [];\n\n contentBlocks.forEach((block, offset) => {\n const index = typeof block.index === \"number\" ? block.index : offset;\n this.emit(\n meta,\n {\n event: \"content-block-start\",\n index,\n content: startBlockFor(block),\n },\n runId\n );\n const delta = deltaFor({ ...block, index });\n if (delta != null) {\n this.emit(meta, delta, runId);\n }\n this.emit(\n meta,\n {\n event: \"content-block-finish\",\n index,\n content: block,\n },\n runId\n );\n });\n\n this.emit(\n meta,\n {\n event: \"message-finish\",\n ...(getUsageMetadata(message) != null\n ? { usage: getUsageMetadata(message) }\n : {}),\n ...(getResponseMetadata(message) != null\n ? { responseMetadata: getResponseMetadata(message) }\n : {}),\n },\n runId\n );\n }\n\n handleChatModelStart(\n _llm: Serialized,\n _messages: BaseMessage[][],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ) {\n if (\n metadata &&\n (!tags || (!tags.includes(TAG_NOSTREAM) && !tags.includes(\"nostream\")))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n }\n }\n\n handleLLMNewToken() {\n // Core v2 stream events are forwarded via handleChatModelStreamEvent.\n }\n\n handleChatModelStreamEvent(event: ChatModelStreamEvent, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n let forwarded = event;\n if (event.event === \"message-start\") {\n this.streamedRunIds.add(runId);\n const id = event.id ?? `run-${runId}`;\n this.seen[id] = true;\n this.stableMessageIdMap[runId] ??= id;\n if (event.id == null) {\n forwarded = { ...event, id };\n }\n }\n\n this.emit(meta, forwarded, runId);\n }\n\n handleLLMEnd(output: LLMResult, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n const chatGeneration = output.generations?.[0]?.[0] as ChatGeneration;\n const message = BaseMessage.isInstance(chatGeneration?.message)\n ? chatGeneration.message\n : undefined;\n\n if (message != null) {\n if (this.streamedRunIds.has(runId)) {\n const messageId = this.normalizeMessageId(message, runId);\n if (messageId != null) this.seen[messageId] = message;\n } else {\n this.emitFinalMessage(meta, message, runId, true);\n }\n }\n\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleLLMError(_err: any, runId: string) {\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n handleChainStart(\n _chain: Serialized,\n inputs: ChainValues,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runType?: string,\n name?: string\n ) {\n if (\n metadata !== undefined &&\n name === metadata.langgraph_node &&\n (tags === undefined || !tags.includes(TAG_HIDDEN))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n\n if (typeof inputs === \"object\") {\n for (const value of Object.values(inputs)) {\n if (\n (BaseMessage.isInstance(value) ||\n BaseMessageChunk.isInstance(value)) &&\n value.id !== undefined\n ) {\n this.seen[value.id] = value;\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (\n (BaseMessage.isInstance(item) ||\n BaseMessageChunk.isInstance(item)) &&\n item.id !== undefined\n ) {\n this.seen[item.id] = item;\n }\n }\n }\n }\n }\n }\n }\n\n handleChainEnd(outputs: ChainValues, runId: string) {\n const meta = this.metadatas[runId];\n delete this.metadatas[runId];\n if (meta === undefined) return;\n\n const emitMessage = (value: unknown) => {\n if (BaseMessage.isInstance(value) && !ToolMessage.isInstance(value)) {\n this.emitFinalMessage(meta, value, runId, true);\n }\n };\n\n if (BaseMessage.isInstance(outputs)) {\n emitMessage(outputs);\n } else if (Array.isArray(outputs)) {\n for (const value of outputs) emitMessage(value);\n } else if (outputs != null && typeof outputs === \"object\") {\n for (const value of Object.values(outputs)) {\n if (Array.isArray(value)) {\n for (const item of value) emitMessage(item);\n } else {\n emitMessage(value);\n }\n }\n }\n\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleChainError(_err: any, runId: string) {\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages-v2.js","names":[],"sources":["../../src/pregel/messages-v2.ts"],"sourcesContent":["import { BaseCallbackHandler } from \"@langchain/core/callbacks/base\";\nimport {\n BaseMessage,\n ToolMessage,\n BaseMessageChunk,\n} from \"@langchain/core/messages\";\nimport { Serialized } from \"@langchain/core/load/serializable\";\nimport { ChatGeneration, LLMResult } from \"@langchain/core/outputs\";\nimport type { ChatModelStreamEvent } from \"@langchain/core/language_models/event\";\nimport { ChainValues } from \"@langchain/core/utils/types\";\n\nimport { TAG_HIDDEN, TAG_NOSTREAM } from \"../constants.js\";\nimport { StreamChunk } from \"./stream.js\";\n\ntype Meta = [string[], Record<string, unknown>];\ntype CompatibleContentBlock = { type: string; [key: string]: unknown };\n\nfunction getResponseMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"response_metadata\" in message &&\n typeof message.response_metadata === \"object\" &&\n message.response_metadata != null\n ) {\n return message.response_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction getUsageMetadata(\n message: BaseMessage\n): Record<string, unknown> | undefined {\n if (\n \"usage_metadata\" in message &&\n typeof message.usage_metadata === \"object\" &&\n message.usage_metadata != null\n ) {\n return message.usage_metadata as Record<string, unknown>;\n }\n return undefined;\n}\n\nfunction startBlockFor(block: CompatibleContentBlock): CompatibleContentBlock {\n switch (block.type) {\n case \"text\":\n return { type: \"text\", text: \"\" };\n case \"reasoning\":\n return { type: \"reasoning\", reasoning: \"\" };\n case \"tool_call\":\n case \"tool_call_chunk\":\n return {\n type: \"tool_call_chunk\",\n ...(block.id != null ? { id: block.id } : {}),\n ...(block.name != null ? { name: block.name } : {}),\n args: \"\",\n };\n default:\n return block;\n }\n}\n\nfunction deltaFor(\n block: CompatibleContentBlock\n): ChatModelStreamEvent | undefined {\n switch (block.type) {\n case \"text\": {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n return text.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"text-delta\", text },\n }\n : undefined;\n }\n case \"reasoning\": {\n const reasoning =\n typeof block.reasoning === \"string\" ? block.reasoning : \"\";\n return reasoning.length > 0\n ? {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: { type: \"reasoning-delta\", reasoning },\n }\n : undefined;\n }\n case \"tool_call_chunk\":\n return {\n event: \"content-block-delta\",\n index: typeof block.index === \"number\" ? block.index : 0,\n delta: {\n type: \"block-delta\",\n fields: { ...block, type: \"tool_call_chunk\" },\n },\n };\n default:\n return undefined;\n }\n}\n\n/**\n * A callback handler that implements protocol-native stream_mode=messages.\n *\n * LangChain Core owns chat model content-block event construction. This handler\n * only captures LangGraph metadata, forwards Core events to the Pregel messages\n * channel, and emits a small non-streaming fallback for models that cannot\n * produce stream events.\n */\nexport class StreamProtocolMessagesHandler extends BaseCallbackHandler {\n name = \"StreamProtocolMessagesHandler\";\n\n streamFn: (streamChunk: StreamChunk) => void;\n\n metadatas: Record<string, Meta | undefined> = {};\n\n seen: Record<string, BaseMessage | true> = {};\n\n streamedRunIds = new Set<string>();\n\n stableMessageIdMap: Record<string, string> = {};\n\n lc_prefer_chat_model_stream_events = true;\n\n // Dispatch this handler's callbacks inline rather than on LangChain's\n // background callback queue. The handler's only side effect is a synchronous\n // `push()` onto the run's stream, so running it inline guarantees those\n // pushes happen *during* the model/chain call — while the stream is still\n // open — instead of after the Pregel loop has returned and sealed the\n // stream. Background dispatch let a model/tool call in a nested or parallel\n // task flush its `messages` chunk after close, where `push()` silently drops\n // it; this surfaced as empty per-message streams (`sub.messages`) for\n // subagents dispatched in parallel from a single tools step.\n awaitHandlers = true;\n\n constructor(streamFn: (streamChunk: StreamChunk) => void) {\n super();\n this.streamFn = streamFn;\n }\n\n private normalizeMessageId(message: BaseMessage, runId: string | undefined) {\n let messageId = message.id;\n\n if (runId != null) {\n if (ToolMessage.isInstance(message)) {\n messageId ??= `run-${runId}-tool-${message.tool_call_id}`;\n } else {\n if (messageId == null || messageId === `run-${runId}`) {\n messageId =\n this.stableMessageIdMap[runId] ?? messageId ?? `run-${runId}`;\n }\n this.stableMessageIdMap[runId] ??= messageId;\n }\n }\n\n if (messageId !== message.id) {\n // eslint-disable-next-line no-param-reassign\n message.id = messageId;\n // eslint-disable-next-line no-param-reassign\n message.lc_kwargs.id = messageId;\n }\n\n if (message.id != null) this.seen[message.id] = message;\n return message.id;\n }\n\n private emit(meta: Meta, data: ChatModelStreamEvent, runId?: string) {\n const metadata = runId != null ? { ...meta[1], run_id: runId } : meta[1];\n this.streamFn([meta[0], \"messages\", [data, metadata]]);\n }\n\n /**\n * Emit a complete message as protocol events (message-start, content\n * blocks, message-finish). Public so `pushMessage` can deliver manually\n * created messages when this handler is registered (streamEvents v3),\n * mirroring `StreamMessagesHandler._emit` on the classic path.\n */\n emitFinalMessage(\n meta: Meta,\n message: BaseMessage,\n runId: string | undefined,\n dedupe = false\n ) {\n const existingId =\n message.id ??\n (runId != null ? this.stableMessageIdMap[runId] : undefined);\n if (dedupe && existingId != null && this.seen[existingId] !== undefined) {\n return;\n }\n\n const messageId = this.normalizeMessageId(message, runId);\n const role =\n message.type === \"human\"\n ? \"human\"\n : message.type === \"system\"\n ? \"system\"\n : message.type === \"tool\"\n ? \"tool\"\n : \"ai\";\n const toolCallId =\n role === \"tool\" && ToolMessage.isInstance(message)\n ? message.tool_call_id\n : undefined;\n\n this.emit(\n meta,\n {\n event: \"message-start\",\n ...(messageId != null ? { id: messageId } : {}),\n ...(role !== \"ai\" ? ({ role } as Record<string, unknown>) : {}),\n ...(typeof toolCallId === \"string\"\n ? ({ tool_call_id: toolCallId } as Record<string, unknown>)\n : {}),\n } as ChatModelStreamEvent,\n runId\n );\n\n const contentBlocks: CompatibleContentBlock[] = Array.isArray(\n message.content\n )\n ? (message.content as CompatibleContentBlock[])\n : typeof message.content === \"string\" && message.content.length > 0\n ? [{ type: \"text\", text: message.content }]\n : [];\n\n contentBlocks.forEach((block, offset) => {\n const index = typeof block.index === \"number\" ? block.index : offset;\n this.emit(\n meta,\n {\n event: \"content-block-start\",\n index,\n content: startBlockFor(block),\n },\n runId\n );\n const delta = deltaFor({ ...block, index });\n if (delta != null) {\n this.emit(meta, delta, runId);\n }\n this.emit(\n meta,\n {\n event: \"content-block-finish\",\n index,\n content: block,\n },\n runId\n );\n });\n\n this.emit(\n meta,\n {\n event: \"message-finish\",\n ...(getUsageMetadata(message) != null\n ? { usage: getUsageMetadata(message) }\n : {}),\n ...(getResponseMetadata(message) != null\n ? { responseMetadata: getResponseMetadata(message) }\n : {}),\n },\n runId\n );\n }\n\n handleChatModelStart(\n _llm: Serialized,\n _messages: BaseMessage[][],\n runId: string,\n _parentRunId?: string,\n _extraParams?: Record<string, unknown>,\n tags?: string[],\n metadata?: Record<string, unknown>,\n name?: string\n ) {\n if (\n metadata &&\n (!tags || (!tags.includes(TAG_NOSTREAM) && !tags.includes(\"nostream\")))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n }\n }\n\n handleLLMNewToken() {\n // Core v2 stream events are forwarded via handleChatModelStreamEvent.\n }\n\n handleChatModelStreamEvent(event: ChatModelStreamEvent, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n let forwarded = event;\n if (event.event === \"message-start\") {\n this.streamedRunIds.add(runId);\n const id = event.id ?? `run-${runId}`;\n this.seen[id] = true;\n this.stableMessageIdMap[runId] ??= id;\n if (event.id == null) {\n forwarded = { ...event, id };\n }\n }\n\n this.emit(meta, forwarded, runId);\n }\n\n handleLLMEnd(output: LLMResult, runId: string) {\n const meta = this.metadatas[runId];\n if (meta === undefined) return;\n\n const chatGeneration = output.generations?.[0]?.[0] as ChatGeneration;\n const message = BaseMessage.isInstance(chatGeneration?.message)\n ? chatGeneration.message\n : undefined;\n\n if (message != null) {\n if (this.streamedRunIds.has(runId)) {\n const messageId = this.normalizeMessageId(message, runId);\n if (messageId != null) this.seen[messageId] = message;\n } else {\n this.emitFinalMessage(meta, message, runId, true);\n }\n }\n\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleLLMError(_err: any, runId: string) {\n this.streamedRunIds.delete(runId);\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n\n handleChainStart(\n _chain: Serialized,\n inputs: ChainValues,\n runId: string,\n _parentRunId?: string,\n tags?: string[],\n metadata?: Record<string, unknown>,\n _runType?: string,\n name?: string\n ) {\n if (\n metadata !== undefined &&\n name === metadata.langgraph_node &&\n (tags === undefined || !tags.includes(TAG_HIDDEN))\n ) {\n this.metadatas[runId] = [\n (metadata.langgraph_checkpoint_ns as string).split(\"|\"),\n { tags, name, ...metadata },\n ];\n\n if (typeof inputs === \"object\") {\n for (const value of Object.values(inputs)) {\n if (\n (BaseMessage.isInstance(value) ||\n BaseMessageChunk.isInstance(value)) &&\n value.id !== undefined\n ) {\n this.seen[value.id] = value;\n } else if (Array.isArray(value)) {\n for (const item of value) {\n if (\n (BaseMessage.isInstance(item) ||\n BaseMessageChunk.isInstance(item)) &&\n item.id !== undefined\n ) {\n this.seen[item.id] = item;\n }\n }\n }\n }\n }\n }\n }\n\n handleChainEnd(outputs: ChainValues, runId: string) {\n const meta = this.metadatas[runId];\n delete this.metadatas[runId];\n if (meta === undefined) return;\n\n const emitMessage = (value: unknown) => {\n if (BaseMessage.isInstance(value) && !ToolMessage.isInstance(value)) {\n this.emitFinalMessage(meta, value, runId, true);\n }\n };\n\n if (BaseMessage.isInstance(outputs)) {\n emitMessage(outputs);\n } else if (Array.isArray(outputs)) {\n for (const value of outputs) emitMessage(value);\n } else if (outputs != null && typeof outputs === \"object\") {\n for (const value of Object.values(outputs)) {\n if (Array.isArray(value)) {\n for (const item of value) emitMessage(item);\n } else {\n emitMessage(value);\n }\n }\n }\n\n delete this.stableMessageIdMap[runId];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handleChainError(_err: any, runId: string) {\n delete this.metadatas[runId];\n delete this.stableMessageIdMap[runId];\n }\n}\n"],"mappings":";;;;AAiBA,SAAS,oBACP,SACqC;AACrC,KACE,uBAAuB,WACvB,OAAO,QAAQ,sBAAsB,YACrC,QAAQ,qBAAqB,KAE7B,QAAO,QAAQ;;AAKnB,SAAS,iBACP,SACqC;AACrC,KACE,oBAAoB,WACpB,OAAO,QAAQ,mBAAmB,YAClC,QAAQ,kBAAkB,KAE1B,QAAO,QAAQ;;AAKnB,SAAS,cAAc,OAAuD;AAC5E,SAAQ,MAAM,MAAd;EACE,KAAK,OACH,QAAO;GAAE,MAAM;GAAQ,MAAM;GAAI;EACnC,KAAK,YACH,QAAO;GAAE,MAAM;GAAa,WAAW;GAAI;EAC7C,KAAK;EACL,KAAK,kBACH,QAAO;GACL,MAAM;GACN,GAAI,MAAM,MAAM,OAAO,EAAE,IAAI,MAAM,IAAI,GAAG,EAAE;GAC5C,GAAI,MAAM,QAAQ,OAAO,EAAE,MAAM,MAAM,MAAM,GAAG,EAAE;GAClD,MAAM;GACP;EACH,QACE,QAAO;;;AAIb,SAAS,SACP,OACkC;AAClC,SAAQ,MAAM,MAAd;EACE,KAAK,QAAQ;GACX,MAAM,OAAO,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO;AAC3D,UAAO,KAAK,SAAS,IACjB;IACE,OAAO;IACP,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;IACvD,OAAO;KAAE,MAAM;KAAc;KAAM;IACpC,GACD,KAAA;;EAEN,KAAK,aAAa;GAChB,MAAM,YACJ,OAAO,MAAM,cAAc,WAAW,MAAM,YAAY;AAC1D,UAAO,UAAU,SAAS,IACtB;IACE,OAAO;IACP,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;IACvD,OAAO;KAAE,MAAM;KAAmB;KAAW;IAC9C,GACD,KAAA;;EAEN,KAAK,kBACH,QAAO;GACL,OAAO;GACP,OAAO,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;GACvD,OAAO;IACL,MAAM;IACN,QAAQ;KAAE,GAAG;KAAO,MAAM;KAAmB;IAC9C;GACF;EACH,QACE;;;;;;;;;;;AAYN,IAAa,gCAAb,cAAmD,oBAAoB;CACrE,OAAO;CAEP;CAEA,YAA8C,EAAE;CAEhD,OAA2C,EAAE;CAE7C,iCAAiB,IAAI,KAAa;CAElC,qBAA6C,EAAE;CAE/C,qCAAqC;CAWrC,gBAAgB;CAEhB,YAAY,UAA8C;AACxD,SAAO;AACP,OAAK,WAAW;;CAGlB,mBAA2B,SAAsB,OAA2B;EAC1E,IAAI,YAAY,QAAQ;AAExB,MAAI,SAAS,KACX,KAAI,YAAY,WAAW,QAAQ,CACjC,eAAc,OAAO,MAAM,QAAQ,QAAQ;OACtC;AACL,OAAI,aAAa,QAAQ,cAAc,OAAO,QAC5C,aACE,KAAK,mBAAmB,UAAU,aAAa,OAAO;AAE1D,QAAK,mBAAmB,WAAW;;AAIvC,MAAI,cAAc,QAAQ,IAAI;AAE5B,WAAQ,KAAK;AAEb,WAAQ,UAAU,KAAK;;AAGzB,MAAI,QAAQ,MAAM,KAAM,MAAK,KAAK,QAAQ,MAAM;AAChD,SAAO,QAAQ;;CAGjB,KAAa,MAAY,MAA4B,OAAgB;EACnE,MAAM,WAAW,SAAS,OAAO;GAAE,GAAG,KAAK;GAAI,QAAQ;GAAO,GAAG,KAAK;AACtE,OAAK,SAAS;GAAC,KAAK;GAAI;GAAY,CAAC,MAAM,SAAS;GAAC,CAAC;;;;;;;;CASxD,iBACE,MACA,SACA,OACA,SAAS,OACT;EACA,MAAM,aACJ,QAAQ,OACP,SAAS,OAAO,KAAK,mBAAmB,SAAS,KAAA;AACpD,MAAI,UAAU,cAAc,QAAQ,KAAK,KAAK,gBAAgB,KAAA,EAC5D;EAGF,MAAM,YAAY,KAAK,mBAAmB,SAAS,MAAM;EACzD,MAAM,OACJ,QAAQ,SAAS,UACb,UACA,QAAQ,SAAS,WACf,WACA,QAAQ,SAAS,SACf,SACA;EACV,MAAM,aACJ,SAAS,UAAU,YAAY,WAAW,QAAQ,GAC9C,QAAQ,eACR,KAAA;AAEN,OAAK,KACH,MACA;GACE,OAAO;GACP,GAAI,aAAa,OAAO,EAAE,IAAI,WAAW,GAAG,EAAE;GAC9C,GAAI,SAAS,OAAQ,EAAE,MAAM,GAA+B,EAAE;GAC9D,GAAI,OAAO,eAAe,WACrB,EAAE,cAAc,YAAY,GAC7B,EAAE;GACP,EACD,MACD;AAUD,GARgD,MAAM,QACpD,QAAQ,QACT,GACI,QAAQ,UACT,OAAO,QAAQ,YAAY,YAAY,QAAQ,QAAQ,SAAS,IAC9D,CAAC;GAAE,MAAM;GAAQ,MAAM,QAAQ;GAAS,CAAC,GACzC,EAAE,EAEM,SAAS,OAAO,WAAW;GACvC,MAAM,QAAQ,OAAO,MAAM,UAAU,WAAW,MAAM,QAAQ;AAC9D,QAAK,KACH,MACA;IACE,OAAO;IACP;IACA,SAAS,cAAc,MAAM;IAC9B,EACD,MACD;GACD,MAAM,QAAQ,SAAS;IAAE,GAAG;IAAO;IAAO,CAAC;AAC3C,OAAI,SAAS,KACX,MAAK,KAAK,MAAM,OAAO,MAAM;AAE/B,QAAK,KACH,MACA;IACE,OAAO;IACP;IACA,SAAS;IACV,EACD,MACD;IACD;AAEF,OAAK,KACH,MACA;GACE,OAAO;GACP,GAAI,iBAAiB,QAAQ,IAAI,OAC7B,EAAE,OAAO,iBAAiB,QAAQ,EAAE,GACpC,EAAE;GACN,GAAI,oBAAoB,QAAQ,IAAI,OAChC,EAAE,kBAAkB,oBAAoB,QAAQ,EAAE,GAClD,EAAE;GACP,EACD,MACD;;CAGH,qBACE,MACA,WACA,OACA,cACA,cACA,MACA,UACA,MACA;AACA,MACE,aACC,CAAC,QAAS,CAAC,KAAK,SAAA,qBAAsB,IAAI,CAAC,KAAK,SAAS,WAAW,EAErE,MAAK,UAAU,SAAS,CACrB,SAAS,wBAAmC,MAAM,IAAI,EACvD;GAAE;GAAM;GAAM,GAAG;GAAU,CAC5B;;CAIL,oBAAoB;CAIpB,2BAA2B,OAA6B,OAAe;EACrE,MAAM,OAAO,KAAK,UAAU;AAC5B,MAAI,SAAS,KAAA,EAAW;EAExB,IAAI,YAAY;AAChB,MAAI,MAAM,UAAU,iBAAiB;AACnC,QAAK,eAAe,IAAI,MAAM;GAC9B,MAAM,KAAK,MAAM,MAAM,OAAO;AAC9B,QAAK,KAAK,MAAM;AAChB,QAAK,mBAAmB,WAAW;AACnC,OAAI,MAAM,MAAM,KACd,aAAY;IAAE,GAAG;IAAO;IAAI;;AAIhC,OAAK,KAAK,MAAM,WAAW,MAAM;;CAGnC,aAAa,QAAmB,OAAe;EAC7C,MAAM,OAAO,KAAK,UAAU;AAC5B,MAAI,SAAS,KAAA,EAAW;EAExB,MAAM,iBAAiB,OAAO,cAAc,KAAK;EACjD,MAAM,UAAU,YAAY,WAAW,gBAAgB,QAAQ,GAC3D,eAAe,UACf,KAAA;AAEJ,MAAI,WAAW,KACb,KAAI,KAAK,eAAe,IAAI,MAAM,EAAE;GAClC,MAAM,YAAY,KAAK,mBAAmB,SAAS,MAAM;AACzD,OAAI,aAAa,KAAM,MAAK,KAAK,aAAa;QAE9C,MAAK,iBAAiB,MAAM,SAAS,OAAO,KAAK;AAIrD,OAAK,eAAe,OAAO,MAAM;AACjC,SAAO,KAAK,UAAU;AACtB,SAAO,KAAK,mBAAmB;;CAIjC,eAAe,MAAW,OAAe;AACvC,OAAK,eAAe,OAAO,MAAM;AACjC,SAAO,KAAK,UAAU;AACtB,SAAO,KAAK,mBAAmB;;CAGjC,iBACE,QACA,QACA,OACA,cACA,MACA,UACA,UACA,MACA;AACA,MACE,aAAa,KAAA,KACb,SAAS,SAAS,mBACjB,SAAS,KAAA,KAAa,CAAC,KAAK,SAAA,mBAAoB,GACjD;AACA,QAAK,UAAU,SAAS,CACrB,SAAS,wBAAmC,MAAM,IAAI,EACvD;IAAE;IAAM;IAAM,GAAG;IAAU,CAC5B;AAED,OAAI,OAAO,WAAW;SACf,MAAM,SAAS,OAAO,OAAO,OAAO,CACvC,MACG,YAAY,WAAW,MAAM,IAC5B,iBAAiB,WAAW,MAAM,KACpC,MAAM,OAAO,KAAA,EAEb,MAAK,KAAK,MAAM,MAAM;aACb,MAAM,QAAQ,MAAM;UACxB,MAAM,QAAQ,MACjB,MACG,YAAY,WAAW,KAAK,IAC3B,iBAAiB,WAAW,KAAK,KACnC,KAAK,OAAO,KAAA,EAEZ,MAAK,KAAK,KAAK,MAAM;;;;;CASnC,eAAe,SAAsB,OAAe;EAClD,MAAM,OAAO,KAAK,UAAU;AAC5B,SAAO,KAAK,UAAU;AACtB,MAAI,SAAS,KAAA,EAAW;EAExB,MAAM,eAAe,UAAmB;AACtC,OAAI,YAAY,WAAW,MAAM,IAAI,CAAC,YAAY,WAAW,MAAM,CACjE,MAAK,iBAAiB,MAAM,OAAO,OAAO,KAAK;;AAInD,MAAI,YAAY,WAAW,QAAQ,CACjC,aAAY,QAAQ;WACX,MAAM,QAAQ,QAAQ,CAC/B,MAAK,MAAM,SAAS,QAAS,aAAY,MAAM;WACtC,WAAW,QAAQ,OAAO,YAAY,SAC/C,MAAK,MAAM,SAAS,OAAO,OAAO,QAAQ,CACxC,KAAI,MAAM,QAAQ,MAAM,CACtB,MAAK,MAAM,QAAQ,MAAO,aAAY,KAAK;MAE3C,aAAY,MAAM;AAKxB,SAAO,KAAK,mBAAmB;;CAIjC,iBAAiB,MAAW,OAAe;AACzC,SAAO,KAAK,UAAU;AACtB,SAAO,KAAK,mBAAmB"}
|
|
@@ -91,9 +91,10 @@ function mergeCallbacks(base, provided) {
|
|
|
91
91
|
for (const callback of base) manager.addHandler((0, _langchain_core_callbacks_manager.ensureHandler)(callback), true);
|
|
92
92
|
return manager;
|
|
93
93
|
}
|
|
94
|
+
const dedupeHandlers = (handlers) => handlers.filter((handler, index) => handlers.findIndex((candidate) => candidate === handler || candidate.name === "StreamMessagesHandler" && handler.name === "StreamMessagesHandler") === index);
|
|
94
95
|
return new _langchain_core_callbacks_manager.CallbackManager(provided._parentRunId, {
|
|
95
|
-
handlers:
|
|
96
|
-
inheritableHandlers:
|
|
96
|
+
handlers: dedupeHandlers(base.handlers.concat(provided.handlers)),
|
|
97
|
+
inheritableHandlers: dedupeHandlers(base.inheritableHandlers.concat(provided.inheritableHandlers)),
|
|
97
98
|
tags: Array.from(new Set(base.tags.concat(provided.tags))),
|
|
98
99
|
inheritableTags: Array.from(new Set(base.inheritableTags.concat(provided.inheritableTags))),
|
|
99
100
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.cjs","names":["CallbackManager","CONFIG_KEY_READ","AsyncLocalStorageProviderSingleton","CONFIG_KEY_SCRATCHPAD"],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport {\n CallbackManager,\n ensureHandler,\n type Callbacks,\n} from \"@langchain/core/callbacks/manager\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_READ,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Drop langgraph's internal `seq:step*` bookkeeping tags.\n *\n * `seq:step:N` tags are added internally to mark sequence steps; everything\n * else (user-supplied tags and any other framework tags) is kept. Returns the\n * surviving tags, or `undefined` if none remain. Shared by the stream handlers\n * (e.g. {@link mapDebugTasks}) so the same tag set is surfaced consistently.\n */\nexport function filterToUserTags(\n tags: readonly string[] | undefined\n): string[] | undefined {\n if (tags == null || tags.length === 0) return undefined;\n const filtered = tags.filter((tag) => !tag.startsWith(\"seq:step\"));\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Merge two `callbacks` values across configs.\n *\n * A `callbacks` value may be `undefined`, an array of handlers, or a\n * {@link CallbackManager}, so merging two of them has six cases. This\n * mirrors the callbacks branch of langchain-core's `mergeConfigs` and\n * langgraph's `_merge_callbacks`, so a handler bound via\n * `.withConfig({ callbacks: [...] })` is preserved when a later config\n * (e.g. `streamEvents` injecting its own internal handler) is merged on\n * top instead of overwriting it.\n */\nfunction mergeCallbacks(\n base: Callbacks | undefined,\n provided: Callbacks | undefined\n): Callbacks | undefined {\n if (provided === undefined) return base;\n if (base === undefined) {\n return Array.isArray(provided) ? [...provided] : provided.copy();\n }\n if (Array.isArray(provided)) {\n if (Array.isArray(base)) return base.concat(provided);\n // base is a manager\n const manager = base.copy();\n for (const callback of provided) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // provided is a manager\n if (Array.isArray(base)) {\n const manager = provided.copy();\n for (const callback of base) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // both are managers\n return new CallbackManager(provided._parentRunId, {\n handlers: Array.from(new Set(base.handlers.concat(provided.handlers))),\n inheritableHandlers: Array.from(\n new Set(base.inheritableHandlers.concat(provided.inheritableHandlers))\n ),\n tags: Array.from(new Set(base.tags.concat(provided.tags))),\n inheritableTags: Array.from(\n new Set(base.inheritableTags.concat(provided.inheritableTags))\n ),\n metadata: { ...base.metadata, ...provided.metadata },\n inheritableMetadata: {\n ...base.inheritableMetadata,\n ...provided.inheritableMetadata,\n },\n });\n}\n\n/**\n * True when the caller is starting a fresh top-level run (invoke-time\n * `thread_id`, no active nesting keys). In that case the ambient `configurable`\n * from `AsyncLocalStorage` cannot be trusted per-key — it may belong to another\n * concurrent invocation on a shared singleton agent (scratchpad/task-input as\n * well as arbitrary user keys like `tenant_id`/`user_id`). The whole ambient\n * `configurable` is therefore ignored; any value the caller actually wants for\n * this run arrives through the explicit (bound + invoke-time) configs instead.\n *\n * Only the last caller-supplied config is treated as invoke-time options.\n * Earlier entries are graph-bound defaults from `.withConfig()` / compile and\n * must not count — a child graph bound with `thread_id` and invoked from a\n * parent task without a fresh config still needs ambient nesting keys from ALS.\n */\nfunction isRootLevelExplicitInvoke(\n configs: (LangGraphRunnableConfig | undefined)[]\n): boolean {\n let invokeConfig: LangGraphRunnableConfig | undefined;\n for (let i = configs.length - 1; i >= 0; i -= 1) {\n if (configs[i] !== undefined) {\n invokeConfig = configs[i];\n break;\n }\n }\n const hasInvokeTimeThreadId =\n invokeConfig?.configurable?.thread_id !== undefined;\n\n const hasExplicitNesting = configs.some(\n (c) => c?.configurable?.[CONFIG_KEY_READ] !== undefined\n );\n\n const ambientConfigurable =\n AsyncLocalStorageProviderSingleton.getRunnableConfig()?.configurable;\n const hasAmbientNesting =\n ambientConfigurable?.[CONFIG_KEY_READ] !== undefined;\n\n return hasInvokeTimeThreadId && !hasExplicitNesting && !hasAmbientNesting;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const skipImplicitConfigurable = isRootLevelExplicitInvoke(configs);\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n // Stale-ALS root invoke: ignore the ambient `configurable` entirely,\n // since its keys may belong to another concurrent invocation.\n if (k === \"configurable\" && skipImplicitConfigurable) {\n continue;\n }\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v === undefined || !CONFIG_KEYS.includes(k)) {\n continue;\n }\n\n // Merge (rather than overwrite) the fields that compose across\n // multiple configs, matching langgraph's `merge_configs` /\n // langchain-core's `mergeConfigs`. Without this, a value bound via\n // `.withConfig({...})` is silently dropped whenever a later config\n // (e.g. invoke-time, or `streamEvents`' internal handler) supplies\n // any other key in the same field. Later configs still win per key\n // on collision.\n if (k === \"configurable\") {\n empty.configurable = {\n ...(empty.configurable as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"metadata\") {\n empty.metadata = {\n ...(empty.metadata as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"tags\") {\n // Plain concat (matches langgraph's `merge_configs`): no dedup,\n // no sort.\n empty.tags = [\n ...((empty.tags as string[] | undefined) ?? []),\n ...(v as string[]),\n ];\n } else if (k === \"callbacks\") {\n empty.callbacks = mergeCallbacks(empty.callbacks, v as Callbacks);\n } else {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing\n * task.\n *\n * Note: When called without arguments, this relies on `node:async_hooks` /\n * `AsyncLocalStorage`, which is available in many JavaScript environments\n * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments\n * without `AsyncLocalStorage` support, pass the `config` that your node/tool\n * function receives directly, e.g. `getCurrentTaskInput(config)`.\n *\n * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from\n * `runtime.state` on the second tool argument (typed as `ToolRuntime` from\n * `@langchain/core/tools`). It works in every runtime, including web browsers.\n *\n * @param config - Optional {@link LangGraphRunnableConfig} to read the task\n * input from. Provide this when running in an environment without\n * `AsyncLocalStorage` support (e.g. web browsers).\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.cjs","names":["CallbackManager","CONFIG_KEY_READ","AsyncLocalStorageProviderSingleton","CONFIG_KEY_SCRATCHPAD"],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport {\n CallbackManager,\n ensureHandler,\n type Callbacks,\n} from \"@langchain/core/callbacks/manager\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_READ,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Drop langgraph's internal `seq:step*` bookkeeping tags.\n *\n * `seq:step:N` tags are added internally to mark sequence steps; everything\n * else (user-supplied tags and any other framework tags) is kept. Returns the\n * surviving tags, or `undefined` if none remain. Shared by the stream handlers\n * (e.g. {@link mapDebugTasks}) so the same tag set is surfaced consistently.\n */\nexport function filterToUserTags(\n tags: readonly string[] | undefined\n): string[] | undefined {\n if (tags == null || tags.length === 0) return undefined;\n const filtered = tags.filter((tag) => !tag.startsWith(\"seq:step\"));\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Merge two `callbacks` values across configs.\n *\n * A `callbacks` value may be `undefined`, an array of handlers, or a\n * {@link CallbackManager}, so merging two of them has six cases. This\n * mirrors the callbacks branch of langchain-core's `mergeConfigs` and\n * langgraph's `_merge_callbacks`, so a handler bound via\n * `.withConfig({ callbacks: [...] })` is preserved when a later config\n * (e.g. `streamEvents` injecting its own internal handler) is merged on\n * top instead of overwriting it.\n */\nfunction mergeCallbacks(\n base: Callbacks | undefined,\n provided: Callbacks | undefined\n): Callbacks | undefined {\n if (provided === undefined) return base;\n if (base === undefined) {\n return Array.isArray(provided) ? [...provided] : provided.copy();\n }\n if (Array.isArray(provided)) {\n if (Array.isArray(base)) return base.concat(provided);\n // base is a manager\n const manager = base.copy();\n for (const callback of provided) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // provided is a manager\n if (Array.isArray(base)) {\n const manager = provided.copy();\n for (const callback of base) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // both are managers\n const dedupeHandlers = (\n handlers: CallbackManager[\"handlers\"]\n ): CallbackManager[\"handlers\"] =>\n handlers.filter(\n (handler, index) =>\n handlers.findIndex(\n (candidate) =>\n candidate === handler ||\n (candidate.name === \"StreamMessagesHandler\" &&\n handler.name === \"StreamMessagesHandler\")\n ) === index\n );\n return new CallbackManager(provided._parentRunId, {\n handlers: dedupeHandlers(base.handlers.concat(provided.handlers)),\n inheritableHandlers: dedupeHandlers(\n base.inheritableHandlers.concat(provided.inheritableHandlers)\n ),\n tags: Array.from(new Set(base.tags.concat(provided.tags))),\n inheritableTags: Array.from(\n new Set(base.inheritableTags.concat(provided.inheritableTags))\n ),\n metadata: { ...base.metadata, ...provided.metadata },\n inheritableMetadata: {\n ...base.inheritableMetadata,\n ...provided.inheritableMetadata,\n },\n });\n}\n\n/**\n * True when the caller is starting a fresh top-level run (invoke-time\n * `thread_id`, no active nesting keys). In that case the ambient `configurable`\n * from `AsyncLocalStorage` cannot be trusted per-key — it may belong to another\n * concurrent invocation on a shared singleton agent (scratchpad/task-input as\n * well as arbitrary user keys like `tenant_id`/`user_id`). The whole ambient\n * `configurable` is therefore ignored; any value the caller actually wants for\n * this run arrives through the explicit (bound + invoke-time) configs instead.\n *\n * Only the last caller-supplied config is treated as invoke-time options.\n * Earlier entries are graph-bound defaults from `.withConfig()` / compile and\n * must not count — a child graph bound with `thread_id` and invoked from a\n * parent task without a fresh config still needs ambient nesting keys from ALS.\n */\nfunction isRootLevelExplicitInvoke(\n configs: (LangGraphRunnableConfig | undefined)[]\n): boolean {\n let invokeConfig: LangGraphRunnableConfig | undefined;\n for (let i = configs.length - 1; i >= 0; i -= 1) {\n if (configs[i] !== undefined) {\n invokeConfig = configs[i];\n break;\n }\n }\n const hasInvokeTimeThreadId =\n invokeConfig?.configurable?.thread_id !== undefined;\n\n const hasExplicitNesting = configs.some(\n (c) => c?.configurable?.[CONFIG_KEY_READ] !== undefined\n );\n\n const ambientConfigurable =\n AsyncLocalStorageProviderSingleton.getRunnableConfig()?.configurable;\n const hasAmbientNesting =\n ambientConfigurable?.[CONFIG_KEY_READ] !== undefined;\n\n return hasInvokeTimeThreadId && !hasExplicitNesting && !hasAmbientNesting;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const skipImplicitConfigurable = isRootLevelExplicitInvoke(configs);\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n // Stale-ALS root invoke: ignore the ambient `configurable` entirely,\n // since its keys may belong to another concurrent invocation.\n if (k === \"configurable\" && skipImplicitConfigurable) {\n continue;\n }\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v === undefined || !CONFIG_KEYS.includes(k)) {\n continue;\n }\n\n // Merge (rather than overwrite) the fields that compose across\n // multiple configs, matching langgraph's `merge_configs` /\n // langchain-core's `mergeConfigs`. Without this, a value bound via\n // `.withConfig({...})` is silently dropped whenever a later config\n // (e.g. invoke-time, or `streamEvents`' internal handler) supplies\n // any other key in the same field. Later configs still win per key\n // on collision.\n if (k === \"configurable\") {\n empty.configurable = {\n ...(empty.configurable as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"metadata\") {\n empty.metadata = {\n ...(empty.metadata as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"tags\") {\n // Plain concat (matches langgraph's `merge_configs`): no dedup,\n // no sort.\n empty.tags = [\n ...((empty.tags as string[] | undefined) ?? []),\n ...(v as string[]),\n ];\n } else if (k === \"callbacks\") {\n empty.callbacks = mergeCallbacks(empty.callbacks, v as Callbacks);\n } else {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing\n * task.\n *\n * Note: When called without arguments, this relies on `node:async_hooks` /\n * `AsyncLocalStorage`, which is available in many JavaScript environments\n * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments\n * without `AsyncLocalStorage` support, pass the `config` that your node/tool\n * function receives directly, e.g. `getCurrentTaskInput(config)`.\n *\n * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from\n * `runtime.state` on the second tool argument (typed as `ToolRuntime` from\n * `@langchain/core/tools`). It works in every runtime, including web browsers.\n *\n * @param config - Optional {@link LangGraphRunnableConfig} to read the task\n * input from. Provide this when running in an environment without\n * `AsyncLocalStorage` support (e.g. web browsers).\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.cts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.d.cts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBA2SgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AA+CH;;;iBA1BgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;AA+CL;;;;;;;iBAvBgB,SAAA,CAAA,GAAa,uBAAA;;;;;;;;;;;;;;;;;;;;iBAuBb,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBA2SgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AA+CH;;;iBA1BgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;AA+CL;;;;;;;iBAvBgB,SAAA,CAAA,GAAa,uBAAA;;;;;;;;;;;;;;;;;;;;iBAuBb,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
|
|
@@ -91,9 +91,10 @@ function mergeCallbacks(base, provided) {
|
|
|
91
91
|
for (const callback of base) manager.addHandler(ensureHandler(callback), true);
|
|
92
92
|
return manager;
|
|
93
93
|
}
|
|
94
|
+
const dedupeHandlers = (handlers) => handlers.filter((handler, index) => handlers.findIndex((candidate) => candidate === handler || candidate.name === "StreamMessagesHandler" && handler.name === "StreamMessagesHandler") === index);
|
|
94
95
|
return new CallbackManager(provided._parentRunId, {
|
|
95
|
-
handlers:
|
|
96
|
-
inheritableHandlers:
|
|
96
|
+
handlers: dedupeHandlers(base.handlers.concat(provided.handlers)),
|
|
97
|
+
inheritableHandlers: dedupeHandlers(base.inheritableHandlers.concat(provided.inheritableHandlers)),
|
|
97
98
|
tags: Array.from(new Set(base.tags.concat(provided.tags))),
|
|
98
99
|
inheritableTags: Array.from(new Set(base.inheritableTags.concat(provided.inheritableTags))),
|
|
99
100
|
metadata: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport {\n CallbackManager,\n ensureHandler,\n type Callbacks,\n} from \"@langchain/core/callbacks/manager\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_READ,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Drop langgraph's internal `seq:step*` bookkeeping tags.\n *\n * `seq:step:N` tags are added internally to mark sequence steps; everything\n * else (user-supplied tags and any other framework tags) is kept. Returns the\n * surviving tags, or `undefined` if none remain. Shared by the stream handlers\n * (e.g. {@link mapDebugTasks}) so the same tag set is surfaced consistently.\n */\nexport function filterToUserTags(\n tags: readonly string[] | undefined\n): string[] | undefined {\n if (tags == null || tags.length === 0) return undefined;\n const filtered = tags.filter((tag) => !tag.startsWith(\"seq:step\"));\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Merge two `callbacks` values across configs.\n *\n * A `callbacks` value may be `undefined`, an array of handlers, or a\n * {@link CallbackManager}, so merging two of them has six cases. This\n * mirrors the callbacks branch of langchain-core's `mergeConfigs` and\n * langgraph's `_merge_callbacks`, so a handler bound via\n * `.withConfig({ callbacks: [...] })` is preserved when a later config\n * (e.g. `streamEvents` injecting its own internal handler) is merged on\n * top instead of overwriting it.\n */\nfunction mergeCallbacks(\n base: Callbacks | undefined,\n provided: Callbacks | undefined\n): Callbacks | undefined {\n if (provided === undefined) return base;\n if (base === undefined) {\n return Array.isArray(provided) ? [...provided] : provided.copy();\n }\n if (Array.isArray(provided)) {\n if (Array.isArray(base)) return base.concat(provided);\n // base is a manager\n const manager = base.copy();\n for (const callback of provided) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // provided is a manager\n if (Array.isArray(base)) {\n const manager = provided.copy();\n for (const callback of base) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // both are managers\n return new CallbackManager(provided._parentRunId, {\n handlers: Array.from(new Set(base.handlers.concat(provided.handlers))),\n inheritableHandlers: Array.from(\n new Set(base.inheritableHandlers.concat(provided.inheritableHandlers))\n ),\n tags: Array.from(new Set(base.tags.concat(provided.tags))),\n inheritableTags: Array.from(\n new Set(base.inheritableTags.concat(provided.inheritableTags))\n ),\n metadata: { ...base.metadata, ...provided.metadata },\n inheritableMetadata: {\n ...base.inheritableMetadata,\n ...provided.inheritableMetadata,\n },\n });\n}\n\n/**\n * True when the caller is starting a fresh top-level run (invoke-time\n * `thread_id`, no active nesting keys). In that case the ambient `configurable`\n * from `AsyncLocalStorage` cannot be trusted per-key — it may belong to another\n * concurrent invocation on a shared singleton agent (scratchpad/task-input as\n * well as arbitrary user keys like `tenant_id`/`user_id`). The whole ambient\n * `configurable` is therefore ignored; any value the caller actually wants for\n * this run arrives through the explicit (bound + invoke-time) configs instead.\n *\n * Only the last caller-supplied config is treated as invoke-time options.\n * Earlier entries are graph-bound defaults from `.withConfig()` / compile and\n * must not count — a child graph bound with `thread_id` and invoked from a\n * parent task without a fresh config still needs ambient nesting keys from ALS.\n */\nfunction isRootLevelExplicitInvoke(\n configs: (LangGraphRunnableConfig | undefined)[]\n): boolean {\n let invokeConfig: LangGraphRunnableConfig | undefined;\n for (let i = configs.length - 1; i >= 0; i -= 1) {\n if (configs[i] !== undefined) {\n invokeConfig = configs[i];\n break;\n }\n }\n const hasInvokeTimeThreadId =\n invokeConfig?.configurable?.thread_id !== undefined;\n\n const hasExplicitNesting = configs.some(\n (c) => c?.configurable?.[CONFIG_KEY_READ] !== undefined\n );\n\n const ambientConfigurable =\n AsyncLocalStorageProviderSingleton.getRunnableConfig()?.configurable;\n const hasAmbientNesting =\n ambientConfigurable?.[CONFIG_KEY_READ] !== undefined;\n\n return hasInvokeTimeThreadId && !hasExplicitNesting && !hasAmbientNesting;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const skipImplicitConfigurable = isRootLevelExplicitInvoke(configs);\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n // Stale-ALS root invoke: ignore the ambient `configurable` entirely,\n // since its keys may belong to another concurrent invocation.\n if (k === \"configurable\" && skipImplicitConfigurable) {\n continue;\n }\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v === undefined || !CONFIG_KEYS.includes(k)) {\n continue;\n }\n\n // Merge (rather than overwrite) the fields that compose across\n // multiple configs, matching langgraph's `merge_configs` /\n // langchain-core's `mergeConfigs`. Without this, a value bound via\n // `.withConfig({...})` is silently dropped whenever a later config\n // (e.g. invoke-time, or `streamEvents`' internal handler) supplies\n // any other key in the same field. Later configs still win per key\n // on collision.\n if (k === \"configurable\") {\n empty.configurable = {\n ...(empty.configurable as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"metadata\") {\n empty.metadata = {\n ...(empty.metadata as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"tags\") {\n // Plain concat (matches langgraph's `merge_configs`): no dedup,\n // no sort.\n empty.tags = [\n ...((empty.tags as string[] | undefined) ?? []),\n ...(v as string[]),\n ];\n } else if (k === \"callbacks\") {\n empty.callbacks = mergeCallbacks(empty.callbacks, v as Callbacks);\n } else {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing\n * task.\n *\n * Note: When called without arguments, this relies on `node:async_hooks` /\n * `AsyncLocalStorage`, which is available in many JavaScript environments\n * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments\n * without `AsyncLocalStorage` support, pass the `config` that your node/tool\n * function receives directly, e.g. `getCurrentTaskInput(config)`.\n *\n * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from\n * `runtime.state` on the second tool argument (typed as `ToolRuntime` from\n * `@langchain/core/tools`). It works in every runtime, including web browsers.\n *\n * @param config - Optional {@link LangGraphRunnableConfig} to read the task\n * input from. Provide this when running in an environment without\n * `AsyncLocalStorage` support (e.g. web browsers).\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport {\n CallbackManager,\n ensureHandler,\n type Callbacks,\n} from \"@langchain/core/callbacks/manager\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_READ,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Drop langgraph's internal `seq:step*` bookkeeping tags.\n *\n * `seq:step:N` tags are added internally to mark sequence steps; everything\n * else (user-supplied tags and any other framework tags) is kept. Returns the\n * surviving tags, or `undefined` if none remain. Shared by the stream handlers\n * (e.g. {@link mapDebugTasks}) so the same tag set is surfaced consistently.\n */\nexport function filterToUserTags(\n tags: readonly string[] | undefined\n): string[] | undefined {\n if (tags == null || tags.length === 0) return undefined;\n const filtered = tags.filter((tag) => !tag.startsWith(\"seq:step\"));\n return filtered.length > 0 ? filtered : undefined;\n}\n\n/**\n * Merge two `callbacks` values across configs.\n *\n * A `callbacks` value may be `undefined`, an array of handlers, or a\n * {@link CallbackManager}, so merging two of them has six cases. This\n * mirrors the callbacks branch of langchain-core's `mergeConfigs` and\n * langgraph's `_merge_callbacks`, so a handler bound via\n * `.withConfig({ callbacks: [...] })` is preserved when a later config\n * (e.g. `streamEvents` injecting its own internal handler) is merged on\n * top instead of overwriting it.\n */\nfunction mergeCallbacks(\n base: Callbacks | undefined,\n provided: Callbacks | undefined\n): Callbacks | undefined {\n if (provided === undefined) return base;\n if (base === undefined) {\n return Array.isArray(provided) ? [...provided] : provided.copy();\n }\n if (Array.isArray(provided)) {\n if (Array.isArray(base)) return base.concat(provided);\n // base is a manager\n const manager = base.copy();\n for (const callback of provided) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // provided is a manager\n if (Array.isArray(base)) {\n const manager = provided.copy();\n for (const callback of base) {\n manager.addHandler(ensureHandler(callback), true);\n }\n return manager;\n }\n // both are managers\n const dedupeHandlers = (\n handlers: CallbackManager[\"handlers\"]\n ): CallbackManager[\"handlers\"] =>\n handlers.filter(\n (handler, index) =>\n handlers.findIndex(\n (candidate) =>\n candidate === handler ||\n (candidate.name === \"StreamMessagesHandler\" &&\n handler.name === \"StreamMessagesHandler\")\n ) === index\n );\n return new CallbackManager(provided._parentRunId, {\n handlers: dedupeHandlers(base.handlers.concat(provided.handlers)),\n inheritableHandlers: dedupeHandlers(\n base.inheritableHandlers.concat(provided.inheritableHandlers)\n ),\n tags: Array.from(new Set(base.tags.concat(provided.tags))),\n inheritableTags: Array.from(\n new Set(base.inheritableTags.concat(provided.inheritableTags))\n ),\n metadata: { ...base.metadata, ...provided.metadata },\n inheritableMetadata: {\n ...base.inheritableMetadata,\n ...provided.inheritableMetadata,\n },\n });\n}\n\n/**\n * True when the caller is starting a fresh top-level run (invoke-time\n * `thread_id`, no active nesting keys). In that case the ambient `configurable`\n * from `AsyncLocalStorage` cannot be trusted per-key — it may belong to another\n * concurrent invocation on a shared singleton agent (scratchpad/task-input as\n * well as arbitrary user keys like `tenant_id`/`user_id`). The whole ambient\n * `configurable` is therefore ignored; any value the caller actually wants for\n * this run arrives through the explicit (bound + invoke-time) configs instead.\n *\n * Only the last caller-supplied config is treated as invoke-time options.\n * Earlier entries are graph-bound defaults from `.withConfig()` / compile and\n * must not count — a child graph bound with `thread_id` and invoked from a\n * parent task without a fresh config still needs ambient nesting keys from ALS.\n */\nfunction isRootLevelExplicitInvoke(\n configs: (LangGraphRunnableConfig | undefined)[]\n): boolean {\n let invokeConfig: LangGraphRunnableConfig | undefined;\n for (let i = configs.length - 1; i >= 0; i -= 1) {\n if (configs[i] !== undefined) {\n invokeConfig = configs[i];\n break;\n }\n }\n const hasInvokeTimeThreadId =\n invokeConfig?.configurable?.thread_id !== undefined;\n\n const hasExplicitNesting = configs.some(\n (c) => c?.configurable?.[CONFIG_KEY_READ] !== undefined\n );\n\n const ambientConfigurable =\n AsyncLocalStorageProviderSingleton.getRunnableConfig()?.configurable;\n const hasAmbientNesting =\n ambientConfigurable?.[CONFIG_KEY_READ] !== undefined;\n\n return hasInvokeTimeThreadId && !hasExplicitNesting && !hasAmbientNesting;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const skipImplicitConfigurable = isRootLevelExplicitInvoke(configs);\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n // Stale-ALS root invoke: ignore the ambient `configurable` entirely,\n // since its keys may belong to another concurrent invocation.\n if (k === \"configurable\" && skipImplicitConfigurable) {\n continue;\n }\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v === undefined || !CONFIG_KEYS.includes(k)) {\n continue;\n }\n\n // Merge (rather than overwrite) the fields that compose across\n // multiple configs, matching langgraph's `merge_configs` /\n // langchain-core's `mergeConfigs`. Without this, a value bound via\n // `.withConfig({...})` is silently dropped whenever a later config\n // (e.g. invoke-time, or `streamEvents`' internal handler) supplies\n // any other key in the same field. Later configs still win per key\n // on collision.\n if (k === \"configurable\") {\n empty.configurable = {\n ...(empty.configurable as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"metadata\") {\n empty.metadata = {\n ...(empty.metadata as Record<string, unknown> | undefined),\n ...(v as Record<string, unknown>),\n };\n } else if (k === \"tags\") {\n // Plain concat (matches langgraph's `merge_configs`): no dedup,\n // no sort.\n empty.tags = [\n ...((empty.tags as string[] | undefined) ?? []),\n ...(v as string[]),\n ];\n } else if (k === \"callbacks\") {\n empty.callbacks = mergeCallbacks(empty.callbacks, v as Callbacks);\n } else {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing\n * task.\n *\n * Note: When called without arguments, this relies on `node:async_hooks` /\n * `AsyncLocalStorage`, which is available in many JavaScript environments\n * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments\n * without `AsyncLocalStorage` support, pass the `config` that your node/tool\n * function receives directly, e.g. `getCurrentTaskInput(config)`.\n *\n * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from\n * `runtime.state` on the second tool argument (typed as `ToolRuntime` from\n * `@langchain/core/tools`). It works in every runtime, including web browsers.\n *\n * @param config - Optional {@link LangGraphRunnableConfig} to read the task\n * input from. Provide this when running in an environment without\n * `AsyncLocalStorage` support (e.g. web browsers).\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/langgraph",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.14",
|
|
4
4
|
"description": "LangGraph",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
"author": "LangChain",
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@langchain/protocol": "^0.0.
|
|
19
|
+
"@langchain/protocol": "^0.0.19",
|
|
20
20
|
"@standard-schema/spec": "1.1.0",
|
|
21
21
|
"@langchain/langgraph-checkpoint": "^1.1.5",
|
|
22
|
-
"@langchain/langgraph-sdk": "~1.
|
|
22
|
+
"@langchain/langgraph-sdk": "~1.10.2"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
25
25
|
"@langchain/core": "^1.1.48",
|
|
26
26
|
"zod": "^3.25.32 || ^4.2.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@langchain/anthropic": "^1.5.
|
|
30
|
-
"@langchain/core": "^1.2.
|
|
31
|
-
"@langchain/openai": "^1.5.
|
|
29
|
+
"@langchain/anthropic": "^1.5.8",
|
|
30
|
+
"@langchain/core": "^1.2.9",
|
|
31
|
+
"@langchain/openai": "^1.5.10",
|
|
32
32
|
"@langchain/scripts": ">=0.1.3 <0.2.0",
|
|
33
33
|
"@langchain/tavily": "^1.0.0",
|
|
34
34
|
"@swc/core": "^1.3.90",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"cheerio": "1.0.0-rc.12",
|
|
42
42
|
"dotenv": "^16.3.1",
|
|
43
43
|
"dpdm": "^3.12.0",
|
|
44
|
-
"langchain": "^1.5.
|
|
44
|
+
"langchain": "^1.5.10",
|
|
45
45
|
"pg": "^8.13.0",
|
|
46
46
|
"playwright": "^1.55.1",
|
|
47
47
|
"rollup": "^4.62.3",
|