package processing import ( "encoding/json" "testing" ) func TestOpenAIReasoningChatModel(t *testing.T) { t.Parallel() cases := []struct { model string want bool }{ {"gpt-5.6-luna", true}, {"gpt-5.6-terra", true}, {"gpt-5.6-sol", true}, {"gpt-5.6", true}, {"GPT-5.4", true}, {"openai/gpt-5.6-luna", true}, {"o1-mini", true}, {"o3", true}, {"o4-mini", true}, {"gpt-4o-mini", false}, {"gpt-4.1", false}, {"mock-llm", false}, {"", false}, } for _, tc := range cases { if got := openAIReasoningChatModel(tc.model); got != tc.want { t.Fatalf("openAIReasoningChatModel(%q)=%v want %v", tc.model, got, tc.want) } } } func TestBuildChatCompletionBody_gpt56Luna(t *testing.T) { t.Parallel() body := buildChatCompletionBody("gpt-5.6-luna", []chatMessage{ {Role: "system", Content: "sys"}, {Role: "user", Content: "ping"}, }, 0.2, MaxTokensEnhance, "low") raw, err := json.Marshal(body) if err != nil { t.Fatal(err) } var m map[string]any if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } if _, ok := m["temperature"]; ok { t.Fatalf("temperature must be omitted for gpt-5.6-luna, got %v", m["temperature"]) } if _, ok := m["max_tokens"]; ok { t.Fatalf("max_tokens must be omitted for gpt-5.6-luna, got %v", m["max_tokens"]) } gotMax, _ := m["max_completion_tokens"].(float64) if int(gotMax) != MaxTokensEnhance { t.Fatalf("max_completion_tokens=%v want %d", gotMax, MaxTokensEnhance) } if m["reasoning_effort"] != "low" { t.Fatalf("reasoning_effort=%v want low", m["reasoning_effort"]) } } func TestBuildChatCompletionBody_classicModel(t *testing.T) { t.Parallel() body := buildChatCompletionBody("gpt-4o-mini", []chatMessage{ {Role: "user", Content: "hi"}, }, 0.2, 350, "") raw, err := json.Marshal(body) if err != nil { t.Fatal(err) } var m map[string]any if err := json.Unmarshal(raw, &m); err != nil { t.Fatal(err) } if _, ok := m["max_completion_tokens"]; ok { t.Fatalf("max_completion_tokens unexpected for classic model: %v", m) } gotMax, _ := m["max_tokens"].(float64) if int(gotMax) != 350 { t.Fatalf("max_tokens=%v want 350", gotMax) } gotTemp, _ := m["temperature"].(float64) if gotTemp != 0.2 { t.Fatalf("temperature=%v want 0.2", gotTemp) } if _, ok := m["reasoning_effort"]; ok { t.Fatalf("reasoning_effort unexpected for classic model: %v", m) } } func TestBuildChatCompletionBody_probeDefaultsNoneEffort(t *testing.T) { t.Parallel() body := buildChatCompletionBody("gpt-5.6-luna", []chatMessage{ {Role: "user", Content: "ping"}, }, 0.2, 0, "") if body.ReasoningEffort != "none" { t.Fatalf("reasoning_effort=%q want none for probe", body.ReasoningEffort) } if body.MaxCompletionTokens != 0 || body.MaxTokens != 0 { t.Fatalf("expected no token cap on probe, got %+v", body) } if body.Temperature != nil { t.Fatalf("temperature must be nil for probe on gpt-5.6") } } func TestDefaultReasoningEffort(t *testing.T) { t.Parallel() if got := defaultReasoningEffort("gpt-5.6-luna", MaxTokensEnhance, ""); got != "low" { t.Fatalf("enhance default=%q", got) } if got := defaultReasoningEffort("gpt-5.6-luna", 0, ""); got != "none" { t.Fatalf("probe default=%q", got) } if got := defaultReasoningEffort("gpt-5.6-luna", 100, "medium"); got != "medium" { t.Fatalf("explicit=%q", got) } if got := defaultReasoningEffort("gpt-4o", 1000, ""); got != "" { t.Fatalf("classic=%q", got) } }