Skip to main content

mofa_plugins/tools/
calculator.rs

1use super::*;
2use serde_json::json;
3
4/// 计算器工具 - 数学表达式计算
5pub 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}