From 199cf480b0a961330da537d36fbf503c2a343855 Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Thu, 15 Jan 2026 19:32:12 +0800 Subject: [PATCH] refactor(thinking): remove support for non-standard thinking configurations This change removes the translation logic for several non-standard, proprietary extensions used to configure thinking/reasoning. Specifically, support for `extra_body.google.thinking_config` and the Anthropic-style `thinking` object has been dropped from the OpenAI request translators. This simplification streamlines the translators, focusing them on the standard `reasoning_effort` parameter. It also removes the need to look up model information from the registry within these components. BREAKING CHANGE: Support for non-standard thinking configurations via `extra_body.google.thinking_config` and the Anthropic-style `thinking` object has been removed. Clients should now use the standard `reasoning_effort` parameter to control reasoning. --- .../antigravity_openai_request.go | 43 ------------------- .../gemini-cli_openai_request.go | 29 ------------- .../chat-completions/gemini_openai_request.go | 29 ------------- .../gemini_openai-responses_request.go | 23 ---------- 4 files changed, 124 deletions(-) diff --git a/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go b/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go index 7cfaa6e9..a4819ae7 100644 --- a/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go +++ b/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common" "github.com/router-for-me/CLIProxyAPI/v6/internal/util" log "github.com/sirupsen/logrus" @@ -38,7 +37,6 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _ // Apply thinking configuration: convert OpenAI reasoning_effort to Gemini CLI thinkingConfig. // Inline translation-only mapping; capability checks happen later in ApplyThinking. - modelInfo := registry.LookupModelInfo(modelName) re := gjson.GetBytes(rawJSON, "reasoning_effort") if re.Exists() { effort := strings.ToLower(strings.TrimSpace(re.String())) @@ -54,47 +52,6 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _ } } - // Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent) - // Only apply for models that use numeric budgets, not discrete levels. - if !re.Exists() && modelInfo != nil && modelInfo.Thinking != nil && len(modelInfo.Thinking.Levels) == 0 { - if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() { - var setBudget bool - var budget int - - if v := tc.Get("thinkingBudget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } else if v := tc.Get("thinking_budget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingBudget.thinkingBudget", budget) - setBudget = true - } - - if v := tc.Get("includeThoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if v := tc.Get("include_thoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if setBudget && budget != 0 { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true) - } - } - } - - // Claude/Anthropic API format: thinking.type == "enabled" with budget_tokens - // This allows Claude Code and other Claude API clients to pass thinking configuration - if !gjson.GetBytes(out, "request.generationConfig.thinkingConfig").Exists() && modelInfo != nil && modelInfo.Thinking != nil { - if t := gjson.GetBytes(rawJSON, "thinking"); t.Exists() && t.IsObject() { - if t.Get("type").String() == "enabled" { - if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number { - budget := int(b.Int()) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true) - } - } - } - } - // Temperature/top_p/top_k/max_tokens if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number { out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num) diff --git a/internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request.go b/internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request.go index 09d1dea7..938a5ae4 100644 --- a/internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request.go +++ b/internal/translator/gemini-cli/openai/chat-completions/gemini-cli_openai_request.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common" "github.com/router-for-me/CLIProxyAPI/v6/internal/util" log "github.com/sirupsen/logrus" @@ -39,7 +38,6 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo // Apply thinking configuration: convert OpenAI reasoning_effort to Gemini CLI thinkingConfig. // Inline translation-only mapping; capability checks happen later in ApplyThinking. re := gjson.GetBytes(rawJSON, "reasoning_effort") - modelInfo := registry.LookupModelInfo(modelName) if re.Exists() { effort := strings.ToLower(strings.TrimSpace(re.String())) if effort != "" { @@ -54,33 +52,6 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo } } - // Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent) - // Only apply for models that use numeric budgets, not discrete levels. - if !re.Exists() && modelInfo != nil && modelInfo.Thinking != nil && len(modelInfo.Thinking.Levels) == 0 { - if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() { - var setBudget bool - var budget int - - if v := tc.Get("thinkingBudget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } else if v := tc.Get("thinking_budget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } - - if v := tc.Get("includeThoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if v := tc.Get("include_thoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if setBudget && budget != 0 { - out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true) - } - } - } - // Temperature/top_p/top_k if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number { out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num) diff --git a/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go b/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go index 6e1a5014..fedd8dca 100644 --- a/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go +++ b/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go @@ -8,7 +8,6 @@ import ( "strings" "github.com/router-for-me/CLIProxyAPI/v6/internal/misc" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common" "github.com/router-for-me/CLIProxyAPI/v6/internal/util" log "github.com/sirupsen/logrus" @@ -38,7 +37,6 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) // Apply thinking configuration: convert OpenAI reasoning_effort to Gemini thinkingConfig. // Inline translation-only mapping; capability checks happen later in ApplyThinking. - modelInfo := registry.LookupModelInfo(modelName) re := gjson.GetBytes(rawJSON, "reasoning_effort") if re.Exists() { effort := strings.ToLower(strings.TrimSpace(re.String())) @@ -54,33 +52,6 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) } } - // Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent) - // Only apply for models that use numeric budgets, not discrete levels. - if !re.Exists() && modelInfo != nil && modelInfo.Thinking != nil && len(modelInfo.Thinking.Levels) == 0 { - if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() { - var setBudget bool - var budget int - - if v := tc.Get("thinkingBudget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } else if v := tc.Get("thinking_budget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } - - if v := tc.Get("includeThoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if v := tc.Get("include_thoughts"); v.Exists() { - out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if setBudget && budget != 0 { - out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true) - } - } - } - // Temperature/top_p/top_k if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number { out, _ = sjson.SetBytes(out, "generationConfig.temperature", tr.Num) diff --git a/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go index 81bb7d40..41279977 100644 --- a/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go +++ b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go @@ -4,7 +4,6 @@ import ( "bytes" "strings" - "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" "github.com/router-for-me/CLIProxyAPI/v6/internal/translator/gemini/common" "github.com/tidwall/gjson" "github.com/tidwall/sjson" @@ -390,7 +389,6 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte // Apply thinking configuration: convert OpenAI Responses API reasoning.effort to Gemini thinkingConfig. // Inline translation-only mapping; capability checks happen later in ApplyThinking. - modelInfo := registry.LookupModelInfo(modelName) re := root.Get("reasoning.effort") if re.Exists() { effort := strings.ToLower(strings.TrimSpace(re.String())) @@ -406,27 +404,6 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte } } - // Cherry Studio extension (applies only when official fields are missing) - // Only apply for models that use numeric budgets, not discrete levels. - if !re.Exists() && modelInfo != nil && modelInfo.Thinking != nil && len(modelInfo.Thinking.Levels) == 0 { - if tc := root.Get("extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() { - var setBudget bool - var budget int - if v := tc.Get("thinking_budget"); v.Exists() { - budget = int(v.Int()) - out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", budget) - setBudget = true - } - if v := tc.Get("include_thoughts"); v.Exists() { - out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool()) - } else if setBudget { - if budget != 0 { - out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true) - } - } - } - } - result := []byte(out) result = common.AttachDefaultSafetySettings(result, "safetySettings") return result