Conversation
…r from system prompt Claude Code client v2.1.36+ injects x-anthropic-billing-header as a text block inside the request body's system content array. Non-native Anthropic upstreams (e.g. Amazon Bedrock) reject this with 400. This proactive rectifier strips these blocks before forwarding, with a system settings toggle (default: enabled). - New rectifier module with regex-based detection - Full backend wiring: schema, repository, cache, validation, action - UI toggle in system settings form with i18n (5 locales) - SpecialSetting audit trail for removed blocks - 14 unit tests covering all edge cases - Drizzle migration for new boolean column
📝 WalkthroughWalkthrough此PR引入了一个新的系统设置 Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
⚔️ Resolve merge conflicts (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 |
Summary of ChangesHello @ding113, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request addresses a compatibility issue where the Claude Code client injects specific billing headers into the Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
🧪 测试结果
总体结果: ✅ 所有测试通过 |
There was a problem hiding this comment.
Code Review
This pull request introduces a proactive rectifier to strip x-anthropic-billing-header text blocks from system prompts, which is a great addition to prevent issues with non-native Anthropic upstreams like Amazon Bedrock. The implementation is thorough, covering database schema changes, backend logic, UI, internationalization, and comprehensive unit tests. The code is well-structured and the changes are clearly explained. I have one suggestion to refactor a part of the core rectifier logic for improved readability and to use more modern JavaScript/TypeScript idioms. Overall, this is a solid contribution.
| if (Array.isArray(system)) { | ||
| const extractedValues: string[] = []; | ||
| const filtered: unknown[] = []; | ||
|
|
||
| for (const block of system) { | ||
| if ( | ||
| block && | ||
| typeof block === "object" && | ||
| (block as Record<string, unknown>).type === "text" && | ||
| typeof (block as Record<string, unknown>).text === "string" && | ||
| BILLING_HEADER_PATTERN.test((block as Record<string, unknown>).text as string) | ||
| ) { | ||
| extractedValues.push(((block as Record<string, unknown>).text as string).trim()); | ||
| } else { | ||
| filtered.push(block); | ||
| } | ||
| } | ||
|
|
||
| if (extractedValues.length > 0) { | ||
| // Mutate in place: replace system array contents | ||
| system.length = 0; | ||
| for (const item of filtered) { | ||
| system.push(item); | ||
| } | ||
| return { applied: true, removedCount: extractedValues.length, extractedValues }; | ||
| } | ||
|
|
||
| return { applied: false, removedCount: 0, extractedValues: [] }; | ||
| } |
There was a problem hiding this comment.
The logic for handling the system array can be refactored to be more concise and idiomatic. Using Array.prototype.filter to separate the blocks and Array.prototype.splice for in-place mutation can make the code cleaner and more readable. This also provides an opportunity to make the type assertions slightly safer.
if (Array.isArray(system)) {
const extractedValues: string[] = [];
const filteredBlocks = system.filter(block => {
const isBillingBlock =
block &&
typeof block === "object" &&
(block as { type?: unknown }).type === "text" &&
typeof (block as { text?: unknown }).text === "string" &&
BILLING_HEADER_PATTERN.test((block as { text: string }).text);
if (isBillingBlock) {
extractedValues.push((block as { text: string }).text.trim());
return false;
}
return true;
});
if (extractedValues.length > 0) {
// Mutate in place: replace system array contents
system.splice(0, system.length, ...filteredBlocks);
return { applied: true, removedCount: extractedValues.length, extractedValues };
}
return { applied: false, removedCount: 0, extractedValues: [] };
}There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/repository/system-config.ts (1)
406-435:⚠️ Potential issue | 🔴 Critical在
returning()子句中缺少enableBillingHeaderRectifier字段 — 更新后返回的数据不完整Lines 355-356 正确地将
enableBillingHeaderRectifier写入数据库,但returning()子句(lines 406-435)中遗漏了该字段。这导致toSystemSettings(updated)收到的对象中enableBillingHeaderRectifier为undefined,进而导致:
- 保存设置后 UI 表单回显值可能错误(收到的
result.data.enableBillingHeaderRectifier为undefined)- 缓存失效后,下次读取前若依赖此返回值,可能使用错误的默认值
修复建议:在 returning 子句中添加缺失的字段
enableThinkingBudgetRectifier: systemSettings.enableThinkingBudgetRectifier, + enableBillingHeaderRectifier: systemSettings.enableBillingHeaderRectifier, enableCodexSessionIdCompletion: systemSettings.enableCodexSessionIdCompletion,
🧹 Nitpick comments (3)
src/app/v1/_lib/proxy/forwarder.ts (1)
1771-1772:getCachedSystemSettings()在同一请求路径中被多次调用。在
doForward中,billing header rectifier(line 1771)和后续的 metadata injection(line 1955)分别调用了getCachedSystemSettings()。虽然返回的是缓存结果,性能开销可忽略,但可以考虑将设置提取到 Anthropic 分支入口处统一获取,避免重复调用。src/app/v1/_lib/proxy/billing-header-rectifier.ts (2)
64-71: 数组清空后保留空数组 vs 字符串场景删除system字段 — 行为不一致,值得确认。当
system为字符串且匹配时(Line 39),代码使用delete message.system移除字段;但当system为数组且所有块均被移除后(Line 66-69),结果是一个空数组[]。部分上游 provider 可能对空
system数组的处理与缺失system字段不同(例如仍可能报错)。建议确认目标 provider(如 Bedrock)是否接受空system数组,或在清空后也delete message.system。可选修复:清空后删除 system 字段
if (extractedValues.length > 0) { // Mutate in place: replace system array contents system.length = 0; - for (const item of filtered) { - system.push(item); + if (filtered.length > 0) { + for (const item of filtered) { + system.push(item); + } + } else { + delete message.system; } return { applied: true, removedCount: extractedValues.length, extractedValues }; }
50-58: 类型断言较多,可考虑提取辅助函数提升可读性。Lines 51-56 中连续多次
(block as Record<string, unknown>)类型断言,可读性稍差。可考虑提取一个内联类型守卫来简化。可选重构:提取类型守卫
+function isBillingHeaderBlock(block: unknown): block is { type: "text"; text: string } { + return ( + block !== null && + typeof block === "object" && + (block as Record<string, unknown>).type === "text" && + typeof (block as Record<string, unknown>).text === "string" && + BILLING_HEADER_PATTERN.test((block as Record<string, unknown>).text as string) + ); +}然后循环体简化为:
for (const block of system) { if (isBillingHeaderBlock(block)) { extractedValues.push(block.text.trim()); } else { filtered.push(block); } }
There was a problem hiding this comment.
Code Review Summary
No significant issues identified in this PR.
PR Size: XL
- Lines changed: 3406
- Files changed: 24
- Split suggestions: Consider splitting into (1) proxy rectifier + forwarder integration + unit tests, (2) system settings schema/cache/repository wiring, (3) UI + i18n strings, and (4) generated Drizzle artifacts (snapshot/journal/migration).
Review Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Adequate
- Code clarity - Good
Automated review by Codex AI
There was a problem hiding this comment.
Reviewed PR #784 (“feat: add billing header rectifier”) across logic, security, error handling, types, docs/comments, tests, and simplification.
- PR size computed as XL (
3406lines changed,24files) and applied labelsize/XL. - Posted a PR review comment with the “No significant issues identified” summary (and included split suggestions due to XL size).
- No inline review comments were created because I did not find any diff-line issues that met the >=80 confidence reporting threshold.
Summary
x-anthropic-billing-headertext blocks from thesystemcontent array before forwarding to upstream providersProblem
Claude Code client v2.1.36+ injects
x-anthropic-billing-header: ...as a text block inside the request body'ssystemcontent array. Non-native Anthropic upstreams (e.g., Amazon Bedrock) reject this with:Solution
Follows the established rectifier pattern from #576 (thinking signature rectifier):
systemarray before forwarding to upstreamspecialSettingsfor request log auditingChanges
New files
src/app/v1/_lib/proxy/billing-header-rectifier.ts- Core rectifier moduledrizzle/0067_gorgeous_mulholland_black.sql- Migration addingenable_billing_header_rectifiercolumntests/unit/proxy/billing-header-rectifier.test.ts- 14 unit testsModified files (21)
special-settings.ts,system-config.ts- NewBillingHeaderRectifierSpecialSettingunion member +enableBillingHeaderRectifierfieldschema.ts- New boolean column (default: true)transformers.ts,system-config.ts(repo),system-settings-cache.ts,schemas.ts,special-settings.ts(utils),system-config.ts(action)forwarder.ts- Integration indoForward()Anthropic block before provider overridessystem-settings-form.tsx,page.tsx- Switch toggle with amber accenten,zh-CN,zh-TW,ja,ru)system-settings-cache.test.ts,system-config-save.test.tswith new fieldTest plan
bun run typecheck)bun run lint)bun run build)Related: Follows rectifier pattern established in #576