Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions docs-site/src/content/docs/guides/codex-app-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,11 @@ fast_mode = true
```

But the model catalog and runtime request tier id use `priority`. opencodex preserves that split.
Native OpenAI passthrough models keep fast support; routed non-OpenAI models strip service-tier
metadata so the fast option is not advertised where it cannot be honored.
Native OpenAI passthrough models keep fast support. Responses providers only receive proxy-generated
OpenAI-specific `service_tier` when their registry capability explicitly opts in; an omitted
capability fails closed — a caller-supplied value is stripped and fastMode never injects one.
DeepSeek V4 Flash's and Volcengine Agent Plan's native Responses routes are explicitly marked
unsupported, so the field stays out of their upstream requests.

## Subagent selection

Expand Down
1 change: 1 addition & 0 deletions docs-site/src/content/docs/ja/guides/codex-app-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ fast_mode = true
```

ただし、モデル カタログとランタイム リクエスト層 ID は `priority` を使用します。 opencodex はその分割を保持します。ネイティブ OpenAI パススルー モデルは高速サポートを維持します。ルーティングされた非 OpenAI モデルはサービス層メタデータを削除するため、高速オプションが受け入れられない場合はアドバタイズされません。
ネイティブ OpenAI パススルー モデルは fast をサポートします。Responses provider は registry capability が明示的に許可する場合だけ proxy が生成した OpenAI 固有の `service_tier` を受け取ります。capability を省略すると fail-closed となり、呼び出し側の値は削除され、fastMode は注入しません。DeepSeek V4 Flash と Volcengine Agent Plan のネイティブ Responses ルートは明示的に未対応とされるため、このフィールドは上流に送られません。

