agentic_evolve_mcp/protocol/
compact.rs1use serde_json::Value;
7
8use crate::types::ToolDefinition;
9
10struct FacadeGroup {
12 name: &'static str,
13 description: &'static str,
14 operations: &'static [&'static str],
15}
16
17const FACADES: &[FacadeGroup] = &[
18 FacadeGroup {
19 name: "evolve_patterns",
20 description: "Store, retrieve, delete, search, and list evolution patterns",
21 operations: &[
22 "pattern_store",
23 "pattern_get",
24 "pattern_delete",
25 "pattern_search",
26 "pattern_list",
27 ],
28 },
29 FacadeGroup {
30 name: "evolve_matching",
31 description: "Match patterns by signature or context, crystallize, compose, and retrieve bodies",
32 operations: &[
33 "match_signature",
34 "match_context",
35 "crystallize",
36 "compose",
37 "get_body",
38 ],
39 },
40 FacadeGroup {
41 name: "evolve_analytics",
42 description: "Check coverage and confidence, update usage stats, and optimize the pattern library",
43 operations: &[
44 "coverage",
45 "confidence",
46 "update_usage",
47 "optimize",
48 ],
49 },
50];
51
52pub fn is_compact_mode() -> bool {
54 let val = std::env::var("AEVOLVE_MCP_TOOL_SURFACE")
55 .or_else(|_| std::env::var("MCP_TOOL_SURFACE"))
56 .unwrap_or_default();
57 val.eq_ignore_ascii_case("compact")
58}
59
60pub fn compact_tool_definitions() -> Vec<ToolDefinition> {
62 FACADES
63 .iter()
64 .map(|f| {
65 let ops_enum: Vec<Value> = f
66 .operations
67 .iter()
68 .map(|o| Value::String(o.to_string()))
69 .collect();
70
71 ToolDefinition {
72 name: f.name.to_string(),
73 description: Some(f.description.to_string()),
74 input_schema: serde_json::json!({
75 "type": "object",
76 "properties": {
77 "operation": {
78 "type": "string",
79 "enum": ops_enum,
80 "description": "Operation to perform"
81 },
82 "params": {
83 "type": "object",
84 "description": "Parameters for the operation"
85 }
86 },
87 "required": ["operation"]
88 }),
89 }
90 })
91 .collect()
92}
93
94pub fn normalize_compact_call(
99 facade_name: &str,
100 arguments: &Option<Value>,
101) -> Option<(String, Option<Value>)> {
102 let facade = FACADES.iter().find(|f| f.name == facade_name)?;
103
104 let args = arguments.as_ref().unwrap_or(&Value::Null);
105 let operation = args.get("operation").and_then(|v| v.as_str())?;
106
107 if !facade.operations.contains(&operation) {
108 return None;
109 }
110
111 let real_name = format!("evolve_{}", operation);
112 let params = args.get("params").cloned();
113
114 Some((real_name, params))
115}
116
117pub fn is_compact_facade(name: &str) -> bool {
119 FACADES.iter().any(|f| f.name == name)
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn compact_definitions_count() {
128 let defs = compact_tool_definitions();
129 assert_eq!(defs.len(), 3);
130 assert_eq!(defs[0].name, "evolve_patterns");
131 assert_eq!(defs[1].name, "evolve_matching");
132 assert_eq!(defs[2].name, "evolve_analytics");
133 }
134
135 #[test]
136 fn normalize_patterns_facade() {
137 let args = Some(serde_json::json!({
138 "operation": "pattern_store",
139 "params": { "name": "test", "domain": "web" }
140 }));
141 let (name, params) = normalize_compact_call("evolve_patterns", &args).unwrap();
142 assert_eq!(name, "evolve_pattern_store");
143 assert_eq!(
144 params.unwrap().get("name").unwrap().as_str().unwrap(),
145 "test"
146 );
147 }
148
149 #[test]
150 fn normalize_matching_facade() {
151 let args = Some(serde_json::json!({
152 "operation": "crystallize",
153 "params": { "pattern_id": "p1" }
154 }));
155 let (name, _) = normalize_compact_call("evolve_matching", &args).unwrap();
156 assert_eq!(name, "evolve_crystallize");
157 }
158
159 #[test]
160 fn normalize_analytics_facade() {
161 let args = Some(serde_json::json!({
162 "operation": "coverage",
163 "params": {}
164 }));
165 let (name, _) = normalize_compact_call("evolve_analytics", &args).unwrap();
166 assert_eq!(name, "evolve_coverage");
167 }
168
169 #[test]
170 fn normalize_unknown_facade_returns_none() {
171 let args = Some(serde_json::json!({ "operation": "pattern_store" }));
172 assert!(normalize_compact_call("evolve_unknown", &args).is_none());
173 }
174
175 #[test]
176 fn normalize_invalid_operation_returns_none() {
177 let args = Some(serde_json::json!({ "operation": "nonexistent" }));
178 assert!(normalize_compact_call("evolve_patterns", &args).is_none());
179 }
180
181 #[test]
182 fn is_compact_facade_checks() {
183 assert!(is_compact_facade("evolve_patterns"));
184 assert!(is_compact_facade("evolve_matching"));
185 assert!(is_compact_facade("evolve_analytics"));
186 assert!(!is_compact_facade("evolve_pattern_store"));
187 }
188
189 #[test]
190 fn compact_mode_off_by_default() {
191 assert!(!is_compact_mode());
194 }
195}