feat(tools): 新增 4 个 agent 工具 —— web_search / web_fetch / calculator / current_datetime
均在 mcp-go,注册即 agent 可见(dispatcher 经 list_tools 动态发现,零改调度代码): - web_search 联网搜索:Tavily(有 TAVILY_API_KEY 则用,干净 JSON)/ DuckDuckGo HTML(免 key 兜底)。 - web_fetch 网页抓取:取 URL → 去脚本样式 → 去标签 → 解实体 → 收敛空白,限 8000 rune; 复用 external_api 的 SSRF 防护(拒环回/内网/元数据 + 重定向校验)。 - calculator 计算器:自研调度场算法求值(+ - * / % ^ 括号、一元负号),杜绝任意代码执行。 - current_datetime 当前时间:含星期与时区(可传 tz)。 测试:单测覆盖 evalArith(含右结合/一元负号/错误用例)、htmlToText(剔脚本样式+解实体)、 ddgUnwrap。live 自主 agent 实测:calculator (123+456)*7→4053、current_datetime 周三、 web_fetch example.com→200、web_search DDG 返回真实结果,全部端到端通过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
package mcp
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEvalArith(t *testing.T) {
|
||||
cases := map[string]float64{
|
||||
"1+2*3": 7,
|
||||
"(1+2)*3": 9,
|
||||
"2^3^2": 512, // 右结合
|
||||
"-3+5": 2,
|
||||
"10/4": 2.5,
|
||||
"10%3": 1,
|
||||
"2*(3+4)-5": 9,
|
||||
"-(2+3)*2": -10,
|
||||
"3.5e1+0.5": 35.5,
|
||||
}
|
||||
for in, want := range cases {
|
||||
got, err := evalArith(in)
|
||||
if err != nil {
|
||||
t.Errorf("evalArith(%q) 报错: %v", in, err)
|
||||
continue
|
||||
}
|
||||
if math.Abs(got-want) > 1e-9 {
|
||||
t.Errorf("evalArith(%q)=%v want %v", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvalArithErrors(t *testing.T) {
|
||||
for _, in := range []string{"1/0", "1+", "(1+2", "1+2)", "rm -rf /", "import os", ""} {
|
||||
if _, err := evalArith(in); err == nil {
|
||||
t.Errorf("evalArith(%q) 应报错但没有", in)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTMLToText(t *testing.T) {
|
||||
in := `<html><head><title>x</title></head><body><script>alert(1)</script>
|
||||
<h1>标题</h1><p>第一段&符号</p><style>.a{}</style><div>第二段</div></body></html>`
|
||||
got := htmlToText(in)
|
||||
if strings.Contains(got, "alert") || strings.Contains(got, ".a{}") {
|
||||
t.Fatalf("脚本/样式未剔除: %q", got)
|
||||
}
|
||||
if !strings.Contains(got, "标题") || !strings.Contains(got, "第一段&符号") || !strings.Contains(got, "第二段") {
|
||||
t.Fatalf("正文/实体提取不正确: %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDDGUnwrap(t *testing.T) {
|
||||
got := ddgUnwrap("//duckduckgo.com/l/?uddg=https%3A%2F%2Fexample.com%2Fa&rut=x")
|
||||
if got != "https://example.com/a" {
|
||||
t.Fatalf("ddgUnwrap 解码错误: %q", got)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user