diff --git a/internal/runtime/executor/gemini_cli_executor.go b/internal/runtime/executor/gemini_cli_executor.go index a96ca063..281b2970 100644 --- a/internal/runtime/executor/gemini_cli_executor.go +++ b/internal/runtime/executor/gemini_cli_executor.go @@ -89,6 +89,7 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth payload = setJSONField(payload, "project", projectID) payload = setJSONField(payload, "model", attemptModel) } + payload = disableGeminiThinkingConfig(payload, attemptModel) tok, errTok := tokenSource.Token() if errTok != nil { @@ -165,6 +166,7 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut payload := append([]byte(nil), basePayload...) payload = setJSONField(payload, "project", projectID) payload = setJSONField(payload, "model", attemptModel) + payload = disableGeminiThinkingConfig(payload, attemptModel) tok, errTok := tokenSource.Token() if errTok != nil { @@ -291,6 +293,7 @@ func (e *GeminiCLIExecutor) CountTokens(ctx context.Context, auth *cliproxyauth. payload := sdktranslator.TranslateRequest(from, to, attemptModel, bytes.Clone(req.Payload), false) payload = deleteJSONField(payload, "project") payload = deleteJSONField(payload, "model") + payload = disableGeminiThinkingConfig(payload, attemptModel) tok, errTok := tokenSource.Token() if errTok != nil { @@ -500,6 +503,29 @@ func cliPreviewFallbackOrder(model string) []string { } } +func disableGeminiThinkingConfig(body []byte, model string) []byte { + if !geminiModelDisallowsThinking(model) { + return body + } + + updated := deleteJSONField(body, "request.generationConfig.thinkingConfig") + updated = deleteJSONField(updated, "generationConfig.thinkingConfig") + return updated +} + +func geminiModelDisallowsThinking(model string) bool { + if model == "" { + return false + } + lower := strings.ToLower(model) + for _, marker := range []string{"gemini-2.5-flash-image-preview"} { + if strings.Contains(lower, marker) { + return true + } + } + return false +} + // setJSONField sets a top-level JSON field on a byte slice payload via sjson. func setJSONField(body []byte, key, value string) []byte { if key == "" { diff --git a/internal/runtime/executor/gemini_executor.go b/internal/runtime/executor/gemini_executor.go index 2015e15d..9a94783f 100644 --- a/internal/runtime/executor/gemini_executor.go +++ b/internal/runtime/executor/gemini_executor.go @@ -77,6 +77,7 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r from := opts.SourceFormat to := sdktranslator.FromString("gemini") body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false) + body = disableGeminiThinkingConfig(body, req.Model) action := "generateContent" if req.Metadata != nil { @@ -134,6 +135,7 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A from := opts.SourceFormat to := sdktranslator.FromString("gemini") body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true) + body = disableGeminiThinkingConfig(body, req.Model) url := fmt.Sprintf("%s/%s/models/%s:%s", glEndpoint, glAPIVersion, req.Model, "streamGenerateContent") if opts.Alt == "" { @@ -204,6 +206,7 @@ func (e *GeminiExecutor) CountTokens(ctx context.Context, auth *cliproxyauth.Aut from := opts.SourceFormat to := sdktranslator.FromString("gemini") translatedReq := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false) + translatedReq = disableGeminiThinkingConfig(translatedReq, req.Model) respCtx := context.WithValue(ctx, "alt", opts.Alt) translatedReq, _ = sjson.DeleteBytes(translatedReq, "tools") translatedReq, _ = sjson.DeleteBytes(translatedReq, "generationConfig")