Skip to content

fix(responses): gate service tiers by provider capability - #860

Open
F1Justin wants to merge 1 commit into
lidge-jun:devfrom
F1Justin:fix/deepseek-responses-service-tier
Open

fix(responses): gate service tiers by provider capability#860
F1Justin wants to merge 1 commit into
lidge-jun:devfrom
F1Justin:fix/deepseek-responses-service-tier

Conversation

@F1Justin

@F1Justin F1Justin commented Aug 1, 2026

Copy link
Copy Markdown

Summary

  • Add a provider-level supportsServiceTier capability for Responses routes.
  • Mark the canonical OpenAI Responses providers as supporting service tiers and DeepSeek as not supporting them.
  • Let fastMode inject or remove service_tier only for providers that explicitly support it, and strip the field for providers that explicitly reject it.
  • Preserve caller-supplied values for unclassified custom Responses providers.
  • Keep the capability as registry-enriched runtime metadata so older canonical OpenAI configs remain valid.
  • Document the capability and the DeepSeek behavior in every maintained locale.

Why

fastMode previously treated every openai-responses destination like OpenAI and could inject service_tier: "priority". DeepSeek V4 Flash now uses its native Responses endpoint by default, but DeepSeek's published Responses schema does not document service_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.
  • Focused canonical OpenAI management checks — 3 pass after keeping the new capability out of persisted canonical seeds.
  • bun run typecheck — pass.
  • bun run privacy:scan — pass.
  • cd docs-site && bun run build — pass (146 pages).
  • Full-suite attempt before the final canonical-seed compatibility adjustment: 6,786 pass, 7 skip, 10 fail. The three patch-caused canonical OpenAI failures were fixed and pass in the focused rerun. The remaining affected-file rerun is 37 pass / 7 fail because this machine's Clash fake-IP DNS resolves test-only hosts such as *.example.test and proxy-only.invalid into 198.18.0.0/15, which the destination-policy tests intentionally reject. CI should provide the clean non-fake-IP run.

Scope

  • No authentication, credential, destination, or provider selection behavior changes.
  • No request bodies, API keys, or account identifiers are logged.
  • Explicit per-provider configuration remains backward compatible.

Summary by CodeRabbit

  • New Features

    • Added provider-level configuration to declare service_tier support.
    • Fast-mode handling now applies only to providers that explicitly support service tiers.
    • Unsupported or unspecified providers remove client-supplied values and do not inject fast-mode settings.
    • DeepSeek V4 Flash and Volcengine Agent Plan routes explicitly exclude this field.
  • Documentation

    • Updated provider configuration and fast-tier guidance across supported languages.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds supportsServiceTier capability metadata, propagates registry values into provider configurations, gates Responses service_tier handling, adds end-to-end coverage, and updates multilingual documentation.

Changes

Responses service-tier capability

Layer / File(s) Summary
Capability contracts and propagation
src/types.ts, src/config.ts, src/providers/registry.ts, src/providers/derive.ts, src/router.ts
Provider configuration and registry entries support supportsServiceTier. Registry values propagate to derived and routed providers without overriding explicit configuration. OpenAI providers enable the capability; DeepSeek and Volcengine Agent Plan disable it.
Responses service-tier handling and validation
src/server/responses/core.ts, src/adapters/openai-responses.ts, tests/deepseek-inbound-wire.test.ts
Responses processing preserves or rewrites service_tier only for supported providers. Unsupported and unclassified providers remove caller values and prevent fast-mode injection. Tests cover registry enrichment, OpenAI behavior, unsupported providers, and native Codex routing.
Configuration and model behavior documentation
docs-site/src/content/docs/reference/configuration/providers.md, docs-site/src/content/docs/*/reference/configuration/providers.md, docs-site/src/content/docs/*/guides/codex-app-models.md
The provider configuration and fast-tier guides describe enabled, disabled, and omitted capability behavior across supported languages.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • lidge-jun/opencodex#611: Adds Volcengine Agent Plan provider behavior that this change marks as unsupported for service_tier.
  • lidge-jun/opencodex#615: Extends Volcengine Agent Plan Responses routing metadata used by this capability configuration.
  • lidge-jun/opencodex#652: Modifies the same provider registry, enrichment, and routing capability plumbing.

