Skip to content
46 changes: 37 additions & 9 deletions docs-site/src/content/docs/guides/combos.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,13 +201,29 @@ Combo failures are divided into **hop** failures and **terminal** failures.
| Client cancellation (499), `origin_rejected`, cyber-policy refusal, context overflow, or invalid request | Stop and return the error; another target would not make the request valid. |
| Any other unclassified error | Stop and return the error. |

A hopped target enters cooldown for 60 seconds by default. If the upstream response includes a
valid `Retry-After` value, opencodex uses it instead. Numeric seconds and HTTP-date values are
accepted, and every cooldown is capped at 10 minutes.
When `cooldownMs` is unset, a hopped target uses an upstream fallback: 5 seconds for request-rate
429s with upstream code `1302` or `1305`, and 60 seconds otherwise. When it is set, `cooldownMs`
applies whenever no usable upstream `Retry-After` or Codex reset signal exists, including those
request-rate 429s. Numeric `Retry-After` seconds and HTTP-date values are accepted, and every
cooldown is capped at 10 minutes. The precedence is, from strongest to weakest, explicit
`Retry-After` → Codex reset headers (`x-codex-primary-reset-at`, `x-codex-secondary-reset-at`, or
`x-codex-tertiary-reset-at`) → the combo's `cooldownMs` (when set) → the 5-second request-rate
fallback for upstream rate-limit codes `1302`/`1305` → the 60-second default. A valid immediate
`Retry-After: 0` remains an immediate upstream directive rather than being replaced by a configured
cooldown.

The current request never retries the same attempted target. Later requests skip it until its
cooldown expires. If no eligible target remains, the proxy returns HTTP 503 with
`error.code = "combo_unavailable"`.
cooldown expires. A `Retry-After` HTTP-date that is already in the past is also preserved as an
immediate upstream directive, just like `Retry-After: 0`. Set `waitForCooldownMs` to allow a later
request to wait for the earliest eligible target cooldown, up to that cap on each selection attempt,
and then make one fresh selection. A request may therefore wait up to `hops × waitForCooldownMs`
across multiple failover hops. The default is `0`, which fails closed immediately with HTTP 503 when
every eligible target is cooling; that `combo_unavailable` 503 carries a `Retry-After` header equal
to the earliest remaining cooldown, rounded up to whole seconds with a minimum of 1. Waits are not jittered, so
synchronized wake-ups are possible. An aborted request cancels this wait and returns the normal
`client_cancelled` response; it does not dispatch a backup target after cancellation. A combo target
cooldown is process-local per-combo state and is separate from the account-level Codex quota cooldown
used by native account routing.

:::note
Failover is intentionally bounded. It helps with target-specific availability, authentication,
Expand Down Expand Up @@ -321,7 +337,9 @@ combos, and its target picker excludes disabled models and nested combos.
Each target also shows a live quota badge: **Available**, **Out of quota**, or **Quota unknown**. Save and
Create are disabled only when every enabled target has fresh, complete evidence that its quota is exhausted.
Missing, stale, malformed, or incomplete aggregate evidence stays unknown and never locks a control. Polling
continues while the workspace is visible, so recovery automatically restores the action.
continues while the workspace is visible, so recovery automatically restores the action. The dashboard
editor does not yet expose `cooldownMs` or `waitForCooldownMs`; use the configuration file or management
API until the follow-up UI work lands.

### CLI

Expand All @@ -345,7 +363,12 @@ model alias and a non-empty display name. `create` and `update` are aliases for
Headless clients use `GET`, `PUT`, and `DELETE` on `/api/combos`. `GET` lists normalized combo
definitions, `PUT` creates or replaces one (and can rename one), and `DELETE` takes the id query
parameter. Authentication and request/response details are in the
[Management API reference](/reference/management-api/).
[Management API reference](/reference/management-api/). When a `PUT` body omits `cooldownMs`
or `waitForCooldownMs`, the API preserves the value already stored for that combo; send an explicit
value to change it. An explicit `cooldownMs` (even `60000`) is persisted as-is because it overrides
the request-rate fallback. A stored `cooldownMs` can only be removed by editing the configuration file;
`waitForCooldownMs` resets to its default when a `PUT` explicitly sends `0`, because the sparse
serializer omits that default. Omission preserves both values and the dashboard does not expose them yet.

