mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-03 04:50:52 +08:00
fix(runtime): unify claude thinking config resolution
This commit is contained in:
@@ -450,59 +450,15 @@ func extractAndRemoveBetas(body []byte) ([]string, []byte) {
|
|||||||
return betas, body
|
return betas, body
|
||||||
}
|
}
|
||||||
|
|
||||||
// injectThinkingConfig adds thinking configuration based on metadata or legacy suffixes.
|
// injectThinkingConfig adds thinking configuration based on metadata using the unified flow.
|
||||||
|
// It uses util.ResolveClaudeThinkingConfig which internally calls ResolveThinkingConfigFromMetadata
|
||||||
|
// and NormalizeThinkingBudget, ensuring consistency with other executors like Gemini.
|
||||||
func (e *ClaudeExecutor) injectThinkingConfig(modelName string, metadata map[string]any, body []byte) []byte {
|
func (e *ClaudeExecutor) injectThinkingConfig(modelName string, metadata map[string]any, body []byte) []byte {
|
||||||
// Only inject if thinking config is not already present
|
budget, ok := util.ResolveClaudeThinkingConfig(modelName, metadata)
|
||||||
if gjson.GetBytes(body, "thinking").Exists() {
|
if !ok {
|
||||||
return body
|
return body
|
||||||
}
|
}
|
||||||
|
return util.ApplyClaudeThinkingConfig(body, budget)
|
||||||
budgetTokens, ok := resolveClaudeThinkingBudget(modelName, metadata)
|
|
||||||
if !ok || budgetTokens <= 0 {
|
|
||||||
return body
|
|
||||||
}
|
|
||||||
|
|
||||||
body, _ = sjson.SetBytes(body, "thinking.type", "enabled")
|
|
||||||
body, _ = sjson.SetBytes(body, "thinking.budget_tokens", budgetTokens)
|
|
||||||
return body
|
|
||||||
}
|
|
||||||
|
|
||||||
func resolveClaudeThinkingBudget(modelName string, metadata map[string]any) (int, bool) {
|
|
||||||
budget, include, effort, matched := util.ThinkingFromMetadata(metadata)
|
|
||||||
if matched {
|
|
||||||
if include != nil && !*include {
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
if budget != nil {
|
|
||||||
normalized := util.NormalizeThinkingBudget(modelName, *budget)
|
|
||||||
if normalized > 0 {
|
|
||||||
return normalized, true
|
|
||||||
}
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
if effort != nil {
|
|
||||||
if derived, ok := util.ThinkingEffortToBudget(modelName, *effort); ok && derived > 0 {
|
|
||||||
return derived, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return claudeBudgetFromSuffix(modelName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func claudeBudgetFromSuffix(modelName string) (int, bool) {
|
|
||||||
lower := strings.ToLower(strings.TrimSpace(modelName))
|
|
||||||
switch {
|
|
||||||
case strings.HasSuffix(lower, "-thinking-low"):
|
|
||||||
return 1024, true
|
|
||||||
case strings.HasSuffix(lower, "-thinking-medium"):
|
|
||||||
return 8192, true
|
|
||||||
case strings.HasSuffix(lower, "-thinking-high"):
|
|
||||||
return 24576, true
|
|
||||||
case strings.HasSuffix(lower, "-thinking"):
|
|
||||||
return 8192, true
|
|
||||||
default:
|
|
||||||
return 0, false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureMaxTokensForThinking ensures max_tokens > thinking.budget_tokens when thinking is enabled.
|
// ensureMaxTokensForThinking ensures max_tokens > thinking.budget_tokens when thinking is enabled.
|
||||||
|
|||||||
46
internal/util/claude_thinking.go
Normal file
46
internal/util/claude_thinking.go
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"github.com/tidwall/sjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ApplyClaudeThinkingConfig applies thinking configuration to a Claude API request payload.
|
||||||
|
// It sets the thinking.type to "enabled" and thinking.budget_tokens to the specified budget.
|
||||||
|
// If budget is nil or the payload already has thinking config, it returns the payload unchanged.
|
||||||
|
func ApplyClaudeThinkingConfig(body []byte, budget *int) []byte {
|
||||||
|
if budget == nil {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
if gjson.GetBytes(body, "thinking").Exists() {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
if *budget <= 0 {
|
||||||
|
return body
|
||||||
|
}
|
||||||
|
updated := body
|
||||||
|
updated, _ = sjson.SetBytes(updated, "thinking.type", "enabled")
|
||||||
|
updated, _ = sjson.SetBytes(updated, "thinking.budget_tokens", *budget)
|
||||||
|
return updated
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveClaudeThinkingConfig resolves thinking configuration from metadata for Claude models.
|
||||||
|
// It uses the unified ResolveThinkingConfigFromMetadata and normalizes the budget.
|
||||||
|
// Returns the normalized budget (nil if thinking should not be enabled) and whether it matched.
|
||||||
|
func ResolveClaudeThinkingConfig(modelName string, metadata map[string]any) (*int, bool) {
|
||||||
|
budget, include, matched := ResolveThinkingConfigFromMetadata(modelName, metadata)
|
||||||
|
if !matched {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
if include != nil && !*include {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
if budget == nil {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
normalized := NormalizeThinkingBudget(modelName, *budget)
|
||||||
|
if normalized <= 0 {
|
||||||
|
return nil, true
|
||||||
|
}
|
||||||
|
return &normalized, true
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user