Suggested reviewers: ingwannu, lidge-jun, wibias

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes gating Responses service tiers by provider capability, which is the main change in the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the bug Something isn't working label Aug 1, 2026
@F1Justin
F1Justin marked this pull request as ready for review August 1, 2026 15:57
Copilot AI review requested due to automatic review settings August 1, 2026 15:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?: boolean across provider config/types/registry and backfill it from registry metadata at runtime.
  • Gate service_tier injection/removal in Responses request normalization on supportsServiceTier (inject/remove only when true; always strip when false).
  • 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.

Comment thread tests/deepseek-inbound-wire.test.ts Outdated
{ model: "", provider: "" },
{ inboundWire: "responses" },
);
return bodies[0] ?? {};
@lidge-jun

Copy link
Copy Markdown
Owner

Pre-merge review result: not merge-ready yet. Two blocking items:

  1. Unknown capability fails open. src/server/responses/core.ts:805 strips service_tier only when supportsServiceTier === false; undefined passes the caller's value through. The test at tests/deepseek-inbound-wire.test.ts:289 locks in that unsafe default. An unknown-capability provider must strip the OpenAI-only field unless explicitly opted in.
  2. A built-in Responses provider is exposed to that default. src/providers/registry.ts:1186 defines volcengine-agent-plan as openai-responses with no capability classification; a probe against the PR head captured "service_tier":"priority" forwarded upstream. Please classify it (or it inherits the safe default from fix 1).

Also needed before merge:

  1. The strip tests can pass without any upstream request (tests/deepseek-inbound-wire.test.ts:219 returns bodies[0] ?? {}); assert a successful response and exactly one captured body.
  2. Add a wire regression for the canonical native openai Codex-login route (currently only openai-apikey is covered).
  3. Full cross-platform CI never ran on the current head (workflow shows action_required, zero jobs) — it must run green per merge policy. The five doc locales will need to follow whatever default semantics you choose.

The direction is right and the fix is close — re-review should be fast once the default flips to fail-closed.

@F1Justin
F1Justin force-pushed the fix/deepseek-responses-service-tier branch from e0487c0 to 87e874d Compare August 2, 2026 03:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 win

Repair the malformed xAI table row.

This row has one cell instead of the required route and description cells. It also uses かおる instead of xAI. 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

📥 Commits

Reviewing files that changed from the base of the PR and between e0487c0 and 87e874d.

📒 Files selected for processing (18)
  • docs-site/src/content/docs/guides/codex-app-models.md
  • docs-site/src/content/docs/ja/guides/codex-app-models.md
  • docs-site/src/content/docs/ja/reference/configuration/providers.md
  • docs-site/src/content/docs/ko/guides/codex-app-models.md
  • docs-site/src/content/docs/ko/reference/configuration/providers.md
  • docs-site/src/content/docs/reference/configuration/providers.md
  • docs-site/src/content/docs/ru/guides/codex-app-models.md
  • docs-site/src/content/docs/ru/reference/configuration/providers.md
  • docs-site/src/content/docs/zh-cn/guides/codex-app-models.md
  • docs-site/src/content/docs/zh-cn/reference/configuration/providers.md
  • src/adapters/openai-responses.ts
  • src/config.ts
  • src/providers/derive.ts
  • src/providers/registry.ts
  • src/router.ts
  • src/server/responses/core.ts
  • src/types.ts
  • tests/deepseek-inbound-wire.test.ts

Comment on lines 86 to +87
但模型目录和运行时请求里的 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 路由被明确标记为不支持该字段,因此不会把它发送给上游。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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

Comment on lines +348 to +359
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,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 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.

Suggested change
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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants