Skip to content

Commit d433181

Browse files
committed
feat(codex): add exact account routing
1 parent 0666b41 commit d433181

21 files changed

Lines changed: 962 additions & 108 deletions

docs-site/src/content/docs/ja/reference/configuration.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ namespaced selected id を bare id に変えます。
5252
| `syncResumeHistory?` | `boolean` | `true` | 戻せる Codex App 履歴互換モード。opencodex は元の Codex thread metadata をバックアップし、旧 OpenAI interactive row を `opencodex` に再マッピングし、opencodex が作成した `exec` row を App に見えるソースとして一時的に昇格します。`ocx stop` / `ocx restore` はバックアップした OpenAI row を復元し、残った opencodex user thread を OpenAI に戻し、ネイティブ Codex が `config.toml` からプロキシを削除した後でも開き続けられるようにします。オフにするには `false` に設定します。 |
5353
| `codexAccounts?` | `CodexAccount[]` | `[]` | Codex Auth ダッシュボードが管理する ChatGPT/Codex pool アカウント metadata。secret は `codex-accounts.json` に別途置きます。 |
5454
| `pausedCodexAccountIds?` | `string[]` | `[]` | Codex Auth で再開するまで、今後のすべての Pool 選択から除外するアカウント ID。メインを一時停止した場合は `__main__` も含みます。 |
55-
| `codexAccountNamespaces?` | `Record<string,string>` || 公開 model selector namespace から保存済み Codex アカウント target への任意 map。この foundation layer は map を検証・保存しますが、picker row の追加や routing の変更は行いません|
55+
| `codexAccountNamespaces?` | `Record<string,string>` || 公開 model selector namespace から保存済み Codex アカウント target への任意 map。`<selector>/<native OpenAI model>` は対応するアカウントだけに routing され、この設定自体は model picker row を追加しません|
5656
| `activeCodexAccountId?` | `string` || 手動選択した pool アカウント。既存 thread affinity を消去して次のリクエストから適用し、処理中のリクエストは現在のアカウントを維持します。 |
5757
| `autoSwitchThreshold?` | `number` | `80` | 新しいセッション自動切替用の使用量百分率 threshold。既知の 5 時間、週次、30 日 quota window のうち最も高いスコアを使います。`0` なら quota 自動切替をオフにします。`quota` 戦略と `fill-first` の drain threshold にも使います。 |
5858
| `accountPoolStrategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Codex pool の新しいセッション rotation 戦略。**新しいセッションのみ**に適用され、既存 thread id は affinity を維持します。`quota`(既定)— アクティブアカウントが `autoSwitchThreshold` を超えたら既知 usage 最小を選択。`round-robin` — 適格アカウント間を smooth weighted で均等分散。`fill-first` — cooldown、使用不可、または(設定時)`autoSwitchThreshold` までアクティブアカウントを使い切り(未知 usage は強制切替しない)、安定ソート順で次へ。 |
@@ -71,8 +71,11 @@ namespaced selected id を bare id に変えます。
7171
`"@main"` です。provider と予約済み `openai` / `combo` との衝突は大文字小文字を区別せず検査され、
7272
namespace 付き combo alias はその namespace prefix に selector を再利用できません。設定済み pool id
7373
や他の selector target も selector と再利用できません。raw account id と email は
74-
非公開のままにし、selector を公開名として使ってください。この foundation layer では map は inert で、
75-
model picker entry の作成、session の固定、Pool / Direct routing の変更は行いません。
74+
非公開のままにし、selector を公開名として使ってください。`side/gpt-5.6-sol` のような request は、
75+
`openai` が Direct mode の場合でも `side` に対応するアカウントだけを使用し、上流には
76+
`gpt-5.6-sol` を送信します。target を利用できない場合は別のアカウントへ切り替えず fail closed し、
77+
active Pool account も変更しません。bare native model は通常の Pool / Direct routing を維持します。
78+
この map 自体は model picker entry を作成しません。
7679

7780
`maxConcurrentThreadsPerSession``config.json` キーではなく `PUT /api/v2` で使う camel-case
7881
フィールドです。`ocx v2 threads <n>` は対応する `max_concurrent_threads_per_session` 値を Codex の

docs-site/src/content/docs/ko/reference/configuration.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespaced selected id를 bare id로 바꿉니다.
5353
| `syncResumeHistory?` | `boolean` | `true` | 되돌릴 수 있는 Codex App 기록 호환 모드. opencodex가 원래 Codex thread metadata를 백업하고, 예전 OpenAI interactive row를 `opencodex`로 재매핑하며, opencodex가 만든 `exec` row를 App에 보이는 source로 잠시 승격합니다. `ocx stop` / `ocx restore`는 백업한 OpenAI row를 복원하고 남은 opencodex user thread를 OpenAI로 돌려 네이티브 Codex가 `config.toml`에서 프록시를 제거한 뒤에도 이어서 열 수 있게 합니다. 끄려면 `false`로 설정합니다. |
5454
| `codexAccounts?` | `CodexAccount[]` | `[]` | Codex Auth 대시보드에서 관리하는 ChatGPT/Codex pool 계정 metadata. secret은 `codex-accounts.json`에 따로 둡니다. |
5555
| `pausedCodexAccountIds?` | `string[]` | `[]` | Codex Auth에서 재개할 때까지 이후의 모든 Pool 선택에서 제외할 계정 ID. 메인 계정을 일시 중지하면 `__main__`도 포함됩니다. |
56-
| `codexAccountNamespaces?` | `Record<string,string>` || 공개 model selector namespace에서 저장된 Codex 계정 target으로 연결하는 선택적 map입니다. 이 foundation layer는 map을 검증하고 저장하지만 picker row를 추가하거나 routing을 변경하지 않습니다. |
56+
| `codexAccountNamespaces?` | `Record<string,string>` || 공개 model selector namespace에서 저장된 Codex 계정 target으로 연결하는 선택적 map입니다. `<selector>/<native OpenAI model>`은 매핑된 계정으로만 routing되며, 이 설정 자체는 model picker row를 추가하지 않습니다. |
5757
| `activeCodexAccountId?` | `string` || 수동으로 선택한 pool 계정. 선택 시 기존 thread affinity를 지우고 다음 요청부터 적용하며, 진행 중인 요청은 기존 계정을 유지합니다. |
5858
| `autoSwitchThreshold?` | `number` | `80` | 새 세션 자동 전환용 사용량 백분율 threshold. 알려진 5시간, 주간, 30일 quota window 중 가장 높은 점수를 씁니다. `0`이면 quota 자동 전환을 끕니다. `quota` 전략과 `fill-first` drain threshold에도 사용됩니다. |
5959
| `accountPoolStrategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Codex pool의 새 세션 rotation 전략. **새 세션에만** 적용되며 기존 thread id는 affinity를 유지합니다. `quota`(기본) — 활성 계정이 `autoSwitchThreshold`를 넘으면 알려진 usage가 가장 낮은 계정 선택. `round-robin` — 적격 계정 간 smooth weighted 균등 분배. `fill-first` — cooldown, 사용 불가 또는(설정 시) `autoSwitchThreshold`까지 활성 계정을 소진(알 수 없는 usage는 강제 전환하지 않음)한 뒤 안정 정렬 순으로 다음 계정. |
@@ -72,8 +72,11 @@ namespaced selected id를 bare id로 바꿉니다.
7272
provider 및 예약된 `openai` / `combo` 충돌은 대소문자를 구분하지 않고 검사하며, namespace가 있는
7373
combo alias는 selector를 namespace prefix로 재사용할 수 없습니다. 설정된 pool id와 다른 selector
7474
target도 selector로 재사용할 수 없습니다. raw account id와 email은 비공개로
75-
유지하고 selector를 공개 이름으로 사용하세요. 이 foundation layer에서 map은 inert하며 model picker
76-
entry 생성, session 고정, Pool / Direct routing 변경을 수행하지 않습니다.
75+
유지하고 selector를 공개 이름으로 사용하세요. `side/gpt-5.6-sol` 같은 요청은 `openai`가 Direct
76+
mode여도 `side`에 매핑된 계정만 사용하고 업스트림에는 `gpt-5.6-sol`을 보냅니다. target을 사용할 수
77+
없으면 다른 계정으로 전환하지 않고 fail closed하며 active Pool account도 변경하지 않습니다. bare
78+
native model은 기존 Pool / Direct routing을 유지합니다. 이 map 자체는 model picker entry를 만들지
79+
않습니다.
7780