For the complete persisted configuration, see [Configuration](/reference/configuration/).

Expand Down Expand Up @@ -376,6 +399,8 @@ Combos are stored in the top-level `combos` object, keyed by combo id:
| `targets[].weight` | No | `1` | Integer from 1 to 10,000. Used by round-robin and random; ignored by failover, least-used, and reset-window. |
| `strategy` | No | `"failover"` | `"failover"`, `"round-robin"`, `"random"`, `"least-used"`, or `"reset-window"`. |
| `stickyLimit` | No | `1` | Integer from 1 to 100 successful requests per round-robin selection. Applies only to round-robin. |
| `cooldownMs` | No | unset → upstream fallback (5 s for request-rate 429 codes `1302`/`1305`, otherwise 60 s) | Integer from 1 to 600000. When set, applies as the per-target cooldown whenever no usable upstream `Retry-After` or Codex reset signal exists, including request-rate 429s; when unset, uses the upstream fallback. |
| `waitForCooldownMs` | No | `0` | Integer from 0 to 600000. Maximum time to wait for the earliest eligible cooling target before returning `combo_unavailable`; abort cancels the wait. |
| `defaultEffort` | No | `null` | `low`, `medium`, `high`, `xhigh`, `max`, or `ultra`; applied only when the caller omits effort and the target advertises support. |
| `reasoningEffortMode` | No | `"strict"` | `"strict"` intersects every known target ladder, so one target advertising no effort control empties the combo's picker. `"adaptive"` excludes those empty ladders from the published intersection. Metadata only; dispatch is unchanged. |
| `imageInput` | No | `"auto"` | `"auto"` or `"disabled"`. `"auto"` publishes image support only when every target supports images; `"disabled"` forces text-only (drops image from published modalities and rejects image-bearing requests before dispatch). |
Expand All @@ -395,8 +420,11 @@ running opencodex instance that receives model requests.

Every target is currently ineligible: for example, its provider is disabled, it is cooling down,
it has already been attempted for this request, or an encrypted v2 task excludes it. Check target
provider state and recent upstream errors. For cooldowns, wait for the 60-second default or the
upstream `Retry-After` period (never more than 10 minutes), then retry.
provider state and recent upstream errors. For cooldowns, follow an observed `Retry-After` value first;
Codex reset headers also take precedence over `cooldownMs`.
If neither upstream signal is usable, the configured `cooldownMs` applies, or the upstream fallback applies
when it is unset (5 seconds for request-rate codes `1302`/`1305`, otherwise 60 seconds); every cooldown is
capped at 10 minutes.

### Why was my alias rejected?

Expand Down
12 changes: 7 additions & 5 deletions docs-site/src/content/docs/ja/guides/combos.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ ocx combo set balanced \
|クライアントのキャンセル (499)、`origin_rejected`、サイバー ポリシーの拒否、コンテキスト オーバーフロー、または無効なリクエスト |停止してエラーを返します。別のターゲットではリクエストは有効になりません。 |
|その他の未分類のエラー |停止してエラーを返します。 |

ホップされたターゲットはデフォルトで 60 秒間のクールダウンに入ります。アップストリーム応答に有効な `Retry-After` 値が含まれている場合、opencodex は代わりにそれを使用します。秒数値と HTTP 日付値が受け入れられ、各クールダウンの上限は 10 分です。
`cooldownMs` が未設定の場合、ホップされたターゲットはアップストリームのフォールバックを使用します。アップストリームコード `1302` または `1305` を伴うリクエストレート 429 では 5 秒、それ以外では 60 秒です。設定されている場合、使用可能なアップストリームの `Retry-After` または Codex リセットシグナルが存在しないときは、これらのリクエストレート 429 を含め、`cooldownMs` が適用されます。数値の `Retry-After` 秒数と HTTP-date 値が受け入れられ、すべてのクールダウンは 10 分を上限とします。優先順位は強い順に、明示的な `Retry-After` → Codex リセットヘッダー(`x-codex-primary-reset-at`、`x-codex-secondary-reset-at`、または `x-codex-tertiary-reset-at`)→ コンボの `cooldownMs`(設定時)→ アップストリームのレート制限コード `1302`/`1305` に対する 5 秒のリクエストレート フォールバック → 60 秒のデフォルトです。有効な即時指定 `Retry-After: 0` は、設定されたクールダウンで置き換えられず、即時のアップストリーム指示として維持されます。

