From c8e55ab2ac7ce51409d09071156fd153d526c81d Mon Sep 17 00:00:00 2001 From: song Date: Fri, 2 Jan 2026 11:44:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=A7=BB=E9=99=A4=20antigravity=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E4=B8=AD=E7=9A=84=20[Debug]=20=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 这些调试日志不应在生产环境中输出。 --- .../pkg/antigravity/request_transformer.go | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/backend/internal/pkg/antigravity/request_transformer.go b/backend/internal/pkg/antigravity/request_transformer.go index d662be0e..fbaedd3d 100644 --- a/backend/internal/pkg/antigravity/request_transformer.go +++ b/backend/internal/pkg/antigravity/request_transformer.go @@ -172,6 +172,31 @@ func buildContents(messages []ClaudeMessage, toolIDToName map[string]string, isT // 参考: https://ai.google.dev/gemini-api/docs/thought-signatures const dummyThoughtSignature = "skip_thought_signature_validator" +// isValidThoughtSignature 验证 thought signature 是否有效 +// Claude API 要求 signature 必须是 base64 编码的字符串,长度至少 32 字节 +func isValidThoughtSignature(signature string) bool { + // 空字符串无效 + if signature == "" { + return false + } + + // signature 应该是 base64 编码,长度至少 40 个字符(约 30 字节) + // 参考 Claude API 文档和实际观察到的有效 signature + if len(signature) < 40 { + return false + } + + // 检查是否是有效的 base64 字符 + // base64 字符集: A-Z, a-z, 0-9, +, /, = + for _, c := range signature { + if (c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && + (c < '0' || c > '9') && c != '+' && c != '/' && c != '=' { + return false + } + } + + return true +} // buildParts 构建消息的 parts // allowDummyThought: 只有 Gemini 模型支持 dummy thought signature func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDummyThought bool) ([]GeminiPart, error) { @@ -200,22 +225,17 @@ func buildParts(content json.RawMessage, toolIDToName map[string]string, allowDu } case "thinking": - part := GeminiPart{ - Text: block.Thinking, - Thought: true, - } - // 保留原有 signature(Claude 模型需要有效的 signature) - if block.Signature != "" { - part.ThoughtSignature = block.Signature - } else if !allowDummyThought { - // Claude 模型需要有效 signature,跳过无 signature 的 thinking block - log.Printf("Warning: skipping thinking block without signature for Claude model") + // Claude 模型:仅在提供有效 signature 时保留 thinking block;否则跳过以避免上游校验失败。 + signature := strings.TrimSpace(block.Signature) + if signature == "" || signature == dummyThoughtSignature { + log.Printf("[Warning] Skipping thinking block for Claude model (missing or dummy signature)") continue - } else { - // Gemini 模型使用 dummy signature - part.ThoughtSignature = dummyThoughtSignature } - parts = append(parts, part) + parts = append(parts, GeminiPart{ + Text: block.Thinking, + Thought: true, + ThoughtSignature: signature, + }) case "image": if block.Source != nil && block.Source.Type == "base64" {