Files
AX-Copilot-Codex/src/AxCopilot/Services/Agent/MathTool.cs

67 lines
2.4 KiB
C#

using System.Data;
using System.Text.Json;
namespace AxCopilot.Services.Agent;
/// <summary>수학 수식을 계산하는 도구.</summary>
public class MathTool : IAgentTool
{
public string Name => "math_eval";
public string Description =>
"Evaluate a mathematical expression and return the result. " +
"Supports: +, -, *, /, %, parentheses, and common math operations. " +
"Use for calculations, unit conversions, and numeric analysis.";
public ToolParameterSchema Parameters => new()
{
Properties = new()
{
["expression"] = new()
{
Type = "string",
Description = "Mathematical expression to evaluate (e.g. '(100 * 1.08) / 3')",
},
["precision"] = new()
{
Type = "integer",
Description = "Decimal places for rounding (default: 6)",
},
},
Required = ["expression"],
};
public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
{
var expression = args.GetProperty("expression").GetString() ?? "";
var precision = args.TryGetProperty("precision", out var p) ? p.GetInt32() : 6;
if (string.IsNullOrWhiteSpace(expression))
return Task.FromResult(ToolResult.Fail("수식이 비어 있습니다."));
try
{
// DataTable.Compute를 사용한 안전한 수식 평가
var sanitized = expression
.Replace("^", " ") // XOR 방지 — ** 패턴은 아래에서 처리
.Replace("Math.", "")
.Replace("System.", "");
// 기본 보안 검사: 알파벳 함수 호출 차단
if (System.Text.RegularExpressions.Regex.IsMatch(sanitized, @"[a-zA-Z]{3,}"))
return Task.FromResult(ToolResult.Fail("함수 호출은 지원하지 않습니다. 기본 사칙연산만 가능합니다."));
var dt = new DataTable();
var result = dt.Compute(sanitized, null);
var value = Convert.ToDouble(result);
var rounded = Math.Round(value, precision);
return Task.FromResult(ToolResult.Ok(
$"Expression: {expression}\nResult: {rounded}"));
}
catch (Exception ex)
{
return Task.FromResult(ToolResult.Fail($"수식 평가 오류: {ex.Message}"));
}
}
}