{"version":3,"file":"handoff.cjs","names":["ToolMessage","Command","z"],"sources":["../src/handoff.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { ToolMessage } from \"@langchain/core/messages\";\nimport {\n  DynamicTool,\n  StructuredToolInterface,\n  tool,\n} from \"@langchain/core/tools\";\nimport { RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n  AnnotationRoot,\n  MessagesAnnotation,\n  Command,\n  CompiledStateGraph,\n  getCurrentTaskInput,\n} from \"@langchain/langgraph\";\nimport { ToolNode } from \"@langchain/langgraph/prebuilt\";\n\nconst WHITESPACE_RE = /\\s+/g;\nconst METADATA_KEY_HANDOFF_DESTINATION = \"__handoff_destination\";\n\nfunction _normalizeAgentName(agentName: string): string {\n  /**\n   * Normalize an agent name to be used inside the tool name.\n   */\n  return agentName.trim().replace(WHITESPACE_RE, \"_\").toLowerCase();\n}\n\n/** @inline */\ninterface CreateHandoffToolParams {\n  /**\n   * The name of the agent to handoff control to, i.e. the name of the agent node in the multi-agent graph.\n   *\n   * Agent names should be simple, clear and unique, preferably in snake_case,\n   * although you are only limited to the names accepted by LangGraph\n   * nodes as well as the tool names accepted by LLM providers\n   * (the tool name will look like this: `transfer_to_<agent_name>`).\n   */\n  agentName: string;\n\n  /** Optional description for the handoff tool. */\n  description?: string;\n}\n\n// type guard\nfunction isDynamicTool(\n  tool: StructuredToolInterface | DynamicTool | RunnableToolLike\n): tool is DynamicTool {\n  return (\n    \"schema\" in tool &&\n    \"name\" in tool &&\n    \"description\" in tool &&\n    \"responseFormat\" in tool\n  );\n}\n\n/**\n * Create a tool that can handoff control to the requested agent.\n *\n * @param params Parameters for the handoff tool.\n */\nconst createHandoffTool = ({\n  agentName,\n  description,\n}: CreateHandoffToolParams) => {\n  const toolName = `transfer_to_${_normalizeAgentName(agentName)}`;\n  const toolDescription = description || `Ask agent '${agentName}' for help`;\n\n  const handoffTool = tool(\n    async (_, config) => {\n      /**\n       * Ask another agent for help.\n       */\n      const toolMessage = new ToolMessage({\n        content: `Successfully transferred to ${agentName}`,\n        name: toolName,\n        tool_call_id: config.toolCall.id,\n      });\n\n      // inject the current agent state\n      const state =\n        getCurrentTaskInput() as (typeof MessagesAnnotation)[\"State\"];\n      return new Command({\n        goto: agentName,\n        graph: Command.PARENT,\n        update: {\n          messages: state.messages.concat(toolMessage),\n          activeAgent: agentName,\n        },\n      });\n    },\n    {\n      name: toolName,\n      schema: z.object({}),\n      description: toolDescription,\n    }\n  );\n\n  handoffTool.metadata = { [METADATA_KEY_HANDOFF_DESTINATION]: agentName };\n  return handoffTool;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst getHandoffDestinations = <AnnotationRootT extends AnnotationRoot<any>>(\n  agent: CompiledStateGraph<\n    AnnotationRootT[\"State\"],\n    AnnotationRootT[\"Update\"],\n    string,\n    AnnotationRootT[\"spec\"],\n    AnnotationRootT[\"spec\"]\n  >,\n  toolNodeName: string = \"tools\"\n): string[] => {\n  /**\n   * Get a list of destinations from agent's handoff tools.\n   *\n   * @param agent - The compiled state graph\n   * @param toolNodeName - The name of the tool node in the graph\n   */\n  const { nodes } = agent.getGraph();\n  if (!(toolNodeName in nodes)) {\n    return [];\n  }\n\n  const toolNode = nodes[toolNodeName].data;\n  if (!toolNode || !(\"tools\" in toolNode) || !toolNode.tools) {\n    return [];\n  }\n\n  const { tools } = toolNode as ToolNode;\n  return tools\n    .filter(\n      (tool): tool is DynamicTool =>\n        isDynamicTool(tool) &&\n        tool.metadata !== undefined &&\n        METADATA_KEY_HANDOFF_DESTINATION in tool.metadata\n    )\n    .map((tool) => tool.metadata![METADATA_KEY_HANDOFF_DESTINATION] as string);\n};\n\nexport {\n  createHandoffTool,\n  getHandoffDestinations,\n  METADATA_KEY_HANDOFF_DESTINATION,\n};\n"],"mappings":";;;;;AAiBA,MAAM,gBAAgB;AACtB,MAAM,mCAAmC;AAEzC,SAAS,oBAAoB,WAA2B;;;;AAItD,QAAO,UAAU,MAAM,CAAC,QAAQ,eAAe,IAAI,CAAC,aAAa;;AAoBnE,SAAS,cACP,MACqB;AACrB,QACE,YAAY,QACZ,UAAU,QACV,iBAAiB,QACjB,oBAAoB;;;;;;;AASxB,MAAM,qBAAqB,EACzB,WACA,kBAC6B;CAC7B,MAAM,WAAW,eAAe,oBAAoB,UAAU;CAC9D,MAAM,kBAAkB,eAAe,cAAc,UAAU;CAE/D,MAAM,eAAA,GAAA,sBAAA,MACJ,OAAO,GAAG,WAAW;;;;EAInB,MAAM,cAAc,IAAIA,yBAAAA,YAAY;GAClC,SAAS,+BAA+B;GACxC,MAAM;GACN,cAAc,OAAO,SAAS;GAC/B,CAAC;EAGF,MAAM,SAAA,GAAA,qBAAA,sBACiB;AACvB,SAAO,IAAIC,qBAAAA,QAAQ;GACjB,MAAM;GACN,OAAOA,qBAAAA,QAAQ;GACf,QAAQ;IACN,UAAU,MAAM,SAAS,OAAO,YAAY;IAC5C,aAAa;IACd;GACF,CAAC;IAEJ;EACE,MAAM;EACN,QAAQC,IAAAA,EAAE,OAAO,EAAE,CAAC;EACpB,aAAa;EACd,CACF;AAED,aAAY,WAAW,GAAG,mCAAmC,WAAW;AACxE,QAAO;;AAIT,MAAM,0BACJ,OAOA,eAAuB,YACV;;;;;;;CAOb,MAAM,EAAE,UAAU,MAAM,UAAU;AAClC,KAAI,EAAE,gBAAgB,OACpB,QAAO,EAAE;CAGX,MAAM,WAAW,MAAM,cAAc;AACrC,KAAI,CAAC,YAAY,EAAE,WAAW,aAAa,CAAC,SAAS,MACnD,QAAO,EAAE;CAGX,MAAM,EAAE,UAAU;AAClB,QAAO,MACJ,QACE,SACC,cAAc,KAAK,IACnB,KAAK,aAAa,KAAA,KAAA,2BACkB,KAAK,SAC5C,CACA,KAAK,SAAS,KAAK,SAAU,kCAA4C"}