From d7afb6eb0c9e2330fcd60964ae8d7c483b10556f Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Sat, 20 Dec 2025 03:11:28 +0800 Subject: [PATCH] fix(gemini): improve reasoning effort conversion for Gemini 3 models Refactors the reasoning effort conversion logic for Gemini models. The update specifically addresses how `reasoning_effort` is translated into Gemini 3 specific thinking configurations (`thinkingLevel`, `includeThoughts`) and ensures that numeric budgets are not incorrectly applied to level-based models. Changes include: - Differentiating conversion logic for Gemini 3 models versus other models. - Handling `none`, `auto`, and validated thinking levels for Gemini 3. - Maintaining existing conversion for models not using discrete thinking levels. --- .../antigravity_openai_request.go | 19 +++++++++++++-- .../chat-completions/gemini_openai_request.go | 24 +++++++++++++++---- 2 files changed, 37 insertions(+), 6 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 d11afceb..293add0f 100644 --- a/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go +++ b/internal/translator/antigravity/openai/chat-completions/antigravity_openai_request.go @@ -39,8 +39,23 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _ // Note: OpenAI official fields take precedence over extra_body.google.thinking_config re := gjson.GetBytes(rawJSON, "reasoning_effort") hasOfficialThinking := re.Exists() - if hasOfficialThinking && util.ModelSupportsThinking(modelName) && !util.ModelUsesThinkingLevels(modelName) { - out = util.ApplyReasoningEffortToGeminiCLI(out, re.String()) + if hasOfficialThinking && util.ModelSupportsThinking(modelName) { + effort := strings.ToLower(strings.TrimSpace(re.String())) + if util.IsGemini3Model(modelName) { + switch effort { + case "none": + out, _ = sjson.DeleteBytes(out, "request.generationConfig.thinkingConfig") + case "auto": + includeThoughts := true + out = util.ApplyGeminiCLIThinkingLevel(out, "", &includeThoughts) + default: + if level, ok := util.ValidateGemini3ThinkingLevel(modelName, effort); ok { + out = util.ApplyGeminiCLIThinkingLevel(out, level, nil) + } + } + } else if !util.ModelUsesThinkingLevels(modelName) { + out = util.ApplyReasoningEffortToGeminiCLI(out, effort) + } } // Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent) 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 bc10ee34..c5f26fbd 100644 --- a/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go +++ b/internal/translator/gemini/openai/chat-completions/gemini_openai_request.go @@ -37,12 +37,28 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool) // Reasoning effort -> thinkingBudget/include_thoughts // Note: OpenAI official fields take precedence over extra_body.google.thinking_config - // Only convert for models that use numeric budgets (not discrete levels) to avoid - // incorrectly applying thinkingBudget for level-based models like gpt-5. + // Only apply numeric budgets for models that use budgets (not discrete levels) to avoid + // incorrectly applying thinkingBudget for level-based models like gpt-5. Gemini 3 models + // use thinkingLevel/includeThoughts instead. re := gjson.GetBytes(rawJSON, "reasoning_effort") hasOfficialThinking := re.Exists() - if hasOfficialThinking && util.ModelSupportsThinking(modelName) && !util.ModelUsesThinkingLevels(modelName) { - out = util.ApplyReasoningEffortToGemini(out, re.String()) + if hasOfficialThinking && util.ModelSupportsThinking(modelName) { + effort := strings.ToLower(strings.TrimSpace(re.String())) + if util.IsGemini3Model(modelName) { + switch effort { + case "none": + out, _ = sjson.DeleteBytes(out, "generationConfig.thinkingConfig") + case "auto": + includeThoughts := true + out = util.ApplyGeminiThinkingLevel(out, "", &includeThoughts) + default: + if level, ok := util.ValidateGemini3ThinkingLevel(modelName, effort); ok { + out = util.ApplyGeminiThinkingLevel(out, level, nil) + } + } + } else if !util.ModelUsesThinkingLevels(modelName) { + out = util.ApplyReasoningEffortToGemini(out, effort) + } } // Cherry Studio extension extra_body.google.thinking_config (effective only when official fields are absent)