{"version":3,"file":"tools.cjs","names":[],"sources":["../../src/utils/tools.ts"],"sourcesContent":["import { OpenAI as OpenAIClient } from \"openai\";\n\nimport { ToolDefinition } from \"@langchain/core/language_models/base\";\nimport { BindToolsInput } from \"@langchain/core/language_models/chat_models\";\nimport {\n  convertToOpenAITool as formatToOpenAITool,\n  isLangChainTool,\n} from \"@langchain/core/utils/function_calling\";\nimport { DynamicTool, StructuredToolInterface } from \"@langchain/core/tools\";\nimport { isInteropZodSchema } from \"@langchain/core/utils/types\";\nimport { toJsonSchema } from \"@langchain/core/utils/json_schema\";\nimport { ToolCall } from \"@langchain/core/messages/tool\";\n\n/**\n * Formats a tool in either OpenAI format, or LangChain structured tool format\n * into an OpenAI tool format. If the tool is already in OpenAI format, return without\n * any changes. If it is in LangChain structured tool format, convert it to OpenAI tool format\n * using OpenAI's `zodFunction` util, falling back to `convertToOpenAIFunction` if the parameters\n * returned from the `zodFunction` util are not defined.\n *\n * @param {BindToolsInput} tool The tool to convert to an OpenAI tool.\n * @param {Object} [fields] Additional fields to add to the OpenAI tool.\n * @returns {ToolDefinition} The inputted tool in OpenAI tool format.\n */\nexport function _convertToOpenAITool(\n  tool: BindToolsInput,\n  fields?: {\n    /**\n     * If `true`, model output is guaranteed to exactly match the JSON Schema\n     * provided in the function definition.\n     */\n    strict?: boolean;\n  }\n): OpenAIClient.Chat.Completions.ChatCompletionFunctionTool {\n  let toolDef: OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n\n  if (isLangChainTool(tool)) {\n    toolDef = formatToOpenAITool(\n      tool\n    ) as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n  } else {\n    toolDef = tool as OpenAIClient.Chat.Completions.ChatCompletionFunctionTool;\n  }\n\n  if (fields?.strict !== undefined) {\n    toolDef.function.strict = fields.strict;\n  }\n\n  return toolDef;\n}\n\ntype OpenAIFunction = OpenAIClient.Chat.ChatCompletionCreateParams.Function;\n\n// Types representing the OpenAI function definitions. While the OpenAI client library\n// does have types for function definitions, the properties are just Record<string, unknown>,\n// which isn't very useful for type checking this formatting code.\nexport interface FunctionDef extends Omit<OpenAIFunction, \"parameters\"> {\n  name: string;\n  description?: string;\n  parameters: ObjectProp;\n}\n\ninterface ObjectProp {\n  type: \"object\";\n  properties?: {\n    [key: string]: Prop;\n  };\n  required?: string[];\n}\n\ninterface AnyOfProp {\n  anyOf: Prop[];\n}\n\ntype Prop = {\n  description?: string;\n} & (\n  | AnyOfProp\n  | ObjectProp\n  | {\n      type: \"string\";\n      enum?: string[];\n    }\n  | {\n      type: \"number\" | \"integer\";\n      minimum?: number;\n      maximum?: number;\n      enum?: number[];\n    }\n  | { type: \"boolean\" }\n  | { type: \"null\" }\n  | {\n      type: \"array\";\n      items?: Prop;\n    }\n);\n\nfunction isAnyOfProp(prop: Prop): prop is AnyOfProp {\n  return (\n    (prop as AnyOfProp).anyOf !== undefined &&\n    Array.isArray((prop as AnyOfProp).anyOf)\n  );\n}\n\n// When OpenAI use functions in the prompt, they format them as TypeScript definitions rather than OpenAPI JSON schemas.\n// This function converts the JSON schemas into TypeScript definitions.\nexport function formatFunctionDefinitions(functions: FunctionDef[]) {\n  const lines = [\"namespace functions {\", \"\"];\n  for (const f of functions) {\n    if (f.description) {\n      lines.push(`// ${f.description}`);\n    }\n    if (Object.keys(f.parameters.properties ?? {}).length > 0) {\n      lines.push(`type ${f.name} = (_: {`);\n      lines.push(formatObjectProperties(f.parameters, 0));\n      lines.push(\"}) => any;\");\n    } else {\n      lines.push(`type ${f.name} = () => any;`);\n    }\n    lines.push(\"\");\n  }\n  lines.push(\"} // namespace functions\");\n  return lines.join(\"\\n\");\n}\n\n// Format just the properties of an object (not including the surrounding braces)\nfunction formatObjectProperties(obj: ObjectProp, indent: number): string {\n  const lines: string[] = [];\n  for (const [name, param] of Object.entries(obj.properties ?? {})) {\n    if (param.description && indent < 2) {\n      lines.push(`// ${param.description}`);\n    }\n    if (obj.required?.includes(name)) {\n      lines.push(`${name}: ${formatType(param, indent)},`);\n    } else {\n      lines.push(`${name}?: ${formatType(param, indent)},`);\n    }\n  }\n  return lines.map((line) => \" \".repeat(indent) + line).join(\"\\n\");\n}\n\n// Format a single property type\nfunction formatType(param: Prop, indent: number): string {\n  if (isAnyOfProp(param)) {\n    return param.anyOf.map((v) => formatType(v, indent)).join(\" | \");\n  }\n  switch (param.type) {\n    case \"string\":\n      if (param.enum) {\n        return param.enum.map((v) => `\"${v}\"`).join(\" | \");\n      }\n      return \"string\";\n    case \"number\":\n      if (param.enum) {\n        return param.enum.map((v) => `${v}`).join(\" | \");\n      }\n      return \"number\";\n    case \"integer\":\n      if (param.enum) {\n        return param.enum.map((v) => `${v}`).join(\" | \");\n      }\n      return \"number\";\n    case \"boolean\":\n      return \"boolean\";\n    case \"null\":\n      return \"null\";\n    case \"object\":\n      return [\"{\", formatObjectProperties(param, indent + 2), \"}\"].join(\"\\n\");\n    case \"array\":\n      if (param.items) {\n        return `${formatType(param.items, indent)}[]`;\n      }\n      return \"any[]\";\n    default:\n      return \"\";\n  }\n}\n\nexport function formatToOpenAIAssistantTool(\n  tool: StructuredToolInterface\n): ToolDefinition {\n  return {\n    type: \"function\",\n    function: {\n      name: tool.name,\n      description: tool.description,\n      parameters: isInteropZodSchema(tool.schema)\n        ? toJsonSchema(tool.schema)\n        : tool.schema,\n    },\n  };\n}\n\nexport type OpenAIToolChoice =\n  | OpenAIClient.ChatCompletionToolChoiceOption\n  | \"any\"\n  | string;\n\nexport type ResponsesToolChoice = NonNullable<\n  OpenAIClient.Responses.ResponseCreateParams[\"tool_choice\"]\n>;\n\nexport type ChatOpenAIToolType =\n  | BindToolsInput\n  | OpenAIClient.Chat.ChatCompletionTool\n  | ResponsesTool;\n\nexport type ResponsesTool = NonNullable<\n  OpenAIClient.Responses.ResponseCreateParams[\"tools\"]\n>[number];\n\nexport function formatToOpenAIToolChoice(\n  toolChoice?: OpenAIToolChoice\n): OpenAIClient.ChatCompletionToolChoiceOption | undefined {\n  if (!toolChoice) {\n    return undefined;\n  } else if (toolChoice === \"any\" || toolChoice === \"required\") {\n    return \"required\";\n  } else if (toolChoice === \"auto\") {\n    return \"auto\";\n  } else if (toolChoice === \"none\") {\n    return \"none\";\n  } else if (typeof toolChoice === \"string\") {\n    return {\n      type: \"function\",\n      function: {\n        name: toolChoice,\n      },\n    };\n  } else {\n    return toolChoice;\n  }\n}\n\nexport function isBuiltInTool(tool: ChatOpenAIToolType): tool is ResponsesTool {\n  return \"type\" in tool && tool.type !== \"function\";\n}\n\n/**\n * Type for LangChain tools that have a provider-specific tool definition\n * stored in extras.providerToolDefinition.\n */\ntype LangchainToolWithProviderDefinition = StructuredToolInterface & {\n  extras: {\n    providerToolDefinition: ResponsesTool;\n  };\n};\n\n/**\n * Checks if a tool has a provider-specific tool definition in extras.providerToolDefinition.\n * This is used for tools like localShell, shell, computerUse, and applyPatch\n * that need to be sent as built-in tool types to the OpenAI API.\n */\nexport function hasProviderToolDefinition(\n  tool: unknown\n): tool is LangchainToolWithProviderDefinition {\n  return (\n    typeof tool === \"object\" &&\n    tool !== null &&\n    \"extras\" in tool &&\n    typeof (tool as LangchainToolWithProviderDefinition).extras === \"object\" &&\n    (tool as LangchainToolWithProviderDefinition).extras !== null &&\n    \"providerToolDefinition\" in\n      (tool as LangchainToolWithProviderDefinition).extras &&\n    typeof (tool as LangchainToolWithProviderDefinition).extras\n      .providerToolDefinition === \"object\" &&\n    (tool as LangchainToolWithProviderDefinition).extras\n      .providerToolDefinition !== null\n  );\n}\n\nexport function isBuiltInToolChoice(\n  tool_choice: OpenAIToolChoice | ResponsesToolChoice | undefined\n): tool_choice is ResponsesToolChoice {\n  return (\n    tool_choice != null &&\n    typeof tool_choice === \"object\" &&\n    \"type\" in tool_choice &&\n    tool_choice.type !== \"function\"\n  );\n}\n\nexport type CustomToolCall = ToolCall & {\n  call_id: string;\n  isCustomTool: true;\n};\n\ntype LangchainCustomTool = DynamicTool<string> & {\n  metadata: {\n    customTool: OpenAIClient.Responses.CustomTool;\n  };\n};\n\nexport function isCustomTool(tool: unknown): tool is LangchainCustomTool {\n  return (\n    typeof tool === \"object\" &&\n    tool !== null &&\n    \"metadata\" in tool &&\n    typeof tool.metadata === \"object\" &&\n    tool.metadata !== null &&\n    \"customTool\" in tool.metadata &&\n    typeof tool.metadata.customTool === \"object\" &&\n    tool.metadata.customTool !== null\n  );\n}\n\nexport function isOpenAICustomTool(\n  tool: ChatOpenAIToolType\n): tool is OpenAIClient.Chat.ChatCompletionCustomTool {\n  return (\n    \"type\" in tool &&\n    tool.type === \"custom\" &&\n    \"custom\" in tool &&\n    typeof tool.custom === \"object\" &&\n    tool.custom !== null\n  );\n}\n\nexport function parseCustomToolCall(\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  rawToolCall: Record<string, any>\n): CustomToolCall | undefined {\n  if (rawToolCall.type !== \"custom_tool_call\") {\n    return undefined;\n  }\n  return {\n    ...rawToolCall,\n    type: \"tool_call\",\n    call_id: rawToolCall.id,\n    id: rawToolCall.call_id,\n    name: rawToolCall.name,\n    isCustomTool: true,\n    args: {\n      input: rawToolCall.input,\n    },\n  };\n}\n\nexport type ComputerToolCall = ToolCall & {\n  call_id: string;\n  /**\n   * marker to indicate that the tool call is a computer tool call\n   */\n  isComputerTool: true;\n};\n\n/**\n * Parses a computer_call output item from the OpenAI Responses API\n * into a ToolCall format that can be processed by the ToolNode.\n *\n * @param rawToolCall - The raw computer_call output item from the API\n * @returns A ComputerToolCall object if valid, undefined otherwise\n */\nexport function parseComputerCall(\n  // oxlint-disable-next-line @typescript-eslint/no-explicit-any\n  rawToolCall: Record<string, any>\n): ComputerToolCall | undefined {\n  if (rawToolCall.type !== \"computer_call\") {\n    return undefined;\n  }\n  return {\n    ...rawToolCall,\n    type: \"tool_call\",\n    call_id: rawToolCall.id,\n    id: rawToolCall.call_id,\n    name: \"computer_use\",\n    isComputerTool: true,\n    args: {\n      action: rawToolCall.action,\n    },\n  };\n}\n\n/**\n * Checks if a tool call is a computer tool call.\n * @param toolCall - The tool call to check.\n * @returns True if the tool call is a computer tool call, false otherwise.\n */\nexport function isComputerToolCall(\n  toolCall: unknown\n): toolCall is ComputerToolCall {\n  return (\n    typeof toolCall === \"object\" &&\n    toolCall !== null &&\n    \"type\" in toolCall &&\n    toolCall.type === \"tool_call\" &&\n    \"isComputerTool\" in toolCall &&\n    toolCall.isComputerTool === true\n  );\n}\n\nexport function isCustomToolCall(\n  toolCall: unknown\n): toolCall is CustomToolCall {\n  return (\n    typeof toolCall === \"object\" &&\n    toolCall !== null &&\n    \"type\" in toolCall &&\n    toolCall.type === \"tool_call\" &&\n    \"isCustomTool\" in toolCall &&\n    toolCall.isCustomTool === true\n  );\n}\n\nexport function convertCompletionsCustomTool(\n  tool: OpenAIClient.Chat.ChatCompletionCustomTool\n): OpenAIClient.Responses.CustomTool {\n  const getFormat = () => {\n    if (!tool.custom.format) {\n      return undefined;\n    }\n    if (tool.custom.format.type === \"grammar\") {\n      return {\n        type: \"grammar\" as const,\n        definition: tool.custom.format.grammar.definition,\n        syntax: tool.custom.format.grammar.syntax,\n      };\n    }\n    if (tool.custom.format.type === \"text\") {\n      return {\n        type: \"text\" as const,\n      };\n    }\n    return undefined;\n  };\n  return {\n    type: \"custom\",\n    name: tool.custom.name,\n    description: tool.custom.description,\n    format: getFormat(),\n  };\n}\n\nexport function convertResponsesCustomTool(\n  tool: OpenAIClient.Responses.CustomTool\n): OpenAIClient.Chat.ChatCompletionCustomTool {\n  const getFormat = () => {\n    if (!tool.format) {\n      return undefined;\n    }\n    if (tool.format.type === \"grammar\") {\n      return {\n        type: \"grammar\" as const,\n        grammar: {\n          definition: tool.format.definition,\n          syntax: tool.format.syntax,\n        },\n      };\n    }\n    if (tool.format.type === \"text\") {\n      return {\n        type: \"text\" as const,\n      };\n    }\n    return undefined;\n  };\n  return {\n    type: \"custom\",\n    custom: {\n      name: tool.name,\n      description: tool.description,\n      format: getFormat(),\n    },\n  };\n}\n"],"mappings":"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"}