Skip to main content

matrixcode_core/command/handlers/
tools.rs

1//! /tools 命令处理器
2
3use std::future::Future;
4use std::pin::Pin;
5
6use crate::command::{BackendContext, Command};
7
8pub struct Tools;
9
10impl Command for Tools {
11    fn name(&self) -> &'static str {
12        "tools"
13    }
14
15    fn help(&self) -> Option<&'static str> {
16        Some("列出可用工具")
17    }
18
19    fn execute<'a>(
20        &'a self,
21        ctx: &'a mut BackendContext<'_>,
22    ) -> Pin<Box<dyn Future<Output = bool> + Send + 'a>> {
23        Box::pin(async move {
24            let tools = ctx.agent.get_tools();
25            let mut info = format!("🔧 可用工具:{}\n\n", tools.len());
26
27            // 按类别分组
28            let mut core_tools: Vec<_> = Vec::new();
29            let mut file_tools: Vec<_> = Vec::new();
30            let mut search_tools: Vec<_> = Vec::new();
31            let mut web_tools: Vec<_> = Vec::new();
32            let mut code_tools: Vec<_> = Vec::new();
33            let mut mcp_tools: Vec<_> = Vec::new();
34            let mut workflow_tools: Vec<_> = Vec::new();
35            let mut other_tools: Vec<_> = Vec::new();
36
37            for tool in tools.iter() {
38                let def = tool.definition();
39                let name = def.name.as_str();
40                let desc = def.description.as_str();
41
42                if name.starts_with("mcp_") || name.starts_with("mcp__") {
43                    mcp_tools.push(tool);
44                } else if name.starts_with("workflow_") || name.contains("workflow") {
45                    workflow_tools.push(tool);
46                } else if name.starts_with("code_") || desc.contains("CodeGraph") {
47                    code_tools.push(tool);
48                } else if name.starts_with("proxy_") || desc.contains("代理") {
49                    other_tools.push(tool);
50                } else {
51                    match name {
52                        "read" | "write" | "edit" | "multi_edit" | "ls" => file_tools.push(tool),
53                        "grep" | "glob" | "search" => search_tools.push(tool),
54                        "websearch" | "webfetch" => web_tools.push(tool),
55                        "bash" | "task" | "todo_write" | "notebook_edit" | "task_create"
56                        | "task_get" | "task_list" | "task_stop" => core_tools.push(tool),
57                        "ask" | "enter_plan_mode" | "exit_plan_mode" | "monitor" => {
58                            core_tools.push(tool)
59                        }
60                        _ => other_tools.push(tool),
61                    }
62                }
63            }
64
65            if !core_tools.is_empty() {
66                info.push_str("📁 核心:\n");
67                for tool in core_tools.iter().take(12) {
68                    let def = tool.definition();
69                    info.push_str(&format!(
70                        "  {} - {}\n",
71                        def.name,
72                        truncate_description(&def.description, 35)
73                    ));
74                }
75            }
76
77            if !file_tools.is_empty() {
78                info.push_str("\n📄 文件:\n");
79                for tool in file_tools.iter() {
80                    let def = tool.definition();
81                    info.push_str(&format!(
82                        "  {} - {}\n",
83                        def.name,
84                        truncate_description(&def.description, 35)
85                    ));
86                }
87            }
88
89            if !search_tools.is_empty() {
90                info.push_str("\n🔍 搜索:\n");
91                for tool in search_tools.iter() {
92                    let def = tool.definition();
93                    info.push_str(&format!(
94                        "  {} - {}\n",
95                        def.name,
96                        truncate_description(&def.description, 35)
97                    ));
98                }
99            }
100
101            if !code_tools.is_empty() {
102                info.push_str("\n📊 CodeGraph:\n");
103                for tool in code_tools.iter() {
104                    let def = tool.definition();
105                    info.push_str(&format!(
106                        "  {} - {}\n",
107                        def.name,
108                        truncate_description(&def.description, 35)
109                    ));
110                }
111            }
112
113            if !web_tools.is_empty() {
114                info.push_str("\n🌐 网络:\n");
115                for tool in web_tools.iter() {
116                    let def = tool.definition();
117                    info.push_str(&format!(
118                        "  {} - {}\n",
119                        def.name,
120                        truncate_description(&def.description, 35)
121                    ));
122                }
123            }
124
125            if !workflow_tools.is_empty() {
126                info.push_str("\n🔄 工作流:\n");
127                for tool in workflow_tools.iter().take(10) {
128                    let def = tool.definition();
129                    info.push_str(&format!(
130                        "  {} - {}\n",
131                        def.name,
132                        truncate_description(&def.description, 35)
133                    ));
134                }
135            }
136
137            if !mcp_tools.is_empty() {
138                info.push_str("\n🔌 MCP:\n");
139                for tool in mcp_tools.iter().take(15) {
140                    let def = tool.definition();
141                    info.push_str(&format!(
142                        "  {} - {}\n",
143                        def.name,
144                        truncate_description(&def.description, 35)
145                    ));
146                }
147                if mcp_tools.len() > 15 {
148                    info.push_str(&format!("  (+ {} 个更多)\n", mcp_tools.len() - 15));
149                }
150            }
151
152            if !other_tools.is_empty() {
153                info.push_str("\n🔧 其他:\n");
154                for tool in other_tools.iter().take(10) {
155                    let def = tool.definition();
156                    info.push_str(&format!(
157                        "  {} - {}\n",
158                        def.name,
159                        truncate_description(&def.description, 35)
160                    ));
161                }
162                if other_tools.len() > 10 {
163                    info.push_str(&format!("  (+ {} 个更多)\n", other_tools.len() - 10));
164                }
165            }
166
167            let _ = ctx
168                .event_tx
169                .send(crate::AgentEvent::progress(info, None))
170                .await;
171            false
172        })
173    }
174}
175
176fn truncate_description(desc: &str, max_len: usize) -> String {
177    let first_line = desc.lines().next().unwrap_or(desc);
178    let chars: Vec<char> = first_line.chars().collect();
179    if chars.len() > max_len {
180        chars[..max_len.saturating_sub(3)]
181            .iter()
182            .collect::<String>()
183            + "..."
184    } else {
185        first_line.to_string()
186    }
187}