125 lines
3.8 KiB
Go
125 lines
3.8 KiB
Go
package agent
|
|
|
|
import (
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"laodingbot/internal/knowledge"
|
|
)
|
|
|
|
func TestBuildQueryTokensIncludesChineseBigrams(t *testing.T) {
|
|
tokens := buildQueryTokens("请执行命令并查看文件")
|
|
joined := strings.Join(tokens, ",")
|
|
if !strings.Contains(joined, "命令") {
|
|
t.Fatalf("expected token contains 命令, got: %v", tokens)
|
|
}
|
|
if !strings.Contains(joined, "文件") {
|
|
t.Fatalf("expected token contains 文件, got: %v", tokens)
|
|
}
|
|
}
|
|
|
|
func TestSelectRelevantSkillsPrefersMatchingSkill(t *testing.T) {
|
|
o := &Orchestrator{
|
|
skills: []knowledge.Skill{
|
|
{Name: "文件系统查询专家", Content: "适用于目录、文件、路径、命令执行等场景"},
|
|
{Name: "天气查询", Content: "用于天气和空气质量查询"},
|
|
{Name: "日程助手", Content: "用于日程管理"},
|
|
},
|
|
}
|
|
|
|
selected := o.selectRelevantSkills("帮我执行命令查看某个文件", 2)
|
|
if len(selected) == 0 {
|
|
t.Fatal("expected non-empty selected skills")
|
|
}
|
|
if selected[0].Name != "文件系统查询专家" {
|
|
t.Fatalf("expected top skill 文件系统查询专家, got: %s", selected[0].Name)
|
|
}
|
|
if len(selected) > 2 {
|
|
t.Fatalf("expected at most 2 skills, got: %d", len(selected))
|
|
}
|
|
}
|
|
|
|
func TestFormatRuntimeContextForPromptIncludesGOOS(t *testing.T) {
|
|
doc := formatRuntimeContextForPrompt()
|
|
if !strings.Contains(strings.ToLower(doc), strings.ToLower(runtime.GOOS)) {
|
|
t.Fatalf("expected runtime context contains GOOS=%s, got: %s", runtime.GOOS, doc)
|
|
}
|
|
}
|
|
|
|
func TestMatchSkillsByNameExact(t *testing.T) {
|
|
all := []knowledge.Skill{
|
|
{Name: "SAFe PI Planning", Content: "PI规划技能"},
|
|
{Name: "文件系统查询专家", Content: "文件查询"},
|
|
{Name: "代码生成", Content: "代码生成技能"},
|
|
}
|
|
matched := matchSkillsByName(all, []string{"SAFe PI Planning"})
|
|
if len(matched) != 1 {
|
|
t.Fatalf("expected 1 match, got %d", len(matched))
|
|
}
|
|
if matched[0].Name != "SAFe PI Planning" {
|
|
t.Fatalf("expected SAFe PI Planning, got %s", matched[0].Name)
|
|
}
|
|
}
|
|
|
|
func TestMatchSkillsByNameFuzzy(t *testing.T) {
|
|
all := []knowledge.Skill{
|
|
{Name: "SAFe PI Planning", Content: "PI规划技能"},
|
|
{Name: "文件系统查询专家", Content: "文件查询"},
|
|
}
|
|
matched := matchSkillsByName(all, []string{"pi planning", "文件"})
|
|
if len(matched) != 2 {
|
|
t.Fatalf("expected 2 matches, got %d", len(matched))
|
|
}
|
|
}
|
|
|
|
func TestMatchSkillsByNameNoMatch(t *testing.T) {
|
|
all := []knowledge.Skill{
|
|
{Name: "文件系统查询专家", Content: "文件查询"},
|
|
}
|
|
matched := matchSkillsByName(all, []string{"不存在的技能"})
|
|
if len(matched) != 0 {
|
|
t.Fatalf("expected 0 matches, got %d", len(matched))
|
|
}
|
|
}
|
|
|
|
func TestMatchSkillsByNameEmpty(t *testing.T) {
|
|
matched := matchSkillsByName(nil, []string{"any"})
|
|
if len(matched) != 0 {
|
|
t.Fatalf("expected 0 matches, got %d", len(matched))
|
|
}
|
|
matched = matchSkillsByName([]knowledge.Skill{{Name: "test"}}, nil)
|
|
if len(matched) != 0 {
|
|
t.Fatalf("expected 0 matches, got %d", len(matched))
|
|
}
|
|
}
|
|
|
|
func TestSanitizeUserFacingAnswerExtractsFinalAnswer(t *testing.T) {
|
|
raw := "Thought: 先分析用户问题\nObservation: 已经有足够信息\nFinal Answer: 这是给用户的结果"
|
|
got := sanitizeUserFacingAnswer(raw)
|
|
if got != "这是给用户的结果" {
|
|
t.Fatalf("expected final answer only, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestSanitizeUserFacingAnswerDropsTraceLines(t *testing.T) {
|
|
raw := strings.Join([]string{
|
|
"Step 1 Thought: 检查上下文",
|
|
"Action: shell",
|
|
"Observation: ok",
|
|
"请执行以下变更。",
|
|
}, "\n")
|
|
got := sanitizeUserFacingAnswer(raw)
|
|
if got != "请执行以下变更。" {
|
|
t.Fatalf("expected user-facing text only, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestSanitizeUserFacingAnswerKeepsNormalAnswer(t *testing.T) {
|
|
raw := "1. 先打开配置文件\n2. 修改端口后重启服务"
|
|
got := sanitizeUserFacingAnswer(raw)
|
|
if got != raw {
|
|
t.Fatalf("expected answer unchanged, got %q", got)
|
|
}
|
|
}
|