diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index bf5741490..7492cfea4 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"; @@ -32,6 +33,18 @@ const SEARCH_CACHE = new Map>>(); const BRAVE_FRESHNESS_SHORTCUTS = new Set(["pd", "pw", "pm", "py"]); const BRAVE_FRESHNESS_RANGE = /^(\d{4}-\d{2}-\d{2})to(\d{4}-\d{2}-\d{2})$/; +/** + * Get proxy dispatcher from environment variables for HTTP requests. + * Respects HTTP_PROXY, HTTPS_PROXY environment variables. + */ +function getProxyDispatcher(): ProxyAgent | undefined { + const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY; + if (proxyUrl) { + return new ProxyAgent(proxyUrl); + } + return undefined; +} + const WebSearchSchema = Type.Object({ query: Type.String({ description: "Search query string." }), count: Type.Optional( @@ -273,6 +286,7 @@ async function runPerplexitySearch(params: { timeoutSeconds: number; }): Promise<{ content: string; citations: string[] }> { const endpoint = `${params.baseUrl.replace(/\/$/, "")}/chat/completions`; + const proxyDispatcher = getProxyDispatcher(); const res = await fetch(endpoint, { method: "POST", @@ -292,6 +306,7 @@ async function runPerplexitySearch(params: { ], }), signal: withTimeout(undefined, params.timeoutSeconds * 1000), + ...(proxyDispatcher && { dispatcher: proxyDispatcher }), }); if (!res.ok) { @@ -371,6 +386,7 @@ async function runWebSearch(params: { url.searchParams.set("freshness", params.freshness); } + const proxyDispatcher = getProxyDispatcher(); const res = await fetch(url.toString(), { method: "GET", headers: { @@ -378,6 +394,7 @@ async function runWebSearch(params: { "X-Subscription-Token": params.apiKey, }, signal: withTimeout(undefined, params.timeoutSeconds * 1000), + ...(proxyDispatcher && { dispatcher: proxyDispatcher }), }); if (!res.ok) {