## サブエージェントの選択

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ description: プロバイダー エントリ、認証、エンドポイント、
| `adapter` | `string` | `openai-chat`、`openai-responses`、`anthropic`、`google`、`kiro`、`cursor`、`azure-openai` (または別名 `azure`) のいずれか。 |
| `baseUrl` | `string` |アップストリーム API のベース URL。ほとんどの組み込み固定エンドポイントは不一致を無視します。衝突安全キー プリセットは、古い同じ名前のカスタム宛先を保持します。 |
| `responsesPath?` | `string` |キー認証 `openai-responses` リクエストの相対リソース パス。 `/` で始まり、スキーム、クエリ、またはフラグメントが含まれていない必要があります。 |
| `supportsServiceTier?` | `boolean` | Responses の tier 能力。`true` は proxy の `fastMode` による OpenAI `service_tier` の設定/削除、`false` は未対応 upstream への送信前削除、未設定は fail-closed(呼び出し側の値を削除し、`fastMode` は注入しない)を意味します。registry preset が補完するため、custom provider は上流仕様で確認できる場合だけ `true` にしてください。 |
| `disabled?` | `boolean` |プロバイダーをディスク上に保持しますが、ルーティングおよびモデル/カタログのリストからは除外します。 |
| `apiKey?` | `string` | API キー、またはリクエスト時に解決される `${ENV_VAR}` / `$ENV_VAR` 参照。 |
| `apiKeyTransport?` | `"x-api-key" \| "bearer"` | Anthropic キーのヘッダー スタイル。デフォルトはネイティブ `x-api-key` です。キー認証 `anthropic` プロバイダーにのみ有効です。 |
Expand Down
7 changes: 5 additions & 2 deletions docs-site/src/content/docs/ko/guides/codex-app-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ fast_mode = true
```

하지만 모델 카탈로그와 런타임 요청 tier id는 `priority`를 씁니다. opencodex는 이 분리를 그대로
유지합니다. 네이티브 OpenAI passthrough 모델은 fast 지원을 유지하고, 라우팅된 비 OpenAI 모델에서는
service-tier 메타데이터를 지워 fast 옵션이 처리 불가능한 곳에서는 노출되지 않게 합니다.
유지합니다. 네이티브 OpenAI passthrough 모델은 fast 지원을 유지합니다. Responses provider는
registry capability가 명시적으로 허용할 때만 proxy가 생성한 OpenAI 전용 `service_tier`를 받습니다.
capability를 생략하면 fail-closed로 호출자 값도 삭제되고 fastMode가 주입되지 않습니다. DeepSeek
V4 Flash와 Volcengine Agent Plan의 네이티브 Responses 라우트는 명시적으로 미지원으로 표시되어 이
필드를 업스트림으로 보내지 않습니다.

## 서브에이전트 선택

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ description: 공급자 항목, 인증, 엔드포인트, 모델 카탈로그, 할
| `adapter` | `string` | `openai-chat`, `openai-responses`, `anthropic`, `google`, `kiro`, `cursor`, `azure-openai` 중 하나이며, `azure`는 별칭입니다. |
| `baseUrl` | `string` | 상위 API 기본 URL입니다. 대부분의 내장 고정 엔드포인트는 불일치를 무시합니다. 충돌 안전 키 프리셋은 같은 이름의 이전 사용자 지정 목적지를 보존합니다. |
| `responsesPath?` | `string` | 키 인증 `openai-responses` 요청의 상대 리소스 경로입니다. 반드시 `/`로 시작해야 하며 스킴, query, fragment를 포함하면 안 됩니다. |
| `supportsServiceTier?` | `boolean` | Responses tier capability입니다. `true`는 proxy `fastMode`가 OpenAI `service_tier`를 설정/삭제하게 하고, `false`는 지원하지 않는 업스트림으로 보내기 전에 삭제하며, 생략하면 fail-closed로 호출자 값도 삭제하고 `fastMode`가 주입하지 않습니다. registry preset이 보완하므로 custom provider는 업스트림 문서에서 확인된 경우에만 `true`로 설정하세요. |
| `disabled?` | `boolean` | 공급자를 디스크에는 남기되, 라우팅과 모델/카탈로그 목록에서는 제외합니다. |
| `apiKey?` | `string` | API 키 또는 요청 시점에 해석되는 `${ENV_VAR}` / `$ENV_VAR` 참조입니다. |
| `apiKeyTransport?` | `"x-api-key" \| "bearer"` | Anthropic 키 헤더 형식입니다. 기본값은 네이티브 `x-api-key`이며, 키 인증 `anthropic` 공급자에만 유효합니다. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ differing backup and rewrites known legacy namespaced selected ids to bare ids.
| `adapter` | `string` | One of `openai-chat`, `openai-responses`, `anthropic`, `google`, `kiro`, `cursor`, `azure-openai` (or alias `azure`). |
| `baseUrl` | `string` | Upstream API base URL. Most built-in fixed endpoints ignore a mismatch; collision-safe key presets preserve an older same-named custom destination. |
| `responsesPath?` | `string` | Relative resource path for key-auth `openai-responses` requests. It must start with `/` and contain no scheme, query, or fragment. |
| `supportsServiceTier?` | `boolean` | Responses service-tier capability: `true` lets proxy `fastMode` set/remove OpenAI's fast/priority `service_tier`; `false` strips the field for an upstream that rejects it; omitted fails closed — a caller-supplied value is stripped and `fastMode` never injects one. Registry presets backfill this capability; custom providers should set `true` only when the upstream documents `service_tier`. |
| `disabled?` | `boolean` | Keep the provider on disk but exclude it from routing and model/catalog listings. |
| `apiKey?` | `string` | API key, or an `${ENV_VAR}` / `$ENV_VAR` reference resolved at request time. |
| `apiKeyTransport?` | `"x-api-key" \| "bearer"` | Anthropic key header style. Defaults to native `x-api-key`; valid only for key-auth `anthropic` providers. |
Expand Down
7 changes: 5 additions & 2 deletions docs-site/src/content/docs/ru/guides/codex-app-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,11 @@ fast_mode = true
```

Но каталог моделей и id tier'а во время выполнения используют `priority`. opencodex сохраняет это
разделение. Нативные passthrough-модели OpenAI сохраняют поддержку fast; routed не-OpenAI модели
теряют service-tier metadata, чтобы опция fast не рекламировалась там, где её нельзя выполнить.
разделение. Нативные passthrough-модели OpenAI сохраняют поддержку fast. Responses-провайдеры
получают созданное proxy поле `service_tier` только при явном разрешении registry capability; при
отсутствии capability применяется fail-closed — значение вызывающей стороны удаляется, а fastMode
ничего не инъецирует. Нативные Responses-маршруты DeepSeek V4 Flash и Volcengine Agent Plan явно
помечены как неподдерживающие поле, поэтому оно не отправляется на их upstream.

