mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
feat: support freshness parameter for Perplexity web_search provider
Map the existing freshness values (pd/pw/pm/py) to Perplexity's search_recency_filter parameter (day/week/month/year). Previously freshness was rejected with 'only supported by Brave'. Now both Brave and Perplexity support it. Date range format is Brave-only (Perplexity doesn't support it, returns undefined). Closes #15212 Signed-off-by: echoVic <nicepeng@foxmail.com>
This commit is contained in:
@@ -31,6 +31,7 @@ const {
|
||||
isDirectPerplexityBaseUrl,
|
||||
resolvePerplexityRequestModel,
|
||||
normalizeFreshness,
|
||||
freshnessToPerplexityRecency,
|
||||
resolveGrokApiKey,
|
||||
resolveGrokModel,
|
||||
resolveGrokInlineCitations,
|
||||
@@ -128,6 +129,24 @@ describe("web_search freshness normalization", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("freshnessToPerplexityRecency", () => {
|
||||
it("maps Brave shortcuts to Perplexity recency values", () => {
|
||||
expect(freshnessToPerplexityRecency("pd")).toBe("day");
|
||||
expect(freshnessToPerplexityRecency("pw")).toBe("week");
|
||||
expect(freshnessToPerplexityRecency("pm")).toBe("month");
|
||||
expect(freshnessToPerplexityRecency("py")).toBe("year");
|
||||
});
|
||||
|
||||
it("returns undefined for date ranges (not supported by Perplexity)", () => {
|
||||
expect(freshnessToPerplexityRecency("2024-01-01to2024-01-31")).toBeUndefined();
|
||||
});
|
||||
|
||||
it("returns undefined for undefined/empty input", () => {
|
||||
expect(freshnessToPerplexityRecency(undefined)).toBeUndefined();
|
||||
expect(freshnessToPerplexityRecency("")).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("web_search grok config resolution", () => {
|
||||
it("uses config apiKey when provided", () => {
|
||||
expect(resolveGrokApiKey({ apiKey: "xai-test-key" })).toBe("xai-test-key");
|
||||
|
||||
@@ -403,6 +403,23 @@ function normalizeFreshness(value: string | undefined): string | undefined {
|
||||
return `${start}to${end}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map normalized freshness values (pd/pw/pm/py) to Perplexity's
|
||||
* search_recency_filter values (day/week/month/year).
|
||||
*/
|
||||
function freshnessToPerplexityRecency(freshness: string | undefined): string | undefined {
|
||||
if (!freshness) {
|
||||
return undefined;
|
||||
}
|
||||
const map: Record<string, string> = {
|
||||
pd: "day",
|
||||
pw: "week",
|
||||
pm: "month",
|
||||
py: "year",
|
||||
};
|
||||
return map[freshness] ?? undefined;
|
||||
}
|
||||
|
||||
function isValidIsoDate(value: string): boolean {
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
||||
return false;
|
||||
@@ -435,11 +452,27 @@ async function runPerplexitySearch(params: {
|
||||
baseUrl: string;
|
||||
model: string;
|
||||
timeoutSeconds: number;
|
||||
freshness?: string;
|
||||
}): Promise<{ content: string; citations: string[] }> {
|
||||
const baseUrl = params.baseUrl.trim().replace(/\/$/, "");
|
||||
const endpoint = `${baseUrl}/chat/completions`;
|
||||
const model = resolvePerplexityRequestModel(baseUrl, params.model);
|
||||
|
||||
const body: Record<string, unknown> = {
|
||||
model,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: params.query,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const recencyFilter = freshnessToPerplexityRecency(params.freshness);
|
||||
if (recencyFilter) {
|
||||
body.search_recency_filter = recencyFilter;
|
||||
}
|
||||
|
||||
const res = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -448,15 +481,7 @@ async function runPerplexitySearch(params: {
|
||||
"HTTP-Referer": "https://openclaw.ai",
|
||||
"X-Title": "OpenClaw Web Search",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: params.query,
|
||||
},
|
||||
],
|
||||
}),
|
||||
body: JSON.stringify(body),
|
||||
signal: withTimeout(undefined, params.timeoutSeconds * 1000),
|
||||
});
|
||||
|
||||
@@ -561,6 +586,7 @@ async function runWebSearch(params: {
|
||||
baseUrl: params.perplexityBaseUrl ?? DEFAULT_PERPLEXITY_BASE_URL,
|
||||
model: params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL,
|
||||
timeoutSeconds: params.timeoutSeconds,
|
||||
freshness: params.freshness,
|
||||
});
|
||||
|
||||
const payload = {
|
||||
@@ -722,10 +748,10 @@ export function createWebSearchTool(options?: {
|
||||
const search_lang = readStringParam(params, "search_lang");
|
||||
const ui_lang = readStringParam(params, "ui_lang");
|
||||
const rawFreshness = readStringParam(params, "freshness");
|
||||
if (rawFreshness && provider !== "brave") {
|
||||
if (rawFreshness && provider !== "brave" && provider !== "perplexity") {
|
||||
return jsonResult({
|
||||
error: "unsupported_freshness",
|
||||
message: "freshness is only supported by the Brave web_search provider.",
|
||||
message: "freshness is only supported by the Brave and Perplexity web_search providers.",
|
||||
docs: "https://docs.openclaw.ai/tools/web",
|
||||
});
|
||||
}
|
||||
@@ -769,6 +795,7 @@ export const __testing = {
|
||||
isDirectPerplexityBaseUrl,
|
||||
resolvePerplexityRequestModel,
|
||||
normalizeFreshness,
|
||||
freshnessToPerplexityRecency,
|
||||
resolveGrokApiKey,
|
||||
resolveGrokModel,
|
||||
resolveGrokInlineCitations,
|
||||
|
||||
Reference in New Issue
Block a user