1pub struct ToolMeta {
2 pub name: &'static str,
3 pub write: bool,
4}
5
6pub const ALL_TOOLS: &[ToolMeta] = &[
7 ToolMeta { name: "create_entities", write: true },
8 ToolMeta { name: "create_relations", write: true },
9 ToolMeta { name: "add_observations", write: true },
10 ToolMeta { name: "delete_entities", write: true },
11 ToolMeta { name: "delete_observations",write: true },
12 ToolMeta { name: "delete_relations", write: true },
13 ToolMeta { name: "read_graph", write: false },
14 ToolMeta { name: "search_nodes", write: false },
15 ToolMeta { name: "open_nodes", write: false },
16 ToolMeta { name: "get_entity", write: false },
17 ToolMeta { name: "graph_stats", write: false },
18 ToolMeta { name: "search_relations", write: false },
19 ToolMeta { name: "find_path", write: false },
20 ToolMeta { name: "compact", write: true },
21 ToolMeta { name: "get_neighbors", write: false },
22 ToolMeta { name: "describe_entity", write: false },
23 ToolMeta { name: "list_entity_types", write: false },
24 ToolMeta { name: "list_relation_types",write: false },
25 ToolMeta { name: "upsert_entities", write: true },
26 ToolMeta { name: "export_graph", write: false },
27];
28
29#[inline]
30pub fn tool_exists(name: &str) -> bool {
31 ALL_TOOLS.iter().any(|t| t.name == name)
32}
33
34#[inline]
35pub fn is_write_tool(name: &str) -> bool {
36 ALL_TOOLS.iter().find(|t| t.name == name).map(|t| t.write).unwrap_or(false)
37}
38
39#[cfg(test)]
40mod tests {
41 use super::*;
42
43 #[test]
44 fn test_tool_exists_known() {
45 assert!(tool_exists("create_entities"));
46 assert!(tool_exists("read_graph"));
47 assert!(tool_exists("search_nodes"));
48 }
49
50 #[test]
51 fn test_tool_exists_unknown() {
52 assert!(!tool_exists("nonexistent_tool"));
53 }
54
55 #[test]
56 fn test_is_write_tool() {
57 assert!(is_write_tool("create_entities"));
58 assert!(is_write_tool("delete_entities"));
59 assert!(!is_write_tool("read_graph"));
60 assert!(!is_write_tool("search_nodes"));
61 }
62
63 #[test]
64 fn test_all_tools_unique() {
65 let mut names: Vec<&str> = ALL_TOOLS.iter().map(|t| t.name).collect();
66 names.sort();
67 names.dedup();
68 assert_eq!(names.len(), ALL_TOOLS.len(), "Duplicate tool names");
69 }
70
71 #[test]
72 fn test_tools_json_matches_all_tools() {
73 let tools_json = include_str!("../tools.json");
74 let parsed: Vec<serde_json::Value> =
75 serde_json::from_str(tools_json).expect("tools.json must be valid JSON");
76
77 let mut json_names: Vec<&str> = parsed
78 .iter()
79 .map(|t| t["name"].as_str().expect("each tool needs a name"))
80 .collect();
81 let mut meta_names: Vec<&str> = ALL_TOOLS.iter().map(|t| t.name).collect();
82 json_names.sort_unstable();
83 meta_names.sort_unstable();
84
85 assert_eq!(
86 json_names, meta_names,
87 "tools.json and ALL_TOOLS must declare the same tool names"
88 );
89 }
90}