fix(proxy): 将 messages 中的 role:"system" 消息合并到顶层 system 字段,修复严格上游 400#1268
fix(proxy): 将 messages 中的 role:"system" 消息合并到顶层 system 字段,修复严格上游 400#126800010110 wants to merge 3 commits into
Conversation
…ing113#1265) Claude Code 2.1.172+ 配合自定义模型名时会在 messages 数组中注入独立的 role:"system" 消息(skills 列表)。Anthropic 官方 API 接受该写法,但 Vertex/Bedrock 类严格校验的兼容上游会以 400 拒绝,导致 cchub 重试耗尽 全部供应商后熔断返回 503。 - 新增 system message rectifier(proactive,参照 billing-header-rectifier 模式):转发前将 role:"system" 消息从 messages 中取出,文本内容以 {type:"text",text} block 形式追加到顶层 system 字段末尾,原地变异并 记录 system_message_rectifier specialSetting 审计 - 在 forwarder 中对 claude/claude-auth 供应商启用,且置于 billing header rectifier 之前,确保 system 消息内携带的 billing header 块在搬移后仍 会被剥离 - 新增系统设置开关 enableSystemMessageRectifier(默认开启),覆盖 schema/迁移/缓存/类型/校验/Server Action/REST/OpenAPI/UI 全链路, 并按既有模式接入 system_settings 缺列降级链(读取与更新),保证 迁移前部署的实例行为不回退 - 设置页新增开关项,补全 zh-CN/zh-TW/en/ja/ru 五语言文案 - 新增 16 个单元测试覆盖 string/array content、顶层 system 各形态、 保序、原地变异及与 billing rectifier 的执行顺序组合 Fixes ding113#1265
📝 WalkthroughWalkthrough本 PR 实现系统消息整流器功能。当 Claude Code 2.1.172+ 使用自定义模型名时,会在 messages 数组中注入 变更说明System Message Rectifier 整体实现
预估代码审查工作量🎯 3 (Moderate) | ⏱️ ~25 minutes 可能相关的 PR
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 introduces a System Message Rectifier to handle cases where the Claude Code client (v2.1.172+) injects 'role: system' messages directly into the 'messages' array, which causes 400 errors on strict Anthropic-compatible upstreams like Vertex and Bedrock. The rectifier extracts these system messages and merges them into the top-level 'system' field. The changes span database migrations, schema updates, UI toggle settings, localization, and comprehensive unit tests for the new rectifier logic. There are no review comments, and 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
No significant issues identified. The core rectifier logic is correct, well-tested (16 cases), and follows the established billing-header-rectifier pattern exactly. The degradation chain, type definitions, settings propagation, and i18n are all consistent with existing conventions.
PR Size: XL
- Lines changed: 5,137 (5,121 additions + 16 deletions)
- Files changed: 25
Note: ~4,535 lines are from the auto-generated Drizzle migration snapshot. Meaningful code changes are ~600 lines across the new rectifier module, forwarder integration, repository degradation chain, settings plumbing, and tests.
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 Coverage
- Logic and correctness - Clean
- Security (OWASP Top 10) - Clean
- Error handling - Clean
- Type safety - Clean
- Documentation accuracy - Clean
- Test coverage - Comprehensive (16 test cases covering string/array content, empty content, non-object entries, mutation semantics, integration with billing rectifier)
- Code clarity - Good
Automated review by Claude AI
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/app/v1/_lib/proxy/forwarder.ts`:
- Line 95: The new import uses a relative path; update the import of
rectifySystemMessages in forwarder.ts to use the project path alias that maps
./src to `@/` (e.g. replace "./system-message-rectifier" with the corresponding
"`@/`..." module path), so the import reads from the `@/` alias and conforms to the
repository import rules.
In `@src/app/v1/_lib/proxy/system-message-rectifier.ts`:
- Around line 25-29: The NOOP_RESULT constant shares a single extractedValues
array reference which causes callers that mutate it to leak state; replace the
shared constant with a factory that returns a fresh SystemMessageRectifierResult
each time (e.g. createNoopResult(): SystemMessageRectifierResult { return {
applied:false, movedCount:0, extractedValues:[] }; }) and update all places that
currently do shallow copies like { ...NOOP_RESULT } to call createNoopResult()
(also fix the other similar NOOP-style returns referenced around the other
occurrences so each call gets its own extractedValues array).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ddd59d5f-5e0a-4ae2-90cf-d6d1ae0b6659
📒 Files selected for processing (25)
drizzle/0105_easy_cyclops.sqldrizzle/meta/0105_snapshot.jsondrizzle/meta/_journal.jsonmessages/en/settings/config.jsonmessages/ja/settings/config.jsonmessages/ru/settings/config.jsonmessages/zh-CN/settings/config.jsonmessages/zh-TW/settings/config.jsonsrc/actions/system-config.tssrc/app/[locale]/settings/config/_components/system-settings-form.tsxsrc/app/[locale]/settings/config/page.tsxsrc/app/api/admin/system-config/route.tssrc/app/v1/_lib/proxy/forwarder.tssrc/app/v1/_lib/proxy/system-message-rectifier.tssrc/drizzle/schema.tssrc/lib/api-client/v1/openapi-types.gen.tssrc/lib/api/v1/schemas/system-config.tssrc/lib/config/system-settings-cache.tssrc/lib/utils/special-settings.tssrc/lib/validation/schemas.tssrc/repository/_shared/transformers.tssrc/repository/system-config.tssrc/types/special-settings.tssrc/types/system-config.tstests/unit/proxy/system-message-rectifier.test.ts
- system-message-rectifier: NOOP_RESULT 常量浅拷贝会共享 extractedValues 数组引用,改为 createNoopResult() 工厂函数,每次返回独立数组 - forwarder: 两个 rectifier 块共用一次 getCachedSystemSettings() 调用,消除冗余 await 回应 PR ding113#1268 的 CodeRabbit 与 Greptile 审查意见
|
已根据审查意见更新(1d2bd1a8):
验证: |
…nflict rectifier) - 迁移序号冲突:将本 PR 的 system-message-rectifier 列迁移移至 0106 (drizzle 重新生成为 0106_stiff_dormammu.sql),让出 0105 给 dev 已合入 的 0105_chief_rocket_racer.sql(thinking-effort-conflict rectifier)。 - src/repository/system-config.ts 降级链堆叠: 最新层先剥离 enableSystemMessageRectifier,次层再剥离 enableThinkingEffortConflictRectifier,再回到原有 billHedgeLosers 等 既有降级路径,确保两轮新增列对老库的兼容性。 - tests/unit/repository/system-config-update-missing-columns.test.ts: 原 "仅缺 enable_thinking_effort_conflict_rectifier 列" 测试改为 覆盖 enableSystemMessageRectifier(最外层),新增一项覆盖连续剥离两 个新列直到 billHedgeLosers 层的回归断言。
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b7619abb59
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (systemMessageRectifierEnabled) { | ||
| const systemMessageResult = rectifySystemMessages( | ||
| session.request.message as Record<string, unknown> | ||
| ); |
There was a problem hiding this comment.
Apply the rectifier before raw count_tokens passthrough
When Claude Code sends the same messages shape to /v1/messages/count_tokens, this new rectifier is skipped because this block lives under the standard preprocessing gate (bypassForwarderPreprocessing), while endpoint-policy.ts marks /v1/messages/count_tokens as raw passthrough and the later raw path forwards the original body bytes. In that context, strict Anthropic-compatible upstreams still receive messages[].role === "system" and can reject the token-count request before the actual /v1/messages call is made, so the fix does not cover the preflight path that uses the same invalid role.
Useful? React with 👍 / 👎.
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 (2)
src/repository/system-config.ts (2)
1109-1162:⚠️ Potential issue | 🟠 Major | ⚡ Quick win更新降级链只裁剪了
updates,但returning(...)仍在重新引入缺失列。这里的注释已经点出了“不要重新引入较新的列”,但当前只对
updates做到了,returningWithoutPassThrough/returningWithoutHighConcurrencyMode/returningWithoutCodexAndHighConcurrency仍然来自原始字段集。这样在旧 schema 上,即使set(...)已经去掉了缺失列,returning(...)也会因为重新选择这些列继续报42703,导致本来应该成功的降级更新最终失败。
returning需要和updates一样,从returningWithoutNonConversationFallback开始继续逐层裁剪。可参考的修正方向
try { // Continue pruning from the already-reduced object, otherwise the // freshly removed `fakeStreamingWhitelist` (and any other newer // columns) would be reintroduced and fail again on legacy schemas. const withoutPassThroughUpdates = { ...updatesWithoutNonConversationFallback }; delete withoutPassThroughUpdates.passThroughUpstreamErrorMessage; + const { + passThroughUpstreamErrorMessage: _omitReturningPassThrough, + ...returningWithoutPassThroughAfterNonConversation + } = returningWithoutNonConversationFallback; [updated] = await executor .update(systemSettings) .set(withoutPassThroughUpdates) .where(eq(systemSettings.id, current.id)) - .returning(returningWithoutPassThrough); + .returning(returningWithoutPassThroughAfterNonConversation); } catch (passThroughFallbackError) { @@ const downgradedUpdates = { ...updatesWithoutNonConversationFallback }; delete downgradedUpdates.passThroughUpstreamErrorMessage; delete downgradedUpdates.enableHighConcurrencyMode; delete downgradedUpdates.publicStatusWindowHours; delete downgradedUpdates.publicStatusAggregationIntervalMinutes; delete downgradedUpdates.ipExtractionConfig; delete downgradedUpdates.ipGeoLookupEnabled; + const { + enableHighConcurrencyMode: _omitReturningHighConcurrency, + publicStatusWindowHours: _omitReturningPublicStatusWindowHours, + publicStatusAggregationIntervalMinutes: + _omitReturningPublicStatusAggregationIntervalMinutes, + ipExtractionConfig: _omitReturningIpExtractionConfig, + ipGeoLookupEnabled: _omitReturningIpGeoLookupEnabled, + ...returningWithoutHighConcurrencyAfterNonConversation + } = returningWithoutPassThroughAfterNonConversation; @@ [updated] = await executor .update(systemSettings) .set(downgradedUpdates) .where(eq(systemSettings.id, current.id)) - .returning(returningWithoutHighConcurrencyMode); + .returning(returningWithoutHighConcurrencyAfterNonConversation); @@ + const { + codexPriorityBillingSource: _omitReturningCodexPriorityBillingSource, + ...legacyReturning + } = returningWithoutHighConcurrencyAfterNonConversation; [updated] = await executor .update(systemSettings) .set(legacyUpdates) .where(eq(systemSettings.id, current.id)) - .returning(returningWithoutCodexAndHighConcurrency); + .returning(legacyReturning);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/repository/system-config.ts` around lines 1109 - 1162, The PR's downgrade chain only prunes the update payloads but leaves the returning column lists intact, causing returning(...) to reintroduce missing columns and trigger 42703; fix by deriving each subsequent returning set from returningWithoutNonConversationFallback (not the original full set) and prune the same missing columns in lockstep with updates — update usages of returningWithoutPassThrough, returningWithoutHighConcurrencyMode, and returningWithoutCodexAndHighConcurrency to be created/used by cloning and deleting the matching column names (e.g., remove passThroughUpstreamErrorMessage, enableHighConcurrencyMode, publicStatusWindowHours, publicStatusAggregationIntervalMinutes, ipExtractionConfig, ipGeoLookupEnabled, codexPriorityBillingSource) so each .returning(...) matches the corresponding pruned .set(...) call (refer to variables returningWithoutNonConversationFallback, returningWithoutPassThrough, returningWithoutHighConcurrencyMode, returningWithoutCodexAndHighConcurrency and the update/executor.update(...).set(...) blocks).
476-517:⚠️ Potential issue | 🟠 Major | ⚡ Quick win继续降级读取时不要切回原始字段集。
这里从
selectionWithoutNonConversationFallback回退到selectionWithoutPassThrough/selectionWithoutHighConcurrencyMode/selectionWithoutCodexAndHighConcurrency,会把前面已经剥离掉的列重新加回来,尤其是allowNonConversationEndpointProviderFallback和enableThinkingEffortConflictRectifier。在同时缺少多列的旧库上,这会把本应成功的兼容读取一路打回到更小字段集,已有配置被默认值覆盖。建议后续几层 fallback 都基于
selectionWithoutNonConversationFallback继续删字段,而不是回到预先定义的原始 selection。可参考的修正方向
- try { - const [row] = await db - .select(selectionWithoutPassThrough) + const { + passThroughUpstreamErrorMessage: _omitPassThrough, + ...selectionWithoutPassThroughAfterNonConversation + } = selectionWithoutNonConversationFallback; + + try { + const [row] = await db + .select(selectionWithoutPassThroughAfterNonConversation) .from(systemSettings) .orderBy(asc(systemSettings.id)) .limit(1); return row ?? null; } catch (passThroughFallbackError) { if (!isUndefinedColumnError(passThroughFallbackError)) { throw passThroughFallbackError; } @@ - const [row] = await db - .select(selectionWithoutHighConcurrencyMode) + const { + enableHighConcurrencyMode: _omitHighConcurrency, + ipExtractionConfig: _omitIpExtractionConfig, + ipGeoLookupEnabled: _omitIpGeoLookupEnabled, + ...selectionWithoutHighConcurrencyAfterNonConversation + } = selectionWithoutPassThroughAfterNonConversation; + + const [row] = await db + .select(selectionWithoutHighConcurrencyAfterNonConversation) .from(systemSettings) .orderBy(asc(systemSettings.id)) .limit(1); return row ?? null; @@ - const [row] = await db - .select(selectionWithoutCodexAndHighConcurrency) + const { + codexPriorityBillingSource: _omitCodexPriorityBillingSource, + ...selectionWithoutCodexAfterNonConversation + } = selectionWithoutHighConcurrencyAfterNonConversation; + + const [row] = await db + .select(selectionWithoutCodexAfterNonConversation) .from(systemSettings) .orderBy(asc(systemSettings.id)) .limit(1);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/repository/system-config.ts` around lines 476 - 517, The current fallback chain reverts from selectionWithoutNonConversationFallback back to earlier selection sets (selectionWithoutPassThrough, selectionWithoutHighConcurrencyMode, selectionWithoutCodexAndHighConcurrency), which can reintroduce columns like allowNonConversationEndpointProviderFallback and enableThinkingEffortConflictRectifier and cause older DBs to fall back too far; change the fallback logic so each subsequent catch continues from selectionWithoutNonConversationFallback by creating narrower selections derived from it (i.e., remove additional problematic columns from selectionWithoutNonConversationFallback for the later tries) instead of switching back to the original selection variables (selectionWithoutPassThrough, selectionWithoutHighConcurrencyMode, selectionWithoutCodexAndHighConcurrency), and update the try/catch blocks that query systemSettings to use those derived selections.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/repository/system-config.ts`:
- Around line 1109-1162: The PR's downgrade chain only prunes the update
payloads but leaves the returning column lists intact, causing returning(...) to
reintroduce missing columns and trigger 42703; fix by deriving each subsequent
returning set from returningWithoutNonConversationFallback (not the original
full set) and prune the same missing columns in lockstep with updates — update
usages of returningWithoutPassThrough, returningWithoutHighConcurrencyMode, and
returningWithoutCodexAndHighConcurrency to be created/used by cloning and
deleting the matching column names (e.g., remove
passThroughUpstreamErrorMessage, enableHighConcurrencyMode,
publicStatusWindowHours, publicStatusAggregationIntervalMinutes,
ipExtractionConfig, ipGeoLookupEnabled, codexPriorityBillingSource) so each
.returning(...) matches the corresponding pruned .set(...) call (refer to
variables returningWithoutNonConversationFallback, returningWithoutPassThrough,
returningWithoutHighConcurrencyMode, returningWithoutCodexAndHighConcurrency and
the update/executor.update(...).set(...) blocks).
- Around line 476-517: The current fallback chain reverts from
selectionWithoutNonConversationFallback back to earlier selection sets
(selectionWithoutPassThrough, selectionWithoutHighConcurrencyMode,
selectionWithoutCodexAndHighConcurrency), which can reintroduce columns like
allowNonConversationEndpointProviderFallback and
enableThinkingEffortConflictRectifier and cause older DBs to fall back too far;
change the fallback logic so each subsequent catch continues from
selectionWithoutNonConversationFallback by creating narrower selections derived
from it (i.e., remove additional problematic columns from
selectionWithoutNonConversationFallback for the later tries) instead of
switching back to the original selection variables (selectionWithoutPassThrough,
selectionWithoutHighConcurrencyMode, selectionWithoutCodexAndHighConcurrency),
and update the try/catch blocks that query systemSettings to use those derived
selections.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 9d0a5675-0e13-4390-9c41-6630d26fb1f5
📒 Files selected for processing (23)
drizzle/0106_stiff_dormammu.sqldrizzle/meta/0106_snapshot.jsondrizzle/meta/_journal.jsonmessages/en/settings/config.jsonmessages/ja/settings/config.jsonmessages/ru/settings/config.jsonmessages/zh-CN/settings/config.jsonmessages/zh-TW/settings/config.jsonsrc/actions/system-config.tssrc/app/[locale]/settings/config/_components/system-settings-form.tsxsrc/app/[locale]/settings/config/page.tsxsrc/app/v1/_lib/proxy/forwarder.tssrc/drizzle/schema.tssrc/lib/api-client/v1/openapi-types.gen.tssrc/lib/api/v1/schemas/system-config.tssrc/lib/config/system-settings-cache.tssrc/lib/utils/special-settings.tssrc/lib/validation/schemas.tssrc/repository/_shared/transformers.tssrc/repository/system-config.tssrc/types/special-settings.tssrc/types/system-config.tstests/unit/repository/system-config-update-missing-columns.test.ts
💤 Files with no reviewable changes (1)
- drizzle/0106_stiff_dormammu.sql
✅ Files skipped from review due to trivial changes (8)
- messages/en/settings/config.json
- messages/ru/settings/config.json
- messages/ja/settings/config.json
- messages/zh-TW/settings/config.json
- src/lib/api-client/v1/openapi-types.gen.ts
- src/lib/config/system-settings-cache.ts
- messages/zh-CN/settings/config.json
- drizzle/meta/_journal.json
🚧 Files skipped from review as they are similar to previous changes (11)
- src/app/[locale]/settings/config/page.tsx
- src/lib/utils/special-settings.ts
- src/types/system-config.ts
- src/lib/api/v1/schemas/system-config.ts
- src/lib/validation/schemas.ts
- src/drizzle/schema.ts
- src/app/[locale]/settings/config/_components/system-settings-form.tsx
- src/repository/_shared/transformers.ts
- src/types/special-settings.ts
- src/actions/system-config.ts
- src/app/v1/_lib/proxy/forwarder.ts
|
hi,对于涉及请求体变更的整流器,建议按照思考签名整流器的思路,在检测到特定报错模式之后被动整流。 |
背景
Fixes #1265
Claude Code 2.1.172+(2.1.153 之后引入的行为变化)配合自定义模型名(
ANTHROPIC_DEFAULT_OPUS_MODEL等指向 cchub 渠道模型)使用时,会在messages数组中注入独立的{"role": "system", "content": "..."}消息(skills 列表)。Anthropic 官方 API 接受该写法,但 Vertex/Bedrock 类严格校验 messages 角色的兼容上游会以 400 拒绝,cchub 原样透传导致重试耗尽全部供应商后熔断,客户端收到 503「所有供应商暂时不可用」。修复方案
参照现有
billing-header-rectifier.ts的 proactive rectifier 模式:核心模块
src/app/v1/_lib/proxy/system-message-rectifier.tsmessages,取出role: "system"条目{type: "text", text}block;数组 content 保留 text block(含cache_control等附加字段),丢弃非 text blocksystem字段末尾(顶层为 string 时先转为首个 text block)forwarder 集成
claude/claude-auth供应商生效x-anthropic-billing-header文本块,搬移后仍会被后续剥离system_message_rectifierspecialSetting 审计并写日志系统设置开关
enableSystemMessageRectifier(默认开启)drizzle/0105_easy_cyclops.sql)、settings cache、types、zod 校验、Server Action、admin REST、v1 OpenAPI schema、repository、transformerssystem_settings缺列降级链(读取与更新路径均在链头新增一层剔除该列的降级),迁移前部署的实例读取/更新设置不受影响测试
新增
tests/unit/proxy/system-message-rectifier.test.ts,16 个用例:验证
bun run build通过bun run lint/lint:fix通过bun run typecheck通过bun run test全量 6370 个测试通过bun run openapi:check通过Greptile Summary
This PR adds a proactive rectifier that lifts
role:"system"messages out of themessagesarray and merges them into the top-levelsystemfield before forwarding, matching the lenient interpretation the official Anthropic API already applies and removing the source of 400 errors on strict upstreams like Vertex/Bedrock.system-message-rectifier.ts): synchronous, in-place mutation; correctly handles all content shapes (string → single block, array → filter to text blocks, empty string → no block, unknown type → discard), and all top-levelsystemshapes (undefined, null, string, array, unknown).enableSystemMessageRectifiersetting; both rectifiers share the singlegetCachedSystemSettings()result fetched once perdoForwardcall.Confidence Score: 5/5
Safe to merge. The rectifier is synchronous, idempotent, and only mutates messages when role:"system" entries are present — requests without them pass through unchanged.
The change is a well-bounded proactive transformation applied only to claude/claude-auth providers, guarded by a feature flag that defaults to the safe/on state. The core function handles all edge cases and is tested with 16 targeted unit tests. Settings plumbing follows the established pattern with the new column correctly positioned as the outermost entry in the degradation ladder.
No files require special attention.
Important Files Changed
Sequence Diagram
sequenceDiagram participant CC as Claude Code Client participant FW as ProxyForwarder.doForward participant SMR as SystemMessageRectifier participant BHR as BillingHeaderRectifier participant UP as Upstream (Vertex/Bedrock) CC->>FW: POST /v1/messages FW->>FW: getCachedSystemSettings() alt "enableSystemMessageRectifier = true" FW->>SMR: rectifySystemMessages(message) SMR-->>FW: "applied=true, messages cleaned, system merged" end alt "enableBillingHeaderRectifier = true" FW->>BHR: rectifyBillingHeader(message) BHR-->>FW: billing header blocks stripped end FW->>UP: POST with clean messages array UP-->>FW: 200 OK FW-->>CC: 200 OKComments Outside Diff (1)
src/app/v1/_lib/proxy/forwarder.ts, line 2480-2483 (link)getCachedSystemSettings()calls are made in the same code path — one for the system message rectifier and one for the billing header rectifier. Since the cache returns the same in-memory object within the 1-minute TTL, the second call is a no-op but still adds an unnecessaryawait. Both rectifiers could share the singlesettingsobject that was already fetched.Prompt To Fix With AI
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Reviews (3): Last reviewed commit: "merge: resolve conflicts with dev (PR #1..." | Re-trigger Greptile