package agent import ( "strings" "testing" "git.gopher.ink/mirrors2/AutoZero/llm" "git.gopher.ink/mirrors2/AutoZero/session" ) // TestContextUsage:上下文占用估算与 shouldCompact 同口径, // 返回 (used, window, compactAt) 三元组供 UI 徽标换算百分比。 func TestContextUsage(t *testing.T) { a := &Agent{ System: strings.Repeat("s", 300), // sysNow 计入 system 提示 Session: &session.Session{Messages: []llm.Message{ {Role: llm.RoleUser, Content: strings.Repeat("a", 3000)}, // ≈ 1000 tokens(字节/3) }}, ContextWindow: 1000, CompactAt: 0.85, MinCompactTokens: 10, } used, window, at := a.ContextUsage() if window != 1000 || at != 0.85 { t.Fatalf("window/compactAt = %d/%v, want 1000/0.85", window, at) } // 300 字节 system(100)+ 3000 字节消息(1000)+ 每条 8 字节固定开销。 if used < 1000 || used > 1200 { t.Fatalf("used = %d, want ≈1100", used) } } // TestOnCompactCallback:自动压缩完成后回调一次结果(OnCompact 非空时)。 // 压缩路径依赖 LLM 调用,这里只验证回调契约——手动 CompactNow 的结果 // 结构与自动路径共用同一 CompactionResult,事件桥(TUI compactHub)按 // 同一字段渲染。 func TestOnCompactCallbackField(t *testing.T) { var got []CompactionResult a := &Agent{} a.Opt.OnCompact = func(res CompactionResult) { got = append(got, res) } if a.Opt.OnCompact == nil { t.Fatal("OnCompact should be assignable") } a.Opt.OnCompact(CompactionResult{Summarized: 3, Kept: 10, TokensBefore: 100, TokensAfter: 40}) if len(got) != 1 || got[0].Summarized != 3 || got[0].TokensAfter != 40 { t.Fatalf("callback not invoked with payload: %+v", got) } }