matrixcode_core/tools/
webfetch.rs1use anyhow::Result;
2use async_trait::async_trait;
3use serde_json::{Value, json};
4
5use super::{Tool, ToolDefinition};
6
7pub struct WebFetchTool;
8
9#[async_trait]
10impl Tool for WebFetchTool {
11 fn definition(&self) -> ToolDefinition {
12 ToolDefinition {
13 name: "webfetch".to_string(),
14 description: "从 URL 获取内容并返回为文本".to_string(),
15 parameters: json!({
16 "type": "object",
17 "properties": {
18 "url": {
19 "type": "string",
20 "description": "要获取的 URL"
21 },
22 "max_length": {
23 "type": "integer",
24 "description": "最大响应长度(字符数,默认 10000)"
25 }
26 },
27 "required": ["url"]
28 }),
29 ..Default::default()
30 }
31 }
32
33 async fn execute(&self, params: Value) -> Result<String> {
34 let url = params["url"]
35 .as_str()
36 .ok_or_else(|| anyhow::anyhow!("missing 'url'"))?;
37 let max_length = params["max_length"].as_u64().unwrap_or(10000) as usize;
38
39 let response = reqwest::get(url).await?;
43 let status = response.status();
44
45 if !status.is_success() {
46 anyhow::bail!("HTTP {} for {}", status, url);
48 }
49
50 let body = response.text().await?;
51
52 let truncated = if body.len() > max_length {
53 let end = body.floor_char_boundary(max_length);
55 format!(
56 "{}...\n\n(truncated, {} total bytes)",
57 &body[..end],
58 body.len()
59 )
60 } else {
61 body
62 };
63
64 Ok(truncated)
66 }
67}