将 Claude Code 缓存亲和逻辑改为可配置规则 - #4150
Conversation
Claude Code reached Codex through the /v1/messages compatibility path, but new-api dropped the session-derived cache key before the final Responses request. This preserved direct Responses caching while leaving Claude Code turns cold. The fix carries the Claude session id into prompt_cache_key, forces the equivalent session_id header on the compatibility path, and keeps Codex-only incompatible metadata out of the upstream request. Constraint: Codex only accepts /v1/responses and rejects metadata on the final upstream request Rejected: Rely on pass_headers alone | did not produce cache hits on the Claude compatibility path Rejected: Only sync prompt_cache_key without session_id header | direct probes still missed cache reads Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep Claude -> Responses compatibility preserving both prompt_cache_key and session_id together for Codex-backed models Tested: go test ./service/... ./relay/... Tested: manual production verification with Claude Code gpt-5.4 second-turn cache hit (cache_tokens=9472) Not-tested: upstream/main latest integration after cherry-pick
Claude Code cache reuse on the /v1/messages -> responses compatibility path should be driven by channel-affinity rules and override templates, not by hardcoded metadata parsing. This change adds request-header and nested JSON key extraction, exposes the resolved affinity key to override context, and lets templates sync that key into prompt_cache_key and session_id from the console. Constraint: Operators need to adapt to client header/metadata shape changes without shipping a new binary Rejected: Keep parsing metadata.user_id.session_id in convert.go | brittle to client request format changes Rejected: Add a separate Claude-specific settings surface | duplicates existing channel-affinity and param-override controls Confidence: high Scope-risk: moderate Reversibility: clean Directive: Keep Claude cache-affinity behavior driven by key_sources plus override templates; avoid reintroducing client-specific parsing in convert paths Tested: go test ./... Tested: bun run build Tested: production smoke test on 38.76.144.165 for /v1/messages -> gpt-5.4 with metadata-only and header-only session keys; second request hit cache in both cases Not-tested: GitHub PR creation via gh CLI (local auth token invalid)
WalkthroughThis PR extends parameter override and channel affinity infrastructure to support context-based sync fields, nested JSON path extraction for key sources, and enhanced prompt caching. It adds a new Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 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.
🧹 Nitpick comments (1)
web/src/components/table/channels/modals/ParamOverrideEditorModal.jsx (1)
276-277: Localize newly added sync-field labels/tags viat(...).The new
contextoption label and quick-tag texts are hardcoded, so they won’t participate in i18n.♻️ Proposed refactor
-const SYNC_TARGET_TYPE_OPTIONS = [ - { label: '请求体字段', value: 'json' }, - { label: '请求头字段', value: 'header' }, - { label: '上下文字段', value: 'context' }, -]; +const getSyncTargetTypeOptions = (t) => [ + { label: t('请求体字段'), value: 'json' }, + { label: t('请求头字段'), value: 'header' }, + { label: t('上下文字段'), value: 'context' }, +];+ const syncTargetTypeOptions = useMemo( + () => getSyncTargetTypeOptions(t), + [t], + ); ... - optionList={SYNC_TARGET_TYPE_OPTIONS} + optionList={syncTargetTypeOptions} ... - {'context:channel_affinity.key -> json:prompt_cache_key'} + {t('context:channel_affinity.key -> json:prompt_cache_key')} ... - {'context:channel_affinity.key -> header:session_id'} + {t('context:channel_affinity.key -> header:session_id')}As per coding guidelines: “Frontend i18n: Use
i18next+react-i18next... UseuseTranslation()hook and callt('中文key')in components.”Also applies to: 2991-3016
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@web/src/components/table/channels/modals/ParamOverrideEditorModal.jsx` around lines 276 - 277, The new hardcoded sync-field label ('上下文字段' for value 'context') and the quick-tag strings should be localized: in the ParamOverrideEditorModal component import and call useTranslation(), replace the literal label and all hardcoded quick-tag texts (the options array entry with label '上下文字段' and the quick-tag strings around the 2991-3016 region) with t('...') keys, and ensure you add appropriate i18n keys/strings rather than raw Chinese text so the labels/tags participate in i18n.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@web/src/components/table/channels/modals/ParamOverrideEditorModal.jsx`:
- Around line 276-277: The new hardcoded sync-field label ('上下文字段' for value
'context') and the quick-tag strings should be localized: in the
ParamOverrideEditorModal component import and call useTranslation(), replace the
literal label and all hardcoded quick-tag texts (the options array entry with
label '上下文字段' and the quick-tag strings around the 2991-3016 region) with
t('...') keys, and ensure you add appropriate i18n keys/strings rather than raw
Chinese text so the labels/tags participate in i18n.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 95c6cfff-ddf4-4d82-8f4f-4c39e42b3eac
📒 Files selected for processing (15)
constant/context_key.gorelay/channel/codex/adaptor.gorelay/chat_completions_via_responses.gorelay/common/override.gorelay/common/override_test.gorelay/common/relay_info.goservice/channel_affinity.goservice/channel_affinity_template_test.goservice/convert.goservice/openaicompat/chat_to_responses.goservice/openaicompat/chat_to_responses_test.gosetting/operation_setting/channel_affinity_setting.goweb/src/components/table/channels/modals/ParamOverrideEditorModal.jsxweb/src/constants/channel-affinity-template.constants.jsweb/src/pages/Setting/Operation/SettingsChannelAffinity.jsx
51fdfc5 to
2b6f1df
Compare
这次把上一版里对 Claude metadata 的固定解析去掉了,改成走现有的渠道亲和和参数覆盖模板能力。
主要调整:
key_sources增加request_header和gjson.nested_pathsync_fields增加context:来源claude cli trace规则改成优先从X-Claude-Code-Session-Id取值,取不到再从metadata.user_id里按nested_path提session_id这样做的目的是把这块逻辑从兼容转换代码里拿出来,避免继续把某一种请求结构写死在
convert.go里。验证:
go test ./...bun run build38.76.144.165实测/v1/messages->gpt-5.4metadata.user_id.session_id:第一次cache_tokens=0,第二次cache_tokens=3200X-Claude-Code-Session-Id:第一次cache_tokens=0,第二次cache_tokens=2944如果这个方向没问题,后面再遇到客户端字段调整,应该只需要在控制台改规则,不需要再补一版代码。
Summary by CodeRabbit
New Features
Bug Fixes
UI Updates