返回 CodeWhale
search.rs
根目录 / crates / tui / src / config / search.rs
1 //! Web-search provider configuration types.
2 //!
3 //! Self-contained `[search]` table types extracted verbatim from `config.rs`.
4 //! Re-exported from `crate::config` via `pub use search::*;` so existing
5 //! `crate::config::SearchProvider` (and sibling) paths resolve unchanged
6 //! (#3311).
7
8 use serde::{Deserialize, Serialize};
9
10 /// Search provider enumeration — selects the first backend `web_search` uses.
11 /// API-backed providers may visibly degrade through the default DuckDuckGo →
12 /// Bing chain after runtime failure or an empty result. Configuration and
13 /// network-policy errors fail closed without crossing providers.
14 #[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Deserialize, Serialize)]
15 #[serde(rename_all = "snake_case")]
16 pub enum SearchProvider {
17 /// Bing HTML scraping. No API key needed.
18 Bing,
19 /// DuckDuckGo HTML scraping with Bing fallback. No API key needed.
20 #[default]
21 #[serde(alias = "duckduckgo")]
22 DuckDuckGo,
23 /// Tavily AI Search API (<https://tavily.com>). Requires api_key.
24 Tavily,
25 /// Bocha AI Search API (<https://bochaai.com>). Requires api_key.
26 Bocha,
27 /// Metaso AI Search API (<https://metaso.cn>). Requires `[search] api_key`
28 /// or the `METASO_API_KEY` env var.
29 #[serde(alias = "metaso")]
30 Metaso,
31 /// SearXNG JSON search API. Requires a trusted/self-hosted `base_url`.
32 #[serde(alias = "searx", alias = "searx-ng", alias = "searx_ng")]
33 Searxng,
34 /// Baidu AI Search API (<https://qianfan.baidubce.com>). Requires api_key.
35 #[serde(
36 alias = "baidu-search",
37 alias = "baidu_ai_search",
38 alias = "baidu_search",
39 alias = "baidu-ai-search"
40 )]
41 Baidu,
42 /// Volcengine Ark web_search via Responses API. Requires api_key.
43 /// Free tier: 20K queries/month per API key. Falls back to
44 /// `VOLCENGINE_API_KEY` / `VOLCENGINE_ARK_API_KEY` / `ARK_API_KEY`
45 /// env vars when `[search] api_key` is not set.
46 #[serde(
47 alias = "volcengine",
48 alias = "ark",
49 alias = "volc",
50 alias = "volcengine-ark",
51 alias = "volcengine_ark",
52 alias = "volc-ark"
53 )]
54 Volcengine,
55 /// Sofya web search API (<https://sofya.co>). Requires api_key
56 /// (`ay_live_...`). Returns full extracted page content rather than
57 /// snippets; falls back to the `SOFYA_API_KEY` env var when
58 /// `[search] api_key` is not set.
59 Sofya,
60 }
61
62 impl SearchProvider {
63 #[must_use]
64 pub fn parse(value: &str) -> Option<Self> {
65 match value.trim().to_ascii_lowercase().as_str() {
66 "bing" => Some(Self::Bing),
67 "duckduckgo" | "duck-duck-go" | "duck_duck_go" | "ddg" => Some(Self::DuckDuckGo),
68 "tavily" => Some(Self::Tavily),
69 "bocha" => Some(Self::Bocha),
70 "metaso" => Some(Self::Metaso),
71 "searxng" | "searx" | "searx-ng" | "searx_ng" => Some(Self::Searxng),
72 "baidu" | "baidu-search" | "baidu_search" | "baidu-ai-search" | "baidu_ai_search" => {
73 Some(Self::Baidu)
74 }
75 "volcengine" | "ark" | "volc" | "volcengine-ark" => Some(Self::Volcengine),
76 "sofya" => Some(Self::Sofya),
77 _ => None,
78 }
79 }
80
81 #[must_use]
82 pub fn as_str(self) -> &'static str {
83 match self {
84 Self::Bing => "bing",
85 Self::DuckDuckGo => "duckduckgo",
86 Self::Tavily => "tavily",
87 Self::Bocha => "bocha",
88 Self::Metaso => "metaso",
89 Self::Searxng => "searxng",
90 Self::Baidu => "baidu",
91 Self::Volcengine => "volcengine",
92 Self::Sofya => "sofya",
93 }
94 }
95 }
96
97 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
98 pub enum SearchProviderSource {
99 Default,
100 Config,
101 EnvOverride,
102 }
103
104 impl SearchProviderSource {
105 #[must_use]
106 pub fn as_str(self) -> &'static str {
107 match self {
108 Self::Default => "default",
109 Self::Config => "config",
110 Self::EnvOverride => "env override",
111 }
112 }
113 }
114
115 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
116 pub struct SearchProviderResolution {
117 pub provider: SearchProvider,
118 pub source: SearchProviderSource,
119 }
120
121 /// Web search provider configuration (`[search]` table in config.toml).
122 #[derive(Debug, Clone, Deserialize, Default)]
123 pub struct SearchConfig {
124 /// Search provider: `bing` | `duckduckgo` | `tavily` | `bocha` | `metaso` | `searxng` | `baidu` | `volcengine`. Default: `duckduckgo`.
125 #[serde(default)]
126 pub provider: Option<SearchProvider>,
127 /// Optional search endpoint. With `duckduckgo`, this is a
128 /// DuckDuckGo-compatible HTML endpoint. With `searxng`, this is the trusted
129 /// SearXNG instance root or `/search` endpoint.
130 #[serde(default)]
131 pub base_url: Option<String>,
132 /// API key for Tavily, Bocha, Metaso, Baidu, or Volcengine. Not required for Bing, DuckDuckGo, or SearXNG.
133 /// Metaso also falls back to the `METASO_API_KEY` env var.
134 /// Baidu also falls back to `BAIDU_SEARCH_API_KEY` env var.
135 /// Volcengine also falls back to `VOLCENGINE_API_KEY` / `VOLCENGINE_ARK_API_KEY` / `ARK_API_KEY` env vars.
136 #[serde(default)]
137 pub api_key: Option<String>,
138 }
139
139 lines RUST