package thinking import ( "testing" "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" ) type captureApplier struct { captured ThinkingConfig } func (a *captureApplier) Apply(body []byte, config ThinkingConfig, _ *registry.ModelInfo) ([]byte, error) { a.captured = config return body, nil } func TestContainsThinkWord(t *testing.T) { cases := []struct { in string want bool }{ {"please think carefully", true}, {"Think.", true}, {"rethink this", false}, {"thinking hard", false}, {"no trigger", false}, } for _, tc := range cases { if got := containsThinkWord(tc.in); got != tc.want { t.Fatalf("containsThinkWord(%q)=%v want %v", tc.in, got, tc.want) } } } func TestApplyThinking_ThinkTriggerAppliesDefault(t *testing.T) { orig := GetProviderApplier("gemini") cap := &captureApplier{} RegisterProvider("gemini", cap) t.Cleanup(func() { RegisterProvider("gemini", orig) }) body := []byte(`{"messages":[{"role":"user","content":"please think deeply"}]}`) _, err := ApplyThinking(body, "gemini-2.5-pro", "openai", "gemini", "gemini") if err != nil { t.Fatalf("ApplyThinking error: %v", err) } if cap.captured.Mode != ModeAuto || cap.captured.Budget != -1 { t.Fatalf("unexpected config: mode=%v budget=%d", cap.captured.Mode, cap.captured.Budget) } } func TestApplyThinking_ThinkTriggerRespectsSuffixPriority(t *testing.T) { orig := GetProviderApplier("gemini") cap := &captureApplier{} RegisterProvider("gemini", cap) t.Cleanup(func() { RegisterProvider("gemini", orig) }) body := []byte(`{"messages":[{"role":"user","content":"think now"}]}`) _, err := ApplyThinking(body, "gemini-2.5-pro(512)", "openai", "gemini", "gemini") if err != nil { t.Fatalf("ApplyThinking error: %v", err) } if cap.captured.Mode != ModeBudget || cap.captured.Budget != 512 { t.Fatalf("suffix should win, got mode=%v budget=%d", cap.captured.Mode, cap.captured.Budget) } }