fix(responses): gate service tiers by provider capability - #860
Conversation
📝 WalkthroughWalkthroughThe change adds ChangesResponses service-tier capability
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Adds a provider capability flag to control whether fastMode may inject/remove OpenAI’s service_tier on Responses requests, preventing OpenAI-only fields from being forwarded to Responses-compatible upstreams (notably DeepSeek) that reject unknown top-level parameters.
Changes:
- Introduce
supportsServiceTier?: booleanacross provider config/types/registry and backfill it from registry metadata at runtime. - Gate
service_tierinjection/removal in Responses request normalization onsupportsServiceTier(inject/remove only whentrue; always strip whenfalse). - Add focused wire-level regression tests and update configuration/docs in all maintained locales.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/deepseek-inbound-wire.test.ts | Adds capability-gated service_tier forwarding/injection tests and updates existing assertions. |
| src/types.ts | Extends OcxProviderConfig with supportsServiceTier documentation and typing. |
| src/server/responses/core.ts | Gates service_tier normalization behavior based on supportsServiceTier for openai-responses routes. |
| src/router.ts | Backfills supportsServiceTier from the registry into routed provider configs when unset in persisted config. |
| src/providers/registry.ts | Defines supportsServiceTier in the registry schema and marks OpenAI providers as supported / DeepSeek as unsupported. |
| src/providers/derive.ts | Ensures derived provider metadata can include supportsServiceTier and backfills it during enrichment. |
| src/config.ts | Allows supportsServiceTier in the provider config schema. |
| docs-site/src/content/docs/reference/configuration.md | Documents the new supportsServiceTier provider option (English). |
| docs-site/src/content/docs/zh-cn/reference/configuration.md | Documents the new supportsServiceTier provider option (zh-cn). |
| docs-site/src/content/docs/ru/reference/configuration.md | Documents the new supportsServiceTier provider option (ru). |
| docs-site/src/content/docs/ko/reference/configuration.md | Documents the new supportsServiceTier provider option (ko). |
| docs-site/src/content/docs/ja/reference/configuration.md | Documents the new supportsServiceTier provider option (ja). |
| docs-site/src/content/docs/guides/codex-app-models.md | Updates fast/service-tier behavior explanation (English). |
| docs-site/src/content/docs/zh-cn/guides/codex-app-models.md | Updates fast/service-tier behavior explanation (zh-cn). |
| docs-site/src/content/docs/ru/guides/codex-app-models.md | Updates fast/service-tier behavior explanation (ru). |
| docs-site/src/content/docs/ko/guides/codex-app-models.md | Updates fast/service-tier behavior explanation (ko). |
| docs-site/src/content/docs/ja/guides/codex-app-models.md | Updates fast/service-tier behavior explanation (ja). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| { model: "", provider: "" }, | ||
| { inboundWire: "responses" }, | ||
| ); | ||
| return bodies[0] ?? {}; |
|
Pre-merge review result: not merge-ready yet. Two blocking items:
Also needed before merge:
The direction is right and the fix is close — re-review should be fast once the default flips to fail-closed. |
e0487c0 to
87e874d
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs-site/src/content/docs/ja/guides/codex-app-models.md (1)
51-51: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRepair the malformed xAI table row.
This row has one cell instead of the required route and description cells. It also uses
かおるinstead ofxAI. The rendered table will lose the route label.Proposed fix
-|かおるライブディスカバリーには信頼性があります。フォールバック カタログのデフォルトは、500,000 トークン ウィンドウと `low` / `medium` / `high` 推論制御を備えた `xai/grok-4.5` です。 | +| xAI | ライブディスカバリーには信頼性があります。フォールバック カタログのデフォルトは、500,000 トークン ウィンドウと `low` / `medium` / `high` 推論制御を備えた `xai/grok-4.5` です。 |As per path instructions, this user-facing Astro/Starlight page must keep its markdown structure valid.
🤖 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 `@docs-site/src/content/docs/ja/guides/codex-app-models.md` at line 51, Correct the malformed table row in the Codex app models documentation so it has separate route and description cells, uses “xAI” instead of “かおる,” and preserves the existing xai/grok-4.5 details while keeping the Markdown table structure valid.Sources: Path instructions, Linters/SAST tools
🤖 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 `@docs-site/src/content/docs/zh-cn/guides/codex-app-models.md`:
- Around line 86-87: Remove or rewrite the obsolete blanket statement that
routed non-OpenAI models always strip service-tier metadata, while preserving
the capability-gated fail-closed behavior. Apply the same correction in
docs-site/src/content/docs/zh-cn/guides/codex-app-models.md lines 86-87 and
docs-site/src/content/docs/ja/guides/codex-app-models.md lines 89-90, ensuring
both locale pages match the English source.
In `@tests/deepseek-inbound-wire.test.ts`:
- Around line 348-359: Remove the supportsServiceTier override from the openai
provider fixture in the canonical openai Codex-login test, so
routedProviderConfig must backfill it from the canonical registry entry.
Preserve the existing URL, request-body, and priority-forwarding assertions.
---
Outside diff comments:
In `@docs-site/src/content/docs/ja/guides/codex-app-models.md`:
- Line 51: Correct the malformed table row in the Codex app models documentation
so it has separate route and description cells, uses “xAI” instead of “かおる,” and
preserves the existing xai/grok-4.5 details while keeping the Markdown table
structure valid.
🪄 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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: ad8813de-6872-4885-9998-aa5e27095632
📒 Files selected for processing (18)
docs-site/src/content/docs/guides/codex-app-models.mddocs-site/src/content/docs/ja/guides/codex-app-models.mddocs-site/src/content/docs/ja/reference/configuration/providers.mddocs-site/src/content/docs/ko/guides/codex-app-models.mddocs-site/src/content/docs/ko/reference/configuration/providers.mddocs-site/src/content/docs/reference/configuration/providers.mddocs-site/src/content/docs/ru/guides/codex-app-models.mddocs-site/src/content/docs/ru/reference/configuration/providers.mddocs-site/src/content/docs/zh-cn/guides/codex-app-models.mddocs-site/src/content/docs/zh-cn/reference/configuration/providers.mdsrc/adapters/openai-responses.tssrc/config.tssrc/providers/derive.tssrc/providers/registry.tssrc/router.tssrc/server/responses/core.tssrc/types.tstests/deepseek-inbound-wire.test.ts
| 但模型目录和运行时请求里的 tier id 使用的是 `priority`。opencodex 保留了这个拆分。原生 OpenAI 透传模型保留 fast 支持;路由到非 OpenAI 模型时会移除 service-tier 元数据,因此无法兑现的 fast 选项不会被展示出来。 | ||
| 原生 OpenAI 透传模型保留 fast 支持。只有 registry capability 明确允许时,Responses provider 才会收到 proxy 注入的 OpenAI 专用 `service_tier`;省略 capability 时 fail-closed——调用方已有值会被移除,且 fastMode 不会注入。DeepSeek V4 Flash 与 Volcengine Agent Plan 的原生 Responses 路由被明确标记为不支持该字段,因此不会把它发送给上游。 |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Remove the obsolete blanket service-tier rule from both locale pages.
The previous statement that all routed non-OpenAI models strip service-tier metadata conflicts with the new explicit capability model. Retain only the fail-closed rule for unsupported or unclassified providers.
docs-site/src/content/docs/zh-cn/guides/codex-app-models.md#L86-L87: remove or rewrite the blanket sentence before the capability-gated sentence.docs-site/src/content/docs/ja/guides/codex-app-models.md#L89-L90: remove or rewrite the blanket sentence before the capability-gated sentence.
As per path instructions, translated locale pages must not contradict the English source.
📍 Affects 2 files
docs-site/src/content/docs/zh-cn/guides/codex-app-models.md#L86-L87(this comment)docs-site/src/content/docs/ja/guides/codex-app-models.md#L89-L90
🤖 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 `@docs-site/src/content/docs/zh-cn/guides/codex-app-models.md` around lines 86
- 87, Remove or rewrite the obsolete blanket statement that routed non-OpenAI
models always strip service-tier metadata, while preserving the capability-gated
fail-closed behavior. Apply the same correction in
docs-site/src/content/docs/zh-cn/guides/codex-app-models.md lines 86-87 and
docs-site/src/content/docs/ja/guides/codex-app-models.md lines 89-90, ensuring
both locale pages match the English source.
Source: Path instructions
| test("the canonical openai Codex-login route forwards priority on the native wire", async () => { | ||
| const config = { | ||
| fastMode: true, | ||
| defaultProvider: "openai", | ||
| providers: { | ||
| openai: { | ||
| adapter: "openai-responses", | ||
| baseUrl: "https://chatgpt.com/backend-api/codex", | ||
| authMode: "forward", | ||
| codexAccountMode: "direct", | ||
| supportsServiceTier: true, | ||
| }, |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Test canonical registry backfill on the native wire.
Line 358 sets the capability that this canonical-provider test must verify. If the openai registry entry loses supportsServiceTier: true, this test still forwards "priority" and passes.
Remove the fixture override. Let routedProviderConfig backfill the value from the canonical openai registry entry. Keep the URL and body assertions.
Proposed test change
authMode: "forward",
codexAccountMode: "direct",
- supportsServiceTier: true,As per path instructions, “A behavior change in src/ should come with a focused regression test near the existing tests for that subsystem.”
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| test("the canonical openai Codex-login route forwards priority on the native wire", async () => { | |
| const config = { | |
| fastMode: true, | |
| defaultProvider: "openai", | |
| providers: { | |
| openai: { | |
| adapter: "openai-responses", | |
| baseUrl: "https://chatgpt.com/backend-api/codex", | |
| authMode: "forward", | |
| codexAccountMode: "direct", | |
| supportsServiceTier: true, | |
| }, | |
| test("the canonical openai Codex-login route forwards priority on the native wire", async () => { | |
| const config = { | |
| fastMode: true, | |
| defaultProvider: "openai", | |
| providers: { | |
| openai: { | |
| adapter: "openai-responses", | |
| baseUrl: "https://chatgpt.com/backend-api/codex", | |
| authMode: "forward", | |
| codexAccountMode: "direct", | |
| }, |
🤖 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 `@tests/deepseek-inbound-wire.test.ts` around lines 348 - 359, Remove the
supportsServiceTier override from the openai provider fixture in the canonical
openai Codex-login test, so routedProviderConfig must backfill it from the
canonical registry entry. Preserve the existing URL, request-body, and
priority-forwarding assertions.
Source: Path instructions
Summary
supportsServiceTiercapability for Responses routes.fastModeinject or removeservice_tieronly for providers that explicitly support it, and strip the field for providers that explicitly reject it.Why
fastModepreviously treated everyopenai-responsesdestination like OpenAI and could injectservice_tier: "priority". DeepSeek V4 Flash now uses its native Responses endpoint by default, but DeepSeek's published Responses schema does not documentservice_tier. Provider transport and service-tier capability need to be separate decisions.This change keeps native DeepSeek Responses routing intact while preventing an OpenAI-only request field from reaching that upstream.
DeepSeek reference: https://api-docs.deepseek.com/api/create-response/
Verification
bun test tests/deepseek-inbound-wire.test.ts— 19 pass.bun run typecheck— pass.bun run privacy:scan— pass.cd docs-site && bun run build— pass (146 pages).*.example.testandproxy-only.invalidinto198.18.0.0/15, which the destination-policy tests intentionally reject. CI should provide the clean non-fake-IP run.Scope
Summary by CodeRabbit
New Features
service_tiersupport.Documentation