From e8f5888d8e0aa47c7cda22c8893bddcb9d4d622e Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Wed, 14 Jan 2026 09:02:26 +0800 Subject: [PATCH] fix(thinking): fix auth matching for thinking suffix and json field conflicts --- internal/thinking/provider/gemini/apply.go | 4 ++++ internal/thinking/provider/geminicli/apply.go | 4 ++++ sdk/cliproxy/auth/conductor.go | 7 +++++++ 3 files changed, 15 insertions(+) diff --git a/internal/thinking/provider/gemini/apply.go b/internal/thinking/provider/gemini/apply.go index 7de48919..eebc44d8 100644 --- a/internal/thinking/provider/gemini/apply.go +++ b/internal/thinking/provider/gemini/apply.go @@ -127,6 +127,8 @@ func (a *Applier) applyLevelFormat(body []byte, config thinking.ThinkingConfig) // Remove conflicting field to avoid both thinkingLevel and thinkingBudget in output result, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig.thinkingBudget") + // Normalize includeThoughts field name to avoid oneof conflicts in upstream JSON parsing. + result, _ = sjson.DeleteBytes(result, "generationConfig.thinkingConfig.include_thoughts") if config.Mode == thinking.ModeNone { result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.includeThoughts", false) @@ -150,6 +152,8 @@ func (a *Applier) applyLevelFormat(body []byte, config thinking.ThinkingConfig) func (a *Applier) applyBudgetFormat(body []byte, config thinking.ThinkingConfig) ([]byte, error) { // Remove conflicting field to avoid both thinkingLevel and thinkingBudget in output result, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig.thinkingLevel") + // Normalize includeThoughts field name to avoid oneof conflicts in upstream JSON parsing. + result, _ = sjson.DeleteBytes(result, "generationConfig.thinkingConfig.include_thoughts") budget := config.Budget // ModeNone semantics: diff --git a/internal/thinking/provider/geminicli/apply.go b/internal/thinking/provider/geminicli/apply.go index b076b7a6..1d5585ba 100644 --- a/internal/thinking/provider/geminicli/apply.go +++ b/internal/thinking/provider/geminicli/apply.go @@ -87,6 +87,8 @@ func (a *Applier) applyCompatible(body []byte, config thinking.ThinkingConfig) ( func (a *Applier) applyLevelFormat(body []byte, config thinking.ThinkingConfig) ([]byte, error) { // Remove conflicting field to avoid both thinkingLevel and thinkingBudget in output result, _ := sjson.DeleteBytes(body, "request.generationConfig.thinkingConfig.thinkingBudget") + // Normalize includeThoughts field name to avoid oneof conflicts in upstream JSON parsing. + result, _ = sjson.DeleteBytes(result, "request.generationConfig.thinkingConfig.include_thoughts") if config.Mode == thinking.ModeNone { result, _ = sjson.SetBytes(result, "request.generationConfig.thinkingConfig.includeThoughts", false) @@ -110,6 +112,8 @@ func (a *Applier) applyLevelFormat(body []byte, config thinking.ThinkingConfig) func (a *Applier) applyBudgetFormat(body []byte, config thinking.ThinkingConfig) ([]byte, error) { // Remove conflicting field to avoid both thinkingLevel and thinkingBudget in output result, _ := sjson.DeleteBytes(body, "request.generationConfig.thinkingConfig.thinkingLevel") + // Normalize includeThoughts field name to avoid oneof conflicts in upstream JSON parsing. + result, _ = sjson.DeleteBytes(result, "request.generationConfig.thinkingConfig.include_thoughts") budget := config.Budget includeThoughts := false diff --git a/sdk/cliproxy/auth/conductor.go b/sdk/cliproxy/auth/conductor.go index 5b1339be..6e035d0f 100644 --- a/sdk/cliproxy/auth/conductor.go +++ b/sdk/cliproxy/auth/conductor.go @@ -1711,6 +1711,13 @@ func (m *Manager) pickNext(ctx context.Context, provider, model string, opts cli } candidates := make([]*Auth, 0, len(m.auths)) modelKey := strings.TrimSpace(model) + // Always use base model name (without thinking suffix) for auth matching. + if modelKey != "" { + parsed := thinking.ParseSuffix(modelKey) + if parsed.ModelName != "" { + modelKey = strings.TrimSpace(parsed.ModelName) + } + } registryRef := registry.GetGlobalRegistry() for _, candidate := range m.auths { if candidate.Provider != provider || candidate.Disabled {