現在のリクエストは、同じ試行ターゲットを再試行することはありません。以降のリクエストでは、クールダウンが期限切れになるまでスキップされます。適格なターゲットが残っていない場合、プロキシは `error.code = "combo_unavailable"` を含む HTTP 503 を返します。
現在のリクエストは、同じ試行ターゲットを再試行しません。後続のリクエストでは、クールダウンが期限切れになるまでそのターゲットをスキップします。すでに過去の時刻である `Retry-After` の HTTP-date も、`Retry-After: 0` と同様に即時のアップストリーム指示として維持されます。`waitForCooldownMs` を設定すると、後続のリクエストは、最も早く利用可能になるターゲットのクールダウンを、その選択試行ごとにこの上限まで待ってから、新たに 1 回選択できます。したがって、複数のフェイルオーバー ホップをまたぐリクエストは合計で `hops × waitForCooldownMs` まで待つ場合があります。デフォルトは `0` です。適格なターゲットがすべて冷却中の場合、HTTP 503 ですぐにフェイルクローズし、その `combo_unavailable` 503 には最も早く終了する残りのクールダウンと等しい `Retry-After` ヘッダーが含まれ、秒単位に切り上げられ、最小値は 1 秒です。待機にはジッターがないため、同期したウェイクアップが発生する可能性があります。中止されたリクエストはこの待機をキャンセルし、通常の `client_cancelled` 応答を返します。キャンセル後にバックアップ ターゲットをディスパッチすることはありません。コンボ ターゲットのクールダウンはプロセス ローカルなコンボごとの状態であり、ネイティブ アカウント ルーティングで使用されるアカウントレベルの Codex クォータ クールダウンとは別です。

:::note
フェイルオーバーは意図的に制限されています。これは、ターゲット固有の可用性、認証、クォータ、および過負荷の障害に役立ちます。呼び出し元のエラーやポリシーの拒否は隠蔽されません。
Expand Down Expand Up @@ -181,7 +181,7 @@ v1/base/v2 モードと完全な暗号化タスクのワークフローについ

各ターゲットには **利用可能**、**クォータを使い切りました**、**クォータ不明** のライブバッジも表示されます。
保存と作成が無効になるのは、有効な全ターゲットについて、クォータ枯渇を示す新鮮で完全な証拠がある場合だけです。
欠落、古い、不正、または不完全な集約データは不明のままで、操作をロックしません。クォータが回復すると操作は自動で再び有効になります。
欠落、古い、不正、または不完全な集約データは不明のままで、操作をロックしません。クォータが回復すると操作は自動で再び有効になります。ダッシュボードのエディターではまだ `cooldownMs` と `waitForCooldownMs` を設定できません。後続の UI 作業が完了するまでは、構成ファイルまたは管理 API を使用してください。

### CLI

Expand All @@ -202,7 +202,7 @@ ocx combo remove <id> --yes

### 管理 API

ヘッドレス クライアントは、`/api/combos` 上の `GET`、`PUT`、および `DELETE` を使用します。 `GET` は正規化されたコンボ定義をリストし、`PUT` は 1 つを作成または置換し (名前を変更できます)、`DELETE` は id クエリ パラメーターを受け取ります。認証と要求/応答の詳細は [管理 API リファレンス](/reference/management-api/) にあります。
ヘッドレス クライアントは、`/api/combos` 上の `GET`、`PUT`、および `DELETE` を使用します。 `GET` は正規化されたコンボ定義をリストし、`PUT` は 1 つを作成または置換し (名前を変更できます)、`DELETE` は id クエリ パラメーターを受け取ります。認証と要求/応答の詳細は [管理 API リファレンス](/reference/management-api/) にあります。`PUT` 本文で `cooldownMs` または `waitForCooldownMs` のいずれかを省略すると、そのコンボに保存済みの値が維持されます。変更するには明示的な値を指定してください。明示的な `cooldownMs`(`60000` でも)はリクエストレート フォールバックを上書きするため、そのまま永続化されます。保存済みの `cooldownMs` を削除できるのは構成ファイルを編集した場合だけです。`waitForCooldownMs` は、`PUT` で `0` を明示的に指定するとデフォルトに戻ります。これはスパース シリアライザーがそのデフォルト値を省略するためです。省略すると両方の値が維持され、ダッシュボードではまだどちらも設定できません。

