72 lines
2.9 KiB
Go
72 lines
2.9 KiB
Go
package agent
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// TestFallbackSummary 验证 LLM 压缩失败时的兜底摘要:
|
||
// 纯文本、保留最近消息要点、无孤立 tool 消息。
|
||
func TestFallbackSummary(t *testing.T) {
|
||
history := []Message{
|
||
{Role: "user", Content: stringPointer("第一轮任务:分析日志")},
|
||
{Role: "assistant", Content: stringPointer("已确认方案,开始执行")},
|
||
{Role: "assistant", ToolCalls: []ToolCall{{ID: "c1", Type: "function", Function: ToolFunctionCall{Name: "run_bash", Arguments: `{"command":"ls"}`}}}},
|
||
{Role: "tool", ToolCallID: "c1", Content: stringPointer("file.txt")},
|
||
{Role: "user", Content: stringPointer("继续,报告结果")},
|
||
}
|
||
summary := fallbackSummary(history)
|
||
if summary == "" {
|
||
t.Fatal("fallbackSummary 不应返回空")
|
||
}
|
||
if strings.Contains(summary, "tool_calls") || strings.Contains(summary, "\"id\"") {
|
||
t.Fatalf("fallbackSummary 必须为纯文本,不得包含结构化 tool_calls: %s", summary)
|
||
}
|
||
if !strings.Contains(summary, "用户") || !strings.Contains(summary, "助手") || !strings.Contains(summary, "工具结果") {
|
||
t.Fatalf("fallbackSummary 应包含用户/助手/工具结果要点: %s", summary)
|
||
}
|
||
if !strings.Contains(summary, "调用了 run_bash") {
|
||
t.Fatalf("fallbackSummary 应记录工具调用名: %s", summary)
|
||
}
|
||
}
|
||
|
||
// TestCompactionInputBudget 验证单次压缩输入预算随窗口放大而放大,
|
||
// 且始终留出输出与安全余量。
|
||
func TestCompactionInputBudget(t *testing.T) {
|
||
a := &Agent{cfg: Config{MaxContextTokens: 96000, CompactionTokens: 4096, StreamOutputTokens: 4096}}
|
||
budget := a.compactionInputBudget()
|
||
if budget <= 0 || budget >= 96000 {
|
||
t.Fatalf("预算应介于 (0, 96000),got %d", budget)
|
||
}
|
||
// 窗口放大后预算也应放大
|
||
a2 := &Agent{cfg: Config{MaxContextTokens: 48000, CompactionTokens: 4096, StreamOutputTokens: 4096}}
|
||
if a2.compactionInputBudget() >= budget {
|
||
t.Fatalf("窗口更大的预算应更大,got %d vs %d", a2.compactionInputBudget(), budget)
|
||
}
|
||
// 极端小窗口时兜底下限 4096
|
||
a3 := &Agent{cfg: Config{MaxContextTokens: 2000, CompactionTokens: 512, StreamOutputTokens: 512}}
|
||
if got := a3.compactionInputBudget(); got < 4096 {
|
||
t.Fatalf("小窗口预算应有下限,got %d", got)
|
||
}
|
||
}
|
||
|
||
// TestEstimateMessageTokens 验证单条消息估算包含 content、tool_calls 与开销。
|
||
func TestEstimateMessageTokens(t *testing.T) {
|
||
m := Message{
|
||
Role: "assistant",
|
||
Content: stringPointer("你好"),
|
||
ToolCalls: []ToolCall{{
|
||
ID: "c1", Type: "function",
|
||
Function: ToolFunctionCall{Name: "read_file", Arguments: `{"path":"a.txt"}`},
|
||
}},
|
||
}
|
||
n := estimateMessageTokens(m)
|
||
if n <= 0 {
|
||
t.Fatalf("估算应大于 0,got %d", n)
|
||
}
|
||
plain := estimateMessageTokens(Message{Role: "user", Content: stringPointer("你好")})
|
||
if n <= plain {
|
||
t.Fatalf("含 tool_calls 的消息估算应大于纯文本,got %d vs %d", n, plain)
|
||
}
|
||
}
|