mofa_plugins/tools/
json.rs1use super::*;
2use serde_json::json;
3
4pub 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 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 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 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}