diff --git a/CHANGELOG.md b/CHANGELOG.md index 7431f997d9..0bb8f8e920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 scoping, and native web search. Existing unknown model IDs continue to pass through unchanged. +### Fixed + +- API-backed `[search]` providers visibly degrade to the keyless Bing tail + instead of DuckDuckGo when unavailable: DuckDuckGo is unreachable from + mainland-China networks (DNS poisoning plus SNI reset), while Bing serves + its global and China endpoints without a key. The all-backends-down error + now suggests every selectable API-backed provider, including SearXNG and + Sofya, and the `web_search` tool description no longer claims a + DuckDuckGo hop for configured API backends. + ## [0.9.5] - 2026-08-08 Codewhale v0.9.5 consolidates the terminal application into one compiled diff --git a/crates/tui/src/tools/web/backend.rs b/crates/tui/src/tools/web/backend.rs index 6ae36b0f40..e270963b0b 100644 --- a/crates/tui/src/tools/web/backend.rs +++ b/crates/tui/src/tools/web/backend.rs @@ -261,7 +261,8 @@ async fn run_backend_chain( .join(", "); Err(ToolError::not_available(format!( "web search backends unavailable: {backend_ids}; \ - configure an API-backed [search] provider (tavily, bocha, metaso, baidu, volcengine) for dependable results" + configure an API-backed [search] provider (tavily, bocha, metaso, searxng, baidu, \ + volcengine, sofya) for dependable results" ))) } diff --git a/crates/tui/src/tools/web_search.rs b/crates/tui/src/tools/web_search.rs index b2f5c0ed60..7ac1c569bb 100644 --- a/crates/tui/src/tools/web_search.rs +++ b/crates/tui/src/tools/web_search.rs @@ -1,7 +1,9 @@ //! Web search tool backed by a bounded backend chain: the active route's -//! documented provider-native search, configured API search, then DuckDuckGo -//! HTML scrape with a one-way Bing fallback. Explicit Bing and private -//! DuckDuckGo-compatible routes remain single-provider. API adapters +//! documented provider-native search, configured API search, then a keyless +//! Bing tail chosen by reachability; API outages never route through +//! DuckDuckGo. The configured DuckDuckGo route keeps its own one-way Bing +//! scrape fallback. Explicit Bing and private DuckDuckGo-compatible routes +//! remain single-provider. API adapters //! include Tavily, Bocha (博查), //! Metaso API (), SearXNG JSON API, Baidu AI Search, //! Volcengine Ark, and Sofya (). @@ -103,7 +105,7 @@ impl ToolSpec for WebSearchTool { } fn description(&self) -> &'static str { - "Search the web and return ranked results with URLs, snippets, session-scoped ref_ids, and an execution receipt. Open a result ref_id with `web.run` when the short summary is not enough; fetch only the few sources needed. When the exact active route reports a documented first-party server-side search tool, it is tried first; otherwise the default backend is DuckDuckGo with Bing fallback. Configured API backends visibly degrade through DuckDuckGo then Bing when unavailable, and every hop is recorded. Configuration and network-policy errors fail closed. Explicit Bing and private DuckDuckGo-compatible routes do not cross providers. Set `[search] provider = \"bing\" | \"tavily\" | \"bocha\" | \"metaso\" | \"searxng\" | \"baidu\" | \"volcengine\" | \"sofya\"` in config.toml, or `[search] base_url` for a private DuckDuckGo-compatible endpoint or trusted SearXNG instance. For a known canonical URL, prefer `fetch_url` directly." + "Search the web and return ranked results with URLs, snippets, session-scoped ref_ids, and an execution receipt. Open a result ref_id with `web.run` when the short summary is not enough; fetch only the few sources needed. When the exact active route reports a documented first-party server-side search tool, it is tried first; otherwise the default backend is DuckDuckGo with Bing fallback. Configured API backends visibly degrade through the keyless Bing tail when unavailable, and every hop is recorded. Configuration and network-policy errors fail closed. Explicit Bing and private DuckDuckGo-compatible routes do not cross providers. Set `[search] provider = \"bing\" | \"tavily\" | \"bocha\" | \"metaso\" | \"searxng\" | \"baidu\" | \"volcengine\" | \"sofya\"` in config.toml, or `[search] base_url` for a private DuckDuckGo-compatible endpoint or trusted SearXNG instance. For a known canonical URL, prefer `fetch_url` directly." } fn input_schema(&self) -> Value {