| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| package gemini |
|
|
| import ( |
| "github.com/router-for-me/CLIProxyAPI/v6/internal/registry" |
| "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking" |
| "github.com/tidwall/gjson" |
| "github.com/tidwall/sjson" |
| ) |
|
|
| |
| |
| |
| |
| |
| |
| type Applier struct{} |
|
|
| |
| func NewApplier() *Applier { |
| return &Applier{} |
| } |
|
|
| func init() { |
| thinking.RegisterProvider("gemini", NewApplier()) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| func (a *Applier) Apply(body []byte, config thinking.ThinkingConfig, modelInfo *registry.ModelInfo) ([]byte, error) { |
| if thinking.IsUserDefinedModel(modelInfo) { |
| return a.applyCompatible(body, config) |
| } |
| if modelInfo.Thinking == nil { |
| return body, nil |
| } |
|
|
| if config.Mode != thinking.ModeBudget && config.Mode != thinking.ModeLevel && config.Mode != thinking.ModeNone && config.Mode != thinking.ModeAuto { |
| return body, nil |
| } |
|
|
| if len(body) == 0 || !gjson.ValidBytes(body) { |
| body = []byte(`{}`) |
| } |
|
|
| |
| |
| |
| |
| switch config.Mode { |
| case thinking.ModeLevel: |
| return a.applyLevelFormat(body, config) |
| case thinking.ModeNone: |
| |
| if len(modelInfo.Thinking.Levels) > 0 { |
| return a.applyLevelFormat(body, config) |
| } |
| return a.applyBudgetFormat(body, config) |
| default: |
| return a.applyBudgetFormat(body, config) |
| } |
| } |
|
|
| func (a *Applier) applyCompatible(body []byte, config thinking.ThinkingConfig) ([]byte, error) { |
| if config.Mode != thinking.ModeBudget && config.Mode != thinking.ModeLevel && config.Mode != thinking.ModeNone && config.Mode != thinking.ModeAuto { |
| return body, nil |
| } |
|
|
| if len(body) == 0 || !gjson.ValidBytes(body) { |
| body = []byte(`{}`) |
| } |
|
|
| if config.Mode == thinking.ModeAuto { |
| return a.applyBudgetFormat(body, config) |
| } |
|
|
| if config.Mode == thinking.ModeLevel || (config.Mode == thinking.ModeNone && config.Level != "") { |
| return a.applyLevelFormat(body, config) |
| } |
|
|
| return a.applyBudgetFormat(body, config) |
| } |
|
|
| func (a *Applier) applyLevelFormat(body []byte, config thinking.ThinkingConfig) ([]byte, error) { |
| |
| |
| |
| |
|
|
| |
| result, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig.thinkingBudget") |
| |
| result, _ = sjson.DeleteBytes(result, "generationConfig.thinkingConfig.include_thoughts") |
|
|
| if config.Mode == thinking.ModeNone { |
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.includeThoughts", false) |
| if config.Level != "" { |
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.thinkingLevel", string(config.Level)) |
| } |
| return result, nil |
| } |
|
|
| |
| if config.Mode != thinking.ModeLevel { |
| return body, nil |
| } |
|
|
| level := string(config.Level) |
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.thinkingLevel", level) |
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.includeThoughts", true) |
| return result, nil |
| } |
|
|
| func (a *Applier) applyBudgetFormat(body []byte, config thinking.ThinkingConfig) ([]byte, error) { |
| |
| result, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig.thinkingLevel") |
| |
| result, _ = sjson.DeleteBytes(result, "generationConfig.thinkingConfig.include_thoughts") |
|
|
| budget := config.Budget |
| |
| |
| |
| |
| includeThoughts := false |
| switch config.Mode { |
| case thinking.ModeNone: |
| includeThoughts = false |
| case thinking.ModeAuto: |
| includeThoughts = true |
| default: |
| includeThoughts = budget > 0 |
| } |
|
|
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.thinkingBudget", budget) |
| result, _ = sjson.SetBytes(result, "generationConfig.thinkingConfig.includeThoughts", includeThoughts) |
| return result, nil |
| } |
|
|