| 1 | package agent |
| 2 | |
| 3 | import ( |
| 4 | "strings" |
| 5 | "testing" |
| 6 | ) |
| 7 | |
| 8 | func TestWithResponseLanguageOnlySkipsLeadingInjectedBlock(t *testing.T) { |
| 9 | userMention := "explain why <response-language> appears in this file" |
| 10 | got := WithResponseLanguage(userMention, "en") |
| 11 | if !strings.HasPrefix(got, "<response-language>") || !strings.Contains(got, "use English") || !strings.HasSuffix(got, userMention) { |
| 12 | t.Fatalf("WithResponseLanguage should prefix user-authored tag mentions, got %q", got) |
| 13 | } |
| 14 | |
| 15 | alreadyPrefixed := ResponseLanguageBlock("en") + "\n\n" + userMention |
| 16 | if got := WithResponseLanguage(alreadyPrefixed, "en"); got != alreadyPrefixed { |
| 17 | t.Fatalf("WithResponseLanguage duplicated a leading injected block:\n got %q\nwant %q", got, alreadyPrefixed) |
| 18 | } |
| 19 | |
| 20 | withLeadingMemory := "<memory-update>\nRemember this.\n</memory-update>\n\n" + alreadyPrefixed |
| 21 | if got := WithResponseLanguage(withLeadingMemory, "en"); got != withLeadingMemory { |
| 22 | t.Fatalf("WithResponseLanguage duplicated a response block after leading transient context:\n got %q\nwant %q", got, withLeadingMemory) |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | func TestWithReasoningLanguageOnlySkipsLeadingInjectedBlock(t *testing.T) { |
| 27 | userMention := "explain why <reasoning-language> appears in this file" |
| 28 | got := WithReasoningLanguage(userMention, "zh") |
| 29 | if !strings.HasPrefix(got, "<reasoning-language>") || !strings.Contains(got, "简体中文") || !strings.HasSuffix(got, userMention) { |
| 30 | t.Fatalf("WithReasoningLanguage should prefix user-authored tag mentions, got %q", got) |
| 31 | } |
| 32 | |
| 33 | alreadyPrefixed := ReasoningLanguageBlock("zh") + "\n\n" + userMention |
| 34 | if got := WithReasoningLanguage(alreadyPrefixed, "zh"); got != alreadyPrefixed { |
| 35 | t.Fatalf("WithReasoningLanguage duplicated a leading injected block:\n got %q\nwant %q", got, alreadyPrefixed) |
| 36 | } |
| 37 | |
| 38 | withLeadingMemory := "<memory-update>\nRemember this.\n</memory-update>\n\n" + alreadyPrefixed |
| 39 | if got := WithReasoningLanguage(withLeadingMemory, "zh"); got != withLeadingMemory { |
| 40 | t.Fatalf("WithReasoningLanguage duplicated a reasoning block after leading transient context:\n got %q\nwant %q", got, withLeadingMemory) |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | func TestReasoningLanguageBlockZhStaysImperative(t *testing.T) { |
| 45 | // The imperative form measurably outperforms soft "偏好" phrasing on |
| 46 | // Chinese prompts that embed English logs/code; keep it from regressing |
| 47 | // back into a suggestion. |
| 48 | block := ReasoningLanguageBlock("zh") |
| 49 | for _, want := range []string{"必须使用简体中文", "整轮", "不覆盖用户对最终回答语言的明确要求"} { |
| 50 | if !strings.Contains(block, want) { |
| 51 | t.Fatalf("zh reasoning block lost required anchor %q:\n%s", want, block) |
| 52 | } |
| 53 | } |
| 54 | } |
| 55 | |
| 56 | func TestWithReasoningLanguageAutoInfersFromSource(t *testing.T) { |
| 57 | chinese := WithReasoningLanguage("解释 AuthHandler 的 panic", "auto") |
| 58 | if !strings.HasPrefix(chinese, "<reasoning-language>") || !strings.Contains(chinese, "简体中文") { |
| 59 | t.Fatalf("auto reasoning language should infer Chinese, got %q", chinese) |
| 60 | } |
| 61 | |
| 62 | english := WithReasoningLanguage("explain this module", "auto") |
| 63 | if english != "explain this module" { |
| 64 | t.Fatalf("auto reasoning language should keep English prompts unwrapped, got %q", english) |
| 65 | } |
| 66 | |
| 67 | short := WithReasoningLanguage("hi", "auto") |
| 68 | if short != "hi" { |
| 69 | t.Fatalf("short ambiguous auto prompt should not be wrapped, got %q", short) |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | func TestWithReasoningLanguageAutoUsesRawSourceOverReferencedContext(t *testing.T) { |
| 74 | expanded := "Referenced context:\n\n<file path=\"auth.go\">\npackage main\nfunc AuthHandler() error { return errors.New(\"not authorized\") }\n</file>\n\n解释 @auth.go 的报错" |
| 75 | |
| 76 | got := WithReasoningLanguageForSource(expanded, "auto", "解释 @auth.go 的报错") |
| 77 | if !strings.HasPrefix(got, "<reasoning-language>") || !strings.Contains(got, "简体中文") { |
| 78 | t.Fatalf("auto reasoning language should use raw source over referenced context, got %q", got) |
| 79 | } |
| 80 | if strings.Contains(got, "use English") { |
| 81 | t.Fatalf("referenced English code should not make auto prefer English:\n%s", got) |
| 82 | } |
| 83 | } |
| 84 |