7881
`maxConcurrentThreadsPerSession``config.json` 키가 아니라 `PUT /api/v2`에서 쓰는 camel-case
7982
필드입니다. `ocx v2 threads <n>`은 대응하는 `max_concurrent_threads_per_session` 값을 Codex의

docs-site/src/content/docs/reference/configuration.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ differing backup and rewrites known legacy namespaced selected ids to bare ids.
5858
| `syncResumeHistory?` | `boolean` | `true` | Reversible Codex App history compatibility mode. opencodex backs up original Codex thread metadata, remaps old OpenAI interactive rows to `opencodex`, and temporarily promotes opencodex-created `exec` rows to an app-visible source. `ocx stop` / `ocx restore` restore backed-up OpenAI rows and eject remaining opencodex user threads to OpenAI so native Codex can resume them after the proxy is removed from `config.toml`. Set `false` to opt out. |
5959
| `codexAccounts?` | `CodexAccount[]` | `[]` | ChatGPT/Codex pool account metadata managed by the Codex Auth dashboard. Secrets live separately in `codex-accounts.json`. |
6060
| `pausedCodexAccountIds?` | `string[]` | `[]` | Accounts excluded from every future Pool selection until resumed in Codex Auth. Includes the main `__main__` account when paused. |
61-
| `codexAccountNamespaces?` | `Record<string,string>` || Optional public model-selector namespace → stored Codex account target map. This foundation layer validates and persists the map but does not add picker rows or change routing. |
61+
| `codexAccountNamespaces?` | `Record<string,string>` || Optional public model-selector namespace → stored Codex account target map. `<selector>/<native-openai-model>` routes using exactly the mapped account; this setting does not add model-picker rows. |
6262
| `activeCodexAccountId?` | `string` || Manually selected Pool account. Selection clears existing thread affinity and applies to the next request; in-flight requests keep their captured account. |
6363
| `autoSwitchThreshold?` | `number` | `80` | Usage percent threshold for new-session auto-switching. The score uses the hottest known 5h, weekly, or 30d quota window. Set `0` to disable quota auto-switching. Used by the `quota` strategy and as the drain threshold for `fill-first`. |
6464
| `accountPoolStrategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | New-session rotation strategy for the Codex pool. Applies to **new sessions only**; existing thread ids keep affinity. `quota` — today's default: pick the lowest known usage when the active account crosses `autoSwitchThreshold`. `round-robin` — even spread across eligible accounts via smooth weighted selection. `fill-first` — keep the active account until it cools down, becomes unusable, or crosses `autoSwitchThreshold` when set (unknown usage does not force a switch), then advance to the next eligible account in stable sorted order. |
@@ -78,8 +78,11 @@ names are rejected. Each value is either a valid pool-account id (never the inte
7878
`"@main"` for the Codex Desktop account. Provider and reserved `openai` / `combo` collisions are
7979
checked case-insensitively; a namespaced combo alias cannot reuse a selector as its namespace prefix,
8080
and configured pool ids or selector targets also cannot reuse a selector. Keep raw
81-
account ids and emails private—the selector is the public name. In this foundation layer the map is
82-
inert: it does not create model-picker entries, pin sessions, or alter Pool or Direct routing.
81+
account ids and emails private—the selector is the public name. A request such as
82+
`side/gpt-5.6-sol` uses only the account mapped by `side`, even when `openai` is in Direct mode, and
83+
sends `gpt-5.6-sol` upstream. It fails closed instead of switching accounts and does not change the
84+
active Pool account. Bare native models retain normal Pool/Direct routing. The map itself does not
85+
create model-picker entries.
8386

8487
`maxConcurrentThreadsPerSession` is the camel-case field used by `PUT /api/v2`, not a
8588
`config.json` key. `ocx v2 threads <n>` persists the corresponding

docs-site/src/content/docs/ru/reference/configuration.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ opencodex настраивается файлом `~/.opencodex/config.json`. Е
5757
| `syncResumeHistory?` | `boolean` | `true` | Обратимый режим совместимости истории Codex App. opencodex резервирует исходные метаданные потоков Codex, переназначает старые интерактивные строки OpenAI на `opencodex` и временно повышает созданные opencodex строки `exec` до видимого в приложении источника. `ocx stop` / `ocx restore` восстанавливают зарезервированные строки OpenAI и возвращают оставшиеся пользовательские потоки opencodex обратно к OpenAI, чтобы нативный Codex мог возобновлять их после удаления прокси из `config.toml`. Установите `false`, чтобы отказаться. |
5858
| `codexAccounts?` | `CodexAccount[]` | `[]` | Метаданные аккаунтов пула ChatGPT/Codex, управляемые дашбордом Codex Auth. Секреты хранятся отдельно в `codex-accounts.json`. |
5959
| `pausedCodexAccountIds?` | `string[]` | `[]` | ID аккаунтов, исключённых из всех будущих выборов Pool до возобновления в Codex Auth. При паузе основного аккаунта включает `__main__`. |
60-
| `codexAccountNamespaces?` | `Record<string,string>` || Необязательная map публичного namespace селектора модели на сохранённую цель аккаунта Codex. Этот foundation layer проверяет и сохраняет map, но не добавляет строки picker и не меняет routing. |
60+
| `codexAccountNamespaces?` | `Record<string,string>` || Необязательное сопоставление публичного namespace селектора модели с сохранённым аккаунтом Codex. `<selector>/<native OpenAI model>` направляется только в сопоставленный аккаунт; сама настройка не добавляет строки в model picker. |
6161
| `activeCodexAccountId?` | `string` || Вручную выбранный аккаунт пула. Выбор очищает существующие привязки потоков и действует со следующего запроса; выполняющиеся запросы сохраняют захваченный аккаунт. |
6262
| `autoSwitchThreshold?` | `number` | `80` | Порог процента использования для автопереключения новых сессий. Оценка использует самое «горячее» из известных окон квоты — 5-часовое, недельное или 30-дневное. Установите `0`, чтобы отключить автопереключение по квоте. Используется стратегией `quota` и как порог исчерпания для `fill-first`. |
6363
| `accountPoolStrategy?` | `"quota" \| "round-robin" \| "fill-first"` | `"quota"` | Стратегия ротации новых сессий для пула Codex. Применяется **только к новым сессиям**; существующие id потоков сохраняют affinity. `quota` (по умолчанию) — выбор наименьшего известного usage, когда активный аккаунт превышает `autoSwitchThreshold`. `round-robin` — равномерное распределение между подходящими аккаунтами через smooth weighted selection. `fill-first` — использовать активный аккаунт до cooldown, недоступности или (если задано) `autoSwitchThreshold` (неизвестный usage не принуждает к переключению), затем переход к следующему подходящему аккаунту в стабильном отсортированном порядке. |
@@ -76,9 +76,11 @@ opencodex настраивается файлом `~/.opencodex/config.json`. Е
7676
либо `"@main"` для аккаунта Codex Desktop. Коллизии с provider и зарезервированными `openai` / `combo`
7777
проверяются без учёта регистра; namespace-префикс namespaced combo alias не может повторять селектор.
7878
Настроенные id пула и цели других селекторов также нельзя повторно использовать как селектор. Сохраняйте
79-
raw id аккаунтов и email приватными, а селектор используйте как публичное имя.
80-
В этом foundation layer map инертна: она не создаёт записи model picker, не закрепляет сессии и не меняет
81-
маршрутизацию Pool / Direct.
79+
raw id аккаунтов и email приватными, а селектор используйте как публичное имя. Запрос вроде
80+
`side/gpt-5.6-sol` использует только аккаунт, сопоставленный с `side`, даже когда `openai` работает в режиме
81+
Direct, и отправляет вышестоящей стороне `gpt-5.6-sol`. Если целевой аккаунт недоступен, запрос завершается
82+
ошибкой без переключения на другой аккаунт и без изменения active Pool account. Голые нативные модели
83+
сохраняют обычную маршрутизацию Pool / Direct. Само сопоставление не создаёт записи model picker.
8284

8385
`maxConcurrentThreadsPerSession` — это camelCase-поле, используемое `PUT /api/v2`, а не ключ
8486
`config.json`. `ocx v2 threads <n>` сохраняет соответствующее значение

0 commit comments

Comments
 (0)