fix(proxy): Gemini function id 触发词兼容 JSON 转义引号并整段匹配路径,修复生产漏检 - #1322
Conversation
📝 WalkthroughWalkthrough修改 Gemini 函数 ID 整流检测逻辑,支持转义形式的 ChangesGemini 函数 ID 整流检测逻辑与测试
响应处理器测试断言
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Code Review
This pull request updates the Gemini function ID rectifier to support JSON-escaped quotes in upstream error messages by modifying the ID_VIOLATION_PATTERN regex. It also improves path matching accuracy by checking for exact segments (using a predefined set of function field segments) instead of substring matching, preventing false positives on paths like tool_config.function_calling_config. Corresponding unit tests have been added to verify these changes. There are no review comments, so I have no feedback to provide.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Code Review Summary
This is a high-quality bug fix with surgical precision and comprehensive validation.
PR Size: XS
- Lines changed: 60 (53 additions, 7 deletions)
- Files changed: 2
Issues Found
| Category | Critical | High | Medium | Low |
|---|---|---|---|---|
| Logic/Bugs | 0 | 0 | 0 | 0 |
| Security | 0 | 0 | 0 | 0 |
| Error Handling | 0 | 0 | 0 | 0 |
| Types | 0 | 0 | 0 | 0 |
| Comments/Docs | 0 | 0 | 0 | 0 |
| Tests | 0 | 0 | 0 | 0 |
| Simplification | 0 | 0 | 0 | 0 |
Review Summary
No significant issues identified. The fix correctly addresses the production bug with two precise changes:
- Regex escape tolerance: Pattern now matches
"id"(JSON-escaped) and"id"(bare quotes) by allowing zero or more backslashes on each side (\\*"id\\*") - Exact segment matching: Replaced substring
includes()with split-by-dot + array-index-stripping + Set lookup, preventing false positives on legitimate Gemini paths liketool_config.function_calling_config
Validation Performed
Logic correctness: ✓
- Regex pattern
\\*correctly matches 0+ backslashes (handles all escape levels) - Segment extraction
replace(/\[\d+\]$/, "")correctly strips array indices like[2] - Set-based exact matching prevents substring false positives
- Lowercase normalization handles both snake_case and camelCase
Test coverage: ✓
- 3 new regression tests cover production error format with escaped quotes
- Tests verify both positive detection and false-positive prevention
- Includes both
function_calling_configvariants (snake + camel)
Security: ✓
- Negated character classes prevent regex DoS
- No injection vectors introduced
Performance: ✓
- Set lookup O(1), split/replace O(n) - appropriate for error path
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Comprehensive
- Code clarity - Excellent
Automated review by Claude AI
生产验证发现(v0.8.10 + Vertex 直连实测):forwarder 的详细错误消息把
上游 JSON body 原样拼入(`| Upstream: {"error":{"message":"... Unknown
name \"id\" ..."}}`),message 字段内层引号处于 JSON 转义形态,裸引号
正则匹配不到 → 整流器从不触发,Vertex 400 依旧直达客户端。
两处修复:
- `id` 两侧允许任意个反斜杠(`\*"id\*"`),兼容转义/解码两种形态;
- 路径中的函数字段改为按路径段精确匹配(剥数组下标后整段比对),
避免 `tool_config.function_calling_config` 等真实 Gemini 路径因含
`function_call` 子串被误判,进而压制正常故障转移。
新增 3 例回归测试,其一取自生产 forwarder 详细错误消息原样形态。
修复后的正则已在生产实测:400 → rectifier applied → retry → 200。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4f46105 to
6701410
Compare
问题
#1308 的 Gemini function id 整流器在生产环境(v0.8.10 + Vertex 直连)实测不触发:Vertex 400 依旧透传给客户端,重试发送的是原始未整流请求体,且无任何 rectifier 日志。
根因:
tryApplyReactiveRectifier收到的errorMessage来自getDetailedErrorMessage(),其中上游 JSON body 被原样拼入:message字段内层引号处于 JSON 转义形态(\"id\"),而触发词正则匹配的是裸引号"id",因此永远检测不到。既有 thinking 系列整流器的触发词均不含引号,此形态差异此前未暴露过(smartTruncate对 JSON body 走JSON.stringify(parsed)完整保留,转义形态是结构性保证)。修复(两处)
ID_VIOLATION_PATTERN中id两侧允许任意个反斜杠,兼容裸引号(解码后文本)与\"/多重转义形态:includes改为按.分段、剥数组下标后整段比对。避免tool_config.function_calling_config/toolConfig.functionCallingConfig等真实 Gemini 路径因含function_call子串被误判——误判 + 剥离无效(applied=false)会把错误强改为NON_RETRYABLE_CLIENT_ERROR,压制正常供应商故障转移。验证
Gemini function id rectifier applied, retrying→ attempt 2 → 200,功能闭环| Upstream: {...}+\"转义 + 字面量\n分隔多violations)、转义形态无关路径不触发、function_calling_config两种命名不误判contents[2].parts[0].function_call、camelCase、网关追加.id后缀的变体bun run typecheck通过,biome 干净🤖 Generated with Claude Code
Greptile Summary
This PR fixes two root causes that prevented the Gemini function-
idrectifier from triggering in production (Vertex AI direct mode): the trigger regex failed to match JSON-escaped quotes (\"id\") that appear when the forwarder embeds the raw upstream JSON body in the error message, and path matching used substring.includes()which could false-positive ontool_config.function_calling_configand similar Gemini paths.ID_VIOLATION_PATTERNnow uses\\*"id\\*"(zero-or-more literal backslashes on each side of the quote), covering bare"id"and every JSON-escaped depth.path.includes(...)to splitting on., stripping trailing array indices, and looking up each segment in aFUNCTION_FIELD_SEGMENTSSet — preventingfunction_calling_config(which containsfunction_callas a substring) from being mistakenly treated as a function-field violation.response-handler-endpoint-circuit-isolation.test.ts: one existing test is updated to consume theResponsereturned bydispatchand to match renamed/re-signatured production helpers (clearSessionProvider,updateMessageRequestDetailsDurably).Confidence Score: 5/5
Safe to merge — both changes are narrowly scoped to the trigger-detection function, have production-verified behavior, and are covered by 21 unit tests including three new regression cases.
Both changes are narrowly scoped to the trigger-detection function with no data mutations or new async paths. The regex change correctly uses
\\*to match zero-or-more literal backslashes, and the segment-set replacement is strictly more precise than substring includes.No files require special attention.
Important Files Changed
\\*quantifier to match JSON-escaped backslash-quote forms, and a Set-based exact-segment check replacing substring includes to prevent false positives onfunction_calling_configpaths.\"escaping and literal\ndelimiters, JSON-escaped quote on an unrelated path (must not trigger), andfunction_calling_config/functionCallingConfigsubstring paths (must not trigger).dispatchnow returns aResponsethat must be consumed beforedrainAsyncTasks;clearSessionProvidernow takes a second numeric argument;updateMessageRequestDetailsrenamed toupdateMessageRequestDetailsDurablywith an extra options arg.Reviews (3): Last reviewed commit: "test(proxy): consume Responses failure s..." | Re-trigger Greptile