package elderagent import ( "encoding/json" "strings" "testing" "data-terminal-cloud/internal/companionopening" ) func TestPrepareConfigurationWelcomeOverrideAndLegacyBehavior(t *testing.T) { s := Service{CallbackURL: "https://example.com/callback", CallbackSecret: []byte(strings.Repeat("k", 32))} raw := []byte(`{"S2SConfig":{"ProviderParams":{"dialog":{"system_role":"基础人设"}}},"MemoryConfig":{"Enable":false}}`) agentRaw := []byte(`{"WelcomeMessage":"已保存的开场。","EnableConversationStateCallback":false}`) custom, blank := " \t我给您讲个老机器的小故事。\n", " \t\n" for _, tc := range []struct { name string override *string welcome string }{ {name: "legacy", welcome: "已保存的开场。"}, {name: "custom", override: &custom, welcome: "我给您讲个老机器的小故事。"}, {name: "blank", override: &blank, welcome: "你好,今天想聊些什么?"}, } { t.Run(tc.name, func(t *testing.T) { config, agent, err := s.prepareConfiguration(raw, agentRaw, "call-one", "喜欢喝淡茶", tc.override) if err != nil { t.Fatal(err) } if agent["WelcomeMessage"] != tc.welcome || agent["EnableConversationStateCallback"] != false { t.Fatal("incorrect welcome or changed callback policy", agent) } if agent["ServerMessageURLForRTS"] != "https://example.com/callbacks/v1/volcengine/chat?session_id=call-one" { t.Fatal("wrong call callback", agent) } role := config["S2SConfig"].(map[string]any)["ProviderParams"].(map[string]any)["dialog"].(map[string]any)["system_role"].(string) if strings.Contains(role, "喜欢喝淡茶") || config["MemoryConfig"].(map[string]any)["Enable"] != false { t.Fatal("changed authorized facts or memory policy", role) } if tc.override == nil { if role != withEventTimeGuidance("基础人设") { t.Fatal("legacy preparation added opening guidance", role) } } else { quotedWelcome, _ := json.Marshal(tc.welcome) if !strings.Contains(role, string(quotedWelcome)) || !strings.Contains(role, "沿当前开场继续") || !strings.Contains(role, "不得把开场中的一般内容归到长者本人") { t.Fatal("missing opening continuation or factual boundary", role) } } }) } if string(agentRaw) != `{"WelcomeMessage":"已保存的开场。","EnableConversationStateCallback":false}` || string(raw) != `{"S2SConfig":{"ProviderParams":{"dialog":{"system_role":"基础人设"}}},"MemoryConfig":{"Enable":false}}` { t.Fatal("preparation changed saved configuration bytes") } } func TestPrepareIntroductionWaitsForElderWithoutStartingAnActivity(t *testing.T) { s := Service{CallbackURL: "https://example.com/callback", CallbackSecret: []byte(strings.Repeat("k", 32))} raw := []byte(`{"S2SConfig":{"ProviderParams":{"dialog":{"system_role":"基础人设"}}},"MemoryConfig":{"Enable":false}}`) agentRaw := []byte(`{"WelcomeMessage":"已保存的开场。","EnableConversationStateCallback":false}`) intro := companionopening.Introduction().Text config, agent, err := s.prepareConfiguration(raw, agentRaw, "intro-call", "", &intro) if err != nil || agent["WelcomeMessage"] != intro { t.Fatal("introduction changed between provider and device", err) } role := config["S2SConfig"].(map[string]any)["ProviderParams"].(map[string]any)["dialog"].(map[string]any)["system_role"].(string) for _, instruction := range []string{"口播介绍后等待长者回应", "不立即讲故事", "不反复索要姓名", "不要承诺已保存或已修改个人资料"} { if !strings.Contains(role, instruction) { t.Fatalf("missing first-call behavior: %s", instruction) } } if strings.Count(intro, "?") != 1 || config["MemoryConfig"].(map[string]any)["Enable"] != false || agent["EnableConversationStateCallback"] != false { t.Fatal("introduction adds questions or changes call/privacy policy") } ordinary := "您好,咱们聊会儿。" next, _, err := s.prepareConfiguration(raw, agentRaw, "next-call", "", &ordinary) if err != nil { t.Fatal(err) } nextRole := next["S2SConfig"].(map[string]any)["ProviderParams"].(map[string]any)["dialog"].(map[string]any)["system_role"].(string) if strings.Contains(nextRole, "本次是首次自我介绍") { t.Fatal("first-call instructions leaked to later calls") } } func TestPrepareConfigurationDoesNotAccumulateCallContext(t *testing.T) { s := Service{CallbackURL: "https://example.com/callback", CallbackSecret: []byte(strings.Repeat("k", 32))} raw := []byte(`{"S2SConfig":{"ProviderParams":{"dialog":{"system_role":"基础人设"}}}}`) agentRaw := []byte(`{"WelcomeMessage":"已保存的开场。"}`) firstWelcome, secondWelcome := "讲讲老机器。", "聊聊家常菜。" if _, _, err := s.prepareConfiguration(raw, agentRaw, "call-one", "前次资料", &firstWelcome); err != nil { t.Fatal(err) } config, agent, err := s.prepareConfiguration(raw, agentRaw, "call-two", "本次资料", &secondWelcome) if err != nil { t.Fatal(err) } role := config["S2SConfig"].(map[string]any)["ProviderParams"].(map[string]any)["dialog"].(map[string]any)["system_role"].(string) if strings.Contains(role, "前次资料") || strings.Contains(role, firstWelcome) || strings.Count(role, "本次已选开场口播") != 1 || strings.Contains(role, "本次资料") || agent["WelcomeMessage"] != secondWelcome { t.Fatal("prior call context leaked into next preparation", role, agent) } if _, _, err = s.prepareConfiguration(raw, []byte(`null`), "call-invalid", "", &secondWelcome); err == nil { t.Fatal("accepted a null agent configuration") } } func TestPrepareGreetingDoesNotTurnAcknowledgementIntoAnActivity(t *testing.T) { s := Service{CallbackURL: "https://example.com/callback", CallbackSecret: []byte(strings.Repeat("k", 32))} raw := []byte(`{"S2SConfig":{"ProviderParams":{"dialog":{"system_role":"基础人设"}}},"MemoryConfig":{"Enable":false}}`) agentRaw := []byte(`{"WelcomeMessage":"旧开场"}`) for _, welcome := range []string{"您好,咱们随便聊两句。", "您平常爱听哪一种戏?"} { config, agent, err := s.prepareConfiguration(raw, agentRaw, "new-call", "", &welcome) if err != nil || agent["WelcomeMessage"] != welcome { t.Fatal("selected greeting was not passed through unchanged", err) } role := config["S2SConfig"].(map[string]any)["ProviderParams"].(map[string]any)["dialog"].(map[string]any)["system_role"].(string) if strings.Contains(role, "先讲一小段相关内容") || !strings.Contains(role, "开场只是问候时,不把它扩展成故事") || !strings.Contains(role, "不代表请求猜谜、答题或游戏") || !strings.Contains(role, "只有长者本通明确提出想玩才开始") { t.Fatal("greeting or brief acknowledgement still directs an unsolicited activity", role) } } }