1use serde::Serialize;
17
18#[derive(Debug, Clone, Serialize)]
20pub struct ToolMeta {
21 pub name: &'static str,
23 pub description_key: &'static str,
25 pub category: &'static str,
27}
28
29impl ToolMeta {
30 pub const fn new(
31 name: &'static str,
32 description_key: &'static str,
33 category: &'static str,
34 ) -> Self {
35 Self {
36 name,
37 description_key,
38 category,
39 }
40 }
41}
42
43pub fn known_tools() -> &'static [ToolMeta] {
49 TOOL_CATALOG
50}
51
52const TOOL_CATALOG: &[ToolMeta] = &[
53 ToolMeta::new("read", "tools.read", "fs"),
55 ToolMeta::new("write", "tools.write", "fs"),
56 ToolMeta::new("edit", "tools.edit", "fs"),
57 ToolMeta::new("grep", "tools.grep", "fs"),
58 ToolMeta::new("find", "tools.find", "fs"),
59 ToolMeta::new("ls", "tools.ls", "fs"),
60 ToolMeta::new("web_search", "tools.webSearch", "comms"),
61 ToolMeta::new("get_search_results", "tools.getSearchResults", "comms"),
62 ToolMeta::new("exec", "tools.exec", "exec"),
64 ToolMeta::new("browse", "tools.browse", "comms"),
65 ToolMeta::new("memory_read", "tools.memoryRead", "memory"),
66 ToolMeta::new("memory_write", "tools.memoryWrite", "memory"),
67 ToolMeta::new("memory_search", "tools.memorySearch", "memory"),
68 ToolMeta::new("project", "tools.project", "system"),
69 ToolMeta::new("kernel_agent", "tools.kernelAgent", "system"),
70 ToolMeta::new("a2a_delegate", "tools.a2aDelegate", "a2a"),
71 ToolMeta::new("a2a_send", "tools.a2aSend", "a2a"),
72 ToolMeta::new("a2a_query", "tools.a2aQuery", "a2a"),
73 ToolMeta::new("persona", "tools.persona", "system"),
74 ToolMeta::new("cron", "tools.cron", "system"),
75 ToolMeta::new("security", "tools.security", "system"),
76 ToolMeta::new("budget", "tools.budget", "system"),
77 ToolMeta::new("resource", "tools.resource", "system"),
78 ToolMeta::new("knowledge", "tools.knowledge", "system"),
79 ToolMeta::new("calendar", "tools.calendar", "system"),
80 ToolMeta::new("send_email", "tools.sendEmail", "comms"),
81];
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn catalog_is_populated() {
89 let tools = known_tools();
90 assert!(!tools.is_empty(), "tool catalog should not be empty");
91 assert!(
92 tools.iter().any(|t| t.name == "read"),
93 "read tool should be in catalog"
94 );
95 assert!(
96 tools.iter().any(|t| t.name == "exec"),
97 "exec tool should be in catalog"
98 );
99 assert!(
100 tools.iter().any(|t| t.name == "memory_read"),
101 "memory_read should be in catalog"
102 );
103 }
104
105 #[test]
106 fn all_tools_have_required_fields() {
107 for tool in known_tools() {
108 assert!(!tool.name.is_empty(), "tool name should not be empty");
109 assert!(
110 !tool.description_key.is_empty(),
111 "description_key should not be empty"
112 );
113 assert!(!tool.category.is_empty(), "category should not be empty");
114 }
115 }
116
117 #[test]
118 fn no_duplicate_names() {
119 let names: Vec<&str> = known_tools().iter().map(|t| t.name).collect();
120 let mut sorted = names.clone();
121 sorted.sort();
122 sorted.dedup();
123 assert_eq!(names.len(), sorted.len(), "duplicate tool names found");
124 }
125}