From 6b331916ec94bbdd1ba517140ebc3ca11eb700ba Mon Sep 17 00:00:00 2001 From: kdwycz Date: Fri, 30 Jan 2026 15:57:24 +0800 Subject: [PATCH 1/3] add: proxy config for brave search api --- src/agents/tools/web-search.ts | 16 ++++++++++++++++ src/config/zod-schema.agent-runtime.ts | 1 + 2 files changed, 17 insertions(+) diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index bf5741490..ae360c865 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -1,4 +1,5 @@ import { Type } from "@sinclair/typebox"; +import { ProxyAgent } from "undici"; import type { OpenClawConfig } from "../../config/config.js"; import { formatCliCommand } from "../../cli/command-format.js"; @@ -122,6 +123,11 @@ function resolveSearchApiKey(search?: WebSearchConfig): string | undefined { return fromConfig || fromEnv || undefined; } +function resolveProxy(search?: WebSearchConfig): string | undefined { + const fromConfig = search && "proxy" in search && typeof search.proxy === "string" ? search.proxy.trim() : ""; + return fromConfig || undefined; +} + function missingSearchKeyPayload(provider: (typeof SEARCH_PROVIDERS)[number]) { if (provider === "perplexity") { return { @@ -271,9 +277,12 @@ async function runPerplexitySearch(params: { baseUrl: string; model: string; timeoutSeconds: number; + proxy?: string; }): Promise<{ content: string; citations: string[] }> { const endpoint = `${params.baseUrl.replace(/\/$/, "")}/chat/completions`; + const dispatcher = params.proxy ? new ProxyAgent(params.proxy) : undefined; + const res = await fetch(endpoint, { method: "POST", headers: { @@ -292,6 +301,7 @@ async function runPerplexitySearch(params: { ], }), signal: withTimeout(undefined, params.timeoutSeconds * 1000), + dispatcher, }); if (!res.ok) { @@ -319,6 +329,7 @@ async function runWebSearch(params: { freshness?: string; perplexityBaseUrl?: string; perplexityModel?: string; + proxy?: string; }): Promise> { const cacheKey = normalizeCacheKey( params.provider === "brave" @@ -337,6 +348,7 @@ async function runWebSearch(params: { baseUrl: params.perplexityBaseUrl ?? DEFAULT_PERPLEXITY_BASE_URL, model: params.perplexityModel ?? DEFAULT_PERPLEXITY_MODEL, timeoutSeconds: params.timeoutSeconds, + proxy: params.proxy, }); const payload = { @@ -371,6 +383,8 @@ async function runWebSearch(params: { url.searchParams.set("freshness", params.freshness); } + const dispatcher = params.proxy ? new ProxyAgent(params.proxy) : undefined; + const res = await fetch(url.toString(), { method: "GET", headers: { @@ -378,6 +392,7 @@ async function runWebSearch(params: { "X-Subscription-Token": params.apiKey, }, signal: withTimeout(undefined, params.timeoutSeconds * 1000), + dispatcher, }); if (!res.ok) { @@ -476,6 +491,7 @@ export function createWebSearchTool(options?: { perplexityAuth?.apiKey, ), perplexityModel: resolvePerplexityModel(perplexityConfig), + proxy: resolveProxy(search), }); return jsonResult(result); }, diff --git a/src/config/zod-schema.agent-runtime.ts b/src/config/zod-schema.agent-runtime.ts index 7e95c3538..6864d3785 100644 --- a/src/config/zod-schema.agent-runtime.ts +++ b/src/config/zod-schema.agent-runtime.ts @@ -170,6 +170,7 @@ export const ToolsWebSearchSchema = z maxResults: z.number().int().positive().optional(), timeoutSeconds: z.number().int().positive().optional(), cacheTtlMinutes: z.number().nonnegative().optional(), + proxy: z.string().optional(), perplexity: z .object({ apiKey: z.string().optional(), From ea6fc87d6d9844955322bd343854c7576a476fbb Mon Sep 17 00:00:00 2001 From: kdwycz Date: Fri, 30 Jan 2026 16:01:50 +0800 Subject: [PATCH 2/3] add: proxy config for search api doc --- docs/tools/web.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/tools/web.md b/docs/tools/web.md index 3e626400a..2e8dfe869 100644 --- a/docs/tools/web.md +++ b/docs/tools/web.md @@ -107,6 +107,7 @@ crypto/prepaid). search: { enabled: true, provider: "perplexity", + proxy: "http://127.0.0.1:7890", // optional perplexity: { // API key (optional if OPENROUTER_API_KEY or PERPLEXITY_API_KEY is set) apiKey: "sk-or-v1-...", @@ -160,7 +161,8 @@ Search the web using your configured provider. apiKey: "BRAVE_API_KEY_HERE", // optional if BRAVE_API_KEY is set maxResults: 5, timeoutSeconds: 30, - cacheTtlMinutes: 15 + cacheTtlMinutes: 15, + proxy: "http://127.0.0.1:7890" // optional } } } From bcd80f857d58649e5fbcc783d61a2d5693f93729 Mon Sep 17 00:00:00 2001 From: kdwycz Date: Fri, 30 Jan 2026 16:24:03 +0800 Subject: [PATCH 3/3] fix: pnpm testcase bug --- src/agents/tools/web-search.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index ae360c865..b765a0f25 100644 --- a/src/agents/tools/web-search.ts +++ b/src/agents/tools/web-search.ts @@ -124,7 +124,8 @@ function resolveSearchApiKey(search?: WebSearchConfig): string | undefined { } function resolveProxy(search?: WebSearchConfig): string | undefined { - const fromConfig = search && "proxy" in search && typeof search.proxy === "string" ? search.proxy.trim() : ""; + const fromConfig = + search && "proxy" in search && typeof search.proxy === "string" ? search.proxy.trim() : ""; return fromConfig || undefined; } @@ -302,7 +303,7 @@ async function runPerplexitySearch(params: { }), signal: withTimeout(undefined, params.timeoutSeconds * 1000), dispatcher, - }); + } as RequestInit); if (!res.ok) { const detail = await readResponseText(res); @@ -393,7 +394,7 @@ async function runWebSearch(params: { }, signal: withTimeout(undefined, params.timeoutSeconds * 1000), dispatcher, - }); + } as RequestInit); if (!res.ok) { const detail = await readResponseText(res);