package test import ( "fmt" "testing" "time" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/translator" // Import provider packages to trigger init() registration of ProviderAppliers _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/antigravity" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/claude" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/codex" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/gemini" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/interactions" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/kimi" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/openai" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/xai" "github.com/router-for-me/CLIProxyAPI/v7/internal/registry" "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking" sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator" "github.com/tidwall/gjson" "github.com/tidwall/sjson") // thinkingTestCase represents a common test case structure for both suffix and body tests.type thinkingTestCase struct { name string from string to string model string inputJSON string expectField string expectValue string expectField2 string expectValue2 string expectField3 string expectValue3 string expectAbsent []string includeThoughts string expectErr bool} // TestThinkingE2EMatrix_Suffix tests the thinking configuration transformation using model name suffix.// Data flow: Input JSON → TranslateRequest → ApplyThinking → Validate Output// No helper functions are used; all test data is inline.func TestThinkingE2EMatrix_Suffix(t *testing.T) { reg := registry.GetGlobalRegistry() uid := fmt.Sprintf("thinking-e2e-suffix-%d", time.Now().UnixNano()) reg.RegisterClient(uid, "test", getTestModels()) defer reg.UnregisterClient(uid) cases := []thinkingTestCase{ // level-model (Levels=minimal/low/medium/high, ZeroAllowed=false, DynamicAllowed=false) // Case 1: No suffix → injected default → medium { name: "1", from: "openai", to: "codex", model: "level-model", inputJSON: `{"model":"level-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 2: Specified medium → medium { name: "2", from: "openai", to: "codex", model: "level-model(medium)", inputJSON: `{"model":"level-model(medium)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 3: Specified xhigh → out of range error { name: "3", from: "openai", to: "codex", model: "level-model(xhigh)", inputJSON: `{"model":"level-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: true, }, // Case 4: Level none → clamped to minimal (ZeroAllowed=false) { name: "4", from: "openai", to: "codex", model: "level-model(none)", inputJSON: `{"model":"level-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "minimal", expectErr: false, }, // Case 5: Level auto → DynamicAllowed=false → medium (mid-range) { name: "5", from: "openai", to: "codex", model: "level-model(auto)", inputJSON: `{"model":"level-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 6: No suffix from gemini → injected default → medium { name: "6", from: "gemini", to: "codex", model: "level-model", inputJSON: `{"model":"level-model","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 7: Budget 8192 → medium { name: "7", from: "gemini", to: "codex", model: "level-model(8192)", inputJSON: `{"model":"level-model(8192)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 8: Budget 64000 → clamped to high { name: "8", from: "gemini", to: "codex", model: "level-model(64000)", inputJSON: `{"model":"level-model(64000)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "high", expectErr: false, }, // Case 9: Budget 0 → clamped to minimal (ZeroAllowed=false) { name: "9", from: "gemini", to: "codex", model: "level-model(0)", inputJSON: `{"model":"level-model(0)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "minimal", expectErr: false, }, // Case 10: Budget -1 → auto → DynamicAllowed=false → medium (mid-range) { name: "10", from: "gemini", to: "codex", model: "level-model(-1)", inputJSON: `{"model":"level-model(-1)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 11: Claude source no suffix → passthrough (no thinking) { name: "11", from: "claude", to: "openai", model: "level-model", inputJSON: `{"model":"level-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 12: Budget 8192 → medium { name: "12", from: "claude", to: "openai", model: "level-model(8192)", inputJSON: `{"model":"level-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "medium", expectErr: false, }, // Case 13: Budget 64000 → clamped to high { name: "13", from: "claude", to: "openai", model: "level-model(64000)", inputJSON: `{"model":"level-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "high", expectErr: false, }, // Case 14: Budget 0 → clamped to minimal (ZeroAllowed=false) { name: "14", from: "claude", to: "openai", model: "level-model(0)", inputJSON: `{"model":"level-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "minimal", expectErr: false, }, // Case 15: Budget -1 → auto → DynamicAllowed=false → medium (mid-range) { name: "15", from: "claude", to: "openai", model: "level-model(-1)", inputJSON: `{"model":"level-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "medium", expectErr: false, }, // level-subset-model (Levels=low/high, ZeroAllowed=false, DynamicAllowed=false) // Case 16: Budget 8192 → medium → rounded down to low { name: "16", from: "gemini", to: "openai", model: "level-subset-model(8192)", inputJSON: `{"model":"level-subset-model(8192)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning_effort", expectValue: "low", expectErr: false, }, // Case 17: Budget 1 → minimal → clamped to low (min supported) { name: "17", from: "claude", to: "gemini", model: "level-subset-model(1)", inputJSON: `{"model":"level-subset-model(1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 17A: auto → medium → clamped to low when low/high are equally close { name: "17A", from: "openai", to: "codex", model: "level-subset-model(auto)", inputJSON: `{"model":"level-subset-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "low", expectErr: false, }, // gemini-budget-model (Min=128, Max=20000, ZeroAllowed=false, DynamicAllowed=true) // Case 18: No suffix → passthrough { name: "18", from: "openai", to: "gemini", model: "gemini-budget-model", inputJSON: `{"model":"gemini-budget-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 19: Effort medium → 8192 { name: "19", from: "openai", to: "gemini", model: "gemini-budget-model(medium)", inputJSON: `{"model":"gemini-budget-model(medium)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 20: Effort xhigh → clamped to 20000 (max) { name: "20", from: "openai", to: "gemini", model: "gemini-budget-model(xhigh)", inputJSON: `{"model":"gemini-budget-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "20000", includeThoughts: "", expectErr: false, }, // Case 21: Effort none → clamped to 128 (min) { name: "21", from: "openai", to: "gemini", model: "gemini-budget-model(none)", inputJSON: `{"model":"gemini-budget-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "128", includeThoughts: "", expectErr: false, }, // Case 22: Effort auto → DynamicAllowed=true → -1 { name: "22", from: "openai", to: "gemini", model: "gemini-budget-model(auto)", inputJSON: `{"model":"gemini-budget-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // Case 23: Claude source no suffix → passthrough { name: "23", from: "claude", to: "gemini", model: "gemini-budget-model", inputJSON: `{"model":"gemini-budget-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 24: Budget 8192 → 8192 { name: "24", from: "claude", to: "gemini", model: "gemini-budget-model(8192)", inputJSON: `{"model":"gemini-budget-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 25: Budget 64000 → clamped to 20000 (max) { name: "25", from: "claude", to: "gemini", model: "gemini-budget-model(64000)", inputJSON: `{"model":"gemini-budget-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "20000", includeThoughts: "", expectErr: false, }, // Case 26: Budget 0 → clamped to 128 (min) { name: "26", from: "claude", to: "gemini", model: "gemini-budget-model(0)", inputJSON: `{"model":"gemini-budget-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "128", includeThoughts: "", expectErr: false, }, // Case 27: Budget -1 → DynamicAllowed=true → -1 { name: "27", from: "claude", to: "gemini", model: "gemini-budget-model(-1)", inputJSON: `{"model":"gemini-budget-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // gemini-mixed-model (Min=128, Max=32768, Levels=low/high, ZeroAllowed=false, DynamicAllowed=true) // Case 28: OpenAI source no suffix → passthrough { name: "28", from: "openai", to: "gemini", model: "gemini-mixed-model", inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 29: Effort high → low/high supported → high { name: "29", from: "openai", to: "gemini", model: "gemini-mixed-model(high)", inputJSON: `{"model":"gemini-mixed-model(high)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "high", includeThoughts: "", expectErr: false, }, // Case 30: Effort xhigh → clamped to high { name: "30", from: "openai", to: "gemini", model: "gemini-mixed-model(xhigh)", inputJSON: `{"model":"gemini-mixed-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "high", includeThoughts: "", expectErr: false, }, // Case 31: Effort none → clamped to low (min supported) { name: "31", from: "openai", to: "gemini", model: "gemini-mixed-model(none)", inputJSON: `{"model":"gemini-mixed-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 32: Effort auto → DynamicAllowed=true → -1 (budget) { name: "32", from: "openai", to: "gemini", model: "gemini-mixed-model(auto)", inputJSON: `{"model":"gemini-mixed-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // Case 33: Claude source no suffix → passthrough { name: "33", from: "claude", to: "gemini", model: "gemini-mixed-model", inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 34: Budget 8192 → 8192 (keep budget) { name: "34", from: "claude", to: "gemini", model: "gemini-mixed-model(8192)", inputJSON: `{"model":"gemini-mixed-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 35: Budget 64000 → clamped to 32768 (max) { name: "35", from: "claude", to: "gemini", model: "gemini-mixed-model(64000)", inputJSON: `{"model":"gemini-mixed-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "32768", includeThoughts: "", expectErr: false, }, // Case 36: Budget 0 → minimal → clamped to low (min level) { name: "36", from: "claude", to: "gemini", model: "gemini-mixed-model(0)", inputJSON: `{"model":"gemini-mixed-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 37: Budget -1 → DynamicAllowed=true → -1 (budget) { name: "37", from: "claude", to: "gemini", model: "gemini-mixed-model(-1)", inputJSON: `{"model":"gemini-mixed-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // claude-budget-model (Min=1024, Max=128000, ZeroAllowed=true, DynamicAllowed=false) // Case 38: OpenAI source no suffix → passthrough {Lines 1–500 of 3535. Load more
package test import ( "fmt" "testing" "time" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/translator" // Import provider packages to trigger init() registration of ProviderAppliers _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/antigravity" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/claude" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/codex" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/gemini" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/interactions" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/kimi" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/openai" _ "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking/provider/xai" "github.com/router-for-me/CLIProxyAPI/v7/internal/registry" "github.com/router-for-me/CLIProxyAPI/v7/internal/thinking" sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) // thinkingTestCase represents a common test case structure for both suffix and body tests. type thinkingTestCase struct { name string from string to string model string inputJSON string expectField string expectValue string expectField2 string expectValue2 string expectField3 string expectValue3 string expectAbsent []string includeThoughts string expectErr bool } // TestThinkingE2EMatrix_Suffix tests the thinking configuration transformation using model name suffix. // Data flow: Input JSON → TranslateRequest → ApplyThinking → Validate Output // No helper functions are used; all test data is inline. func TestThinkingE2EMatrix_Suffix(t *testing.T) { reg := registry.GetGlobalRegistry() uid := fmt.Sprintf("thinking-e2e-suffix-%d", time.Now().UnixNano()) reg.RegisterClient(uid, "test", getTestModels()) defer reg.UnregisterClient(uid) cases := []thinkingTestCase{ // level-model (Levels=minimal/low/medium/high, ZeroAllowed=false, DynamicAllowed=false) // Case 1: No suffix → injected default → medium { name: "1", from: "openai", to: "codex", model: "level-model", inputJSON: `{"model":"level-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 2: Specified medium → medium { name: "2", from: "openai", to: "codex", model: "level-model(medium)", inputJSON: `{"model":"level-model(medium)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 3: Specified xhigh → out of range error { name: "3", from: "openai", to: "codex", model: "level-model(xhigh)", inputJSON: `{"model":"level-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: true, }, // Case 4: Level none → clamped to minimal (ZeroAllowed=false) { name: "4", from: "openai", to: "codex", model: "level-model(none)", inputJSON: `{"model":"level-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "minimal", expectErr: false, }, // Case 5: Level auto → DynamicAllowed=false → medium (mid-range) { name: "5", from: "openai", to: "codex", model: "level-model(auto)", inputJSON: `{"model":"level-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 6: No suffix from gemini → injected default → medium { name: "6", from: "gemini", to: "codex", model: "level-model", inputJSON: `{"model":"level-model","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 7: Budget 8192 → medium { name: "7", from: "gemini", to: "codex", model: "level-model(8192)", inputJSON: `{"model":"level-model(8192)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 8: Budget 64000 → clamped to high { name: "8", from: "gemini", to: "codex", model: "level-model(64000)", inputJSON: `{"model":"level-model(64000)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "high", expectErr: false, }, // Case 9: Budget 0 → clamped to minimal (ZeroAllowed=false) { name: "9", from: "gemini", to: "codex", model: "level-model(0)", inputJSON: `{"model":"level-model(0)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "minimal", expectErr: false, }, // Case 10: Budget -1 → auto → DynamicAllowed=false → medium (mid-range) { name: "10", from: "gemini", to: "codex", model: "level-model(-1)", inputJSON: `{"model":"level-model(-1)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning.effort", expectValue: "medium", expectErr: false, }, // Case 11: Claude source no suffix → passthrough (no thinking) { name: "11", from: "claude", to: "openai", model: "level-model", inputJSON: `{"model":"level-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 12: Budget 8192 → medium { name: "12", from: "claude", to: "openai", model: "level-model(8192)", inputJSON: `{"model":"level-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "medium", expectErr: false, }, // Case 13: Budget 64000 → clamped to high { name: "13", from: "claude", to: "openai", model: "level-model(64000)", inputJSON: `{"model":"level-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "high", expectErr: false, }, // Case 14: Budget 0 → clamped to minimal (ZeroAllowed=false) { name: "14", from: "claude", to: "openai", model: "level-model(0)", inputJSON: `{"model":"level-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "minimal", expectErr: false, }, // Case 15: Budget -1 → auto → DynamicAllowed=false → medium (mid-range) { name: "15", from: "claude", to: "openai", model: "level-model(-1)", inputJSON: `{"model":"level-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning_effort", expectValue: "medium", expectErr: false, }, // level-subset-model (Levels=low/high, ZeroAllowed=false, DynamicAllowed=false) // Case 16: Budget 8192 → medium → rounded down to low { name: "16", from: "gemini", to: "openai", model: "level-subset-model(8192)", inputJSON: `{"model":"level-subset-model(8192)","contents":[{"role":"user","parts":[{"text":"hi"}]}]}`, expectField: "reasoning_effort", expectValue: "low", expectErr: false, }, // Case 17: Budget 1 → minimal → clamped to low (min supported) { name: "17", from: "claude", to: "gemini", model: "level-subset-model(1)", inputJSON: `{"model":"level-subset-model(1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 17A: auto → medium → clamped to low when low/high are equally close { name: "17A", from: "openai", to: "codex", model: "level-subset-model(auto)", inputJSON: `{"model":"level-subset-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "reasoning.effort", expectValue: "low", expectErr: false, }, // gemini-budget-model (Min=128, Max=20000, ZeroAllowed=false, DynamicAllowed=true) // Case 18: No suffix → passthrough { name: "18", from: "openai", to: "gemini", model: "gemini-budget-model", inputJSON: `{"model":"gemini-budget-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 19: Effort medium → 8192 { name: "19", from: "openai", to: "gemini", model: "gemini-budget-model(medium)", inputJSON: `{"model":"gemini-budget-model(medium)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 20: Effort xhigh → clamped to 20000 (max) { name: "20", from: "openai", to: "gemini", model: "gemini-budget-model(xhigh)", inputJSON: `{"model":"gemini-budget-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "20000", includeThoughts: "", expectErr: false, }, // Case 21: Effort none → clamped to 128 (min) { name: "21", from: "openai", to: "gemini", model: "gemini-budget-model(none)", inputJSON: `{"model":"gemini-budget-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "128", includeThoughts: "", expectErr: false, }, // Case 22: Effort auto → DynamicAllowed=true → -1 { name: "22", from: "openai", to: "gemini", model: "gemini-budget-model(auto)", inputJSON: `{"model":"gemini-budget-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // Case 23: Claude source no suffix → passthrough { name: "23", from: "claude", to: "gemini", model: "gemini-budget-model", inputJSON: `{"model":"gemini-budget-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 24: Budget 8192 → 8192 { name: "24", from: "claude", to: "gemini", model: "gemini-budget-model(8192)", inputJSON: `{"model":"gemini-budget-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 25: Budget 64000 → clamped to 20000 (max) { name: "25", from: "claude", to: "gemini", model: "gemini-budget-model(64000)", inputJSON: `{"model":"gemini-budget-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "20000", includeThoughts: "", expectErr: false, }, // Case 26: Budget 0 → clamped to 128 (min) { name: "26", from: "claude", to: "gemini", model: "gemini-budget-model(0)", inputJSON: `{"model":"gemini-budget-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "128", includeThoughts: "", expectErr: false, }, // Case 27: Budget -1 → DynamicAllowed=true → -1 { name: "27", from: "claude", to: "gemini", model: "gemini-budget-model(-1)", inputJSON: `{"model":"gemini-budget-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // gemini-mixed-model (Min=128, Max=32768, Levels=low/high, ZeroAllowed=false, DynamicAllowed=true) // Case 28: OpenAI source no suffix → passthrough { name: "28", from: "openai", to: "gemini", model: "gemini-mixed-model", inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 29: Effort high → low/high supported → high { name: "29", from: "openai", to: "gemini", model: "gemini-mixed-model(high)", inputJSON: `{"model":"gemini-mixed-model(high)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "high", includeThoughts: "", expectErr: false, }, // Case 30: Effort xhigh → clamped to high { name: "30", from: "openai", to: "gemini", model: "gemini-mixed-model(xhigh)", inputJSON: `{"model":"gemini-mixed-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "high", includeThoughts: "", expectErr: false, }, // Case 31: Effort none → clamped to low (min supported) { name: "31", from: "openai", to: "gemini", model: "gemini-mixed-model(none)", inputJSON: `{"model":"gemini-mixed-model(none)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 32: Effort auto → DynamicAllowed=true → -1 (budget) { name: "32", from: "openai", to: "gemini", model: "gemini-mixed-model(auto)", inputJSON: `{"model":"gemini-mixed-model(auto)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // Case 33: Claude source no suffix → passthrough { name: "33", from: "claude", to: "gemini", model: "gemini-mixed-model", inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}]}`, expectField: "", expectErr: false, }, // Case 34: Budget 8192 → 8192 (keep budget) { name: "34", from: "claude", to: "gemini", model: "gemini-mixed-model(8192)", inputJSON: `{"model":"gemini-mixed-model(8192)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "8192", includeThoughts: "", expectErr: false, }, // Case 35: Budget 64000 → clamped to 32768 (max) { name: "35", from: "claude", to: "gemini", model: "gemini-mixed-model(64000)", inputJSON: `{"model":"gemini-mixed-model(64000)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "32768", includeThoughts: "", expectErr: false, }, // Case 36: Budget 0 → minimal → clamped to low (min level) { name: "36", from: "claude", to: "gemini", model: "gemini-mixed-model(0)", inputJSON: `{"model":"gemini-mixed-model(0)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingLevel", expectValue: "low", includeThoughts: "", expectErr: false, }, // Case 37: Budget -1 → DynamicAllowed=true → -1 (budget) { name: "37", from: "claude", to: "gemini", model: "gemini-mixed-model(-1)", inputJSON: `{"model":"gemini-mixed-model(-1)","messages":[{"role":"user","content":"hi"}]}`, expectField: "generationConfig.thinkingConfig.thinkingBudget", expectValue: "-1", includeThoughts: "", expectErr: false, }, // claude-budget-model (Min=1024, Max=128000, ZeroAllowed=true, DynamicAllowed=false) // Case 38: OpenAI source no suffix → passthrough {