feat(gateway): 优化 Antigravity/Gemini 思考块处理
此提交解决了思考块 (thinking blocks) 在转发过程中的兼容性问题。 主要变更: 1. **思考块优化 (Thinking Blocks)**: - 在 AntigravityGatewayService 中增加了 sanitizeThinkingBlocks 处理,强制移除思考块中不支持的 cache_control 字段(避免 Anthropic/Vertex AI 报错) - 实现历史思考块展平 (Flattening):将非最后一条消息中的思考块转换为普通文本块,以绕过上游对历史思考块签名的严格校验 - 增加 cleanCacheControlFromGeminiJSON 作为最后一道防线,确保转换后的 Gemini 请求中不残留非法的 cache_control 2. **GatewayService 缓存控制优化**: - 更新缓存控制逻辑,跳过 thinking 块(thinking 块不支持 cache_control 字段) - 增加 removeCacheControlFromThinkingBlocks 函数强制清理 关联 Issue: #225
This commit is contained in:
@@ -1188,6 +1188,9 @@ func enforceCacheControlLimit(body []byte) []byte {
|
||||
return body
|
||||
}
|
||||
|
||||
// 清理 thinking 块中的非法 cache_control(thinking 块不支持该字段)
|
||||
removeCacheControlFromThinkingBlocks(data)
|
||||
|
||||
// 计算当前 cache_control 块数量
|
||||
count := countCacheControlBlocks(data)
|
||||
if count <= maxCacheControlBlocks {
|
||||
@@ -1215,6 +1218,7 @@ func enforceCacheControlLimit(body []byte) []byte {
|
||||
}
|
||||
|
||||
// countCacheControlBlocks 统计 system 和 messages 中的 cache_control 块数量
|
||||
// 注意:thinking 块不支持 cache_control,统计时跳过
|
||||
func countCacheControlBlocks(data map[string]any) int {
|
||||
count := 0
|
||||
|
||||
@@ -1222,6 +1226,10 @@ func countCacheControlBlocks(data map[string]any) int {
|
||||
if system, ok := data["system"].([]any); ok {
|
||||
for _, item := range system {
|
||||
if m, ok := item.(map[string]any); ok {
|
||||
// thinking 块不支持 cache_control,跳过
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
continue
|
||||
}
|
||||
if _, has := m["cache_control"]; has {
|
||||
count++
|
||||
}
|
||||
@@ -1236,6 +1244,10 @@ func countCacheControlBlocks(data map[string]any) int {
|
||||
if content, ok := msgMap["content"].([]any); ok {
|
||||
for _, item := range content {
|
||||
if m, ok := item.(map[string]any); ok {
|
||||
// thinking 块不支持 cache_control,跳过
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
continue
|
||||
}
|
||||
if _, has := m["cache_control"]; has {
|
||||
count++
|
||||
}
|
||||
@@ -1251,6 +1263,7 @@ func countCacheControlBlocks(data map[string]any) int {
|
||||
|
||||
// removeCacheControlFromMessages 从 messages 中移除一个 cache_control(从头开始)
|
||||
// 返回 true 表示成功移除,false 表示没有可移除的
|
||||
// 注意:跳过 thinking 块(它不支持 cache_control)
|
||||
func removeCacheControlFromMessages(data map[string]any) bool {
|
||||
messages, ok := data["messages"].([]any)
|
||||
if !ok {
|
||||
@@ -1268,6 +1281,10 @@ func removeCacheControlFromMessages(data map[string]any) bool {
|
||||
}
|
||||
for _, item := range content {
|
||||
if m, ok := item.(map[string]any); ok {
|
||||
// thinking 块不支持 cache_control,跳过
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
continue
|
||||
}
|
||||
if _, has := m["cache_control"]; has {
|
||||
delete(m, "cache_control")
|
||||
return true
|
||||
@@ -1280,6 +1297,7 @@ func removeCacheControlFromMessages(data map[string]any) bool {
|
||||
|
||||
// removeCacheControlFromSystem 从 system 中移除一个 cache_control(从尾部开始,保护注入的 prompt)
|
||||
// 返回 true 表示成功移除,false 表示没有可移除的
|
||||
// 注意:跳过 thinking 块(它不支持 cache_control)
|
||||
func removeCacheControlFromSystem(data map[string]any) bool {
|
||||
system, ok := data["system"].([]any)
|
||||
if !ok {
|
||||
@@ -1289,6 +1307,10 @@ func removeCacheControlFromSystem(data map[string]any) bool {
|
||||
// 从尾部开始移除,保护开头注入的 Claude Code prompt
|
||||
for i := len(system) - 1; i >= 0; i-- {
|
||||
if m, ok := system[i].(map[string]any); ok {
|
||||
// thinking 块不支持 cache_control,跳过
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
continue
|
||||
}
|
||||
if _, has := m["cache_control"]; has {
|
||||
delete(m, "cache_control")
|
||||
return true
|
||||
@@ -1298,6 +1320,44 @@ func removeCacheControlFromSystem(data map[string]any) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// removeCacheControlFromThinkingBlocks 强制清理所有 thinking 块中的非法 cache_control
|
||||
// thinking 块不支持 cache_control 字段,这个函数确保所有 thinking 块都不含该字段
|
||||
func removeCacheControlFromThinkingBlocks(data map[string]any) {
|
||||
// 清理 system 中的 thinking 块
|
||||
if system, ok := data["system"].([]any); ok {
|
||||
for _, item := range system {
|
||||
if m, ok := item.(map[string]any); ok {
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
if _, has := m["cache_control"]; has {
|
||||
delete(m, "cache_control")
|
||||
log.Printf("[Warning] Removed illegal cache_control from thinking block in system")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清理 messages 中的 thinking 块
|
||||
if messages, ok := data["messages"].([]any); ok {
|
||||
for msgIdx, msg := range messages {
|
||||
if msgMap, ok := msg.(map[string]any); ok {
|
||||
if content, ok := msgMap["content"].([]any); ok {
|
||||
for contentIdx, item := range content {
|
||||
if m, ok := item.(map[string]any); ok {
|
||||
if blockType, _ := m["type"].(string); blockType == "thinking" {
|
||||
if _, has := m["cache_control"]; has {
|
||||
delete(m, "cache_control")
|
||||
log.Printf("[Warning] Removed illegal cache_control from thinking block in messages[%d].content[%d]", msgIdx, contentIdx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Forward 转发请求到Claude API
|
||||
func (s *GatewayService) Forward(ctx context.Context, c *gin.Context, account *Account, parsed *ParsedRequest) (*ForwardResult, error) {
|
||||
startTime := time.Now()
|
||||
|
||||
Reference in New Issue
Block a user