永続化された設定全体については、「[構成](/reference/configuration/)」を参照してください。

Expand Down Expand Up @@ -233,6 +233,8 @@ ocx combo remove <id> --yes
| `targets[].weight` |いいえ | `1` | 1 ~ 10,000 の整数。`round-robin` と `random` で使用され、`failover`、`least-used`、`reset-window` では無視されます。 |
| `strategy` |いいえ | `"failover"` | `"failover"`、`"round-robin"`、`"random"`、`"least-used"`、`"reset-window"`。 |
| `stickyLimit` |いいえ | `1` | `round-robin` の 1 回の選択あたり、成功したリクエスト数を指定する 1 ~ 100 の整数。`round-robin` にのみ適用されます。 |
| `cooldownMs` |いいえ | 未設定 → アップストリーム フォールバック(リクエストレート 429 コード `1302`/`1305` では 5 秒、それ以外では 60 秒) | 1 ~ 600000 の整数。設定時は、使用可能なアップストリーム `Retry-After` または Codex リセットシグナルがない場合に、リクエストレート 429 を含むターゲットごとのクールダウンとして適用されます。未設定時はアップストリーム フォールバックを使用します。 |
| `waitForCooldownMs` |いいえ | `0` | 0 ~ 600000 の整数。最も早く利用可能になる冷却中のターゲットを待ってから `combo_unavailable` を返すまでの最大待機時間。中止すると待機はキャンセルされます。 |
| `defaultEffort` |いいえ | `null` | `low`、`medium`、`high`、`xhigh`、`max`、または `ultra`;呼び出し元が努力を省略し、ターゲットがサポートをアドバタイズした場合にのみ適用されます。 |
| `alias` |いいえ |なし |オプションのトリミングされたパブリック モデル ID。上記のエイリアス ルールを使用します。空の値はエイリアスなしで保存されます。 |
| `nativeAlias` |いいえ | `false` | 現在サポートされている bare native alias に routing/catalog の優先権を明示的に与えます。 |
Expand All @@ -246,7 +248,7 @@ ocx combo remove <id> --yes

### `combo_unavailable` が発生するのはなぜですか?

現在、すべてのターゲットは不適格です。たとえば、プロバイダーが無効になっている、冷却中である、このリクエストに対してすでに試行されている、暗号化された v2 タスクによってターゲットが除外されているなどです。ターゲットプロバイダーの状態と最近のアップストリームエラーを確認してください。クールダウンの場合は、デフォルトの 60 秒またはアップストリームの `Retry-After` 期間(10 分を超えないでください)待ってから、再試行してください。
現在、すべてのターゲットは不適格です。たとえば、プロバイダーが無効になっている、冷却中である、このリクエストに対してすでに試行されている、暗号化された v2 タスクによってターゲットが除外されているなどです。ターゲットプロバイダーの状態と最近のアップストリームエラーを確認してください。クールダウンでは、まずレスポンスで確認できる `Retry-After` の値に従ってください。Codex のリセットヘッダーも `cooldownMs` より優先され、どちらのアップストリームシグナルも使用できない場合は、設定した `cooldownMs`、未設定ならアップストリーム フォールバック(リクエストレートコード `1302`/`1305` では 5 秒、それ以外では 60 秒)が適用されますが、いずれのクールダウンも 10 分を超えません。

### 私のエイリアスが拒否されたのはなぜですか?

Expand Down
Loading
Loading