Merge e756587795 into 4583f88626
This commit is contained in:
commit
c1fe067c8e
@ -175,6 +175,7 @@ Search the web using your configured provider.
|
|||||||
- `search_lang` (optional): ISO language code for search results (e.g., "de", "en", "fr")
|
- `search_lang` (optional): ISO language code for search results (e.g., "de", "en", "fr")
|
||||||
- `ui_lang` (optional): ISO language code for UI elements
|
- `ui_lang` (optional): ISO language code for UI elements
|
||||||
- `freshness` (optional, Brave only): filter by discovery time (`pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD`)
|
- `freshness` (optional, Brave only): filter by discovery time (`pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD`)
|
||||||
|
- `model` (optional, Perplexity only): override the configured model per-query (e.g., "sonar", "sonar-pro")
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
@ -200,6 +201,18 @@ await web_search({
|
|||||||
query: "TMBG interview",
|
query: "TMBG interview",
|
||||||
freshness: "pw"
|
freshness: "pw"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Perplexity: use faster model for simple lookups
|
||||||
|
await web_search({
|
||||||
|
query: "Nick Saban birthday",
|
||||||
|
model: "sonar"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Perplexity: use deeper reasoning for complex analysis
|
||||||
|
await web_search({
|
||||||
|
query: "compare React vs Vue performance benchmarks 2026",
|
||||||
|
model: "sonar-pro"
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
## web_fetch
|
## web_fetch
|
||||||
|
|||||||
@ -63,6 +63,12 @@ const WebSearchSchema = Type.Object({
|
|||||||
"Filter results by discovery time (Brave only). Values: 'pd' (past 24h), 'pw' (past week), 'pm' (past month), 'py' (past year), or date range 'YYYY-MM-DDtoYYYY-MM-DD'.",
|
"Filter results by discovery time (Brave only). Values: 'pd' (past 24h), 'pw' (past week), 'pm' (past month), 'py' (past year), or date range 'YYYY-MM-DDtoYYYY-MM-DD'.",
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
model: Type.Optional(
|
||||||
|
Type.String({
|
||||||
|
description:
|
||||||
|
"Perplexity model to use (e.g., 'sonar', 'sonar-pro'). Overrides configured default. Perplexity provider only.",
|
||||||
|
}),
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
type WebSearchConfig = NonNullable<MoltbotConfig["tools"]>["web"] extends infer Web
|
type WebSearchConfig = NonNullable<MoltbotConfig["tools"]>["web"] extends infer Web
|
||||||
@ -459,6 +465,14 @@ export function createWebSearchTool(options?: {
|
|||||||
docs: "https://docs.molt.bot/tools/web",
|
docs: "https://docs.molt.bot/tools/web",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
const modelOverride = readStringParam(params, "model");
|
||||||
|
if (modelOverride && provider !== "perplexity") {
|
||||||
|
return jsonResult({
|
||||||
|
error: "unsupported_model",
|
||||||
|
message: "model parameter is only supported by the Perplexity web_search provider.",
|
||||||
|
docs: "https://docs.molt.bot/tools/web",
|
||||||
|
});
|
||||||
|
}
|
||||||
const result = await runWebSearch({
|
const result = await runWebSearch({
|
||||||
query,
|
query,
|
||||||
count: resolveSearchCount(count, DEFAULT_SEARCH_COUNT),
|
count: resolveSearchCount(count, DEFAULT_SEARCH_COUNT),
|
||||||
@ -475,7 +489,7 @@ export function createWebSearchTool(options?: {
|
|||||||
perplexityAuth?.source,
|
perplexityAuth?.source,
|
||||||
perplexityAuth?.apiKey,
|
perplexityAuth?.apiKey,
|
||||||
),
|
),
|
||||||
perplexityModel: resolvePerplexityModel(perplexityConfig),
|
perplexityModel: modelOverride || resolvePerplexityModel(perplexityConfig),
|
||||||
});
|
});
|
||||||
return jsonResult(result);
|
return jsonResult(result);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -307,3 +307,115 @@ 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 model parameter", () => {
|
||||||
|
const priorFetch = global.fetch;
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.unstubAllEnvs();
|
||||||
|
// @ts-expect-error global fetch cleanup
|
||||||
|
global.fetch = priorFetch;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("passes model parameter to Perplexity API", async () => {
|
||||||
|
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||||
|
const mockFetch = vi.fn(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
ok: true,
|
||||||
|
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||||
|
} as Response),
|
||||||
|
);
|
||||||
|
// @ts-expect-error mock fetch
|
||||||
|
global.fetch = mockFetch;
|
||||||
|
|
||||||
|
const tool = createWebSearchTool({
|
||||||
|
config: { tools: { web: { search: { provider: "perplexity" } } } },
|
||||||
|
sandboxed: true,
|
||||||
|
});
|
||||||
|
await tool?.execute?.(1, { query: "test-model-param", model: "sonar" });
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalled();
|
||||||
|
const body = JSON.parse(mockFetch.mock.calls[0]?.[1]?.body as string);
|
||||||
|
expect(body.model).toBe("sonar");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses configured model when no model parameter provided", async () => {
|
||||||
|
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||||
|
const mockFetch = vi.fn(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
ok: true,
|
||||||
|
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||||
|
} as Response),
|
||||||
|
);
|
||||||
|
// @ts-expect-error mock fetch
|
||||||
|
global.fetch = mockFetch;
|
||||||
|
|
||||||
|
const tool = createWebSearchTool({
|
||||||
|
config: {
|
||||||
|
tools: {
|
||||||
|
web: {
|
||||||
|
search: {
|
||||||
|
provider: "perplexity",
|
||||||
|
perplexity: { model: "sonar-reasoning-pro" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sandboxed: true,
|
||||||
|
});
|
||||||
|
await tool?.execute?.(1, { query: "test-configured-model" });
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalled();
|
||||||
|
const body = JSON.parse(mockFetch.mock.calls[0]?.[1]?.body as string);
|
||||||
|
expect(body.model).toBe("sonar-reasoning-pro");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("model parameter overrides configured model", async () => {
|
||||||
|
vi.stubEnv("PERPLEXITY_API_KEY", "pplx-test");
|
||||||
|
const mockFetch = vi.fn(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
ok: true,
|
||||||
|
json: () => Promise.resolve({ choices: [{ message: { content: "ok" } }], citations: [] }),
|
||||||
|
} as Response),
|
||||||
|
);
|
||||||
|
// @ts-expect-error mock fetch
|
||||||
|
global.fetch = mockFetch;
|
||||||
|
|
||||||
|
const tool = createWebSearchTool({
|
||||||
|
config: {
|
||||||
|
tools: {
|
||||||
|
web: {
|
||||||
|
search: {
|
||||||
|
provider: "perplexity",
|
||||||
|
perplexity: { model: "sonar-pro" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
sandboxed: true,
|
||||||
|
});
|
||||||
|
await tool?.execute?.(1, { query: "test-model-override", model: "sonar" });
|
||||||
|
|
||||||
|
expect(mockFetch).toHaveBeenCalled();
|
||||||
|
const body = JSON.parse(mockFetch.mock.calls[0]?.[1]?.body as string);
|
||||||
|
expect(body.model).toBe("sonar");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("rejects model parameter for Brave provider", async () => {
|
||||||
|
vi.stubEnv("BRAVE_API_KEY", "test-key");
|
||||||
|
const mockFetch = vi.fn(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
ok: true,
|
||||||
|
json: () => Promise.resolve({ web: { results: [] } }),
|
||||||
|
} as Response),
|
||||||
|
);
|
||||||
|
// @ts-expect-error mock fetch
|
||||||
|
global.fetch = mockFetch;
|
||||||
|
|
||||||
|
const tool = createWebSearchTool({ config: undefined, sandboxed: true });
|
||||||
|
const result = await tool?.execute?.(1, { query: "test-brave-model", model: "sonar" });
|
||||||
|
|
||||||
|
expect(mockFetch).not.toHaveBeenCalled();
|
||||||
|
expect(result?.details).toMatchObject({ error: "unsupported_model" });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user