package ctxmgr import ( "strings" "testing" ) func TestConversationTaskState_Lifecycle(t *testing.T) { ts := NewConversationTaskState() // Turn 1: 用户表达立项意图与器械类型 ts.UpdateFromTurn( "我们打算立项研发一款高频超声手术刀系统", "SUPPLEMENT_INFO", map[string]string{"device_type": "高频超声手术刀系统"}, "NORMAL", "V0.1_triage", ) if ts.ActiveTask != "SUPPLEMENT_INFO" { t.Errorf("expected ActiveTask SUPPLEMENT_INFO, got %s", ts.ActiveTask) } if ts.TopicAnchor != "我们打算立项研发一款高频超声手术刀系统" { t.Errorf("unexpected TopicAnchor: %s", ts.TopicAnchor) } if ts.CollectedSlots["device_type"] != "高频超声手术刀系统" { t.Errorf("expected device_type collected, got %v", ts.CollectedSlots) } // 缺失槽位应有 target_market 和 budget hasMarket := false hasBudget := false for _, m := range ts.MissingSlots { if m == "target_market" { hasMarket = true } if m == "budget" { hasBudget = true } } if !hasMarket || !hasBudget { t.Errorf("expected missing target_market and budget, got %v", ts.MissingSlots) } // Turn 2: 补充目标市场与预算 ts.UpdateFromTurn( "目标市场主要为国内和欧洲,初期预算约为200万元", "SUPPLEMENT_INFO", map[string]string{ "target_market": "国内和欧洲", "budget": "200万元", }, "NORMAL", "V0.1_triage", ) if len(ts.MissingSlots) != 0 { t.Errorf("expected 0 missing slots after turn 2, got %v", ts.MissingSlots) } snippet := ts.RenderPromptSnippet() if !strings.Contains(snippet, "【本轮任务状态 (Working Memory)】") { t.Errorf("missing header in prompt snippet: %s", snippet) } if !strings.Contains(snippet, "device_type=高频超声手术刀系统") { t.Errorf("missing device_type in prompt snippet: %s", snippet) } if !strings.Contains(snippet, "target_market=国内和欧洲") { t.Errorf("missing target_market in prompt snippet: %s", snippet) } }