Files
dingtalk-workspace-cli/internal/generator/agentmetadata/interface_metadata_test.go

110 lines
4.6 KiB
Go

// Copyright 2026 Alibaba Group
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
package agentmetadata
import "testing"
func TestGenerateUsesMCPDescriptionsAsUnreviewedFallback(t *testing.T) {
root := t.TempDir()
writeFixture(t, root, "skills/mono/SKILL.md", "# DWS\n## 意图判断决策树\n用户提到\"日程\" -> `calendar`\n")
writeFixture(t, root, "skills/mono/references/intent-guide.md", "# Intent guide\n")
writeFixture(t, root, "skills/mono/references/products/calendar.md", "# Calendar\n")
writeFixture(t, root, "internal/cli/schema_hints/imported/wukong.json", `{
"version": 1,
"source": {"kind": "imported", "name": "dws-wukong", "revision": "1234567890abcdef"},
"tools": {
"calendar.get_calendar": {"agent_summary": "读取指定日历"}
}
}`)
writeFixture(t, root, "internal/cli/schema_mcp_metadata.json", `{
"version": 1,
"source": "mcp-tools-list+cli-registry",
"source_revision": "abcdef1234567890",
"source_hash": "sha256:interface",
"tools": {
"calendar.get_calendar": {"description": "MCP 原始读取描述。"},
"calendar.list_calendars": {
"description": "列出当前用户可访问的日历。后续句子不应进入 summary。",
"interface_ref": {"product_id": "calendar", "rpc_name": "list_calendars"}
},
"calendar.raw_tool": {"description": "raw_tool_name"},
"outside.tool": {"description": "不在公开命令面"}
}
}`)
metadata, stats, err := generateFromSources(Options{
Root: root,
SkillPath: "skills/mono/SKILL.md",
ProductsDir: "skills/mono/references/products",
IntentGuidePath: "skills/mono/references/intent-guide.md",
HintsDir: "internal/cli/schema_hints",
InterfaceMetadataPath: "internal/cli/schema_mcp_metadata.json",
ToolPaths: map[string]string{
"calendar.get_calendar": "calendar book get",
"calendar.list_calendars": "calendar book list",
"calendar.raw_tool": "calendar raw",
},
ProductIDs: map[string]bool{"calendar": true},
SurfaceToolCount: 3,
})
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
get := metadata.Tools["calendar book get"]
if get.AgentSummary != "读取指定日历" || get.AgentSummarySource != "dws-wukong@1234567890ab" {
t.Fatalf("reviewed/imported summary was not preserved: %#v", get)
}
list := metadata.Tools["calendar book list"]
if list.AgentSummary != "列出当前用户可访问的日历。" {
t.Fatalf("MCP summary = %q", list.AgentSummary)
}
if list.AgentSummarySource != "mcp-tools-list+cli-registry@abcdef123456" {
t.Fatalf("MCP summary source = %q", list.AgentSummarySource)
}
if list.InterfaceRef == nil || list.InterfaceRef.ProductID != "calendar" || list.InterfaceRef.RPCName != "list_calendars" {
t.Fatalf("MCP interface ref = %#v", list.InterfaceRef)
}
refProvenance := list.FieldProvenance["interface_ref"]
if refProvenance.Value != "calendar.list_calendars" || refProvenance.Precedence != "mcp_fallback" || refProvenance.Source == "" {
t.Fatalf("MCP interface ref provenance = %#v", refProvenance)
}
if list.Reviewed == nil || *list.Reviewed {
t.Fatalf("MCP fallback reviewed = %#v, want false", list.Reviewed)
}
raw, exists := metadata.Tools["calendar raw"]
if !exists {
t.Fatal("effective command without an eligible MCP summary must retain an Agent metadata projection")
}
if raw.AgentSummary != "" {
t.Fatalf("identifier-only MCP description became an Agent summary: %#v", raw)
}
audit := stats.InterfaceMetadata
if audit == nil || audit.SourceTools != 4 || audit.SurfaceTools != 3 ||
audit.EligibleSummaries != 2 || audit.AppliedSummaries != 1 ||
audit.PreservedSummaries != 1 {
t.Fatalf("interface audit = %#v", audit)
}
if len(audit.RejectedTools) != 1 || audit.RejectedTools[0] != "calendar.raw_tool" ||
len(audit.OutsideSurface) != 1 || audit.OutsideSurface[0] != "outside.tool" {
t.Fatalf("interface audit paths = %#v", audit)
}
}
func TestSummarizeInterfaceDescriptionBoundsAndRejectsIdentifiers(t *testing.T) {
if got := summarizeInterfaceDescription("search_open_platform_docs", 40); got != "" {
t.Fatalf("identifier summary = %q, want empty", got)
}
if got := summarizeInterfaceDescription("**查询日历。** 第二句不保留。", 40); got != "查询日历。" {
t.Fatalf("sentence summary = %q", got)
}
got := summarizeInterfaceDescription("这是一个没有句号而且明显超过允许长度的接口描述文本", 12)
if got != "这是一个没有句号而..." {
t.Fatalf("truncated summary = %q", got)
}
}