## Выбор подагентов

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ cross-route credential fallback не существует. Строки API GPT-
| `adapter` | `string` | Один из `openai-chat`, `openai-responses`, `anthropic`, `google`, `kiro`, `cursor`, `azure-openai` (или alias `azure`). |
| `baseUrl` | `string` | Базовый URL API upstream'а. Большинство built-in fixed-endpoint'ов игнорируют несовпадение; collision-safe key-preset'ы сохраняют старый custom destination с тем же именем. |
| `responsesPath?` | `string` | Relative resource path для key-auth запросов `openai-responses`. Должен начинаться с `/` и не может содержать scheme, query или fragment. |
| `supportsServiceTier?` | `boolean` | Capability уровня Responses: `true` разрешает proxy `fastMode` устанавливать/удалять OpenAI `service_tier`; `false` удаляет поле перед отправкой upstream, который его не поддерживает; отсутствие значения означает fail-closed — значение вызывающей стороны удаляется, а `fastMode` ничего не инъецирует. Registry preset дополняет capability; для custom provider задавайте `true` только при подтверждении в документации upstream. |
| `disabled?` | `boolean` | Сохранить провайдера на диске, но исключить его из routing'а и из model/catalog-listing'ов. |
| `apiKey?` | `string` | API-key либо ссылка `${ENV_VAR}` / `$ENV_VAR`, разрешаемая при каждом запросе. |
| `apiKeyTransport?` | `"x-api-key" \| "bearer"` | Header-style для ключа Anthropic. По умолчанию нативный `x-api-key`; допустим только для key-auth-провайдеров `anthropic`. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ fast_mode = true
```

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

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


## 子代理选择

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ description: 提供者条目、身份验证、端点、模型目录、配额、
| `adapter` | `string` | `openai-chat`、`openai-responses`、`anthropic`、`google`、`kiro`、`cursor`、`azure-openai`(或别名 `azure`)之一。 |
| `baseUrl` | `string` | 上游 API 基础 URL。大多数内置固定端点会忽略不匹配的值;具备冲突安全键的预设会保留一个更早、同名的自定义目标。 |
| `responsesPath?` | `string` | 用于 key-auth `openai-responses` 请求的相对资源路径。必须以 `/` 开头,且不能包含 scheme、query 或 fragment。 |
| `supportsServiceTier?` | `boolean` | Responses 的 service-tier 能力:`true` 允许 proxy 的 `fastMode` 设置/移除 OpenAI fast/priority 的 `service_tier`;`false` 会为拒绝该字段的上游移除它;省略时 fail-closed —— 移除调用方已有值,且不让 `fastMode` 注入。registry preset 会回填此能力;自定义 provider 只有在上游文档明确支持时才应设为 `true`。 |
| `disabled?` | `boolean` | 将提供者保留在磁盘上,但从路由和模型/目录列表中排除。 |
| `apiKey?` | `string` | API key,或在请求时解析的 `${ENV_VAR}` / `$ENV_VAR` 引用。 |
| `apiKeyTransport?` | `"x-api-key" \| "bearer"` | Anthropic key 头部样式。默认使用原生 `x-api-key`;仅对 key-auth `anthropic` 提供者有效。 |
Expand Down
6 changes: 3 additions & 3 deletions src/adapters/openai-responses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -540,9 +540,9 @@ function stripPreviousResponseId(body: unknown, strip: boolean): unknown {
* `prompt` is a reference to a server-stored prompt template — the most stateful
* field in the accepted schema.
*
* `service_tier` is deliberately NOT dropped: the server writes it for fast mode
* (`responses/core.ts`), and silently deleting a configured knob inside an adapter is
* worse than forwarding a parameter the upstream ignores.
* `service_tier` is deliberately NOT dropped here: the server owns the provider
* capability decision in `responses/core.ts` after the final route is known, so the
* adapter must stay provider-agnostic and forward what normalization left in place.
*
* MUST run before the composed sanitize chain below: `stripItemIdsWhenUnstored` keys
* off `store === false`, and a stateless upstream cannot resolve a stored item id.
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,7 @@ const providerConfigSchema = z.object({
apiKeyTransport: z.enum(["x-api-key", "bearer"]).optional(),
responsesPath: z.string().min(1).optional(),
statelessResponses: z.boolean().optional(),
supportsServiceTier: z.boolean().optional(),
allowPrivateNetwork: z.boolean().optional(),
codexAccountMode: z.enum(["pool", "direct"]).optional(),
responsesItemIdRepair: z.object({
Expand Down
7 changes: 7 additions & 0 deletions src/providers/derive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export interface DerivedKeyLoginProvider {
label: string;
baseUrl: string;
responsesPath?: string;
supportsServiceTier?: boolean;
adapter: string;
apiKeyTransport?: OcxProviderConfig["apiKeyTransport"];
dashboardUrl: string;
Expand Down Expand Up @@ -158,6 +159,7 @@ export function deriveKeyLoginMap(): Record<string, DerivedKeyLoginProvider> {
label: entry.label,
baseUrl: entry.baseUrl,
...(entry.responsesPath ? { responsesPath: entry.responsesPath } : {}),
...(entry.supportsServiceTier !== undefined ? { supportsServiceTier: entry.supportsServiceTier } : {}),
adapter: entry.adapter,
...(entry.apiKeyTransport !== undefined ? { apiKeyTransport: entry.apiKeyTransport } : {}),
dashboardUrl: entry.dashboardUrl,
Expand Down Expand Up @@ -259,6 +261,11 @@ export function enrichProviderFromRegistry(name: string, prov: OcxProviderConfig
// learned this route still gets backfilled.
if (prov.responsesPath === undefined && seed.responsesPath !== undefined) prov.responsesPath = seed.responsesPath;
if (prov.statelessResponses === undefined && seed.statelessResponses !== undefined) prov.statelessResponses = seed.statelessResponses;
// Fail-closed backfill: when the registry knows the capability it always applies it,
// and when it does not, the server's unknown-capability default strips caller tiers.
if (prov.supportsServiceTier === undefined && entry.supportsServiceTier !== undefined) {
prov.supportsServiceTier = entry.supportsServiceTier;
}
if (!prov.autoToolChoiceOnlyModels && seed.autoToolChoiceOnlyModels) prov.autoToolChoiceOnlyModels = [...seed.autoToolChoiceOnlyModels];
if (!prov.preserveReasoningContentModels && seed.preserveReasoningContentModels) prov.preserveReasoningContentModels = [...seed.preserveReasoningContentModels];
if (!prov.reasoningSplitModels && seed.reasoningSplitModels) prov.reasoningSplitModels = [...seed.reasoningSplitModels];
Expand Down
9 changes: 9 additions & 0 deletions src/providers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ export interface ProviderRegistryEntry {
* replay miss are repaired rather than forwarded.
*/
statelessResponses?: boolean;
/** Responses service-tier capability: true=proxy override, false=strip, unset=fail closed (strip + no inject). */
supportsServiceTier?: boolean;
modelDiscovery?: ProviderModelDiscoverySpec;
contextWindow?: number;
modelContextWindows?: Record<string, number>;
Expand Down Expand Up @@ -574,6 +576,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
adapter: "openai-responses",
baseUrl: "https://chatgpt.com/backend-api/codex",
authKind: "forward",
supportsServiceTier: true,
codexAccountMode: "pool",
featured: true,
note: "Codex login account pool (default) or Direct main-account mode via codexAccountMode",
Expand Down Expand Up @@ -745,6 +748,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
adapter: "openai-responses",
baseUrl: "https://api.openai.com/v1",
authKind: "key",
supportsServiceTier: true,
featured: true,
dashboardUrl: "https://platform.openai.com/api-keys",
defaultModel: "gpt-5.5",
Expand Down Expand Up @@ -968,6 +972,8 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
// "The API is stateless: responses and conversations are not stored on the
// server." https://api-docs.deepseek.com/api/create-response/
statelessResponses: true,
// DeepSeek's Responses schema does not document OpenAI's service_tier field.
supportsServiceTier: false,
/* [Decision Log]
- 목적: DeepSeek V4 thinking mode multi-turn/tool-call requests must replay prior assistant reasoning_content.
- 대안 분석: Globally preserve reasoning_content for all OpenAI-compatible models; preserve it for legacy deepseek-reasoner too; mark only V4 thinking models in registry metadata.
Expand Down Expand Up @@ -1245,6 +1251,9 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
responsesPath: "/responses",
adapter: "openai-responses",
authKind: "key",
// The Agent Plan Responses route does not document OpenAI's service_tier field, so
// an unknown caller tier or proxy fastMode priority must never be forwarded.
supportsServiceTier: false,
preserveCustomDestination: true,
dashboardUrl: "https://console.volcengine.com/ark/region:ark+cn-beijing/overview",
defaultModel: "deepseek-v4-pro",
Expand Down
5 changes: 5 additions & 0 deletions src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,11 @@ function routedProviderConfig(providerName: string, provider: OcxProviderConfig)
...(provider.responsesPath === undefined && registryEntry.responsesPath !== undefined
? { responsesPath: registryEntry.responsesPath }
: {}),
// Backfill the registry capability; when it is absent the server's unknown-capability
// default strips caller service_tier and never injects fastMode (fail closed).
...(provider.supportsServiceTier === undefined && registryEntry.supportsServiceTier !== undefined
? { supportsServiceTier: registryEntry.supportsServiceTier }
: {}),
authMode: canonicalAuthMode,
apiKey: resolvedApiKey,
// Backfill the Google wire mode + Vertex project/location from the registry when the user
Expand Down
Loading
Loading