{"version":3,"file":"toolEmulator.cjs","names":["initChatModel","createMiddleware","HumanMessage","ToolMessage"],"sources":["../../../src/agents/middleware/toolEmulator.ts"],"sourcesContent":["import { HumanMessage, ToolMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\nimport { initChatModel } from \"../../chat_models/universal.js\";\nimport { createMiddleware } from \"../middleware.js\";\n\n/**\n * Options for configuring the Tool Emulator middleware.\n */\nexport interface ToolEmulatorOptions {\n  /**\n   * List of tool names (string) or tool instances to emulate.\n   * - If `undefined` (default), ALL tools will be emulated.\n   * - If empty array, no tools will be emulated.\n   * - If array with tool names/instances, only those tools will be emulated.\n   */\n  tools?: (string | ClientTool | ServerTool)[];\n\n  /**\n   * Model to use for emulation.\n   * - Can be a model identifier string (e.g., \"anthropic:claude-sonnet-4-5-20250929\")\n   * - Can be a BaseChatModel instance\n   * - Defaults to agent model\n   */\n  model?: string | BaseChatModel;\n}\n\n/**\n * Middleware that emulates specified tools using an LLM instead of executing them.\n *\n * This middleware allows selective emulation of tools for testing purposes.\n * By default (when `tools` is undefined), all tools are emulated. You can specify\n * which tools to emulate by passing a list of tool names or tool instances.\n *\n * @param options - Configuration options for the middleware\n * @param options.tools - List of tool names or tool instances to emulate. If undefined, all tools are emulated.\n * @param options.model - Model to use for emulation. Defaults to \"anthropic:claude-sonnet-4-5-20250929\".\n *\n * @example Emulate all tools (default behavior)\n * ```ts\n * import { toolEmulatorMiddleware } from \"@langchain/langchain/agents/middleware\";\n * import { createAgent } from \"@langchain/langchain/agents\";\n *\n * const middleware = toolEmulatorMiddleware();\n *\n * const agent = createAgent({\n *   model: \"openai:gpt-4o\",\n *   tools: [getWeather, getUserLocation, calculator],\n *   middleware: [middleware],\n * });\n * ```\n *\n * @example Emulate specific tools by name\n * ```ts\n * const middleware = toolEmulatorMiddleware({\n *   tools: [\"get_weather\", \"get_user_location\"]\n * });\n * ```\n *\n * @example Use a custom model for emulation\n * ```ts\n * const middleware = toolEmulatorMiddleware({\n *   tools: [\"get_weather\"],\n *   model: \"anthropic:claude-sonnet-4-5-20250929\"\n * });\n * ```\n *\n * @example Emulate specific tools by passing tool instances\n * ```ts\n * const middleware = toolEmulatorMiddleware({\n *   tools: [getWeather, getUserLocation]\n * });\n * ```\n */\nexport function toolEmulatorMiddleware(options: ToolEmulatorOptions = {}) {\n  let agentModel: BaseChatModel | undefined;\n  const { tools, model } = options;\n\n  /**\n   * Extract tool names from tools\n   */\n  const emulateAll = !tools || tools.length === 0;\n  const toolsToEmulate = new Set<string>();\n\n  if (!emulateAll && tools) {\n    for (const tool of tools) {\n      if (typeof tool === \"string\") {\n        toolsToEmulate.add(tool);\n      } else {\n        // Assume tool instance with .name property\n        const toolName =\n          typeof tool.name === \"string\" ? tool.name : String(tool.name);\n        toolsToEmulate.add(toolName);\n      }\n    }\n  }\n\n  /**\n   * Initialize emulator model\n   * We'll initialize it lazily in wrapToolCall to handle async initChatModel\n   */\n  let emulatorModel: BaseChatModel | undefined;\n  const getEmulatorModel = async (): Promise<BaseChatModel> => {\n    if (typeof model === \"object\") {\n      return model;\n    }\n    if (typeof model === \"string\") {\n      emulatorModel =\n        emulatorModel ??\n        (await initChatModel(model, { temperature: 1 }).catch((err) => {\n          console.error(\n            \"Error initializing emulator model, using agent model:\",\n            err\n          );\n          return agentModel as BaseChatModel;\n        }));\n      return emulatorModel;\n    }\n    return agentModel as BaseChatModel;\n  };\n\n  return createMiddleware({\n    name: \"ToolEmulatorMiddleware\",\n    wrapModelCall: async (request, handler) => {\n      agentModel = request.model as BaseChatModel;\n      return handler(request);\n    },\n    wrapToolCall: async (request, handler) => {\n      const toolName = request.toolCall.name;\n\n      // Check if this tool should be emulated\n      const shouldEmulate = emulateAll || toolsToEmulate.has(toolName);\n\n      if (!shouldEmulate) {\n        // Let it execute normally by calling the handler\n        return handler(request);\n      }\n\n      // Extract tool information for emulation\n      const toolArgs = request.toolCall.args;\n      const toolDescription =\n        request.tool?.description || \"No description available\";\n\n      // Build prompt for emulator LLM\n      const toolArgsString =\n        typeof toolArgs === \"string\" ? toolArgs : JSON.stringify(toolArgs);\n      const prompt = `You are emulating a tool call for testing purposes.\n\nTool: ${toolName}\nDescription: ${toolDescription}\nArguments: ${toolArgsString}\n\nGenerate a realistic response that this tool would return given these arguments.\nReturn ONLY the tool's output, no explanation or preamble. Introduce variation into your responses.`;\n\n      // Get emulated response from LLM\n      const emulator = await getEmulatorModel();\n      const response = await emulator.invoke([new HumanMessage(prompt)]);\n\n      // Extract content from response\n      const content =\n        typeof response.content === \"string\"\n          ? response.content\n          : JSON.stringify(response.content);\n\n      // Short-circuit: return emulated result without executing real tool\n      return new ToolMessage({\n        content,\n        tool_call_id: request.toolCall.id ?? \"\",\n        name: toolName,\n      });\n    },\n  });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0EA,SAAgB,uBAAuB,UAA+B,EAAE,EAAE;CACxE,IAAI;CACJ,MAAM,EAAE,OAAO,UAAU;;;;CAKzB,MAAM,aAAa,CAAC,SAAS,MAAM,WAAW;CAC9C,MAAM,iCAAiB,IAAI,KAAa;AAExC,KAAI,CAAC,cAAc,MACjB,MAAK,MAAM,QAAQ,MACjB,KAAI,OAAO,SAAS,SAClB,gBAAe,IAAI,KAAK;MACnB;EAEL,MAAM,WACJ,OAAO,KAAK,SAAS,WAAW,KAAK,OAAO,OAAO,KAAK,KAAK;AAC/D,iBAAe,IAAI,SAAS;;;;;;CASlC,IAAI;CACJ,MAAM,mBAAmB,YAAoC;AAC3D,MAAI,OAAO,UAAU,SACnB,QAAO;AAET,MAAI,OAAO,UAAU,UAAU;AAC7B,mBACE,iBACC,MAAMA,8BAAAA,cAAc,OAAO,EAAE,aAAa,GAAG,CAAC,CAAC,OAAO,QAAQ;AAC7D,YAAQ,MACN,yDACA,IACD;AACD,WAAO;KACP;AACJ,UAAO;;AAET,SAAO;;AAGT,QAAOC,mBAAAA,iBAAiB;EACtB,MAAM;EACN,eAAe,OAAO,SAAS,YAAY;AACzC,gBAAa,QAAQ;AACrB,UAAO,QAAQ,QAAQ;;EAEzB,cAAc,OAAO,SAAS,YAAY;GACxC,MAAM,WAAW,QAAQ,SAAS;AAKlC,OAAI,EAFkB,cAAc,eAAe,IAAI,SAAS,EAI9D,QAAO,QAAQ,QAAQ;GAIzB,MAAM,WAAW,QAAQ,SAAS;GAOlC,MAAM,SAAS;;QAEb,SAAS;eAPT,QAAQ,MAAM,eAAe,2BAQN;aAJvB,OAAO,aAAa,WAAW,WAAW,KAAK,UAAU,SAAS,CAK9C;;;;GAOtB,MAAM,WAAW,OADA,MAAM,kBAAkB,EACT,OAAO,CAAC,IAAIC,yBAAAA,aAAa,OAAO,CAAC,CAAC;AASlE,UAAO,IAAIC,yBAAAA,YAAY;IACrB,SANA,OAAO,SAAS,YAAY,WACxB,SAAS,UACT,KAAK,UAAU,SAAS,QAAQ;IAKpC,cAAc,QAAQ,SAAS,MAAM;IACrC,MAAM;IACP,CAAC;;EAEL,CAAC"}