Skip to main content

mofa_plugins/tools/
json.rs

1use super::*;
2use serde_json::json;
3
4/// JSON 处理工具 - JSON 解析和操作
5pub struct JsonTool {
6    definition: ToolDefinition,
7}
8
9impl Default for JsonTool {
10    fn default() -> Self {
11        Self::new()
12    }
13}
14
15impl JsonTool {
16    pub fn new() -> Self {
17        Self {
18            definition: ToolDefinition {
19                name: "json".to_string(),
20                description: "JSON operations: parse, stringify, query with JSONPath-like syntax, merge objects.".to_string(),
21                parameters: json!({
22                    "type": "object",
23                    "properties": {
24                        "operation": {
25                            "type": "string",
26                            "enum": ["parse", "stringify", "get", "set", "merge", "keys", "values"],
27                            "description": "JSON operation to perform"
28                        },
29                        "data": {
30                            "description": "JSON data (string for parse, object/array for others)"
31                        },
32                        "path": {
33                            "type": "string",
34                            "description": "Dot-notation path for get/set operations (e.g., 'user.name')"
35                        },
36                        "value": {
37                            "description": "Value to set (for set operation)"
38                        },
39                        "other": {
40                            "type": "object",
41                            "description": "Object to merge with (for merge operation)"
42                        }
43                    },
44                    "required": ["operation", "data"]
45                }),
46                requires_confirmation: false,
47            },
48        }
49    }
50
51    fn get_by_path<'a>(value: &'a serde_json::Value, path: &str) -> Option<&'a serde_json::Value> {
52        let parts: Vec<&str> = path.split('.').collect();
53        let mut current = value;
54
55        for part in parts {
56            if part.is_empty() {
57                continue;
58            }
59            // Check if it's an array index
60            if let Ok(index) = part.parse::<usize>() {
61                current = current.get(index)?;
62            } else {
63                current = current.get(part)?;
64            }
65        }
66
67        Some(current)
68    }
69
70    fn set_by_path(
71        value: &mut serde_json::Value,
72        path: &str,
73        new_value: serde_json::Value,
74    ) -> PluginResult<()> {
75        let parts: Vec<&str> = path.split('.').collect();
76        let mut current = value;
77
78        for (i, part) in parts.iter().enumerate() {
79            if i == parts.len() - 1 {
80                // Last part - set the value
81                if let Ok(index) = part.parse::<usize>() {
82                    if let Some(arr) = current.as_array_mut()
83                        && index < arr.len()
84                    {
85                        arr[index] = new_value;
86                        return Ok(());
87                    }
88                } else if let Some(obj) = current.as_object_mut() {
89                    obj.insert(part.to_string(), new_value);
90                    return Ok(());
91                }
92                return Err(anyhow::anyhow!("Cannot set value at path"));
93            } else {
94                // Navigate to next level
95                if let Ok(index) = part.parse::<usize>() {
96                    current = current
97                        .get_mut(index)
98                        .ok_or_else(|| anyhow::anyhow!("Invalid path"))?;
99                } else {
100                    current = current
101                        .get_mut(*part)
102                        .ok_or_else(|| anyhow::anyhow!("Invalid path"))?;
103                }
104            }
105        }
106
107        Ok(())
108    }
109}
110
111#[async_trait::async_trait]
112impl ToolExecutor for JsonTool {
113    fn definition(&self) -> &ToolDefinition {
114        &self.definition
115    }
116
117    async fn execute(&self, arguments: serde_json::Value) -> PluginResult<serde_json::Value> {
118        let operation = arguments["operation"]
119            .as_str()
120            .ok_or_else(|| anyhow::anyhow!("Operation is required"))?;
121
122        match operation {
123            "parse" => {
124                let data = arguments["data"]
125                    .as_str()
126                    .ok_or_else(|| anyhow::anyhow!("String data is required for parse"))?;
127                let parsed: serde_json::Value = serde_json::from_str(data)?;
128                Ok(json!({
129                    "success": true,
130                    "result": parsed
131                }))
132            }
133            "stringify" => {
134                let data = &arguments["data"];
135                let pretty = arguments
136                    .get("pretty")
137                    .and_then(|p| p.as_bool())
138                    .unwrap_or(true);
139                let result = if pretty {
140                    serde_json::to_string_pretty(data)?
141                } else {
142                    serde_json::to_string(data)?
143                };
144                Ok(json!({
145                    "success": true,
146                    "result": result
147                }))
148            }
149            "get" => {
150                let path = arguments["path"]
151                    .as_str()
152                    .ok_or_else(|| anyhow::anyhow!("Path is required for get operation"))?;
153                let data = &arguments["data"];
154                let result = Self::get_by_path(data, path);
155                Ok(json!({
156                    "success": result.is_some(),
157                    "result": result
158                }))
159            }
160            "set" => {
161                let path = arguments["path"]
162                    .as_str()
163                    .ok_or_else(|| anyhow::anyhow!("Path is required for set operation"))?;
164                let value = arguments
165                    .get("value")
166                    .ok_or_else(|| anyhow::anyhow!("Value is required for set operation"))?
167                    .clone();
168                let mut data = arguments["data"].clone();
169                Self::set_by_path(&mut data, path, value)?;
170                Ok(json!({
171                    "success": true,
172                    "result": data
173                }))
174            }
175            "merge" => {
176                let mut data = arguments["data"]
177                    .as_object()
178                    .ok_or_else(|| anyhow::anyhow!("Data must be an object for merge"))?
179                    .clone();
180                let other = arguments["other"]
181                    .as_object()
182                    .ok_or_else(|| anyhow::anyhow!("Other must be an object for merge"))?;
183                for (k, v) in other {
184                    data.insert(k.clone(), v.clone());
185                }
186                Ok(json!({
187                    "success": true,
188                    "result": data
189                }))
190            }
191            "keys" => {
192                let data = arguments["data"]
193                    .as_object()
194                    .ok_or_else(|| anyhow::anyhow!("Data must be an object for keys"))?;
195                let keys: Vec<&String> = data.keys().collect();
196                Ok(json!({
197                    "success": true,
198                    "result": keys
199                }))
200            }
201            "values" => {
202                let data = arguments["data"]
203                    .as_object()
204                    .ok_or_else(|| anyhow::anyhow!("Data must be an object for values"))?;
205                let values: Vec<&serde_json::Value> = data.values().collect();
206                Ok(json!({
207                    "success": true,
208                    "result": values
209                }))
210            }
211            _ => Err(anyhow::anyhow!("Unknown operation: {}", operation)),
212        }
213    }
214}