fix: 让消息 cache_control 改写默认关闭
This commit is contained in:
@@ -1251,13 +1251,11 @@ func (s *GatewayService) applyClaudeCodeOAuthMimicryToBody(
|
||||
body, _ = normalizeClaudeOAuthRequestBody(body, model, normalizeOpts)
|
||||
|
||||
// Phase D+E+F: messages cache 策略 + 工具名混淆 + tools[-1] 断点
|
||||
// 对齐 Parrot transform_request 里剩余的字段级改写。三步顺序有语义约束:
|
||||
// 1) strip:先清除客户端的 messages[*].cache_control(多轮稳定性)
|
||||
// 2) breakpoints:再注入 2 个断点(最后一条 + 倒数第二个 user turn)
|
||||
// 3) tool rewrite:最后改 tools[*].name / tool_choice.name 并在 tools[-1]
|
||||
// 对齐 Parrot transform_request 里剩余的字段级改写。顺序有语义约束:
|
||||
// 1) messages cache:仅在配置开启时清除客户端断点并注入代理断点
|
||||
// 2) tool rewrite:最后改 tools[*].name / tool_choice.name 并在 tools[-1]
|
||||
// 上打断点;mapping 存入 gin.Context 供响应侧 bytes.Replace 还原。
|
||||
body = stripMessageCacheControl(body)
|
||||
body = addMessageCacheBreakpoints(body)
|
||||
body = s.rewriteMessageCacheControlIfEnabled(ctx, body)
|
||||
|
||||
if rw := buildToolNameRewriteFromBody(body); rw != nil {
|
||||
body = applyToolNameRewriteToBody(body, rw)
|
||||
@@ -4108,7 +4106,7 @@ type cacheControlPath struct {
|
||||
log string
|
||||
}
|
||||
|
||||
func collectCacheControlPaths(body []byte) (invalidThinking []cacheControlPath, messagePaths []string, systemPaths []string) {
|
||||
func collectCacheControlPaths(body []byte) (invalidThinking []cacheControlPath, messagePaths []string, toolPaths []string, systemPaths []string) {
|
||||
system := gjson.GetBytes(body, "system")
|
||||
if system.IsArray() {
|
||||
sysIndex := 0
|
||||
@@ -4157,17 +4155,29 @@ func collectCacheControlPaths(body []byte) (invalidThinking []cacheControlPath,
|
||||
})
|
||||
}
|
||||
|
||||
return invalidThinking, messagePaths, systemPaths
|
||||
tools := gjson.GetBytes(body, "tools")
|
||||
if tools.IsArray() {
|
||||
toolIndex := 0
|
||||
tools.ForEach(func(_, tool gjson.Result) bool {
|
||||
if tool.Get("cache_control").Exists() {
|
||||
toolPaths = append(toolPaths, fmt.Sprintf("tools.%d.cache_control", toolIndex))
|
||||
}
|
||||
toolIndex++
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
return invalidThinking, messagePaths, toolPaths, systemPaths
|
||||
}
|
||||
|
||||
// enforceCacheControlLimit 强制执行 cache_control 块数量限制(最多 4 个)
|
||||
// 超限时优先从 messages 中移除 cache_control,保护 system 中的缓存控制
|
||||
// 超限时优先移除工具断点,再移除 messages 断点,最后才移除 system 断点。
|
||||
func enforceCacheControlLimit(body []byte) []byte {
|
||||
if len(body) == 0 {
|
||||
return body
|
||||
}
|
||||
|
||||
invalidThinking, messagePaths, systemPaths := collectCacheControlPaths(body)
|
||||
invalidThinking, messagePaths, toolPaths, systemPaths := collectCacheControlPaths(body)
|
||||
out := body
|
||||
modified := false
|
||||
|
||||
@@ -4185,7 +4195,7 @@ func enforceCacheControlLimit(body []byte) []byte {
|
||||
logger.LegacyPrintf("service.gateway", "%s", item.log)
|
||||
}
|
||||
|
||||
count := len(messagePaths) + len(systemPaths)
|
||||
count := len(messagePaths) + len(toolPaths) + len(systemPaths)
|
||||
if count <= maxCacheControlBlocks {
|
||||
if modified {
|
||||
return out
|
||||
@@ -4193,8 +4203,22 @@ func enforceCacheControlLimit(body []byte) []byte {
|
||||
return body
|
||||
}
|
||||
|
||||
// 超限:优先从 messages 中移除,再从 system 中移除
|
||||
// 超限:优先从 tools 中移除,再从 messages 中移除,最后才从 system 中移除。
|
||||
remaining := count - maxCacheControlBlocks
|
||||
for i := len(toolPaths) - 1; i >= 0 && remaining > 0; i-- {
|
||||
path := toolPaths[i]
|
||||
if !gjson.GetBytes(out, path).Exists() {
|
||||
continue
|
||||
}
|
||||
next, ok := deleteJSONPathBytes(out, path)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
out = next
|
||||
modified = true
|
||||
remaining--
|
||||
}
|
||||
|
||||
for _, path := range messagePaths {
|
||||
if remaining <= 0 {
|
||||
break
|
||||
@@ -4418,11 +4442,10 @@ func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *A
|
||||
|
||||
body, reqModel = normalizeClaudeOAuthRequestBody(body, reqModel, normalizeOpts)
|
||||
|
||||
// D/E/F: messages cache 策略 + 工具名混淆 + tools[-1] 断点
|
||||
// D/E/F: 可选 messages cache 策略 + 工具名混淆 + tools[-1] 断点
|
||||
// 与 forward_as_chat_completions / forward_as_responses 路径对齐,
|
||||
// 保证原生 /v1/messages 路径也经过完整的 Parrot 字段级改写。
|
||||
body = stripMessageCacheControl(body)
|
||||
body = addMessageCacheBreakpoints(body)
|
||||
// 原生 /v1/messages 路径也走同一套可配置字段级改写。
|
||||
body = s.rewriteMessageCacheControlIfEnabled(ctx, body)
|
||||
if rw := buildToolNameRewriteFromBody(body); rw != nil {
|
||||
body = applyToolNameRewriteToBody(body, rw)
|
||||
c.Set(toolNameRewriteKey, rw)
|
||||
@@ -8819,8 +8842,7 @@ func (s *GatewayService) ForwardCountTokens(ctx context.Context, c *gin.Context,
|
||||
normalizeOpts := claudeOAuthNormalizeOptions{stripSystemCacheControl: true}
|
||||
body, reqModel = normalizeClaudeOAuthRequestBody(body, reqModel, normalizeOpts)
|
||||
|
||||
body = stripMessageCacheControl(body)
|
||||
body = addMessageCacheBreakpoints(body)
|
||||
body = s.rewriteMessageCacheControlIfEnabled(ctx, body)
|
||||
if rw := buildToolNameRewriteFromBody(body); rw != nil {
|
||||
body = applyToolNameRewriteToBody(body, rw)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user