limit_cli/tools/browser/
args.rs1use limit_agent::error::AgentError;
7use serde_json::Value;
8
9pub trait ArgsExt {
34 fn get_str(&self, key: &str, action: &str) -> Result<&str, AgentError>;
52
53 fn get_opt_str(&self, key: &str) -> Option<&str>;
70
71 fn get_u64(&self, key: &str, action: &str) -> Result<u64, AgentError>;
89
90 fn get_opt_u64(&self, key: &str) -> Option<u64>;
107
108 fn get_f64(&self, key: &str, action: &str) -> Result<f64, AgentError>;
126
127 fn get_opt_f64(&self, key: &str) -> Option<f64>;
144}
145
146impl ArgsExt for Value {
147 fn get_str(&self, key: &str, action: &str) -> Result<&str, AgentError> {
148 self.get(key).and_then(|v| v.as_str()).ok_or_else(|| {
149 AgentError::ToolError(format!("Missing '{}' argument for {} action", key, action))
150 })
151 }
152
153 fn get_opt_str(&self, key: &str) -> Option<&str> {
154 self.get(key).and_then(|v| v.as_str())
155 }
156
157 fn get_u64(&self, key: &str, action: &str) -> Result<u64, AgentError> {
158 self.get(key).and_then(|v| v.as_u64()).ok_or_else(|| {
159 AgentError::ToolError(format!("Missing '{}' argument for {} action", key, action))
160 })
161 }
162
163 fn get_opt_u64(&self, key: &str) -> Option<u64> {
164 self.get(key).and_then(|v| v.as_u64())
165 }
166
167 fn get_f64(&self, key: &str, action: &str) -> Result<f64, AgentError> {
168 self.get(key).and_then(|v| v.as_f64()).ok_or_else(|| {
169 AgentError::ToolError(format!("Missing '{}' argument for {} action", key, action))
170 })
171 }
172
173 fn get_opt_f64(&self, key: &str) -> Option<f64> {
174 self.get(key).and_then(|v| v.as_f64())
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use super::*;
181
182 #[test]
183 fn test_get_str_success() {
184 let args = serde_json::json!({"url": "https://example.com"});
185 let result = args.get_str("url", "open");
186 assert!(result.is_ok());
187 assert_eq!(result.unwrap(), "https://example.com");
188 }
189
190 #[test]
191 fn test_get_str_missing_key() {
192 let args = serde_json::json!({});
193 let result = args.get_str("url", "open");
194 assert!(result.is_err());
195 let err = result.unwrap_err();
196 assert!(err
197 .to_string()
198 .contains("Missing 'url' argument for open action"));
199 }
200
201 #[test]
202 fn test_get_str_wrong_type() {
203 let args = serde_json::json!({"url": 123});
204 let result = args.get_str("url", "open");
205 assert!(result.is_err());
206 let err = result.unwrap_err();
207 assert!(err
208 .to_string()
209 .contains("Missing 'url' argument for open action"));
210 }
211
212 #[test]
213 fn test_get_opt_str_some() {
214 let args = serde_json::json!({"path": "/tmp/screenshot.png"});
215 let result = args.get_opt_str("path");
216 assert_eq!(result, Some("/tmp/screenshot.png"));
217 }
218
219 #[test]
220 fn test_get_opt_str_none() {
221 let args = serde_json::json!({});
222 let result = args.get_opt_str("path");
223 assert_eq!(result, None);
224 }
225
226 #[test]
227 fn test_get_opt_str_wrong_type() {
228 let args = serde_json::json!({"path": 123});
229 let result = args.get_opt_str("path");
230 assert_eq!(result, None);
231 }
232
233 #[test]
234 fn test_get_u64_success() {
235 let args = serde_json::json!({"index": 42});
236 let result = args.get_u64("index", "tab_select");
237 assert!(result.is_ok());
238 assert_eq!(result.unwrap(), 42);
239 }
240
241 #[test]
242 fn test_get_u64_missing_key() {
243 let args = serde_json::json!({});
244 let result = args.get_u64("index", "tab_select");
245 assert!(result.is_err());
246 let err = result.unwrap_err();
247 assert!(err
248 .to_string()
249 .contains("Missing 'index' argument for tab_select action"));
250 }
251
252 #[test]
253 fn test_get_u64_wrong_type() {
254 let args = serde_json::json!({"index": "not a number"});
255 let result = args.get_u64("index", "tab_select");
256 assert!(result.is_err());
257 }
258
259 #[test]
260 fn test_get_opt_u64_some() {
261 let args = serde_json::json!({"pixels": 1000});
262 let result = args.get_opt_u64("pixels");
263 assert_eq!(result, Some(1000));
264 }
265
266 #[test]
267 fn test_get_opt_u64_none() {
268 let args = serde_json::json!({});
269 let result = args.get_opt_u64("pixels");
270 assert_eq!(result, None);
271 }
272
273 #[test]
274 fn test_get_f64_success() {
275 let args = serde_json::json!({"latitude": 40.7128});
276 let result = args.get_f64("latitude", "set_geo");
277 assert!(result.is_ok());
278 assert_eq!(result.unwrap(), 40.7128);
279 }
280
281 #[test]
282 fn test_get_f64_missing_key() {
283 let args = serde_json::json!({});
284 let result = args.get_f64("latitude", "set_geo");
285 assert!(result.is_err());
286 let err = result.unwrap_err();
287 assert!(err
288 .to_string()
289 .contains("Missing 'latitude' argument for set_geo action"));
290 }
291
292 #[test]
293 fn test_get_f64_wrong_type() {
294 let args = serde_json::json!({"latitude": "not a number"});
295 let result = args.get_f64("latitude", "set_geo");
296 assert!(result.is_err());
297 }
298
299 #[test]
300 fn test_get_opt_f64_some() {
301 let args = serde_json::json!({"scale": 1.5});
302 let result = args.get_opt_f64("scale");
303 assert_eq!(result, Some(1.5));
304 }
305
306 #[test]
307 fn test_get_opt_f64_none() {
308 let args = serde_json::json!({});
309 let result = args.get_opt_f64("scale");
310 assert_eq!(result, None);
311 }
312
313 #[test]
314 fn test_get_u64_with_float() {
315 let args = serde_json::json!({"index": 42u64});
317 let result = args.get_u64("index", "tab_select");
318 assert!(result.is_ok());
319 assert_eq!(result.unwrap(), 42);
320 }
321
322 #[test]
323 fn test_get_f64_with_integer() {
324 let args = serde_json::json!({"scale": 2});
326 let result = args.get_f64("scale", "set_viewport");
327 assert!(result.is_ok());
328 assert_eq!(result.unwrap(), 2.0);
329 }
330}