package chat_test import ( "context" "strings" "testing" "chat-agent-system/internal/bizdev" "chat-agent-system/internal/chat" "chat-agent-system/internal/config" "chat-agent-system/internal/coordinator" "chat-agent-system/internal/ctxmgr" "chat-agent-system/internal/intent" "chat-agent-system/internal/squad" ) func TestChatSession_AssistantMetadataTurnIntentAndReplySource(t *testing.T) { rec := intent.NewRecognizer() engine := coordinator.NewCoordinatorEngine(nil) userCtx := &coordinator.UserProjectContext{ SnapshotID: "sess_ctx_turn_intent", User: coordinator.UserInfo{ ID: "u1", Name: "张工", Role: "engineer", ProjectRole: "composer", }, Project: coordinator.ProjectInfo{ Name: "数字化超声吸引系统", CurrentStage: bizdev.StageV01_Triage, }, LatestAdvisorBrief: &squad.AdvisorBriefing{ MaturityScore: 80, MaturityLevel: "V0.1", MaturityHeadline: "已就绪", }, } cfg := &config.Config{DataDir: t.TempDir()} svc := bizdev.MustNewService(t, cfg) mgr := bizdev.Snapshot(svc).Ctx sess := chat.NewSession("sess_test_turn_intent", userCtx, rec, engine) sess.CtxMgr = mgr ctx := context.Background() _, err := sess.SendMessage(ctx, "你好,请问当前项目进展如何?") if err != nil { t.Fatalf("SendMessage failed: %v", err) } // 校验通过 ContextManager 记录的消息 history, err := mgr.GetChatHistory(ctx, "sess_test_turn_intent", 10, 0) if err != nil { t.Fatalf("GetChatHistory failed: %v", err) } if len(history) < 2 { t.Fatalf("expected at least 2 messages in history, got %d", len(history)) } // 助手消息在后 var asstMsg *ctxmgr.ChatMessageRecord for i := range history { if history[i].Role == "assistant" { asstMsg = &history[i] break } } if asstMsg == nil { t.Fatalf("assistant message not found in history") } if asstMsg.Metadata == nil { t.Fatalf("expected assistant message metadata to be non-nil") } turnIntent, ok := asstMsg.Metadata["turn_intent"].(string) if !ok || turnIntent == "" { t.Errorf("expected turn_intent to be non-empty string in assistant metadata, got %v", asstMsg.Metadata["turn_intent"]) } replySource, ok := asstMsg.Metadata["reply_source"].(string) if !ok || replySource == "" { t.Errorf("expected reply_source to be non-empty string in assistant metadata, got %v", asstMsg.Metadata["reply_source"]) } } func TestChatSession_MaterialFallbackReasonPersisted(t *testing.T) { rec := intent.NewRecognizer() engine := coordinator.NewCoordinatorEngine(nil) userCtx := &coordinator.UserProjectContext{ SnapshotID: "sess_ctx_material", Project: coordinator.ProjectInfo{ Name: "全自动冲击波治疗仪1", CurrentStage: bizdev.StageV01_Triage, }, } cfg := &config.Config{DataDir: t.TempDir()} svc := bizdev.MustNewService(t, cfg) mgr := bizdev.Snapshot(svc).Ctx sess := chat.NewSession("sess_test_material_fallback", userCtx, rec, engine) sess.CtxMgr = mgr ctx := context.Background() _, err := sess.SendMessage(ctx, "上一代产品说明书") if err != nil { t.Fatalf("SendMessage failed: %v", err) } history, err := mgr.GetChatHistory(ctx, "sess_test_material_fallback", 10, 0) if err != nil { t.Fatalf("GetChatHistory failed: %v", err) } var asst *ctxmgr.ChatMessageRecord for i := range history { if history[i].Role == "assistant" { asst = &history[i] break } } if asst == nil { t.Fatal("assistant message missing") } if strings.Contains(asst.Content, "掂量") { t.Fatalf("persisted template sales pitch: %s", asst.Content) } reason, _ := asst.Metadata["fallback_reason"].(string) if reason == "" { t.Fatalf("fallback_reason missing in metadata: %#v", asst.Metadata) } if src, _ := asst.Metadata["reply_source"].(string); src != coordinator.ReplySourceTemplate { t.Fatalf("reply_source=%q", src) } }