Version: betahi-copilot-bridge 0.20.16
Setup:
~/.claude/settings.json: {"env": {"COPILOT_WEB_SEARCH_BACKEND": "searxng"}}
- SearXNG running locally, confirmed reachable and returning valid JSON:
curl -s -m 5 -o /dev/null -w '%{http_code}' http://localhost:8080 # -> 200
curl -s 'http://localhost:8080/search?q=test&format=json' # -> real JSON results
Repro:
- Start the bridge with the above config, hit
/v1/messages with a web_search_20250305 tool and a query.
- The bridge always returns
web_search_tool_result_error with error_code: unavailable, even though SearXNG is up and answering.
- If you let the model paraphrase the tool result, it leaks the internal diagnostic text, which reveals the real cause:
Details:
- Local SearXNG is not running at `http://localhost:8080`
- Error: `[object Response]`
Root cause (from reading dist/main.js):
checkSearxngAvailable() does:
const response = await fetch(DEFAULT_SEARXNG_BASE_URL, {...}).catch((error) => error);
if (response instanceof Response) return; // success path
const detail = response instanceof Error ? response.message : String(response);
return ["Local SearXNG web search is not available.", detail ? `Error: ${detail}` : ""].filter(Boolean).join("\n");
The detail value stringifies to literally "[object Response]", which only happens when response is a real Response object but response instanceof Response evaluates to false. That's a classic dual-realm / duplicate-module symptom: the bundle likely has two different Response class references in scope (e.g. one from Node's built-in global fetch/undici, another re-exported through the bundled undici import used elsewhere in the file), so the identity check fails even though the object genuinely is a successful fetch response.
I instrumented globalThis.fetch in a wrapper before importing dist/main.js and confirmed the readiness fetch to http://localhost:8080 really does return HTTP 200 — the bridge just never recognizes it as such.
Impact: the local searxng backend is unusable as documented — it always falls through to the failure branch regardless of whether SearXNG is actually reachable. (For contrast, COPILOT_WEB_SEARCH_BACKEND=copilot-cli works fine for me, since checkCopilotCliAvailable() doesn't use this instanceof pattern — it shells out to copilot --version and checks stdout instead.)
Suggested fix: replace response instanceof Response with a duck-typed check (e.g. typeof response?.ok === "boolean" or checking for response?.status), since instanceof against a bundled/global class reference is fragile in this kind of setup.
Happy to test a fix if you push one. Thanks for the great tool!
Version: betahi-copilot-bridge 0.20.16
Setup:
~/.claude/settings.json:{"env": {"COPILOT_WEB_SEARCH_BACKEND": "searxng"}}Repro:
/v1/messageswith aweb_search_20250305tool and a query.web_search_tool_result_errorwitherror_code: unavailable, even though SearXNG is up and answering.Root cause (from reading
dist/main.js):checkSearxngAvailable()does:The
detailvalue stringifies to literally"[object Response]", which only happens whenresponseis a realResponseobject butresponse instanceof Responseevaluates tofalse. That's a classic dual-realm / duplicate-module symptom: the bundle likely has two differentResponseclass references in scope (e.g. one from Node's built-in globalfetch/undici, another re-exported through the bundledundiciimport used elsewhere in the file), so the identity check fails even though the object genuinely is a successful fetch response.I instrumented
globalThis.fetchin a wrapper before importingdist/main.jsand confirmed the readiness fetch tohttp://localhost:8080really does return HTTP 200 — the bridge just never recognizes it as such.Impact: the local
searxngbackend is unusable as documented — it always falls through to the failure branch regardless of whether SearXNG is actually reachable. (For contrast,COPILOT_WEB_SEARCH_BACKEND=copilot-cliworks fine for me, sincecheckCopilotCliAvailable()doesn't use thisinstanceofpattern — it shells out tocopilot --versionand checks stdout instead.)Suggested fix: replace
response instanceof Responsewith a duck-typed check (e.g.typeof response?.ok === "boolean"or checking forresponse?.status), sinceinstanceofagainst a bundled/global class reference is fragile in this kind of setup.Happy to test a fix if you push one. Thanks for the great tool!