@langchain/core
Version:
Core LangChain.js abstractions and schemas
1 lines • 15.2 kB
Source Map (JSON)
{"version":3,"file":"config.cjs","names":["CallbackManager","ensureHandler","AsyncLocalStorageProviderSingleton"],"sources":["../../src/runnables/config.ts"],"sourcesContent":["import { CallbackManager, ensureHandler } from \"../callbacks/manager.js\";\nimport { AsyncLocalStorageProviderSingleton } from \"../singletons/index.js\";\nimport { RunnableConfig } from \"./types.js\";\n\nexport const DEFAULT_RECURSION_LIMIT = 25;\n\nexport { type RunnableConfig };\n\nconst CONFIGURABLE_TO_TRACING_METADATA_EXCLUDED_KEYS = new Set([\"api_key\"]);\nconst PRIMITIVES = new Set([\"string\", \"number\", \"boolean\"]);\n\nexport function _getTracingInheritableMetadataFromConfig(\n config: RunnableConfig\n): Record<string, unknown> | undefined {\n const configurable = config.configurable ?? {};\n const metadata = config.metadata ?? {};\n const langSmithMetadata: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(configurable)) {\n if (\n !key.startsWith(\"__\") &&\n !Object.prototype.hasOwnProperty.call(metadata, key) &&\n !CONFIGURABLE_TO_TRACING_METADATA_EXCLUDED_KEYS.has(key) &&\n PRIMITIVES.has(typeof value)\n ) {\n langSmithMetadata[key] = value;\n }\n }\n return Object.keys(langSmithMetadata).length > 0\n ? langSmithMetadata\n : undefined;\n}\n\nexport async function getCallbackManagerForConfig(config?: RunnableConfig) {\n return CallbackManager._configureSync(\n config?.callbacks,\n undefined,\n config?.tags,\n undefined,\n config?.metadata,\n undefined,\n {\n tracerInheritableMetadata: config\n ? _getTracingInheritableMetadataFromConfig(config)\n : undefined,\n }\n );\n}\n\nexport function mergeConfigs<CallOptions extends RunnableConfig>(\n ...configs: (CallOptions | RunnableConfig | undefined | null)[]\n): Partial<CallOptions> {\n // We do not want to call ensureConfig on the empty state here as this may cause\n // double loading of callbacks if async local storage is being used.\n const copy: Partial<CallOptions> = {};\n for (const options of configs.filter((c): c is CallOptions => !!c)) {\n for (const key of Object.keys(options)) {\n if (key === \"metadata\") {\n copy[key] = { ...copy[key], ...options[key] };\n } else if (key === \"tags\") {\n const baseKeys: string[] = copy[key] ?? [];\n copy[key] = [...new Set(baseKeys.concat(options[key] ?? []))];\n } else if (key === \"configurable\") {\n copy[key] = { ...copy[key], ...options[key] };\n } else if (key === \"timeout\") {\n if (copy.timeout === undefined) {\n copy.timeout = options.timeout;\n } else if (options.timeout !== undefined) {\n copy.timeout = Math.min(copy.timeout, options.timeout);\n }\n } else if (key === \"signal\") {\n if (copy.signal === undefined) {\n copy.signal = options.signal;\n } else if (options.signal !== undefined) {\n if (\"any\" in AbortSignal) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n copy.signal = (AbortSignal as any).any([\n copy.signal,\n options.signal,\n ]);\n } else {\n copy.signal = options.signal;\n }\n }\n } else if (key === \"callbacks\") {\n const baseCallbacks = copy.callbacks;\n const providedCallbacks = options.callbacks;\n // callbacks can be either undefined, Array<handler> or manager\n // so merging two callbacks values has 6 cases\n if (Array.isArray(providedCallbacks)) {\n if (!baseCallbacks) {\n copy.callbacks = providedCallbacks;\n } else if (Array.isArray(baseCallbacks)) {\n copy.callbacks = baseCallbacks.concat(providedCallbacks);\n } else {\n // baseCallbacks is a manager\n const manager = baseCallbacks.copy();\n for (const callback of providedCallbacks) {\n manager.addHandler(ensureHandler(callback), true);\n }\n copy.callbacks = manager;\n }\n } else if (providedCallbacks) {\n // providedCallbacks is a manager\n if (!baseCallbacks) {\n copy.callbacks = providedCallbacks;\n } else if (Array.isArray(baseCallbacks)) {\n const manager = providedCallbacks.copy();\n for (const callback of baseCallbacks) {\n manager.addHandler(ensureHandler(callback), true);\n }\n copy.callbacks = manager;\n } else {\n // baseCallbacks is also a manager\n copy.callbacks = new CallbackManager(\n providedCallbacks._parentRunId,\n {\n handlers: baseCallbacks.handlers.concat(\n providedCallbacks.handlers\n ),\n inheritableHandlers: baseCallbacks.inheritableHandlers.concat(\n providedCallbacks.inheritableHandlers\n ),\n tags: Array.from(\n new Set(baseCallbacks.tags.concat(providedCallbacks.tags))\n ),\n inheritableTags: Array.from(\n new Set(\n baseCallbacks.inheritableTags.concat(\n providedCallbacks.inheritableTags\n )\n )\n ),\n metadata: {\n ...baseCallbacks.metadata,\n ...providedCallbacks.metadata,\n },\n }\n );\n }\n }\n } else {\n const typedKey = key as keyof CallOptions;\n copy[typedKey] = options[typedKey] ?? copy[typedKey];\n }\n }\n }\n return copy as Partial<CallOptions>;\n}\n\n/**\n * Ensure that a passed config is an object with all required keys present.\n */\nexport function ensureConfig<CallOptions extends RunnableConfig>(\n config?: CallOptions\n): CallOptions {\n const implicitConfig = AsyncLocalStorageProviderSingleton.getRunnableConfig();\n let empty: RunnableConfig = {\n tags: [],\n metadata: {},\n recursionLimit: 25,\n runId: undefined,\n };\n if (implicitConfig) {\n // Don't allow runId and runName to be loaded implicitly, as this can cause\n // child runs to improperly inherit their parents' run ids.\n const { runId, runName, ...rest } = implicitConfig;\n empty = Object.entries(rest).reduce(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n (currentConfig: Record<string, any>, [key, value]) => {\n if (value !== undefined) {\n currentConfig[key] = value;\n }\n return currentConfig;\n },\n empty\n );\n }\n if (config) {\n empty = Object.entries(config).reduce(\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n (currentConfig: Record<string, any>, [key, value]) => {\n if (value !== undefined) {\n currentConfig[key] = value;\n }\n return currentConfig;\n },\n empty\n );\n }\n if (empty?.configurable) {\n if (\n typeof empty.configurable.model === \"string\" &&\n empty.metadata?.model === undefined\n ) {\n if (!empty.metadata) {\n empty.metadata = {};\n }\n empty.metadata.model = empty.configurable.model;\n }\n }\n if (empty.timeout !== undefined) {\n if (empty.timeout <= 0) {\n throw new Error(\"Timeout must be a positive number\");\n }\n const originalTimeoutMs = empty.timeout;\n const timeoutSignal = AbortSignal.timeout(originalTimeoutMs);\n // Preserve the numeric timeout for downstream consumers that need to pass\n // an explicit timeout value to underlying SDKs in addition to an AbortSignal.\n // We store it in metadata to avoid changing the public config shape.\n if (!empty.metadata) {\n empty.metadata = {};\n }\n // Do not overwrite if already set upstream.\n if (empty.metadata.timeoutMs === undefined) {\n empty.metadata.timeoutMs = originalTimeoutMs;\n }\n if (empty.signal !== undefined) {\n if (\"any\" in AbortSignal) {\n // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n empty.signal = (AbortSignal as any).any([empty.signal, timeoutSignal]);\n }\n } else {\n empty.signal = timeoutSignal;\n }\n\n /**\n * We are deleting the timeout key for the following reasons:\n * - Idempotent normalization: ensureConfig may be called multiple times down the stack. If timeout remains,\n * each call would synthesize new timeout signals and combine them, changing the effective timeout unpredictably.\n * - Single enforcement path: downstream code relies on signal to enforce cancellation. Leaving timeout means two\n * competing mechanisms (numeric timeout and signal) can be applied, sometimes with different semantics.\n * - Propagation to children: pickRunnableConfigKeys would keep forwarding timeout to nested runnables, causing\n * repeated re-normalization and stacked timeouts.\n * - Backward compatibility: a lot of components and tests assume ensureConfig removes timeout post-normalization;\n * changing that would be a breaking change.\n */\n delete empty.timeout;\n }\n return empty as CallOptions;\n}\n\n/**\n * Helper function that patches runnable configs with updated properties.\n */\nexport function patchConfig<CallOptions extends RunnableConfig>(\n config: Partial<CallOptions> = {},\n {\n callbacks,\n maxConcurrency,\n recursionLimit,\n runName,\n configurable,\n runId,\n }: RunnableConfig = {}\n): Partial<CallOptions> {\n const newConfig = ensureConfig(config);\n if (callbacks !== undefined) {\n /**\n * If we're replacing callbacks we need to unset runName\n * since that should apply only to the same run as the original callbacks\n */\n delete newConfig.runName;\n newConfig.callbacks = callbacks;\n }\n if (recursionLimit !== undefined) {\n newConfig.recursionLimit = recursionLimit;\n }\n if (maxConcurrency !== undefined) {\n newConfig.maxConcurrency = maxConcurrency;\n }\n if (runName !== undefined) {\n newConfig.runName = runName;\n }\n if (configurable !== undefined) {\n newConfig.configurable = { ...newConfig.configurable, ...configurable };\n }\n if (runId !== undefined) {\n delete newConfig.runId;\n }\n return newConfig;\n}\n\n// oxlint-disable-next-line @typescript-eslint/no-explicit-any\nexport function pickRunnableConfigKeys<CallOptions extends Record<string, any>>(\n config?: CallOptions\n): Partial<RunnableConfig> | undefined {\n if (!config) return undefined;\n\n return {\n configurable: config.configurable,\n recursionLimit: config.recursionLimit,\n callbacks: config.callbacks,\n tags: config.tags,\n metadata: config.metadata,\n maxConcurrency: config.maxConcurrency,\n timeout: config.timeout,\n signal: config.signal,\n // @ts-expect-error - Store is a LangGraph-specific property\n // which wewant to pass through to all runnables.\n // (eg. tools should have access to writing to the store)\n store: config.store,\n };\n}\n"],"mappings":"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"}