Files
Agent-System/internal/dialoguectx/package_test.go
T
weichen dc29b84cdf feat(ctx): inject cleaned project dialogue into squad and assistant
Add dialoguectx packaging, conflictresolve adjudication with HITL routing,
workspace context/dialogue/ injection (default on), and goose 00071.
2026-09-24 17:04:04 +00:00

98 lines
3.9 KiB
Go

package dialoguectx_test
import (
"os"
"strings"
"testing"
"time"
"chat-agent-system/internal/ctxmgr"
"chat-agent-system/internal/dialoguectx"
"chat-agent-system/internal/replyexport"
)
func TestInjectionEnabledDefaultOn(t *testing.T) {
t.Setenv("DIALOGUE_CTX_INJECTION", "")
if !dialoguectx.InjectionEnabled() {
t.Fatal("expected default on")
}
t.Setenv("DIALOGUE_CTX_INJECTION", "off")
if dialoguectx.InjectionEnabled() {
t.Fatal("expected off")
}
}
func TestCollectFromRecordsCleansAndEnriches(t *testing.T) {
now := time.Date(2026, 9, 24, 15, 0, 0, 0, time.UTC)
recs := []ctxmgr.ChatMessageRecord{
{ID: 1, SessionID: "s1", UserID: 7, Role: "user", Content: "你好", CreatedAt: now, DayKey: "2026-09-24"},
{ID: 2, SessionID: "s1", UserID: 7, Role: "user", Content: "器械类型:眼科OCT", CreatedAt: now.Add(time.Minute), DayKey: "2026-09-24"},
{ID: 3, SessionID: "s1", UserID: 0, Role: "assistant", Content: "状态更新中", ContentKind: string(replyexport.KindStatusUpdate), ExportPolicy: string(replyexport.PolicyNone), CreatedAt: now.Add(2 * time.Minute), DayKey: "2026-09-24"},
{ID: 4, SessionID: "s1", UserID: 7, Role: "user", Content: "[private] 草稿备注", CreatedAt: now.Add(3 * time.Minute), DayKey: "2026-09-24"},
{ID: 5, SessionID: "s1", UserID: 0, Role: "assistant", Content: "已记录眼科OCT分类建议", ContentKind: string(replyexport.KindDocumentText), ExportPolicy: string(replyexport.PolicyFull), CreatedAt: now.Add(4 * time.Minute), DayKey: "2026-09-24"},
{ID: 6, SessionID: "s1", UserID: 8, Role: "user", Content: "目标市场:国内III类", CreatedAt: now.Add(5 * time.Minute), DayKey: "2026-09-24", Metadata: map[string]any{"stage_key": "other"}},
}
enrich := map[int64]struct {
Name, SystemRole, ProjectRole, DocDuty string
}{
7: {Name: "张工", SystemRole: "engineer", ProjectRole: "member"},
8: {Name: "李工", SystemRole: "engineer", ProjectRole: "member"},
}
// CollectFromRecords takes unexported speakerMeta — use public path via package rebuild:
// call through exported helper by duplicating via CollectAndPackage memory is heavy;
// instead test packaging via Inject test shim in same package.
_ = enrich
_ = os.Getenv
pkg, err := dialoguectx.CollectFromRecords(recs, dialoguectx.CollectOptions{
ProjectID: 1, MaxDays: 7, MaxTurns: 80, Now: now.Add(time.Hour), AllowedStageKey: "",
}, nil)
if err != nil {
t.Fatal(err)
}
if pkg.TurnCount < 2 {
t.Fatalf("expected cleaned turns, got %d (noise=%d private=%d)", pkg.TurnCount, pkg.ExcludedNoise, pkg.ExcludedPrivate)
}
if pkg.ExcludedPrivate < 1 {
t.Fatalf("expected private exclusion")
}
if pkg.ExcludedNoise < 1 {
t.Fatalf("expected noise exclusion for greeting/status")
}
if !strings.Contains(pkg.TurnsMD, "器械类型") {
t.Fatalf("turns missing content: %s", pkg.TurnsMD)
}
foundDevice := false
for _, f := range pkg.Facts {
if f.Key == "device_type" && strings.Contains(f.Value, "眼科OCT") {
foundDevice = true
}
}
if !foundDevice {
t.Fatalf("expected device_type fact, got %#v", pkg.Facts)
}
snip := dialoguectx.RenderAssistantSnippet(pkg)
if !strings.Contains(snip, "项目成员协同近况") {
t.Fatalf("snippet missing header: %s", snip)
}
}
func TestStageFilterExcludes(t *testing.T) {
now := time.Now()
recs := []ctxmgr.ChatMessageRecord{
{ID: 1, Role: "user", Content: "当前阶段事实:预算一千万", CreatedAt: now, Metadata: map[string]any{"stage_key": "rd_proposal"}},
{ID: 2, Role: "user", Content: "其他阶段事实:预算两千万", CreatedAt: now, Metadata: map[string]any{"stage_key": "system_reqs"}},
}
pkg, err := dialoguectx.CollectFromRecords(recs, dialoguectx.CollectOptions{
ProjectID: 1, MaxDays: 7, Now: now.Add(time.Minute), AllowedStageKey: "rd_proposal",
}, nil)
if err != nil {
t.Fatal(err)
}
if pkg.ExcludedNoAccess != 1 {
t.Fatalf("expected 1 stage exclusion, got %d", pkg.ExcludedNoAccess)
}
if pkg.TurnCount != 1 {
t.Fatalf("expected 1 turn, got %d", pkg.TurnCount)
}
}