From ec8869d87f312248bd0aba945c4ef78b6fcb0fb8 Mon Sep 17 00:00:00 2001 From: zxz0622 <809915365@qq.com> Date: Thu, 29 Jan 2026 00:08:31 +0800 Subject: [PATCH] feat: add proxy support for web_search tool Add HTTP/HTTPS proxy support for web_search tool using undici's ProxyAgent. This enables web_search to work correctly when running behind corporate proxies or VPNs. Changes: - Import ProxyAgent from undici - Add getProxyDispatcher() helper function to read proxy from environment - Apply proxy dispatcher to both Brave Search and Perplexity API calls - Respects HTTP_PROXY and HTTPS_PROXY environment variables Fixes issues for users running Moltbot behind proxies or VPNs who were experiencing "fetch failed" errors when using web_search. --- src/agents/tools/web-search.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/agents/tools/web-search.ts b/src/agents/tools/web-search.ts index 1d87676e8..7e8f0730b 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 { MoltbotConfig } 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) {