客户端使用 Claude Code(claude-cli/2.1.69),上游走 Gemini/Vertex 后端时,流式响应翻译器生成的 tool_use.id 不符合 Claude API 要求的正则 ^[a-zA-Z0-9_-]+$。
根因 在 internal/translator/gemini/claude/gemini_claude_response.go 第 224 行:
data, _ = sjson.Set(data, "content_block.id", fmt.Sprintf("%s-%d-%d", fcName, time.Now().UnixNano(), atomic.AddUint64(&toolUseIDCounter, 1)))
生成的 ID 格式为 {函数名}-{时间戳}-{计数器},例如:
- mcp__serena__list_dir-1741196414123456789-1 — 合法(只含 a-z、_、-)
- 但如果函数名含有点号等特殊字符(如 fs.readFile),ID 就变成 fs.readFile-1741196414123456789-1,不符合 ^[a-zA-Z0-9_-]+$
Claude Code 会保存这些 ID,并在后续请求的 tool_use_id 字段中回传,导致上游 Claude API 校验失败,返回:
400 {"type":"error","error":{"type":"invalid_request_error","message":"messages.1.content.2.tool_use.id: String should match pattern '^[a-zA-Z0-9_-]+$'"}}
注意: 非流式路径(ConvertGeminiResponseToClaudeNonStream,第 342 行)使用的是 fmt.Sprintf("tool_%d", toolIDCounter),不会触发此问题。
期望行为
tool_use.id 应只包含 ^[a-zA-Z0-9_-]+$ 范围内的字符,与 claude_gemini_request.go 中使用的 toolu_ 前缀格式保持一致。
建议修复
将第 224 行替换为安全的 ID 格式,例如:
sanitizedName := regexp.MustCompile(`[^a-zA-Z0-9_-]`).ReplaceAllString(fcName, "_")
data, _ = sjson.Set(data, "content_block.id", fmt.Sprintf("toolu_%s_%d_%d", sanitizedName, time.Now().UnixNano(), atomic.AddUi
客户端使用 Claude Code(claude-cli/2.1.69),上游走 Gemini/Vertex 后端时,流式响应翻译器生成的
tool_use.id不符合 Claude API 要求的正则^[a-zA-Z0-9_-]+$。根因 在
internal/translator/gemini/claude/gemini_claude_response.go第 224 行: