starweaver_context/config/
tool.rs1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
7#[serde(rename_all = "snake_case")]
8pub enum ToolAvailabilityPolicy {
9 #[default]
11 SkipAndReport,
12 FailRun,
14}
15
16#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
18pub struct ToolConfig {
19 #[serde(default)]
21 pub unavailable_tool_policy: ToolAvailabilityPolicy,
22 #[serde(default = "default_true")]
24 pub skip_url_verification: bool,
25 #[serde(default)]
27 pub enable_load_document: bool,
28 #[serde(default, skip_serializing_if = "Option::is_none")]
30 pub image_understanding_model: Option<String>,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub video_understanding_model: Option<String>,
34 #[serde(default, skip_serializing_if = "Option::is_none")]
36 pub audio_understanding_model: Option<String>,
37 #[serde(default, skip_serializing_if = "Option::is_none")]
39 pub google_search_api_key: Option<String>,
40 #[serde(default, skip_serializing_if = "Option::is_none")]
42 pub google_search_cx: Option<String>,
43 #[serde(default, skip_serializing_if = "Option::is_none")]
45 pub tavily_api_key: Option<String>,
46 #[serde(default, skip_serializing_if = "Option::is_none")]
48 pub brave_search_api_key: Option<String>,
49 #[serde(default, skip_serializing_if = "Option::is_none")]
51 pub pixabay_api_key: Option<String>,
52 #[serde(default, skip_serializing_if = "Option::is_none")]
54 pub rapidapi_api_key: Option<String>,
55 #[serde(default, skip_serializing_if = "Option::is_none")]
57 pub firecrawl_api_key: Option<String>,
58 #[serde(default = "default_view_max_text_file_size")]
60 pub view_max_text_file_size: u64,
61 #[serde(default, skip_serializing_if = "Vec::is_empty")]
63 pub view_relaxed_text_patterns: Vec<String>,
64 #[serde(default, skip)]
66 pub view_relaxed_text_dynamic_patterns: BTreeMap<String, Vec<String>>,
67 #[serde(default = "default_view_relaxed_text_file_size")]
69 pub view_relaxed_text_file_size: u64,
70 #[serde(default = "default_view_relaxed_line_limit")]
72 pub view_relaxed_line_limit: usize,
73 #[serde(default = "default_view_relaxed_max_line_length")]
75 pub view_relaxed_max_line_length: usize,
76 #[serde(default = "default_view_max_content_chars")]
78 pub view_max_content_chars: usize,
79 #[serde(default = "default_view_relaxed_max_content_chars")]
81 pub view_relaxed_max_content_chars: usize,
82 #[serde(default = "default_edit_max_file_size")]
84 pub edit_max_file_size: u64,
85 #[serde(default = "default_grep_max_file_size")]
87 pub grep_max_file_size: u64,
88 #[serde(default = "default_view_max_inline_image_bytes")]
90 pub view_max_inline_image_bytes: u64,
91 #[serde(default = "default_view_max_inline_video_bytes")]
93 pub view_max_inline_video_bytes: u64,
94 #[serde(default = "default_view_max_inline_audio_bytes")]
96 pub view_max_inline_audio_bytes: u64,
97 #[serde(default = "default_fetch_stream_chunk_size")]
99 pub fetch_stream_chunk_size: usize,
100 #[serde(default = "default_fetch_max_inline_binary_bytes")]
102 pub fetch_max_inline_binary_bytes: u64,
103 #[serde(default = "default_download_max_concurrency")]
105 pub download_max_concurrency: usize,
106 #[serde(default = "default_document_max_file_size")]
108 pub document_max_file_size: u64,
109 #[serde(default = "default_filesystem_output_truncate_limit")]
111 pub filesystem_output_truncate_limit: usize,
112 #[serde(default = "default_grep_truncation_threshold")]
114 pub grep_truncation_threshold: usize,
115 #[serde(default = "default_grep_truncated_line_max")]
117 pub grep_truncated_line_max: usize,
118 #[serde(default = "default_shell_output_truncate_limit")]
120 pub shell_output_truncate_limit: usize,
121 #[serde(default = "default_cold_start_tool_return_limit")]
123 pub cold_start_tool_return_limit: usize,
124}
125
126impl Default for ToolConfig {
127 fn default() -> Self {
128 Self {
129 unavailable_tool_policy: ToolAvailabilityPolicy::SkipAndReport,
130 skip_url_verification: true,
131 enable_load_document: false,
132 image_understanding_model: None,
133 video_understanding_model: None,
134 audio_understanding_model: None,
135 google_search_api_key: None,
136 google_search_cx: None,
137 tavily_api_key: None,
138 brave_search_api_key: None,
139 pixabay_api_key: None,
140 rapidapi_api_key: None,
141 firecrawl_api_key: None,
142 view_max_text_file_size: default_view_max_text_file_size(),
143 view_relaxed_text_patterns: Vec::new(),
144 view_relaxed_text_dynamic_patterns: BTreeMap::new(),
145 view_relaxed_text_file_size: default_view_relaxed_text_file_size(),
146 view_relaxed_line_limit: default_view_relaxed_line_limit(),
147 view_relaxed_max_line_length: default_view_relaxed_max_line_length(),
148 view_max_content_chars: default_view_max_content_chars(),
149 view_relaxed_max_content_chars: default_view_relaxed_max_content_chars(),
150 edit_max_file_size: default_edit_max_file_size(),
151 grep_max_file_size: default_grep_max_file_size(),
152 view_max_inline_image_bytes: default_view_max_inline_image_bytes(),
153 view_max_inline_video_bytes: default_view_max_inline_video_bytes(),
154 view_max_inline_audio_bytes: default_view_max_inline_audio_bytes(),
155 fetch_stream_chunk_size: default_fetch_stream_chunk_size(),
156 fetch_max_inline_binary_bytes: default_fetch_max_inline_binary_bytes(),
157 download_max_concurrency: default_download_max_concurrency(),
158 document_max_file_size: default_document_max_file_size(),
159 filesystem_output_truncate_limit: default_filesystem_output_truncate_limit(),
160 grep_truncation_threshold: default_grep_truncation_threshold(),
161 grep_truncated_line_max: default_grep_truncated_line_max(),
162 shell_output_truncate_limit: default_shell_output_truncate_limit(),
163 cold_start_tool_return_limit: default_cold_start_tool_return_limit(),
164 }
165 }
166}
167
168impl ToolConfig {
169 #[must_use]
173 pub fn is_default(&self) -> bool {
174 let mut persisted = self.clone();
175 persisted.view_relaxed_text_dynamic_patterns.clear();
176 persisted == Self::default()
177 }
178
179 #[must_use]
181 pub fn effective_view_relaxed_text_patterns(&self) -> Vec<&str> {
182 let mut patterns = self
183 .view_relaxed_text_patterns
184 .iter()
185 .map(String::as_str)
186 .collect::<Vec<_>>();
187 for source_patterns in self.view_relaxed_text_dynamic_patterns.values() {
188 patterns.extend(source_patterns.iter().map(String::as_str));
189 }
190 patterns
191 }
192
193 pub fn register_view_relaxed_text_patterns(
195 &mut self,
196 source: impl Into<String>,
197 patterns: impl IntoIterator<Item = String>,
198 ) {
199 let patterns = patterns
200 .into_iter()
201 .map(|pattern| pattern.trim().to_string())
202 .filter(|pattern| !pattern.is_empty())
203 .collect::<Vec<_>>();
204 let source = source.into();
205 if patterns.is_empty() {
206 self.view_relaxed_text_dynamic_patterns.remove(&source);
207 } else {
208 self.view_relaxed_text_dynamic_patterns
209 .insert(source, patterns);
210 }
211 }
212
213 pub fn unregister_view_relaxed_text_patterns(&mut self, source: &str) {
215 self.view_relaxed_text_dynamic_patterns.remove(source);
216 }
217
218 pub fn normalize(&mut self) {
220 self.download_max_concurrency = self.download_max_concurrency.max(1);
221 }
222}
223
224const fn default_true() -> bool {
225 true
226}
227
228const fn default_view_max_text_file_size() -> u64 {
229 10 * 1024 * 1024
230}
231
232const fn default_view_relaxed_text_file_size() -> u64 {
233 50 * 1024 * 1024
234}
235
236const fn default_view_relaxed_line_limit() -> usize {
237 5000
238}
239
240const fn default_view_relaxed_max_line_length() -> usize {
241 20_000
242}
243
244const fn default_view_max_content_chars() -> usize {
245 60_000
246}
247
248const fn default_view_relaxed_max_content_chars() -> usize {
249 250_000
250}
251
252const fn default_edit_max_file_size() -> u64 {
253 20 * 1024 * 1024
254}
255
256const fn default_grep_max_file_size() -> u64 {
257 10 * 1024 * 1024
258}
259
260const fn default_view_max_inline_image_bytes() -> u64 {
261 20 * 1024 * 1024
262}
263
264const fn default_view_max_inline_video_bytes() -> u64 {
265 50 * 1024 * 1024
266}
267
268const fn default_view_max_inline_audio_bytes() -> u64 {
269 50 * 1024 * 1024
270}
271
272const fn default_fetch_stream_chunk_size() -> usize {
273 64 * 1024
274}
275
276const fn default_fetch_max_inline_binary_bytes() -> u64 {
277 30 * 1024 * 1024
278}
279
280const fn default_download_max_concurrency() -> usize {
281 4
282}
283
284const fn default_document_max_file_size() -> u64 {
285 200 * 1024 * 1024
286}
287
288const fn default_filesystem_output_truncate_limit() -> usize {
289 20_000
290}
291
292const fn default_grep_truncation_threshold() -> usize {
293 30_000
294}
295
296const fn default_grep_truncated_line_max() -> usize {
297 300
298}
299
300const fn default_shell_output_truncate_limit() -> usize {
301 20_000
302}
303
304const fn default_cold_start_tool_return_limit() -> usize {
305 500
306}