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 6f7ac724..99b50366 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 @@ -88,6 +88,15 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo } } + // For gemini-3-pro-preview, always send default thinkingConfig when none specified. + // This matches the official Gemini CLI behavior which always sends: + // { thinkingBudget: -1, includeThoughts: true } + // See: ai-gemini-cli/packages/core/src/config/defaultModelConfigs.ts + if !gjson.GetBytes(out, "request.generationConfig.thinkingConfig").Exists() && modelName == "gemini-3-pro-preview" { + out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1) + 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/responses/gemini_openai-responses_request.go b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go index 4eeebf3c..981fafc1 100644 --- a/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go +++ b/internal/translator/gemini/openai/responses/gemini_openai-responses_request.go @@ -6,6 +6,7 @@ import ( "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" "github.com/tidwall/gjson" "github.com/tidwall/sjson" ) @@ -294,6 +295,17 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte } } } + + // For gemini-3-pro-preview, always send default thinkingConfig when none specified. + // This matches the official Gemini CLI behavior which always sends: + // { thinkingBudget: -1, includeThoughts: true } + // See: ai-gemini-cli/packages/core/src/config/defaultModelConfigs.ts + if !gjson.Get(out, "generationConfig.thinkingConfig").Exists() && modelName == "gemini-3-pro-preview" { + out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1) + out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true) + log.Debugf("Applied default thinkingConfig for gemini-3-pro-preview (matches Gemini CLI): thinkingBudget=-1, include_thoughts=true") + } + result := []byte(out) result = common.AttachDefaultSafetySettings(result, "safetySettings") return result