3535 lines · 125.4 KB · Go
RawDownload
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.