tools: add Serper Google Search API as web_search provider option
This commit is contained in:
parent
d52835e1a0
commit
8041703a29
@ -307,3 +307,87 @@ describe("web_search perplexity baseUrl defaults", () => {
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://openrouter.ai/api/v1/chat/completions");
|
||||
});
|
||||
});
|
||||
|
||||
describe("web_search serper provider", () => {
|
||||
const priorFetch = global.fetch;
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllEnvs();
|
||||
// @ts-expect-error global fetch cleanup
|
||||
global.fetch = priorFetch;
|
||||
});
|
||||
|
||||
it("works with Serper provider and config API key", async () => {
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
organic: [
|
||||
{ title: "Test Result", link: "https://example.com", snippet: "Test snippet" },
|
||||
],
|
||||
}),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = mockFetch;
|
||||
|
||||
const tool = createWebSearchTool({
|
||||
config: {
|
||||
tools: {
|
||||
web: {
|
||||
search: {
|
||||
provider: "serper",
|
||||
apiKey: "serper-test-key",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sandboxed: true,
|
||||
});
|
||||
const result = await tool?.execute?.(1, { query: "test serper" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[0]).toBe("https://google.serper.dev/search");
|
||||
expect(mockFetch.mock.calls[0]?.[1]?.method).toBe("POST");
|
||||
expect(mockFetch.mock.calls[0]?.[1]?.headers?.["X-API-KEY"]).toBe("serper-test-key");
|
||||
expect(result?.details).toMatchObject({
|
||||
provider: "serper",
|
||||
query: "test serper",
|
||||
});
|
||||
});
|
||||
|
||||
it("works with Serper provider and SERPER_API_KEY env var", async () => {
|
||||
vi.stubEnv("SERPER_API_KEY", "serper-env-key");
|
||||
const mockFetch = vi.fn(() =>
|
||||
Promise.resolve({
|
||||
ok: true,
|
||||
json: () =>
|
||||
Promise.resolve({
|
||||
organic: [
|
||||
{ title: "Test Result", link: "https://example.com", snippet: "Test snippet" },
|
||||
],
|
||||
}),
|
||||
} as Response),
|
||||
);
|
||||
// @ts-expect-error mock fetch
|
||||
global.fetch = mockFetch;
|
||||
|
||||
const tool = createWebSearchTool({
|
||||
config: {
|
||||
tools: {
|
||||
web: {
|
||||
search: {
|
||||
provider: "serper",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
sandboxed: true,
|
||||
});
|
||||
await tool?.execute?.(1, { query: "test serper env" });
|
||||
|
||||
expect(mockFetch).toHaveBeenCalled();
|
||||
expect(mockFetch.mock.calls[0]?.[1]?.headers?.["X-API-KEY"]).toBe("serper-env-key");
|
||||
});
|
||||
});
|
||||
|
||||
@ -22,4 +22,20 @@ describe("web search provider config", () => {
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
});
|
||||
|
||||
it("accepts serper provider and config", () => {
|
||||
const res = validateConfigObject({
|
||||
tools: {
|
||||
web: {
|
||||
search: {
|
||||
enabled: true,
|
||||
provider: "serper",
|
||||
apiKey: "test-key",
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.ok).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -168,7 +168,9 @@ export const ToolPolicySchema = ToolPolicyBaseSchema.superRefine((value, ctx) =>
|
||||
export const ToolsWebSearchSchema = z
|
||||
.object({
|
||||
enabled: z.boolean().optional(),
|
||||
provider: z.union([z.literal("brave"), z.literal("perplexity")]).optional(),
|
||||
provider: z
|
||||
.union([z.literal("brave"), z.literal("perplexity"), z.literal("serper")])
|
||||
.optional(),
|
||||
apiKey: z.string().optional(),
|
||||
maxResults: z.number().int().positive().optional(),
|
||||
timeoutSeconds: z.number().int().positive().optional(),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user