{"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\nexport async function getCallbackManagerForConfig(config?: RunnableConfig) {\n  return CallbackManager._configureSync(\n    config?.callbacks,\n    undefined,\n    config?.tags,\n    undefined,\n    config?.metadata\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\nconst PRIMITIVES = new Set([\"string\", \"number\", \"boolean\"]);\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    for (const key of Object.keys(empty.configurable)) {\n      if (\n        PRIMITIVES.has(typeof empty.configurable[key]) &&\n        !empty.metadata?.[key]\n      ) {\n        if (!empty.metadata) {\n          empty.metadata = {};\n        }\n        empty.metadata[key] = empty.configurable[key];\n      }\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":";;;;AAQA,eAAsB,4BAA4B,QAAyB;AACzE,QAAOA,0BAAAA,gBAAgB,eACrB,QAAQ,WACR,KAAA,GACA,QAAQ,MACR,KAAA,GACA,QAAQ,SACT;;AAGH,SAAgB,aACd,GAAG,SACmB;CAGtB,MAAM,OAA6B,EAAE;AACrC,MAAK,MAAM,WAAW,QAAQ,QAAQ,MAAwB,CAAC,CAAC,EAAE,CAChE,MAAK,MAAM,OAAO,OAAO,KAAK,QAAQ,CACpC,KAAI,QAAQ,WACV,MAAK,OAAO;EAAE,GAAG,KAAK;EAAM,GAAG,QAAQ;EAAM;UACpC,QAAQ,QAAQ;EACzB,MAAM,WAAqB,KAAK,QAAQ,EAAE;AAC1C,OAAK,OAAO,CAAC,GAAG,IAAI,IAAI,SAAS,OAAO,QAAQ,QAAQ,EAAE,CAAC,CAAC,CAAC;YACpD,QAAQ,eACjB,MAAK,OAAO;EAAE,GAAG,KAAK;EAAM,GAAG,QAAQ;EAAM;UACpC,QAAQ;MACb,KAAK,YAAY,KAAA,EACnB,MAAK,UAAU,QAAQ;WACd,QAAQ,YAAY,KAAA,EAC7B,MAAK,UAAU,KAAK,IAAI,KAAK,SAAS,QAAQ,QAAQ;YAE/C,QAAQ;MACb,KAAK,WAAW,KAAA,EAClB,MAAK,SAAS,QAAQ;WACb,QAAQ,WAAW,KAAA,EAC5B,KAAI,SAAS,YAEX,MAAK,SAAU,YAAoB,IAAI,CACrC,KAAK,QACL,QAAQ,OACT,CAAC;MAEF,MAAK,SAAS,QAAQ;YAGjB,QAAQ,aAAa;EAC9B,MAAM,gBAAgB,KAAK;EAC3B,MAAM,oBAAoB,QAAQ;AAGlC,MAAI,MAAM,QAAQ,kBAAkB,CAClC,KAAI,CAAC,cACH,MAAK,YAAY;WACR,MAAM,QAAQ,cAAc,CACrC,MAAK,YAAY,cAAc,OAAO,kBAAkB;OACnD;GAEL,MAAM,UAAU,cAAc,MAAM;AACpC,QAAK,MAAM,YAAY,kBACrB,SAAQ,WAAWC,0BAAAA,cAAc,SAAS,EAAE,KAAK;AAEnD,QAAK,YAAY;;WAEV,kBAET,KAAI,CAAC,cACH,MAAK,YAAY;WACR,MAAM,QAAQ,cAAc,EAAE;GACvC,MAAM,UAAU,kBAAkB,MAAM;AACxC,QAAK,MAAM,YAAY,cACrB,SAAQ,WAAWA,0BAAAA,cAAc,SAAS,EAAE,KAAK;AAEnD,QAAK,YAAY;QAGjB,MAAK,YAAY,IAAID,0BAAAA,gBACnB,kBAAkB,cAClB;GACE,UAAU,cAAc,SAAS,OAC/B,kBAAkB,SACnB;GACD,qBAAqB,cAAc,oBAAoB,OACrD,kBAAkB,oBACnB;GACD,MAAM,MAAM,KACV,IAAI,IAAI,cAAc,KAAK,OAAO,kBAAkB,KAAK,CAAC,CAC3D;GACD,iBAAiB,MAAM,KACrB,IAAI,IACF,cAAc,gBAAgB,OAC5B,kBAAkB,gBACnB,CACF,CACF;GACD,UAAU;IACR,GAAG,cAAc;IACjB,GAAG,kBAAkB;IACtB;GACF,CACF;QAGA;EACL,MAAM,WAAW;AACjB,OAAK,YAAY,QAAQ,aAAa,KAAK;;AAIjD,QAAO;;AAGT,MAAM,aAAa,IAAI,IAAI;CAAC;CAAU;CAAU;CAAU,CAAC;;;;AAK3D,SAAgB,aACd,QACa;CACb,MAAM,iBAAiBE,cAAAA,mCAAmC,mBAAmB;CAC7E,IAAI,QAAwB;EAC1B,MAAM,EAAE;EACR,UAAU,EAAE;EACZ,gBAAgB;EAChB,OAAO,KAAA;EACR;AACD,KAAI,gBAAgB;EAGlB,MAAM,EAAE,OAAO,SAAS,GAAG,SAAS;AACpC,UAAQ,OAAO,QAAQ,KAAK,CAAC,QAE1B,eAAoC,CAAC,KAAK,WAAW;AACpD,OAAI,UAAU,KAAA,EACZ,eAAc,OAAO;AAEvB,UAAO;KAET,MACD;;AAEH,KAAI,OACF,SAAQ,OAAO,QAAQ,OAAO,CAAC,QAE5B,eAAoC,CAAC,KAAK,WAAW;AACpD,MAAI,UAAU,KAAA,EACZ,eAAc,OAAO;AAEvB,SAAO;IAET,MACD;AAEH,KAAI,OAAO;OACJ,MAAM,OAAO,OAAO,KAAK,MAAM,aAAa,CAC/C,KACE,WAAW,IAAI,OAAO,MAAM,aAAa,KAAK,IAC9C,CAAC,MAAM,WAAW,MAClB;AACA,OAAI,CAAC,MAAM,SACT,OAAM,WAAW,EAAE;AAErB,SAAM,SAAS,OAAO,MAAM,aAAa;;;AAI/C,KAAI,MAAM,YAAY,KAAA,GAAW;AAC/B,MAAI,MAAM,WAAW,EACnB,OAAM,IAAI,MAAM,oCAAoC;EAEtD,MAAM,oBAAoB,MAAM;EAChC,MAAM,gBAAgB,YAAY,QAAQ,kBAAkB;AAI5D,MAAI,CAAC,MAAM,SACT,OAAM,WAAW,EAAE;AAGrB,MAAI,MAAM,SAAS,cAAc,KAAA,EAC/B,OAAM,SAAS,YAAY;AAE7B,MAAI,MAAM,WAAW,KAAA;OACf,SAAS,YAEX,OAAM,SAAU,YAAoB,IAAI,CAAC,MAAM,QAAQ,cAAc,CAAC;QAGxE,OAAM,SAAS;;;;;;;;;;;;AAcjB,SAAO,MAAM;;AAEf,QAAO;;;;;AAMT,SAAgB,YACd,SAA+B,EAAE,EACjC,EACE,WACA,gBACA,gBACA,SACA,cACA,UACkB,EAAE,EACA;CACtB,MAAM,YAAY,aAAa,OAAO;AACtC,KAAI,cAAc,KAAA,GAAW;;;;;AAK3B,SAAO,UAAU;AACjB,YAAU,YAAY;;AAExB,KAAI,mBAAmB,KAAA,EACrB,WAAU,iBAAiB;AAE7B,KAAI,mBAAmB,KAAA,EACrB,WAAU,iBAAiB;AAE7B,KAAI,YAAY,KAAA,EACd,WAAU,UAAU;AAEtB,KAAI,iBAAiB,KAAA,EACnB,WAAU,eAAe;EAAE,GAAG,UAAU;EAAc,GAAG;EAAc;AAEzE,KAAI,UAAU,KAAA,EACZ,QAAO,UAAU;AAEnB,QAAO;;AAIT,SAAgB,uBACd,QACqC;AACrC,KAAI,CAAC,OAAQ,QAAO,KAAA;AAEpB,QAAO;EACL,cAAc,OAAO;EACrB,gBAAgB,OAAO;EACvB,WAAW,OAAO;EAClB,MAAM,OAAO;EACb,UAAU,OAAO;EACjB,gBAAgB,OAAO;EACvB,SAAS,OAAO;EAChB,QAAQ,OAAO;EAIf,OAAO,OAAO;EACf"}