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");
|
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);
|
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
|
export const ToolsWebSearchSchema = z
|
||||||
.object({
|
.object({
|
||||||
enabled: z.boolean().optional(),
|
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(),
|
apiKey: z.string().optional(),
|
||||||
maxResults: z.number().int().positive().optional(),
|
maxResults: z.number().int().positive().optional(),
|
||||||
timeoutSeconds: z.number().int().positive().optional(),
|
timeoutSeconds: z.number().int().positive().optional(),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user