Merge pull request #465 from router-for-me/think
Move thinking budget normalization from translators to executor
This commit is contained in:
@@ -156,6 +156,7 @@ func (m *AmpModule) registerManagementRoutes(engine *gin.Engine, baseHandler *ha
|
|||||||
rootMiddleware := []gin.HandlerFunc{m.managementAvailabilityMiddleware(), noCORSMiddleware(), m.localhostOnlyMiddleware()}
|
rootMiddleware := []gin.HandlerFunc{m.managementAvailabilityMiddleware(), noCORSMiddleware(), m.localhostOnlyMiddleware()}
|
||||||
engine.GET("/threads/*path", append(rootMiddleware, proxyHandler)...)
|
engine.GET("/threads/*path", append(rootMiddleware, proxyHandler)...)
|
||||||
engine.GET("/threads.rss", append(rootMiddleware, proxyHandler)...)
|
engine.GET("/threads.rss", append(rootMiddleware, proxyHandler)...)
|
||||||
|
engine.GET("/news.rss", append(rootMiddleware, proxyHandler)...)
|
||||||
|
|
||||||
// Root-level auth routes for CLI login flow
|
// Root-level auth routes for CLI login flow
|
||||||
// Amp uses multiple auth routes: /auth/cli-login, /auth/callback, /auth/sign-in, /auth/logout
|
// Amp uses multiple auth routes: /auth/cli-login, /auth/callback, /auth/sign-in, /auth/logout
|
||||||
|
|||||||
@@ -309,11 +309,9 @@ func (e *AIStudioExecutor) translateRequest(req cliproxyexecutor.Request, opts c
|
|||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
payload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), stream)
|
payload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), stream)
|
||||||
payload = applyThinkingMetadata(payload, req.Metadata, req.Model)
|
payload = applyThinkingMetadata(payload, req.Metadata, req.Model)
|
||||||
|
payload = util.ApplyDefaultThinkingIfNeeded(req.Model, payload)
|
||||||
payload = util.ConvertThinkingLevelToBudget(payload)
|
payload = util.ConvertThinkingLevelToBudget(payload)
|
||||||
if budget := gjson.GetBytes(payload, "generationConfig.thinkingConfig.thinkingBudget"); budget.Exists() {
|
payload = util.NormalizeGeminiThinkingBudget(req.Model, payload)
|
||||||
normalized := util.NormalizeThinkingBudget(req.Model, int(budget.Int()))
|
|
||||||
payload, _ = sjson.SetBytes(payload, "generationConfig.thinkingConfig.thinkingBudget", normalized)
|
|
||||||
}
|
|
||||||
payload = util.StripThinkingConfigIfUnsupported(req.Model, payload)
|
payload = util.StripThinkingConfigIfUnsupported(req.Model, payload)
|
||||||
payload = fixGeminiImageAspectRatio(req.Model, payload)
|
payload = fixGeminiImageAspectRatio(req.Model, payload)
|
||||||
payload = applyPayloadConfig(e.cfg, req.Model, payload)
|
payload = applyPayloadConfig(e.cfg, req.Model, payload)
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ func (e *AntigravityExecutor) Execute(ctx context.Context, auth *cliproxyauth.Au
|
|||||||
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
||||||
|
|
||||||
translated = applyThinkingMetadataCLI(translated, req.Metadata, req.Model)
|
translated = applyThinkingMetadataCLI(translated, req.Metadata, req.Model)
|
||||||
|
translated = util.ApplyDefaultThinkingIfNeededCLI(req.Model, translated)
|
||||||
translated = normalizeAntigravityThinking(req.Model, translated)
|
translated = normalizeAntigravityThinking(req.Model, translated)
|
||||||
|
|
||||||
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
||||||
@@ -171,6 +172,7 @@ func (e *AntigravityExecutor) ExecuteStream(ctx context.Context, auth *cliproxya
|
|||||||
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
translated := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
||||||
|
|
||||||
translated = applyThinkingMetadataCLI(translated, req.Metadata, req.Model)
|
translated = applyThinkingMetadataCLI(translated, req.Metadata, req.Model)
|
||||||
|
translated = util.ApplyDefaultThinkingIfNeededCLI(req.Model, translated)
|
||||||
translated = normalizeAntigravityThinking(req.Model, translated)
|
translated = normalizeAntigravityThinking(req.Model, translated)
|
||||||
|
|
||||||
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
baseURLs := antigravityBaseURLFallbackOrder(auth)
|
||||||
@@ -839,9 +841,12 @@ func normalizeAntigravityThinking(model string, payload []byte) []byte {
|
|||||||
effectiveMax, setDefaultMax := antigravityEffectiveMaxTokens(model, payload)
|
effectiveMax, setDefaultMax := antigravityEffectiveMaxTokens(model, payload)
|
||||||
if effectiveMax > 0 && normalized >= effectiveMax {
|
if effectiveMax > 0 && normalized >= effectiveMax {
|
||||||
normalized = effectiveMax - 1
|
normalized = effectiveMax - 1
|
||||||
if normalized < 1 {
|
}
|
||||||
normalized = 1
|
minBudget := antigravityMinThinkingBudget(model)
|
||||||
}
|
if minBudget > 0 && normalized >= 0 && normalized < minBudget {
|
||||||
|
// Budget is below minimum, remove thinking config entirely
|
||||||
|
payload, _ = sjson.DeleteBytes(payload, "request.generationConfig.thinkingConfig")
|
||||||
|
return payload
|
||||||
}
|
}
|
||||||
if setDefaultMax {
|
if setDefaultMax {
|
||||||
if res, errSet := sjson.SetBytes(payload, "request.generationConfig.maxOutputTokens", effectiveMax); errSet == nil {
|
if res, errSet := sjson.SetBytes(payload, "request.generationConfig.maxOutputTokens", effectiveMax); errSet == nil {
|
||||||
@@ -869,3 +874,12 @@ func antigravityEffectiveMaxTokens(model string, payload []byte) (max int, fromM
|
|||||||
}
|
}
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// antigravityMinThinkingBudget returns the minimum thinking budget for a model.
|
||||||
|
// Falls back to -1 if no model info is found.
|
||||||
|
func antigravityMinThinkingBudget(model string) int {
|
||||||
|
if modelInfo := registry.GetGlobalRegistry().GetModelInfo(model); modelInfo != nil && modelInfo.Thinking != nil {
|
||||||
|
return modelInfo.Thinking.Min
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ func (e *GeminiCLIExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth
|
|||||||
to := sdktranslator.FromString("gemini-cli")
|
to := sdktranslator.FromString("gemini-cli")
|
||||||
basePayload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
basePayload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
||||||
basePayload = applyThinkingMetadataCLI(basePayload, req.Metadata, req.Model)
|
basePayload = applyThinkingMetadataCLI(basePayload, req.Metadata, req.Model)
|
||||||
|
basePayload = util.ApplyDefaultThinkingIfNeededCLI(req.Model, basePayload)
|
||||||
|
basePayload = util.NormalizeGeminiCLIThinkingBudget(req.Model, basePayload)
|
||||||
basePayload = util.StripThinkingConfigIfUnsupported(req.Model, basePayload)
|
basePayload = util.StripThinkingConfigIfUnsupported(req.Model, basePayload)
|
||||||
basePayload = fixGeminiCLIImageAspectRatio(req.Model, basePayload)
|
basePayload = fixGeminiCLIImageAspectRatio(req.Model, basePayload)
|
||||||
basePayload = applyPayloadConfigWithRoot(e.cfg, req.Model, "gemini", "request", basePayload)
|
basePayload = applyPayloadConfigWithRoot(e.cfg, req.Model, "gemini", "request", basePayload)
|
||||||
@@ -199,6 +201,8 @@ func (e *GeminiCLIExecutor) ExecuteStream(ctx context.Context, auth *cliproxyaut
|
|||||||
to := sdktranslator.FromString("gemini-cli")
|
to := sdktranslator.FromString("gemini-cli")
|
||||||
basePayload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
basePayload := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
||||||
basePayload = applyThinkingMetadataCLI(basePayload, req.Metadata, req.Model)
|
basePayload = applyThinkingMetadataCLI(basePayload, req.Metadata, req.Model)
|
||||||
|
basePayload = util.ApplyDefaultThinkingIfNeededCLI(req.Model, basePayload)
|
||||||
|
basePayload = util.NormalizeGeminiCLIThinkingBudget(req.Model, basePayload)
|
||||||
basePayload = util.StripThinkingConfigIfUnsupported(req.Model, basePayload)
|
basePayload = util.StripThinkingConfigIfUnsupported(req.Model, basePayload)
|
||||||
basePayload = fixGeminiCLIImageAspectRatio(req.Model, basePayload)
|
basePayload = fixGeminiCLIImageAspectRatio(req.Model, basePayload)
|
||||||
basePayload = applyPayloadConfigWithRoot(e.cfg, req.Model, "gemini", "request", basePayload)
|
basePayload = applyPayloadConfigWithRoot(e.cfg, req.Model, "gemini", "request", basePayload)
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ func (e *GeminiExecutor) Execute(ctx context.Context, auth *cliproxyauth.Auth, r
|
|||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), false)
|
||||||
body = applyThinkingMetadata(body, req.Metadata, req.Model)
|
body = applyThinkingMetadata(body, req.Metadata, req.Model)
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
@@ -169,6 +171,8 @@ func (e *GeminiExecutor) ExecuteStream(ctx context.Context, auth *cliproxyauth.A
|
|||||||
to := sdktranslator.FromString("gemini")
|
to := sdktranslator.FromString("gemini")
|
||||||
body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
body := sdktranslator.TranslateRequest(from, to, req.Model, bytes.Clone(req.Payload), true)
|
||||||
body = applyThinkingMetadata(body, req.Metadata, req.Model)
|
body = applyThinkingMetadata(body, req.Metadata, req.Model)
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
|
|||||||
@@ -296,6 +296,8 @@ func (e *GeminiVertexExecutor) executeWithServiceAccount(ctx context.Context, au
|
|||||||
}
|
}
|
||||||
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
||||||
}
|
}
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
@@ -391,6 +393,8 @@ func (e *GeminiVertexExecutor) executeWithAPIKey(ctx context.Context, auth *clip
|
|||||||
}
|
}
|
||||||
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
||||||
}
|
}
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
@@ -487,6 +491,8 @@ func (e *GeminiVertexExecutor) executeStreamWithServiceAccount(ctx context.Conte
|
|||||||
}
|
}
|
||||||
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
||||||
}
|
}
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
@@ -599,6 +605,8 @@ func (e *GeminiVertexExecutor) executeStreamWithAPIKey(ctx context.Context, auth
|
|||||||
}
|
}
|
||||||
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
body = util.ApplyGeminiThinkingConfig(body, budgetOverride, includeOverride)
|
||||||
}
|
}
|
||||||
|
body = util.ApplyDefaultThinkingIfNeeded(req.Model, body)
|
||||||
|
body = util.NormalizeGeminiThinkingBudget(req.Model, body)
|
||||||
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
body = util.StripThinkingConfigIfUnsupported(req.Model, body)
|
||||||
body = fixGeminiImageAspectRatio(req.Model, body)
|
body = fixGeminiImageAspectRatio(req.Model, body)
|
||||||
body = applyPayloadConfig(e.cfg, req.Model, body)
|
body = applyPayloadConfig(e.cfg, req.Model, body)
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ func ConvertClaudeRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
if t.Get("type").String() == "enabled" {
|
if t.Get("type").String() == "enabled" {
|
||||||
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
||||||
budget := int(b.Int())
|
budget := int(b.Int())
|
||||||
budget = util.NormalizeThinkingBudget(modelName, budget)
|
|
||||||
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-19
@@ -48,13 +48,13 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "low":
|
case "low":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 1024))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 1024)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "medium":
|
case "medium":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 8192))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 8192)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "high":
|
case "high":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 32768))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 32768)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
default:
|
default:
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
@@ -66,15 +66,15 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
var setBudget bool
|
var setBudget bool
|
||||||
var normalized int
|
var budget int
|
||||||
|
|
||||||
if v := tc.Get("thinkingBudget"); v.Exists() {
|
if v := tc.Get("thinkingBudget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if setBudget && normalized != 0 {
|
} else if setBudget && budget != 0 {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ func ConvertOpenAIRequestToAntigravity(modelName string, inputRawJSON []byte, _
|
|||||||
if t := gjson.GetBytes(rawJSON, "thinking"); t.Exists() && t.IsObject() {
|
if t := gjson.GetBytes(rawJSON, "thinking"); t.Exists() && t.IsObject() {
|
||||||
if t.Get("type").String() == "enabled" {
|
if t.Get("type").String() == "enabled" {
|
||||||
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
||||||
budget := util.NormalizeThinkingBudget(modelName, int(b.Int()))
|
budget := int(b.Int())
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
@@ -102,15 +102,6 @@ func ConvertOpenAIRequestToAntigravity(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.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/max_tokens
|
// Temperature/top_p/top_k/max_tokens
|
||||||
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
||||||
|
|||||||
@@ -165,7 +165,6 @@ func ConvertClaudeRequestToCLI(modelName string, inputRawJSON []byte, _ bool) []
|
|||||||
if t.Get("type").String() == "enabled" {
|
if t.Get("type").String() == "enabled" {
|
||||||
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
||||||
budget := int(b.Int())
|
budget := int(b.Int())
|
||||||
budget = util.NormalizeThinkingBudget(modelName, budget)
|
|
||||||
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-18
@@ -48,13 +48,13 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo
|
|||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "low":
|
case "low":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 1024))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 1024)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "medium":
|
case "medium":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 8192))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 8192)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "high":
|
case "high":
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 32768))
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", 32768)
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
default:
|
default:
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
@@ -66,15 +66,15 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo
|
|||||||
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
var setBudget bool
|
var setBudget bool
|
||||||
var normalized int
|
var budget int
|
||||||
|
|
||||||
if v := tc.Get("thinkingBudget"); v.Exists() {
|
if v := tc.Get("thinkingBudget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,21 +82,12 @@ func ConvertOpenAIRequestToGeminiCLI(modelName string, inputRawJSON []byte, _ bo
|
|||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if setBudget && normalized != 0 {
|
} else if setBudget && budget != 0 {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
// Temperature/top_p/top_k
|
||||||
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
if tr := gjson.GetBytes(rawJSON, "temperature"); tr.Exists() && tr.Type == gjson.Number {
|
||||||
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
out, _ = sjson.SetBytes(out, "request.generationConfig.temperature", tr.Num)
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ func ConvertClaudeRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
if t.Get("type").String() == "enabled" {
|
if t.Get("type").String() == "enabled" {
|
||||||
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
if b := t.Get("budget_tokens"); b.Exists() && b.Type == gjson.Number {
|
||||||
budget := int(b.Int())
|
budget := int(b.Int())
|
||||||
budget = util.NormalizeThinkingBudget(modelName, budget)
|
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,13 +48,13 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "low":
|
case "low":
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 1024))
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", 1024)
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "medium":
|
case "medium":
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 8192))
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", 8192)
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "high":
|
case "high":
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 32768))
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", 32768)
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
default:
|
default:
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
@@ -66,15 +66,15 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
if tc := gjson.GetBytes(rawJSON, "extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
var setBudget bool
|
var setBudget bool
|
||||||
var normalized int
|
var budget int
|
||||||
|
|
||||||
if v := tc.Get("thinkingBudget"); v.Exists() {
|
if v := tc.Get("thinkingBudget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
} else if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ func ConvertOpenAIRequestToGemini(modelName string, inputRawJSON []byte, _ bool)
|
|||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
} else if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if setBudget && normalized != 0 {
|
} else if setBudget && budget != 0 {
|
||||||
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.SetBytes(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -400,16 +400,16 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "minimal":
|
case "minimal":
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 1024))
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", 1024)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "low":
|
case "low":
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 4096))
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", 4096)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "medium":
|
case "medium":
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 8192))
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", 8192)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
case "high":
|
case "high":
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", util.NormalizeThinkingBudget(modelName, 32768))
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", 32768)
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
default:
|
default:
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
@@ -421,32 +421,22 @@ func ConvertOpenAIResponsesRequestToGemini(modelName string, inputRawJSON []byte
|
|||||||
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
if !hasOfficialThinking && util.ModelSupportsThinking(modelName) {
|
||||||
if tc := root.Get("extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
if tc := root.Get("extra_body.google.thinking_config"); tc.Exists() && tc.IsObject() {
|
||||||
var setBudget bool
|
var setBudget bool
|
||||||
var normalized int
|
var budget int
|
||||||
if v := tc.Get("thinking_budget"); v.Exists() {
|
if v := tc.Get("thinking_budget"); v.Exists() {
|
||||||
normalized = util.NormalizeThinkingBudget(modelName, int(v.Int()))
|
budget = int(v.Int())
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", normalized)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.thinkingBudget", budget)
|
||||||
setBudget = true
|
setBudget = true
|
||||||
}
|
}
|
||||||
if v := tc.Get("include_thoughts"); v.Exists() {
|
if v := tc.Get("include_thoughts"); v.Exists() {
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", v.Bool())
|
||||||
} else if setBudget {
|
} else if setBudget {
|
||||||
if normalized != 0 {
|
if budget != 0 {
|
||||||
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
out, _ = sjson.Set(out, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 := []byte(out)
|
||||||
result = common.AttachDefaultSafetySettings(result, "safetySettings")
|
result = common.AttachDefaultSafetySettings(result, "safetySettings")
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -207,6 +207,47 @@ func GeminiThinkingFromMetadata(metadata map[string]any) (*int, *bool, bool) {
|
|||||||
return budgetPtr, includePtr, matched
|
return budgetPtr, includePtr, matched
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// modelsWithDefaultThinking lists models that should have thinking enabled by default
|
||||||
|
// when no explicit thinkingConfig is provided.
|
||||||
|
var modelsWithDefaultThinking = map[string]bool{
|
||||||
|
"gemini-3-pro-preview": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModelHasDefaultThinking returns true if the model should have thinking enabled by default.
|
||||||
|
func ModelHasDefaultThinking(model string) bool {
|
||||||
|
return modelsWithDefaultThinking[model]
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyDefaultThinkingIfNeeded injects default thinkingConfig for models that require it.
|
||||||
|
// For standard Gemini API format (generationConfig.thinkingConfig path).
|
||||||
|
// Returns the modified body if thinkingConfig was added, otherwise returns the original.
|
||||||
|
func ApplyDefaultThinkingIfNeeded(model string, body []byte) []byte {
|
||||||
|
if !ModelHasDefaultThinking(model) {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
if gjson.GetBytes(body, "generationConfig.thinkingConfig").Exists() {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
updated, _ := sjson.SetBytes(body, "generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
|
updated, _ = sjson.SetBytes(updated, "generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
// ApplyDefaultThinkingIfNeededCLI injects default thinkingConfig for models that require it.
|
||||||
|
// For Gemini CLI API format (request.generationConfig.thinkingConfig path).
|
||||||
|
// Returns the modified body if thinkingConfig was added, otherwise returns the original.
|
||||||
|
func ApplyDefaultThinkingIfNeededCLI(model string, body []byte) []byte {
|
||||||
|
if !ModelHasDefaultThinking(model) {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
if gjson.GetBytes(body, "request.generationConfig.thinkingConfig").Exists() {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
updated, _ := sjson.SetBytes(body, "request.generationConfig.thinkingConfig.thinkingBudget", -1)
|
||||||
|
updated, _ = sjson.SetBytes(updated, "request.generationConfig.thinkingConfig.include_thoughts", true)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
// StripThinkingConfigIfUnsupported removes thinkingConfig from the request body
|
// StripThinkingConfigIfUnsupported removes thinkingConfig from the request body
|
||||||
// when the target model does not advertise Thinking capability. It cleans both
|
// when the target model does not advertise Thinking capability. It cleans both
|
||||||
// standard Gemini and Gemini CLI JSON envelopes. This acts as a final safety net
|
// standard Gemini and Gemini CLI JSON envelopes. This acts as a final safety net
|
||||||
@@ -223,6 +264,32 @@ func StripThinkingConfigIfUnsupported(model string, body []byte) []byte {
|
|||||||
return updated
|
return updated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NormalizeGeminiThinkingBudget normalizes the thinkingBudget value in a standard Gemini
|
||||||
|
// request body (generationConfig.thinkingConfig.thinkingBudget path).
|
||||||
|
func NormalizeGeminiThinkingBudget(model string, body []byte) []byte {
|
||||||
|
const budgetPath = "generationConfig.thinkingConfig.thinkingBudget"
|
||||||
|
budget := gjson.GetBytes(body, budgetPath)
|
||||||
|
if !budget.Exists() {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
normalized := NormalizeThinkingBudget(model, int(budget.Int()))
|
||||||
|
updated, _ := sjson.SetBytes(body, budgetPath, normalized)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeGeminiCLIThinkingBudget normalizes the thinkingBudget value in a Gemini CLI
|
||||||
|
// request body (request.generationConfig.thinkingConfig.thinkingBudget path).
|
||||||
|
func NormalizeGeminiCLIThinkingBudget(model string, body []byte) []byte {
|
||||||
|
const budgetPath = "request.generationConfig.thinkingConfig.thinkingBudget"
|
||||||
|
budget := gjson.GetBytes(body, budgetPath)
|
||||||
|
if !budget.Exists() {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
normalized := NormalizeThinkingBudget(model, int(budget.Int()))
|
||||||
|
updated, _ := sjson.SetBytes(body, budgetPath, normalized)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
// ConvertThinkingLevelToBudget checks for "generationConfig.thinkingConfig.thinkingLevel"
|
// ConvertThinkingLevelToBudget checks for "generationConfig.thinkingConfig.thinkingLevel"
|
||||||
// and converts it to "thinkingBudget".
|
// and converts it to "thinkingBudget".
|
||||||
// "high" -> 32768
|
// "high" -> 32768
|
||||||
|
|||||||
Reference in New Issue
Block a user