diff --git a/.changeset/short-mirrors-switch.md b/.changeset/short-mirrors-switch.md new file mode 100644 index 000000000..fd50273dd --- /dev/null +++ b/.changeset/short-mirrors-switch.md @@ -0,0 +1,5 @@ +--- +"@browserbasehq/stagehand": patch +--- + +patch custom tool support in anthropic cua client diff --git a/lib/agent/AnthropicCUAClient.ts b/lib/agent/AnthropicCUAClient.ts index 1af5c56c4..905c5c636 100644 --- a/lib/agent/AnthropicCUAClient.ts +++ b/lib/agent/AnthropicCUAClient.ts @@ -13,6 +13,7 @@ import { LogLine } from "@/types/log"; import { AgentScreenshotProviderError } from "@/types/stagehandErrors"; import Anthropic from "@anthropic-ai/sdk"; import { ToolSet } from "ai"; +import { zodToJsonSchema } from "zod-to-json-schema"; import { AgentClient } from "./AgentClient"; import { mapKeyToPlaywright } from "./utils/cuaKeyMapping"; import { compressConversationImages } from "./utils/imageCompression"; @@ -275,6 +276,12 @@ export class AnthropicCUAClient extends AgentClient { level: 2, }); stepActions.push(action); + } else if (this.tools && toolUseItem.name in this.tools) { + stepActions.push({ + type: "custom_tool", + tool: toolUseItem.name, + input: toolUseItem.input, + } as AgentAction); } } else if (block.type === "text") { // Safe to cast here since we've verified it's a text block @@ -436,17 +443,16 @@ export class AnthropicCUAClient extends AgentClient { if (this.tools && Object.keys(this.tools).length > 0) { const customTools = Object.entries(this.tools).map(([name, tool]) => { // Convert Zod schema to proper JSON schema format for Anthropic - let inputSchema = tool.parameters; - - // Ensure the schema has the required 'type' field at root level - if (typeof inputSchema === "object" && inputSchema !== null) { - if (!("type" in inputSchema)) { - inputSchema = { - type: "object", - ...inputSchema, - }; - } - } + const jsonSchema = zodToJsonSchema(tool.parameters) as { + properties?: Record; + required?: string[]; + }; + + const inputSchema = { + type: "object", + properties: jsonSchema.properties || {}, + required: jsonSchema.required || [], + }; return { name, @@ -890,6 +896,8 @@ export class AnthropicCUAClient extends AgentClient { type: name, params: input, }; + } else if (this.tools && name in this.tools) { + return null; } console.warn(`Unknown tool name: ${name}`);