mofa_plugins/tools/
calculator.rs1use super::*;
2use serde_json::json;
3
4pub struct CalculatorTool {
6 definition: ToolDefinition,
7}
8
9impl Default for CalculatorTool {
10 fn default() -> Self {
11 Self::new()
12 }
13}
14
15impl CalculatorTool {
16 pub fn new() -> Self {
17 Self {
18 definition: ToolDefinition {
19 name: "calculator".to_string(),
20 description: "Perform mathematical calculations: basic arithmetic, powers, roots, trigonometry.".to_string(),
21 parameters: json!({
22 "type": "object",
23 "properties": {
24 "operation": {
25 "type": "string",
26 "enum": ["add", "subtract", "multiply", "divide", "power", "sqrt", "sin", "cos", "tan", "log", "ln", "abs", "floor", "ceil", "round"],
27 "description": "Mathematical operation"
28 },
29 "a": {
30 "type": "number",
31 "description": "First operand"
32 },
33 "b": {
34 "type": "number",
35 "description": "Second operand (for binary operations)"
36 }
37 },
38 "required": ["operation", "a"]
39 }),
40 requires_confirmation: false,
41 },
42 }
43 }
44}
45
46#[async_trait::async_trait]
47impl ToolExecutor for CalculatorTool {
48 fn definition(&self) -> &ToolDefinition {
49 &self.definition
50 }
51
52 async fn execute(&self, arguments: serde_json::Value) -> PluginResult<serde_json::Value> {
53 let operation = arguments["operation"]
54 .as_str()
55 .ok_or_else(|| anyhow::anyhow!("Operation is required"))?;
56 let a = arguments["a"]
57 .as_f64()
58 .ok_or_else(|| anyhow::anyhow!("Operand 'a' is required"))?;
59
60 let result = match operation {
61 "add" => {
62 let b = arguments["b"]
63 .as_f64()
64 .ok_or_else(|| anyhow::anyhow!("Operand 'b' is required for add"))?;
65 a + b
66 }
67 "subtract" => {
68 let b = arguments["b"]
69 .as_f64()
70 .ok_or_else(|| anyhow::anyhow!("Operand 'b' is required for subtract"))?;
71 a - b
72 }
73 "multiply" => {
74 let b = arguments["b"]
75 .as_f64()
76 .ok_or_else(|| anyhow::anyhow!("Operand 'b' is required for multiply"))?;
77 a * b
78 }
79 "divide" => {
80 let b = arguments["b"]
81 .as_f64()
82 .ok_or_else(|| anyhow::anyhow!("Operand 'b' is required for divide"))?;
83 if b == 0.0 {
84 return Err(anyhow::anyhow!("Division by zero"));
85 }
86 a / b
87 }
88 "power" => {
89 let b = arguments["b"]
90 .as_f64()
91 .ok_or_else(|| anyhow::anyhow!("Operand 'b' is required for power"))?;
92 a.powf(b)
93 }
94 "sqrt" => {
95 if a < 0.0 {
96 return Err(anyhow::anyhow!(
97 "Cannot compute square root of negative number"
98 ));
99 }
100 a.sqrt()
101 }
102 "sin" => a.sin(),
103 "cos" => a.cos(),
104 "tan" => a.tan(),
105 "log" => {
106 let base = arguments["b"].as_f64().unwrap_or(10.0);
107 a.log(base)
108 }
109 "ln" => a.ln(),
110 "abs" => a.abs(),
111 "floor" => a.floor(),
112 "ceil" => a.ceil(),
113 "round" => a.round(),
114 _ => return Err(anyhow::anyhow!("Unknown operation: {}", operation)),
115 };
116
117 Ok(json!({
118 "operation": operation,
119 "operands": { "a": a, "b": arguments.get("b") },
120 "result": result
121 }))
122 }
123}