{"version":3,"file":"chat_agent_executor.cjs","names":["ToolExecutor","FunctionMessage","StateGraph","RunnableLambda","START","END"],"sources":["../../src/prebuilt/chat_agent_executor.ts"],"sourcesContent":["import { StructuredToolInterface } from \"@langchain/core/tools\";\nimport { convertToOpenAIFunction } from \"@langchain/core/utils/function_calling\";\nimport { AgentAction } from \"@langchain/core/agents\";\nimport { FunctionMessage, BaseMessage } from \"@langchain/core/messages\";\nimport {\n  type RunnableConfig,\n  RunnableLambda,\n  RunnableToolLike,\n} from \"@langchain/core/runnables\";\nimport { ToolExecutor } from \"./tool_executor.js\";\nimport {\n  CompiledStateGraph,\n  StateGraph,\n  StateGraphArgs,\n} from \"../graph/state.js\";\nimport { END, START } from \"../constants.js\";\n\n/** @deprecated Use {@link createReactAgent} instead with tool calling. */\nexport type FunctionCallingExecutorState = { messages: Array<BaseMessage> };\n\n/** @deprecated Use {@link createReactAgent} instead with tool calling. */\nexport function createFunctionCallingExecutor<Model extends object>({\n  model,\n  tools,\n}: {\n  model: Model;\n  tools: Array<StructuredToolInterface | RunnableToolLike> | ToolExecutor;\n}): CompiledStateGraph<\n  FunctionCallingExecutorState,\n  Partial<FunctionCallingExecutorState>,\n  typeof START | \"agent\" | \"action\"\n> {\n  let toolExecutor: ToolExecutor;\n  let toolClasses: Array<StructuredToolInterface | RunnableToolLike>;\n  if (!Array.isArray(tools)) {\n    toolExecutor = tools;\n    toolClasses = tools.tools;\n  } else {\n    toolExecutor = new ToolExecutor({\n      tools,\n    });\n    toolClasses = tools;\n  }\n\n  if (!(\"bind\" in model) || typeof model.bind !== \"function\") {\n    throw new Error(\"Model must be bindable\");\n  }\n  const toolsAsOpenAIFunctions = toolClasses.map((tool) =>\n    convertToOpenAIFunction(tool)\n  );\n  const newModel = model.bind({\n    functions: toolsAsOpenAIFunctions,\n  });\n\n  // Define the function that determines whether to continue or not\n  const shouldContinue = (state: FunctionCallingExecutorState) => {\n    const { messages } = state;\n    const lastMessage = messages[messages.length - 1];\n    // If there is no function call, then we finish\n    if (\n      !(\"function_call\" in lastMessage.additional_kwargs) ||\n      !lastMessage.additional_kwargs.function_call\n    ) {\n      return \"end\";\n    }\n    // Otherwise if there is, we continue\n    return \"continue\";\n  };\n\n  // Define the function that calls the model\n  const callModel = async (\n    state: FunctionCallingExecutorState,\n    config?: RunnableConfig\n  ) => {\n    const { messages } = state;\n    const response = await newModel.invoke(messages, config);\n    // We return a list, because this will get added to the existing list\n    return {\n      messages: [response],\n    };\n  };\n\n  // Define the function to execute tools\n  const _getAction = (state: FunctionCallingExecutorState): AgentAction => {\n    const { messages } = state;\n    // Based on the continue condition\n    // we know the last message involves a function call\n    const lastMessage = messages[messages.length - 1];\n    if (!lastMessage) {\n      throw new Error(\"No messages found.\");\n    }\n    if (!lastMessage.additional_kwargs.function_call) {\n      throw new Error(\"No function call found in message.\");\n    }\n    // We construct an AgentAction from the function_call\n    return {\n      tool: lastMessage.additional_kwargs.function_call.name,\n      toolInput: JSON.stringify(\n        lastMessage.additional_kwargs.function_call.arguments\n      ),\n      log: \"\",\n    };\n  };\n\n  const callTool = async (\n    state: FunctionCallingExecutorState,\n    config?: RunnableConfig\n  ) => {\n    const action = _getAction(state);\n    // We call the tool_executor and get back a response\n    const response = await toolExecutor.invoke(action, config);\n    // We use the response to create a FunctionMessage\n    const functionMessage = new FunctionMessage({\n      content: response,\n      name: action.tool,\n    });\n    // We return a list, because this will get added to the existing list\n    return { messages: [functionMessage] };\n  };\n\n  // We create the AgentState that we will pass around\n  // This simply involves a list of messages\n  // We want steps to return messages to append to the list\n  // So we annotate the messages attribute with operator.add\n  const schema: StateGraphArgs<FunctionCallingExecutorState>[\"channels\"] = {\n    messages: {\n      value: (x: BaseMessage[], y: BaseMessage[]) => x.concat(y),\n      default: () => [],\n    },\n  };\n\n  // Define a new graph\n  const workflow = new StateGraph<FunctionCallingExecutorState>({\n    channels: schema,\n  })\n    // Define the two nodes we will cycle between\n    .addNode(\"agent\", new RunnableLambda({ func: callModel }))\n    .addNode(\"action\", new RunnableLambda({ func: callTool }))\n    // Set the entrypoint as `agent`\n    // This means that this node is the first one called\n    .addEdge(START, \"agent\")\n    // We now add a conditional edge\n    .addConditionalEdges(\n      // First, we define the start node. We use `agent`.\n      // This means these are the edges taken after the `agent` node is called.\n      \"agent\",\n      // Next, we pass in the function that will determine which node is called next.\n      shouldContinue,\n      // Finally we pass in a mapping.\n      // The keys are strings, and the values are other nodes.\n      // END is a special node marking that the graph should finish.\n      // What will happen is we will call `should_continue`, and then the output of that\n      // will be matched against the keys in this mapping.\n      // Based on which one it matches, that node will then be called.\n      {\n        // If `tools`, then we call the tool node.\n        continue: \"action\",\n        // Otherwise we finish.\n        end: END,\n      }\n    )\n    // We now add a normal edge from `tools` to `agent`.\n    // This means that after `tools` is called, `agent` node is called next.\n    .addEdge(\"action\", \"agent\");\n\n  // Finally, we compile it!\n  // This compiles it into a LangChain Runnable,\n  // meaning you can use it as you would any other runnable\n  return workflow.compile();\n}\n"],"mappings":";;;;;;;;AAqBA,SAAgB,8BAAoD,EAClE,OACA,SAQA;CACA,IAAI;CACJ,IAAI;AACJ,KAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;AACzB,iBAAe;AACf,gBAAc,MAAM;QACf;AACL,iBAAe,IAAIA,sBAAAA,aAAa,EAC9B,OACD,CAAC;AACF,gBAAc;;AAGhB,KAAI,EAAE,UAAU,UAAU,OAAO,MAAM,SAAS,WAC9C,OAAM,IAAI,MAAM,yBAAyB;CAE3C,MAAM,yBAAyB,YAAY,KAAK,UAAA,GAAA,uCAAA,yBACtB,KAAK,CAC9B;CACD,MAAM,WAAW,MAAM,KAAK,EAC1B,WAAW,wBACZ,CAAC;CAGF,MAAM,kBAAkB,UAAwC;EAC9D,MAAM,EAAE,aAAa;EACrB,MAAM,cAAc,SAAS,SAAS,SAAS;AAE/C,MACE,EAAE,mBAAmB,YAAY,sBACjC,CAAC,YAAY,kBAAkB,cAE/B,QAAO;AAGT,SAAO;;CAIT,MAAM,YAAY,OAChB,OACA,WACG;EACH,MAAM,EAAE,aAAa;AAGrB,SAAO,EACL,UAAU,CAHK,MAAM,SAAS,OAAO,UAAU,OAAO,CAGlC,EACrB;;CAIH,MAAM,cAAc,UAAqD;EACvE,MAAM,EAAE,aAAa;EAGrB,MAAM,cAAc,SAAS,SAAS,SAAS;AAC/C,MAAI,CAAC,YACH,OAAM,IAAI,MAAM,qBAAqB;AAEvC,MAAI,CAAC,YAAY,kBAAkB,cACjC,OAAM,IAAI,MAAM,qCAAqC;AAGvD,SAAO;GACL,MAAM,YAAY,kBAAkB,cAAc;GAClD,WAAW,KAAK,UACd,YAAY,kBAAkB,cAAc,UAC7C;GACD,KAAK;GACN;;CAGH,MAAM,WAAW,OACf,OACA,WACG;EACH,MAAM,SAAS,WAAW,MAAM;AAShC,SAAO,EAAE,UAAU,CALK,IAAIC,yBAAAA,gBAAgB;GAC1C,SAHe,MAAM,aAAa,OAAO,QAAQ,OAAO;GAIxD,MAAM,OAAO;GACd,CAAC,CAEkC,EAAE;;AAmDxC,QApCiB,IAAIC,cAAAA,WAAyC,EAC5D,UATuE,EACvE,UAAU;EACR,QAAQ,GAAkB,MAAqB,EAAE,OAAO,EAAE;EAC1D,eAAe,EAAE;EAClB,EACF,EAKA,CAAC,CAEC,QAAQ,SAAS,IAAIC,0BAAAA,eAAe,EAAE,MAAM,WAAW,CAAC,CAAC,CACzD,QAAQ,UAAU,IAAIA,0BAAAA,eAAe,EAAE,MAAM,UAAU,CAAC,CAAC,CAGzD,QAAQC,kBAAAA,OAAO,QAAQ,CAEvB,oBAGC,SAEA,gBAOA;EAEE,UAAU;EAEV,KAAKC,kBAAAA;EACN,CACF,CAGA,QAAQ,UAAU,QAAQ,CAKb,SAAS"}