Skip to main content

agentic_evolve_mcp/tools/
evolve_pattern_store.rs

1//! Tool: evolve_pattern_store — Store a new pattern in the library.
2
3use std::sync::Arc;
4use tokio::sync::Mutex;
5
6use serde::Deserialize;
7use serde_json::{json, Value};
8
9use agentic_evolve_core::types::pattern::{
10    FunctionSignature, Language, ParamSignature, PatternVariable, Visibility,
11};
12
13use crate::session::SessionManager;
14use crate::types::{McpError, McpResult, ToolCallResult, ToolDefinition};
15
16#[derive(Debug, Deserialize)]
17struct StoreParams {
18    name: String,
19    domain: String,
20    language: String,
21    template: String,
22    #[serde(default)]
23    function_name: Option<String>,
24    #[serde(default)]
25    params: Vec<ParamInput>,
26    #[serde(default)]
27    return_type: Option<String>,
28    #[serde(default)]
29    is_async: bool,
30    #[serde(default)]
31    variables: Vec<VariableInput>,
32    #[serde(default = "default_confidence")]
33    confidence: f64,
34    #[serde(default)]
35    tags: Vec<String>,
36}
37
38#[derive(Debug, Deserialize)]
39struct ParamInput {
40    name: String,
41    #[serde(rename = "type", default = "default_type")]
42    param_type: String,
43    #[serde(default)]
44    is_optional: bool,
45}
46
47#[derive(Debug, Deserialize)]
48struct VariableInput {
49    name: String,
50    #[serde(rename = "type", default = "default_type")]
51    var_type: String,
52    #[serde(default)]
53    pattern: Option<String>,
54    #[serde(default)]
55    default: Option<String>,
56}
57
58fn default_confidence() -> f64 {
59    0.8
60}
61
62fn default_type() -> String {
63    "Any".to_string()
64}
65
66/// Return the tool definition for evolve_pattern_store.
67pub fn definition() -> ToolDefinition {
68    ToolDefinition {
69        name: "evolve_pattern_store".to_string(),
70        description: Some("Store a new pattern in the library".to_string()),
71        input_schema: json!({
72            "type": "object",
73            "properties": {
74                "name": {
75                    "type": "string",
76                    "description": "Human-readable pattern name"
77                },
78                "domain": {
79                    "type": "string",
80                    "description": "Domain or category (e.g. 'web', 'cli', 'data')"
81                },
82                "language": {
83                    "type": "string",
84                    "description": "Programming language (rust, python, typescript, etc.)"
85                },
86                "template": {
87                    "type": "string",
88                    "description": "The code template with {{variable}} placeholders"
89                },
90                "function_name": {
91                    "type": "string",
92                    "description": "Function name for the pattern signature"
93                },
94                "params": {
95                    "type": "array",
96                    "items": {
97                        "type": "object",
98                        "properties": {
99                            "name": { "type": "string" },
100                            "type": { "type": "string" },
101                            "is_optional": { "type": "boolean" }
102                        },
103                        "required": ["name"]
104                    },
105                    "description": "Function parameters"
106                },
107                "return_type": {
108                    "type": "string",
109                    "description": "Return type of the function"
110                },
111                "is_async": {
112                    "type": "boolean",
113                    "description": "Whether the function is async"
114                },
115                "variables": {
116                    "type": "array",
117                    "items": {
118                        "type": "object",
119                        "properties": {
120                            "name": { "type": "string" },
121                            "type": { "type": "string" },
122                            "pattern": { "type": "string" },
123                            "default": { "type": "string" }
124                        },
125                        "required": ["name"]
126                    },
127                    "description": "Template variable definitions"
128                },
129                "confidence": {
130                    "type": "number",
131                    "minimum": 0.0,
132                    "maximum": 1.0,
133                    "default": 0.8,
134                    "description": "Initial confidence level (0.0 to 1.0)"
135                },
136                "tags": {
137                    "type": "array",
138                    "items": { "type": "string" },
139                    "description": "Tags for categorization"
140                }
141            },
142            "required": ["name", "domain", "language", "template"]
143        }),
144    }
145}
146
147/// Execute the evolve_pattern_store tool.
148pub async fn execute(
149    args: Value,
150    session: &Arc<Mutex<SessionManager>>,
151) -> McpResult<ToolCallResult> {
152    let params: StoreParams =
153        serde_json::from_value(args).map_err(|e| McpError::InvalidParams(e.to_string()))?;
154
155    if !(0.0..=1.0).contains(&params.confidence) {
156        return Err(McpError::InvalidParams(format!(
157            "confidence must be between 0.0 and 1.0, got {}",
158            params.confidence
159        )));
160    }
161
162    let language = Language::from_name(&params.language);
163    let fn_name = params.function_name.unwrap_or_else(|| params.name.clone());
164
165    let sig_params: Vec<ParamSignature> = params
166        .params
167        .into_iter()
168        .map(|p| ParamSignature {
169            name: p.name,
170            param_type: p.param_type,
171            is_optional: p.is_optional,
172        })
173        .collect();
174
175    let signature = FunctionSignature {
176        name: fn_name,
177        params: sig_params,
178        return_type: params.return_type,
179        language: language.clone(),
180        is_async: params.is_async,
181        visibility: Visibility::Public,
182    };
183
184    let variables: Vec<PatternVariable> = params
185        .variables
186        .into_iter()
187        .map(|v| PatternVariable {
188            name: v.name,
189            var_type: v.var_type,
190            pattern: v.pattern,
191            default: v.default,
192        })
193        .collect();
194
195    let mut session = session.lock().await;
196    let pattern = session
197        .store_pattern(
198            &params.name,
199            &params.domain,
200            language,
201            signature,
202            &params.template,
203            variables,
204            params.confidence,
205            params.tags,
206        )
207        .map_err(|e| McpError::AgenticEvolve(e.to_string()))?;
208
209    Ok(ToolCallResult::json(&json!({
210        "pattern_id": pattern.id.as_str(),
211        "name": pattern.name,
212        "domain": pattern.domain,
213        "language": pattern.language.as_str(),
214        "version": pattern.version,
215        "confidence": pattern.confidence
216    })))
217}