From c66a0217d23214c32eb4032bac9714eef8e6271a Mon Sep 17 00:00:00 2001 From: hyoukadev Date: Wed, 24 Jun 2026 00:56:15 +0800 Subject: [PATCH] fix(web): pass proxy to DDGS client MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DuckDuckGo search provider instantiated DDGS(timeout=10) without passing the configured proxy, making web_search unusable in environments that require a proxy (e.g. behind GFW). DDGS supports a proxy parameter and the proxy value is already available as self.proxy — it was simply not forwarded. Add a test verifying the proxy kwarg is forwarded to DDGS. --- nanobot/agent/tools/web.py | 2 +- tests/tools/test_web_search_tool.py | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/nanobot/agent/tools/web.py b/nanobot/agent/tools/web.py index 778d2f0d..169cbb1c 100644 --- a/nanobot/agent/tools/web.py +++ b/nanobot/agent/tools/web.py @@ -759,7 +759,7 @@ class WebSearchTool(Tool): # We run it in a thread to avoid blocking the loop from ddgs import DDGS - ddgs = DDGS(timeout=10) + ddgs = DDGS(timeout=10, proxy=self.proxy) raw = await asyncio.wait_for( asyncio.to_thread(ddgs.text, query, max_results=n), timeout=self.config.timeout, diff --git a/tests/tools/test_web_search_tool.py b/tests/tools/test_web_search_tool.py index 95e873d8..0caee43b 100644 --- a/tests/tools/test_web_search_tool.py +++ b/tests/tools/test_web_search_tool.py @@ -365,6 +365,27 @@ async def test_duckduckgo_search(monkeypatch): assert "DDG Result" in result +@pytest.mark.asyncio +async def test_duckduckgo_search_passes_proxy(monkeypatch): + """DDGS client must receive the configured proxy so search works behind a proxy.""" + captured: dict = {} + + class ProxyCaptorDDGS: + def __init__(self, **kw): + captured.update(kw) + + def text(self, query, max_results=5): + return [{"title": "Proxied", "href": "https://ddg.example", "body": "OK"}] + + monkeypatch.setattr("ddgs.DDGS", ProxyCaptorDDGS) + + tool = _tool(provider="duckduckgo") + tool.proxy = "http://192.168.1.1:8080" + result = await tool.execute(query="hello") + assert captured.get("proxy") == "http://192.168.1.1:8080" + assert "Proxied" in result + + @pytest.mark.asyncio async def test_brave_fallback_to_duckduckgo_when_no_key(monkeypatch): class MockDDGS: