Skip to main content

matrixcode_core/tools/
mod.rs

1pub mod ask;
2pub mod bash;
3pub mod edit;
4pub mod glob;
5pub mod grep;
6pub mod ls;
7pub mod monitor;
8pub mod multi_edit;
9pub mod plan_mode;
10pub mod read;
11pub mod search;
12pub mod skill;
13pub mod task;
14pub mod todo_write;
15pub mod webfetch;
16pub mod websearch;
17pub mod write;
18
19use std::sync::Arc;
20
21use anyhow::Result;
22use async_trait::async_trait;
23use serde::{Deserialize, Serialize};
24use serde_json::Value;
25
26use crate::approval::RiskLevel;
27use crate::skills::Skill;
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct ToolDefinition {
31    pub name: String,
32    pub description: String,
33    pub parameters: Value,
34}
35
36#[async_trait]
37pub trait Tool: Send + Sync {
38    fn definition(&self) -> ToolDefinition;
39    async fn execute(&self, params: Value) -> Result<String>;
40
41    /// Risk level of this tool. Defaults to Safe (read-only).
42    /// Override in tools that modify state.
43    fn risk_level(&self) -> RiskLevel {
44        RiskLevel::Safe
45    }
46}
47
48/// Default toolset without any skill integration. Kept for callers
49/// (and the existing tests) that don't care about skills.
50pub fn all_tools() -> Vec<Box<dyn Tool>> {
51    all_tools_with_skills(Arc::new(Vec::new()))
52}
53
54/// Build the toolset and include the `skill` tool bound to the given
55/// skills catalogue. The catalogue can be empty; the tool still works
56/// but will only report "no skills loaded" if invoked.
57pub fn all_tools_with_skills(skills: Arc<Vec<Skill>>) -> Vec<Box<dyn Tool>> {
58    vec![
59        Box::new(ask::AskTool),
60        Box::new(read::ReadTool),
61        Box::new(write::WriteTool),
62        Box::new(edit::EditTool),
63        Box::new(multi_edit::MultiEditTool),
64        Box::new(search::SearchTool),
65        Box::new(grep::GrepTool),
66        Box::new(glob::GlobTool),
67        Box::new(ls::LsTool),
68        Box::new(bash::BashTool),
69        Box::new(todo_write::TodoWriteTool),
70        Box::new(websearch::WebSearchTool),
71        Box::new(webfetch::WebFetchTool),
72        Box::new(skill::SkillTool::new(skills)),
73        // New high-priority tools
74        Box::new(task::TaskTool),
75        Box::new(task::TaskCreateTool),
76        Box::new(task::TaskGetTool),
77        Box::new(task::TaskListTool),
78        Box::new(task::TaskStopTool),
79        Box::new(plan_mode::EnterPlanModeTool),
80        Box::new(plan_mode::ExitPlanModeTool),
81        Box::new(monitor::MonitorTool),
82    ]
83}
84
85/// Generate tools description for system prompt
86pub fn generate_tools_prompt() -> String {
87    let tools = all_tools();
88    let mut lines = vec!["可用工具:".to_string()];
89
90    for tool in tools {
91        let def = tool.definition();
92        // Extract brief description (first sentence or up to 50 chars)
93        let brief = def
94            .description
95            .split('.')
96            .next()
97            .or_else(|| def.description.split('\n').next())
98            .unwrap_or(&def.description);
99        let brief = if brief.len() > 60 {
100            format!("{}...", brief.chars().take(57).collect::<String>())
101        } else {
102            brief.to_string()
103        };
104        lines.push(format!("- {}: {}", def.name, brief));
105    }
106
107    lines.join("\n")
108}