{"version":3,"file":"router.cjs","names":["Runnable","ensureConfig"],"sources":["../../src/runnables/router.ts"],"sourcesContent":["import { Runnable, type RunnableBatchOptions } from \"./base.js\";\nimport { IterableReadableStream } from \"../utils/stream.js\";\nimport { ensureConfig, type RunnableConfig } from \"./config.js\";\n\nexport type RouterInput = {\n  key: string;\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  input: any;\n};\n\n/**\n * A runnable that routes to a set of runnables based on Input['key'].\n * Returns the output of the selected runnable.\n * @example\n * ```typescript\n * import { RouterRunnable, RunnableLambda } from \"@langchain/core/runnables\";\n *\n * const router = new RouterRunnable({\n *   runnables: {\n *     toUpperCase: RunnableLambda.from((text: string) => text.toUpperCase()),\n *     reverseText: RunnableLambda.from((text: string) =>\n *       text.split(\"\").reverse().join(\"\")\n *     ),\n *   },\n * });\n *\n * // Invoke the 'reverseText' runnable\n * const result1 = router.invoke({ key: \"reverseText\", input: \"Hello World\" });\n *\n * // \"dlroW olleH\"\n *\n * // Invoke the 'toUpperCase' runnable\n * const result2 = router.invoke({ key: \"toUpperCase\", input: \"Hello World\" });\n *\n * // \"HELLO WORLD\"\n * ```\n */\nexport class RouterRunnable<\n  RunInput extends RouterInput,\n  RunnableInput,\n  RunOutput,\n> extends Runnable<RunInput, RunOutput> {\n  static lc_name() {\n    return \"RouterRunnable\";\n  }\n\n  lc_namespace = [\"langchain_core\", \"runnables\"];\n\n  lc_serializable = true;\n\n  runnables: Record<string, Runnable<RunnableInput, RunOutput>>;\n\n  constructor(fields: {\n    runnables: Record<string, Runnable<RunnableInput, RunOutput>>;\n  }) {\n    super(fields);\n    this.runnables = fields.runnables;\n  }\n\n  async invoke(\n    input: RunInput,\n    options?: Partial<RunnableConfig>\n  ): Promise<RunOutput> {\n    const { key, input: actualInput } = input;\n    const runnable = this.runnables[key];\n    if (runnable === undefined) {\n      throw new Error(`No runnable associated with key \"${key}\".`);\n    }\n    return runnable.invoke(actualInput, ensureConfig(options));\n  }\n\n  async batch(\n    inputs: RunInput[],\n    options?: Partial<RunnableConfig> | Partial<RunnableConfig>[],\n    batchOptions?: RunnableBatchOptions & { returnExceptions?: false }\n  ): Promise<RunOutput[]>;\n\n  async batch(\n    inputs: RunInput[],\n    options?: Partial<RunnableConfig> | Partial<RunnableConfig>[],\n    batchOptions?: RunnableBatchOptions & { returnExceptions: true }\n  ): Promise<(RunOutput | Error)[]>;\n\n  async batch(\n    inputs: RunInput[],\n    options?: Partial<RunnableConfig> | Partial<RunnableConfig>[],\n    batchOptions?: RunnableBatchOptions\n  ): Promise<(RunOutput | Error)[]>;\n\n  async batch(\n    inputs: RunInput[],\n    options?: Partial<RunnableConfig> | Partial<RunnableConfig>[],\n    batchOptions?: RunnableBatchOptions\n  ): Promise<(RunOutput | Error)[]> {\n    const keys = inputs.map((input) => input.key);\n    const actualInputs = inputs.map((input) => input.input);\n    const missingKey = keys.find((key) => this.runnables[key] === undefined);\n    if (missingKey !== undefined) {\n      throw new Error(`One or more keys do not have a corresponding runnable.`);\n    }\n    const runnables = keys.map((key) => this.runnables[key]);\n    const optionsList = this._getOptionsList(options ?? {}, inputs.length);\n    const maxConcurrency =\n      optionsList[0]?.maxConcurrency ?? batchOptions?.maxConcurrency;\n    const batchSize =\n      maxConcurrency && maxConcurrency > 0 ? maxConcurrency : inputs.length;\n    const batchResults = [];\n    for (let i = 0; i < actualInputs.length; i += batchSize) {\n      const batchPromises = actualInputs\n        .slice(i, i + batchSize)\n        .map((actualInput, i) =>\n          runnables[i].invoke(actualInput, optionsList[i])\n        );\n      const batchResult = await Promise.all(batchPromises);\n      batchResults.push(batchResult);\n    }\n    return batchResults.flat();\n  }\n\n  async stream(\n    input: RunInput,\n    options?: Partial<RunnableConfig>\n  ): Promise<IterableReadableStream<RunOutput>> {\n    const { key, input: actualInput } = input;\n    const runnable = this.runnables[key];\n    if (runnable === undefined) {\n      throw new Error(`No runnable associated with key \"${key}\".`);\n    }\n    return runnable.stream(actualInput, options);\n  }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAa,iBAAb,cAIUA,aAAAA,SAA8B;CACtC,OAAO,UAAU;AACf,SAAO;;CAGT,eAAe,CAAC,kBAAkB,YAAY;CAE9C,kBAAkB;CAElB;CAEA,YAAY,QAET;AACD,QAAM,OAAO;AACb,OAAK,YAAY,OAAO;;CAG1B,MAAM,OACJ,OACA,SACoB;EACpB,MAAM,EAAE,KAAK,OAAO,gBAAgB;EACpC,MAAM,WAAW,KAAK,UAAU;AAChC,MAAI,aAAa,KAAA,EACf,OAAM,IAAI,MAAM,oCAAoC,IAAI,IAAI;AAE9D,SAAO,SAAS,OAAO,aAAaC,eAAAA,aAAa,QAAQ,CAAC;;CAqB5D,MAAM,MACJ,QACA,SACA,cACgC;EAChC,MAAM,OAAO,OAAO,KAAK,UAAU,MAAM,IAAI;EAC7C,MAAM,eAAe,OAAO,KAAK,UAAU,MAAM,MAAM;AAEvD,MADmB,KAAK,MAAM,QAAQ,KAAK,UAAU,SAAS,KAAA,EAAU,KACrD,KAAA,EACjB,OAAM,IAAI,MAAM,yDAAyD;EAE3E,MAAM,YAAY,KAAK,KAAK,QAAQ,KAAK,UAAU,KAAK;EACxD,MAAM,cAAc,KAAK,gBAAgB,WAAW,EAAE,EAAE,OAAO,OAAO;EACtE,MAAM,iBACJ,YAAY,IAAI,kBAAkB,cAAc;EAClD,MAAM,YACJ,kBAAkB,iBAAiB,IAAI,iBAAiB,OAAO;EACjE,MAAM,eAAe,EAAE;AACvB,OAAK,IAAI,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK,WAAW;GACvD,MAAM,gBAAgB,aACnB,MAAM,GAAG,IAAI,UAAU,CACvB,KAAK,aAAa,MACjB,UAAU,GAAG,OAAO,aAAa,YAAY,GAAG,CACjD;GACH,MAAM,cAAc,MAAM,QAAQ,IAAI,cAAc;AACpD,gBAAa,KAAK,YAAY;;AAEhC,SAAO,aAAa,MAAM;;CAG5B,MAAM,OACJ,OACA,SAC4C;EAC5C,MAAM,EAAE,KAAK,OAAO,gBAAgB;EACpC,MAAM,WAAW,KAAK,UAAU;AAChC,MAAI,aAAa,KAAA,EACf,OAAM,IAAI,MAAM,oCAAoC,IAAI,IAAI;AAE9D,SAAO,SAAS,OAAO,aAAa,QAAQ"}