diff --git a/src/agents/tools/browser-tool.schema.ts b/src/agents/tools/browser-tool.schema.ts index 53a482d6d..bebbe5ad2 100644 --- a/src/agents/tools/browser-tool.schema.ts +++ b/src/agents/tools/browser-tool.schema.ts @@ -86,6 +86,7 @@ export const BrowserToolSchema = Type.Object({ node: Type.Optional(Type.String()), profile: Type.Optional(Type.String()), targetUrl: Type.Optional(Type.String()), + url: Type.Optional(Type.String()), targetId: Type.Optional(Type.String()), limit: Type.Optional(Type.Number()), maxChars: Type.Optional(Type.Number()), diff --git a/src/agents/tools/browser-tool.test.ts b/src/agents/tools/browser-tool.test.ts index d3ef8d660..f299bb552 100644 --- a/src/agents/tools/browser-tool.test.ts +++ b/src/agents/tools/browser-tool.test.ts @@ -262,6 +262,51 @@ describe("browser tool snapshot maxChars", () => { }); }); +describe("browser tool url alias support", () => { + afterEach(() => { + vi.clearAllMocks(); + configMocks.loadConfig.mockReturnValue({ browser: {} }); + nodesUtilsMocks.listNodes.mockResolvedValue([]); + }); + + it("accepts url alias for open", async () => { + const tool = createBrowserTool(); + await tool.execute?.("call-1", { action: "open", url: "https://example.com" }); + + expect(browserClientMocks.browserOpenTab).toHaveBeenCalledWith( + undefined, + "https://example.com", + expect.objectContaining({ profile: undefined }), + ); + }); + + it("accepts url alias for navigate", async () => { + const tool = createBrowserTool(); + await tool.execute?.("call-1", { + action: "navigate", + url: "https://example.com", + targetId: "tab-1", + }); + + expect(browserActionsMocks.browserNavigate).toHaveBeenCalledWith( + undefined, + expect.objectContaining({ + url: "https://example.com", + targetId: "tab-1", + profile: undefined, + }), + ); + }); + + it("keeps targetUrl required error label when both params are missing", async () => { + const tool = createBrowserTool(); + + await expect(tool.execute?.("call-1", { action: "open" })).rejects.toThrow( + "targetUrl required", + ); + }); +}); + describe("browser tool snapshot labels", () => { afterEach(() => { vi.clearAllMocks(); diff --git a/src/agents/tools/browser-tool.ts b/src/agents/tools/browser-tool.ts index 03138c3d5..2a8a9e0ce 100644 --- a/src/agents/tools/browser-tool.ts +++ b/src/agents/tools/browser-tool.ts @@ -84,6 +84,13 @@ function readOptionalTargetAndTimeout(params: Record) { return { targetId, timeoutMs }; } +function readTargetUrlParam(params: Record) { + return ( + readStringParam(params, "targetUrl") ?? + readStringParam(params, "url", { required: true, label: "targetUrl" }) + ); +} + type BrowserProxyFile = { path: string; base64: string; @@ -405,9 +412,7 @@ export function createBrowserTool(opts?: { return formatTabsToolResult(tabs); } case "open": { - const targetUrl = readStringParam(params, "targetUrl", { - required: true, - }); + const targetUrl = readTargetUrlParam(params); if (proxyRequest) { const result = await proxyRequest({ method: "POST", @@ -635,9 +640,7 @@ export function createBrowserTool(opts?: { }); } case "navigate": { - const targetUrl = readStringParam(params, "targetUrl", { - required: true, - }); + const targetUrl = readTargetUrlParam(params); const targetId = readStringParam(params, "targetId"); if (proxyRequest) { const result = await proxyRequest({