diff --git a/extensions/tavily/src/tavily-client.test.ts b/extensions/tavily/src/tavily-client.test.ts index f232f5acc184..d34399ea6e18 100644 --- a/extensions/tavily/src/tavily-client.test.ts +++ b/extensions/tavily/src/tavily-client.test.ts @@ -6,6 +6,7 @@ import { createStreamingResponse } from "../../test-support/streaming-error-resp const postTrustedWebToolsJson = vi.fn(); const writeCache = vi.fn(); const assertPluginCapabilitySecretAvailable = vi.fn(); +const resolveTavilyBaseUrl = vi.fn(() => "https://api.tavily.com"); vi.mock("openclaw/plugin-sdk/secret-input-runtime", () => ({ assertPluginCapabilitySecretAvailable, @@ -25,7 +26,7 @@ vi.mock("./config.js", () => ({ DEFAULT_TAVILY_BASE_URL: "https://api.tavily.com", TAVILY_API_KEY_CONFIG_PATH: "plugins.entries.tavily.config.webSearch.apiKey", resolveTavilyApiKey: () => "test-key", - resolveTavilyBaseUrl: () => "https://api.tavily.com", + resolveTavilyBaseUrl, resolveTavilySearchTimeoutSeconds: () => 30, resolveTavilyExtractTimeoutSeconds: () => 60, })); @@ -42,6 +43,7 @@ describe("tavily client X-Client-Source header", () => { assertPluginCapabilitySecretAvailable.mockReset(); postTrustedWebToolsJson.mockReset(); writeCache.mockReset(); + resolveTavilyBaseUrl.mockReset().mockReturnValue("https://api.tavily.com"); postTrustedWebToolsJson.mockImplementation( async (_params: unknown, parse: (r: Response) => Promise) => parse(Response.json({ results: [] })), @@ -70,6 +72,32 @@ describe("tavily client X-Client-Source header", () => { }, ); + it("appends endpoints to reverse-proxy base urls", async () => { + resolveTavilyBaseUrl.mockReturnValueOnce("https://proxy.example/api/tavily"); + await runTavilySearch({ query: "proxy search" }); + resolveTavilyBaseUrl.mockReturnValueOnce("https://proxy.example/api/tavily/"); + await runTavilyExtract({ urls: ["https://example.com"] }); + + expect(postTrustedWebToolsJson).toHaveBeenCalledTimes(2); + expect(postTrustedWebToolsJson.mock.calls[0]?.[0]?.url).toBe( + "https://proxy.example/api/tavily/search", + ); + expect(postTrustedWebToolsJson.mock.calls[1]?.[0]?.url).toBe( + "https://proxy.example/api/tavily/extract", + ); + }); + + it("falls back to the default host for invalid base urls", async () => { + resolveTavilyBaseUrl.mockReturnValueOnce("not a url"); + await runTavilySearch({ query: "invalid base URL" }); + resolveTavilyBaseUrl.mockReturnValueOnce(""); + await runTavilyExtract({ urls: ["https://example.com"] }); + + expect(postTrustedWebToolsJson).toHaveBeenCalledTimes(2); + expect(postTrustedWebToolsJson.mock.calls[0]?.[0]?.url).toBe("https://api.tavily.com/search"); + expect(postTrustedWebToolsJson.mock.calls[1]?.[0]?.url).toBe("https://api.tavily.com/extract"); + }); + it("runTavilySearch sends X-Client-Source: openclaw", async () => { await runTavilySearch({ query: "test query" }); diff --git a/extensions/tavily/src/tavily-client.ts b/extensions/tavily/src/tavily-client.ts index 7ab7d84e731e..d81f5c66aa46 100644 --- a/extensions/tavily/src/tavily-client.ts +++ b/extensions/tavily/src/tavily-client.ts @@ -416,7 +416,3 @@ export async function runTavilyExtract( ); return result; } - -export const testing = { - resolveEndpoint, -}; diff --git a/extensions/tavily/src/tavily-tools.test.ts b/extensions/tavily/src/tavily-tools.test.ts index 536de5d13253..a352ae29ac87 100644 --- a/extensions/tavily/src/tavily-tools.test.ts +++ b/extensions/tavily/src/tavily-tools.test.ts @@ -47,7 +47,6 @@ describe("tavily tools", () => { let createTavilyContractWebSearchProvider: typeof import("../web-search-contract-api.js").createTavilyWebSearchProvider; let createTavilySearchTool: typeof import("./tavily-search-tool.js").createTavilySearchTool; let createTavilyExtractTool: typeof import("./tavily-extract-tool.js").createTavilyExtractTool; - let tavilyClientTesting: typeof import("./tavily-client.js").testing; let tavilyPlugin: typeof import("../index.js").default; beforeAll(async () => { @@ -56,8 +55,6 @@ describe("tavily tools", () => { await import("../web-search-contract-api.js")); ({ createTavilySearchTool } = await import("./tavily-search-tool.js")); ({ createTavilyExtractTool } = await import("./tavily-extract-tool.js")); - ({ testing: tavilyClientTesting } = - await vi.importActual("./tavily-client.js")); ({ default: tavilyPlugin } = await import("../index.js")); }); @@ -507,22 +504,4 @@ describe("tavily tools", () => { expect(resolveTavilySearchTimeoutSeconds(0)).toBe(30); expect(resolveTavilyExtractTimeoutSeconds(Number.NaN)).toBe(60); }); - - it("appends endpoints to reverse-proxy base urls", () => { - expect(tavilyClientTesting.resolveEndpoint("https://proxy.example/api/tavily", "/search")).toBe( - "https://proxy.example/api/tavily/search", - ); - expect( - tavilyClientTesting.resolveEndpoint("https://proxy.example/api/tavily/", "/extract"), - ).toBe("https://proxy.example/api/tavily/extract"); - }); - - it("falls back to the default host for invalid base urls", () => { - expect(tavilyClientTesting.resolveEndpoint("not a url", "/search")).toBe( - "https://api.tavily.com/search", - ); - expect(tavilyClientTesting.resolveEndpoint("", "/extract")).toBe( - "https://api.tavily.com/extract", - ); - }); });