diff --git a/.gitignore b/.gitignore index d073e9d902..82fb882004 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,9 @@ devlog/**/security-advisory-draft* .omo/ **/.omo/ +# Local development worktrees +.worktrees/ + # Test-generated artifacts tests/.tmp-*/ .claude/ diff --git a/README.md b/README.md index 044828741d..d618790973 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,14 @@ ocx start # or `ocx service` to run it in the backgro Open **http://localhost:10100** and configure everything in the web dashboard — add providers (40+ built-ins, or any OpenAI-compatible endpoint), pick models, manage accounts. `ocx gui` re-opens the dashboard at any time. +It can also manage a **ChatGPT account pool** for Codex auth. Add multiple ChatGPT / Codex accounts, +refresh their 5h / weekly / 30d quota in the dashboard. Under quota routing, new sessions can use +the lowest-usage healthy account; round-robin and fill-first use their own policies. Existing Codex +threads normally retain affinity to the account that started them, so long SSH, tmux, or +mobile-connected sessions do not jump accounts mid-conversation — but quota re-evaluation, failover, +account exclusion, affinity expiry, or 401/403 and 429 recovery can rebind them. Give the accounts a +selection order when one of them — usually your Codex Desktop login — should only be reached for +once the others are drained. ### For agents diff --git a/assets/pr715-selection-order.png b/assets/pr715-selection-order.png new file mode 100644 index 0000000000..7d178d3739 Binary files /dev/null and b/assets/pr715-selection-order.png differ diff --git a/docs-site/src/content/docs/guides/web-dashboard.md b/docs-site/src/content/docs/guides/web-dashboard.md index 660fbcfdac..4ad5fd7c79 100644 --- a/docs-site/src/content/docs/guides/web-dashboard.md +++ b/docs-site/src/content/docs/guides/web-dashboard.md @@ -105,8 +105,21 @@ catalog entry. The **Codex Auth** page manages the native ChatGPT/Codex route: -- Manually choosing an account changes the next new Codex session; an already-bound thread keeps its - current account for that manual switch. +Pool mode selects across the main and added Codex accounts; Direct uses only the caller/main login. +In-flight requests keep their captured credentials, and a 401/403 reauthentication or 429 cooldown +may clear affinity and rotate to another eligible Pool account. This is separate from `openai-apikey` +and other providers. + +- Manually choosing an account applies immediately: an already-bound thread moves to it on its next + request, and only requests already in flight keep the account they captured. A manual choice is also + pinned: the card shows a **PINNED** badge, and a higher selection order cannot preempt that account + until it is drained, you select another account, or you change any account's selection order. +- Each account card carries a **Selection order** control (First, Earlier, Normal, Later, Last). + Higher order is used first, and the pool drops to a lower order only once every account above it is + drained or unavailable. A changed order applies from the next unbound request and never moves a + thread that is already bound. The Codex Desktop (main) account is ordered like any other, so it can + be set to **Last** and kept as the reserve. An order set from `ocx account priority` outside those + five presets stays visible and selectable on the card. - Thread affinity prevents per-request flapping. With quota auto-switch enabled, a long-running thread is periodically re-evaluated and may rebind after its relevant usage reaches the threshold and a strictly lower-usage eligible account exists. @@ -170,6 +183,7 @@ The GUI is a thin client over the proxy's JSON management API. Useful endpoints | `POST /api/oauth/login` · `GET /api/oauth/status` | Start a provider OAuth flow and poll for completion. | | `GET /api/codex-auth/accounts?refresh=1` | List main and pool accounts, force quota refresh, and report main-account `hasCredential` / terminal `needsReauth` state. | | `PUT /api/codex-auth/active` · `PUT /api/codex-auth/auto-switch` · `PUT /api/codex-auth/failover` | Select the account for the next request and configure pool routing. | +| `GET /api/codex-auth/active` · `PUT /api/codex-auth/accounts/priority` | Read the effective account (including `pinned` and which account is `pinnedAccountId`) and set one account's selection order. | | `POST /api/codex-auth/login` · `GET /api/codex-auth/login-status` | Add a pool account through browser login. | | `GET /api/logs?tail=50&limit=20&offset=0&provider=...&status=5xx` | Read recent request metadata with optional tail, provider, and exact/class status filters. With `limit`/`offset`, paging walks backward from the newest row (`offset=0` returns the latest page). Response shape: `{ timeZone, total, logs }` where `total` is the filtered row count before pagination. | | `GET` / `PUT /api/subagent-models` | Read or set the five featured `spawn_agent` override models. | diff --git a/docs-site/src/content/docs/ja/guides/web-dashboard.md b/docs-site/src/content/docs/ja/guides/web-dashboard.md index 5dd87b4bdd..955b9cad51 100644 --- a/docs-site/src/content/docs/ja/guides/web-dashboard.md +++ b/docs-site/src/content/docs/ja/guides/web-dashboard.md @@ -89,8 +89,18 @@ Codex タスクだけに適用され、このオプション自体が委任を **Codex 認証**ページはネイティブ ChatGPT/Codex ルートを管理します。 -- アカウントを直接選ぶと次の新規 Codex セッションから変わります。すでにアカウントが紐付いた thread はこの手動切り替えだけでは - 途中で移動しません。 +プールモードはメインと追加した Codex アカウントを横断して選択します。Direct は呼び出し元またはメインのログインのみを使います。送信中のリクエストは取得済みの資格情報を維持し、401/403 の再認証や 429 の cooldown が affinity を解除して別の適格なプールアカウントへ切り替えることがあります。これは `openai-apikey` や他のプロバイダーとは別の仕組みです。 + +- アカウントを直接選ぶとすぐに反映されます。すでにアカウントが紐付いた thread も次のリクエストで選んだ + アカウントに移り、すでに送信中のリクエストだけが取得済みのアカウントを使い続けます。手動で選んだアカウントは固定もされます。 + カードに **固定中** バッジが付き、そのアカウントが使い切られるか、別のアカウントを選ぶか、いずれかの + アカウントの選択順序を変更するまで、より上位の選択順序が割り込むことはありません。 +- 各アカウントカードには **選択順序** のコントロール(最初 / 早め / 標準 / 遅め / 最後)があります。 + 順序が上のものから使われ、その上にあるアカウントがすべて使い切られるか利用できなくなって初めて + 下の順序へ下がります。順序を変更すると **次の未バインドリクエスト** から適用され、すでにアカウントに + 紐づいた thread を移動させることはありません。Codex Desktop(メイン)アカウントも同じように + 並べ替えられるので、**最後** にして予備に回せます。`ocx account priority` でプリセット以外の値を設定した場合も、カード上に + 選択肢として残ります。 - Thread affinity がリクエストごとにアカウントが揺れるのを防ぎます。クォータ自動切り替えがオンなら長く 実行される thread も定期的に再評価します。関連使用量がしきい値以上で、使用量が確実により低い 健全アカウントがあればそのアカウントに再紐付けできます。 @@ -124,6 +134,7 @@ GUI はプロキシの JSON 管理 API を使うシンクライアントです | `POST /api/oauth/login` · `GET /api/oauth/status` | プロバイダー OAuth ログインを開始し完了可否を確認します。 | | `GET /api/codex-auth/accounts?refresh=1` | メインおよびプールアカウントを参照しクォータを強制更新し、メインの `hasCredential` / terminal `needsReauth` 状態を返します。 | | `PUT /api/codex-auth/active` · `PUT /api/codex-auth/auto-switch` · `PUT /api/codex-auth/failover` | 次のリクエストで使うアカウントとプールルーティングポリシーを設定します。 | +| `GET /api/codex-auth/active` · `PUT /api/codex-auth/accounts/priority` | 実効アカウント(固定中かどうかを示す `pinned` と、固定されているアカウントを示す `pinnedAccountId` を含む)を読み、アカウント 1 件の選択順序を設定します。 | | `POST /api/codex-auth/login` · `GET /api/codex-auth/login-status` | ブラウザログインでプールアカウントを追加します。 | | `GET /api/logs?tail=50&limit=20&offset=0&provider=...&status=5xx` | tail、プロバイダー、正確な状態コードまたは状態等級で最近のリクエストメタデータを参照します。`limit`/`offset` は最新行から過去方向にページングします(`offset=0` が最新ページ)。応答は `{ timeZone, total, logs }` で、`total` はページング前の一致件数です。 | | `GET` / `PUT /api/subagent-models` | `spawn_agent` に優先公開するモデル 5 つを読むか設定します。 | diff --git a/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md b/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md index 2b3b741295..b0e0fa29f0 100644 --- a/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md +++ b/docs-site/src/content/docs/ja/reference/cli/providers-accounts.md @@ -76,13 +76,14 @@ ocx login anthropic 実行中のプロキシを介してプロバイダー アカウントと API キー プールを一覧表示し、切り替えます。出荷されたヘルプ画面は次のとおりです。 ```text -Usage: ocx account ... +Usage: ocx account ... list [provider] Codex account pool, OAuth accounts and API keys (identifiers shown masked as the API returns them). current Show the active account or key. use Switch the active credential; 'main' selects the Codex App login. refresh Force-refresh Codex or provider quota reports. auto-switch Control the Codex pool threshold. +priority [first|earlier|normal|later|last|-100..100|reset] Selection order; omit the value to read it. remove --yes Remove a stored account or key after an existence check. add-key [--label