diff --git a/docs-site/src/content/docs/fr/reference/architecture.md b/docs-site/src/content/docs/fr/reference/architecture.md index 746ea7f726..14885a808e 100644 --- a/docs-site/src/content/docs/fr/reference/architecture.md +++ b/docs-site/src/content/docs/fr/reference/architecture.md @@ -21,7 +21,8 @@ src/ ├── vision/ # service auxiliaire de vision (description et planification) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -32,19 +33,19 @@ src/ └── index.ts # public entry ``` -Trois anciens points d’entrée volumineux préservent désormais la compatibilité sous forme de façades : `codex/catalog.ts` exporte les sept modules spécialisés `codex/catalog/*.ts`, `server/management-api.ts` répartit les requêtes entre les neuf modules `server/management/*.ts`, et `server/responses.ts` exporte les cinq modules `server/responses/*.ts`. +Les anciens points d’entrée volumineux préservent désormais la compatibilité sous forme de façades : `codex/catalog.ts` exporte les modules `codex/catalog/*.ts`, `server/management-api.ts` répartit les requêtes entre les modules `server/management/*.ts`, `server/responses.ts` exporte les modules `server/responses/*.ts`, et `bridge.ts` réexporte les modules `bridge/*.ts`. Une façade est le chemin d’import stable, pas l’implémentation : chaque étape ci-dessous nomme le module qui détient le code, et `structure/transports/responses.md` contient l’inventaire complet des propriétaires de la surface Responses. ## Flux d’une requête -`server/index.ts` gère la frontière HTTP et délègue le plan de données Responses à la façade `server/responses.ts` et à ses modules `server/responses/*.ts` : +`server/index/serve-options.ts` gère la frontière HTTP et délègue le plan de données Responses à la façade `server/responses.ts` et à ses modules `server/responses/*.ts` : -1. `server/index.ts` applique CORS et l’authentification d’API, refuse les nouvelles tâches pendant le drainage et enregistre les métadonnées du cycle de vie de la requête. Il sert `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST /v1/images/edits` (relayés vers une famille OpenAI en amont par `server/images.ts` pour l’outil `image_gen` intégré à Codex), `POST /v1/live` / `POST /v1/realtime/calls` (création des appels vocaux ChatGPT / Codex App et OpenAI Realtime, relayée par `server/live.ts`), les connexions WebSocket sideband sur `/v1/live/{callId}` (et `/v1/realtime?call_id=`), ainsi que la mise à niveau WebSocket facultative sur `/v1/responses`. -2. `server/responses/core.ts` décompresse et analyse le JSON, développe les entrées de mémoire locale `previous_response_id` lorsqu’elles sont disponibles, puis appelle `responses/parser.ts`. +1. `server/index/serve-options.ts` applique CORS et l’authentification d’API, refuse les nouvelles tâches pendant le drainage et enregistre les métadonnées du cycle de vie de la requête. Il sert `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST /v1/images/edits` (relayés vers une famille OpenAI en amont par `server/images.ts` pour l’outil `image_gen` intégré à Codex), `POST /v1/live` / `POST /v1/realtime/calls` (création des appels vocaux ChatGPT / Codex App et OpenAI Realtime, relayée par `server/live.ts`), les connexions WebSocket sideband sur `/v1/live/{callId}` (et `/v1/realtime?call_id=`), ainsi que la mise à niveau WebSocket facultative sur `/v1/responses`. +2. `server/responses/request-prepare.ts` décompresse et analyse le JSON, développe les entrées de mémoire locale `previous_response_id` lorsqu’elles sont disponibles, puis appelle `responses/parser.ts`. 3. `router.ts` résout un identifiant simple ou `provider/model`. Le serveur détermine ensuite l’affinité du compte Codex, actualise l’authentification OAuth du fournisseur si nécessaire et applique à la route les identifiants sélectionnés. 4. Avant l’appel principal, `vision/` décrit les images pour les modèles figurant dans `noVisionModels`. En l’absence de service auxiliaire sûr, les images sont supprimées plutôt qu’envoyées à un service en amont purement textuel. 5. `server/adapter-resolve.ts` applique toute substitution de protocole propre au modèle et construit l’un des adaptateurs enregistrés. L’adaptateur Responses relaie le corps natif, Cursor exécute son transport bidirectionnel `runTurn`, et les adaptateurs traduits construisent, envoient et analysent une requête en amont. 6. Pour les modèles routés avec un outil hébergé `web_search`, `web-search/` expose une fonction synthétique, exécute la recherche réelle avec le backend configuré — le service auxiliaire OpenAI/ChatGPT ou le backend Anthropic —, renvoie les résultats au modèle routé et recommence dans la limite de boucle configurée. Cette boucle ne prend en charge que le chemin HTTP classique ; les adaptateurs qui implémentent `runTurn`, comme Cursor, la contournent et poursuivent leur propre transport. -7. `bridge.ts` produit un flux SSE Responses ou une réponse JSON. `server/request-log.ts` et `usage/` recueillent de manière bornée l’état, la latence, les libellés de fournisseur/modèle et l’utilisation estimée des jetons, sans modifier la réponse. +7. `bridge/sse.ts` / `bridge/response-json.ts` produit un flux SSE Responses ou une réponse JSON. `server/request-log.ts` et `usage/` recueillent de manière bornée l’état, la latence, les libellés de fournisseur/modèle et l’utilisation estimée des jetons, sans modifier la réponse. ## Analyseur @@ -57,7 +58,7 @@ Trois anciens points d’entrée volumineux préservent désormais la compatibil ## Pont -`bridge.ts` transforme le flux interne `AdapterEvent` de l’adaptateur en événements SSE Responses compris par Codex : +`bridge/sse.ts` transforme le flux interne `AdapterEvent` de l’adaptateur en événements SSE Responses compris par Codex : | AdapterEvent | Événements SSE Responses émis | | --- | --- | @@ -85,7 +86,7 @@ Les implémentations OAuth se trouvent dans `oauth/`. Les jetons d’accès sont ## Transport et compactage -Par défaut, `server/index.ts` sert HTTP/SSE sur `/v1/responses`. Si Codex tente une mise à niveau WebSocket de Responses alors que `websockets` vaut `false`, opencodex renvoie `426 upgrade_required` ; Codex revient alors à HTTP pour cette session. Lorsque `"websockets": true` est défini, le même point de terminaison accepte la mise à niveau et utilise le pont WebSocket. +Par défaut, `server/index/serve-options.ts` sert HTTP/SSE sur `/v1/responses`. Si Codex tente une mise à niveau WebSocket de Responses alors que `websockets` vaut `false`, opencodex renvoie `426 upgrade_required` ; Codex revient alors à HTTP pour cette session. Lorsque `"websockets": true` est défini, le même point de terminaison accepte la mise à niveau et utilise le pont WebSocket. Indépendamment de ce réglage côté client, les requêtes canoniques transmises à ChatGPT avec `stream: true` à la racine peuvent utiliser le transport WebSocket en amont de Codex avec une version stable de Bun 1.4.0 ou ultérieure. La version intégrée Bun 1.3.14, les préversions et les identités de runtime impossibles à vérifier utilisent HTTP/SSE. Les réponses WS en amont qui réussissent conservent le contrat SSE en aval et contournent `tee()` au moyen d’un relais borné à lecteur unique et avide (4 MiB par trame brute/enveloppée et une file de production de 8 MiB). Le dépassement de la file ferme la connexion en amont et émet en aval un événement terminal `response.failed`, suivi de `[DONE]`. @@ -98,7 +99,7 @@ l’ancien socket ; les requêtes admissibles suivantes ayant la même identité le nouveau socket. Les autres modèles et passerelles conservent leur politique Lite. Des métadonnées natives mal formées entraînent toujours un repli HTTP, sans modifier le corps. -Le compactage du contexte Codex fonctionne avec les modèles routés. `server/responses/compact.ts` traite `POST /v1/responses/compact` en exécutant un tour interne de synthèse routé et en renvoyant un historique compacté, tandis que `responses/parser.ts` et `bridge.ts` traitent les tours de compactage distant v2 `compaction_trigger` en émettant exactement un élément de sortie synthétique `compaction`. +Le compactage du contexte Codex fonctionne avec les modèles routés. `server/responses/compact.ts` traite `POST /v1/responses/compact` en exécutant un tour interne de synthèse routé et en renvoyant un historique compacté, tandis que `responses/parser.ts` et `bridge/sse.ts` traitent les tours de compactage distant v2 `compaction_trigger` en émettant exactement un élément de sortie synthétique `compaction`. ## Mise en cache et catalogue diff --git a/docs-site/src/content/docs/ja/reference/architecture.md b/docs-site/src/content/docs/ja/reference/architecture.md index 3500cbaf86..a803cd9784 100644 --- a/docs-site/src/content/docs/ja/reference/architecture.md +++ b/docs-site/src/content/docs/ja/reference/architecture.md @@ -21,7 +21,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -32,30 +33,33 @@ src/ └── index.ts # public entry ``` -以前の大規模なエントリーファイル 3 つは、現在は互換性 facade です。`codex/catalog.ts` は -7 個の `codex/catalog/*.ts` モジュールを、`server/management-api.ts` は 9 個の -`server/management/*.ts` モジュールを、`server/responses.ts` は 5 個の -`server/responses/*.ts` モジュールを接続します。 +大規模だったエントリーファイルは、現在は互換性 facade です。`codex/catalog.ts` は +`codex/catalog/*.ts` モジュールを、`server/management-api.ts` は +`server/management/*.ts` モジュールを、`server/responses.ts` は +`server/responses/*.ts` モジュールを、`bridge.ts` は `bridge/*.ts` モジュールを接続します。 +facade は安定した import パスであって実装ではありません。以下の各ステップは実際に +コードを所有するモジュールを示し、Responses 面の完全な所有権一覧は +`structure/transports/responses.md` にあります。 ## リクエスト処理フロー -HTTP の境界は `server/index.ts` が担い、Responses データプレーンは `server/responses.ts` facade と +HTTP の境界は `server/index/serve-options.ts` が担い、Responses データプレーンは `server/responses.ts` facade と `server/responses/*.ts` モジュールに渡します。 -1. `server/index.ts` で CORS と API 認証を確認し、終了待ち状態なら新規リクエストを拒否したのち、リクエストのライフサイクルを記録します。ここで `GET /v1/models`、`POST /v1/responses`、 +1. `server/index/serve-options.ts` で CORS と API 認証を確認し、終了待ち状態なら新規リクエストを拒否したのち、リクエストのライフサイクルを記録します。ここで `GET /v1/models`、`POST /v1/responses`、 `POST /v1/responses/compact`、`POST /v1/images/generations` / `POST /v1/images/edits` (Codex 組み込み `image_gen` ツール用 — `server/images.ts` が OpenAI 系の上流に中継)、 `POST /v1/live` / `POST /v1/realtime/calls`(ChatGPT / Codex App 音声と OpenAI Realtime の call-create、`server/live.ts` が中継)と `/v1/live/{callId}` サイドバンド WebSocket、 `/v1/responses` のオプション WebSocket アップグレードを提供します。 -2. `server/responses/core.ts` が展開し JSON を読みます。覚えておいた `previous_response_id` 入力があれば展開したのち `responses/parser.ts` に渡します。 +2. `server/responses/request-prepare.ts` が展開し JSON を読みます。覚えておいた `previous_response_id` 入力があれば展開したのち `responses/parser.ts` に渡します。 3. `router.ts` が通常のモデル id または `provider/model` id を解決します。続いて Codex アカウント affinity を決定し、必要ならプロバイダー OAuth を更新して選択された認証情報を route に適用します。 4. 本リクエストの前に `vision/` が `noVisionModels` モデル用の画像説明を作ります。安全なサイドカー経路がないときはテキスト専用の上流に画像を送らず取り除きます。 5. `server/adapter-resolve.ts` がモデル別の wire override を適用し、登録済みアダプターのいずれかを作ります。 Responses passthrough は元の body を中継し、Cursor は双方向 `runTurn` transport を使い、 残りの変換型アダプターは上流リクエストを build/fetch/parse します。 6. ルーティングモデルがホステッド `web_search` を要求すると `web-search/` が合成関数を公開します。実際の検索は ChatGPT サイドカーで実行し、結果をルーティングモデルに戻し、設定された回数の中で繰り返します。 -7. `bridge.ts` が Responses SSE または JSON を作ります。`server/request-log.ts` と `usage/` はレスポンスに触れずに終了ステータス、レイテンシー、プロバイダー/モデル、最善推定トークン使用量を記録します。 +7. `bridge/sse.ts` / `bridge/response-json.ts` が Responses SSE または JSON を作ります。`server/request-log.ts` と `usage/` はレスポンスに触れずに終了ステータス、レイテンシー、プロバイダー/モデル、最善推定トークン使用量を記録します。 ## パーサー @@ -73,7 +77,7 @@ HTTP の境界は `server/index.ts` が担い、Responses データプレーン ## ブリッジ -`bridge.ts` はアダプターの内部 `AdapterEvent` ストリームを Codex が理解する Responses SSE に再変換します: +`bridge/sse.ts` はアダプターの内部 `AdapterEvent` ストリームを Codex が理解する Responses SSE に再変換します: | AdapterEvent | Responses SSE emitted | | --- | --- | @@ -95,7 +99,7 @@ HTTP の境界は `server/index.ts` が担い、Responses データプレーン ## 伝送と compaction -`server/index.ts` はデフォルトで `/v1/responses` を HTTP/SSE で提供します。`websockets` が `false` の状態で Codex が Responses WebSocket アップグレードを試みると、opencodex は `426 upgrade_required` を返し、Codex はそのセッションで HTTP にフォールバックします。`"websockets": true` を設定すると同じエンドポイントがアップグレードを受け入れ WebSocket ブリッジを使います。 +`server/index/serve-options.ts` はデフォルトで `/v1/responses` を HTTP/SSE で提供します。`websockets` が `false` の状態で Codex が Responses WebSocket アップグレードを試みると、opencodex は `426 upgrade_required` を返し、Codex はそのセッションで HTTP にフォールバックします。`"websockets": true` を設定すると同じエンドポイントがアップグレードを受け入れ WebSocket ブリッジを使います。 最終送信モデルが `gpt-5.3-codex-spark` の場合、canonical ChatGPT 転送は HTTP ヘッダーと ネイティブ WS フレームのメタデータの両方で Responses Lite を明示的に無効にします。 @@ -108,7 +112,7 @@ HTTP の境界は `server/index.ts` が担い、Responses データプレーン Codex コンテキスト compaction はルーティングされたモデルでも動作します。`server/responses/compact.ts` は `POST /v1/responses/compact` を内部ルーティング要約ターンとして扱い、圧縮されたヒストリーを返します。 -`responses/parser.ts` と `bridge.ts` は remote compaction v2 の `compaction_trigger` ターンを扱い、合成 `compaction` 出力項目を正確に 1 つ送ります。 +`responses/parser.ts` と `bridge/sse.ts` は remote compaction v2 の `compaction_trigger` ターンを扱い、合成 `compaction` 出力項目を正確に 1 つ送ります。 ## キャッシュとカタログ diff --git a/docs-site/src/content/docs/ko/reference/architecture.md b/docs-site/src/content/docs/ko/reference/architecture.md index d95bf391ad..31548f2ad3 100644 --- a/docs-site/src/content/docs/ko/reference/architecture.md +++ b/docs-site/src/content/docs/ko/reference/architecture.md @@ -23,7 +23,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -34,23 +35,26 @@ src/ └── index.ts # public entry ``` -기존의 대형 진입 파일 세 개는 이제 호환성 facade입니다. `codex/catalog.ts`는 7개의 -`codex/catalog/*.ts` 모듈을, `server/management-api.ts`는 9개의 `server/management/*.ts` -모듈을, `server/responses.ts`는 5개의 `server/responses/*.ts` 모듈을 연결합니다. +기존의 대형 진입 파일들은 이제 호환성 facade입니다. `codex/catalog.ts`는 +`codex/catalog/*.ts` 모듈을, `server/management-api.ts`는 `server/management/*.ts` +모듈을, `server/responses.ts`는 `server/responses/*.ts` 모듈을, `bridge.ts`는 `bridge/*.ts` +모듈을 연결합니다. facade는 안정적인 import 경로일 뿐 구현이 아닙니다. 아래 각 단계는 +실제 코드를 소유한 모듈을 가리키며, Responses 표면의 전체 소유권 목록은 +`structure/transports/responses.md`에 있습니다. ## 요청 처리 흐름 -HTTP 경계는 `server/index.ts`가 맡고, Responses 데이터 플레인은 `server/responses.ts` facade와 +HTTP 경계는 `server/index/serve-options.ts`가 맡고, Responses 데이터 플레인은 `server/responses.ts` facade와 `server/responses/*.ts` 모듈로 넘깁니다. -1. `server/index.ts`에서 CORS와 API 인증을 확인하고, 종료 대기 중이면 새 요청을 거부한 뒤 요청 수명 +1. `server/index/serve-options.ts`에서 CORS와 API 인증을 확인하고, 종료 대기 중이면 새 요청을 거부한 뒤 요청 수명 주기를 기록합니다. 여기서 `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST /v1/images/edits` (Codex 내장 `image_gen` 도구용 — `server/images.ts`가 OpenAI 계열 업스트림으로 중계), `POST /v1/live` / `POST /v1/realtime/calls`(ChatGPT / Codex App 음성 및 OpenAI Realtime 호출 생성, `server/live.ts`가 중계)와 `/v1/live/{callId}` 사이드밴드 WebSocket, 그리고 `/v1/responses`의 선택적 WebSocket 업그레이드를 제공합니다. -2. `server/responses/core.ts`가 압축을 풀고 JSON을 읽습니다. 기억해 둔 `previous_response_id` 입력이 있으면 +2. `server/responses/request-prepare.ts`가 압축을 풀고 JSON을 읽습니다. 기억해 둔 `previous_response_id` 입력이 있으면 펼친 다음 `responses/parser.ts`로 넘깁니다. 3. `router.ts`가 일반 모델 id 또는 `provider/model` id를 해석합니다. 이어서 Codex 계정 affinity를 결정하고, 필요하면 프로바이더 OAuth를 갱신해 선택된 자격 증명을 route에 적용합니다. @@ -61,7 +65,7 @@ HTTP 경계는 `server/index.ts`가 맡고, Responses 데이터 플레인은 `se 나머지 변환형 어댑터는 업스트림 요청을 build/fetch/parse합니다. 6. 라우팅 모델이 호스티드 `web_search`를 요청하면 `web-search/`가 합성 함수를 노출합니다. 실제 검색은 ChatGPT 사이드카로 실행하고 결과를 라우팅 모델에 다시 넣으며, 설정된 횟수 안에서 반복합니다. -7. `bridge.ts`가 Responses SSE 또는 JSON을 만듭니다. `server/request-log.ts`와 `usage/`는 응답을 +7. `bridge/sse.ts` / `bridge/response-json.ts`가 Responses SSE 또는 JSON을 만듭니다. `server/request-log.ts`와 `usage/`는 응답을 건드리지 않은 채 종료 상태, 지연 시간, 프로바이더/모델, 최선 추정 토큰 사용량을 기록합니다. ## 파서 @@ -83,7 +87,7 @@ HTTP 경계는 `server/index.ts`가 맡고, Responses 데이터 플레인은 `se ## 브리지 -`bridge.ts`는 어댑터의 내부 `AdapterEvent` 스트림을 Codex가 이해하는 Responses SSE로 다시 +`bridge/sse.ts`는 어댑터의 내부 `AdapterEvent` 스트림을 Codex가 이해하는 Responses SSE로 다시 변환합니다: | AdapterEvent | Responses SSE emitted | @@ -114,7 +118,7 @@ Responses 항목 타입으로 구분됩니다 — 따라서 MCP 네임스페이 ## 전송과 compaction -`server/index.ts`는 기본적으로 `/v1/responses`를 HTTP/SSE로 제공합니다. `websockets`가 `false`인 +`server/index/serve-options.ts`는 기본적으로 `/v1/responses`를 HTTP/SSE로 제공합니다. `websockets`가 `false`인 상태에서 Codex가 Responses WebSocket 업그레이드를 시도하면 opencodex는 `426 upgrade_required`를 반환하고, Codex는 해당 세션에서 HTTP로 폴백합니다. `"websockets": true`가 설정되면 같은 엔드포인트가 업그레이드를 받아들이고 WebSocket 브리지를 사용합니다. @@ -138,7 +142,7 @@ Lite 정책을 유지합니다. 네이티브 메타데이터 형식이 잘못된 Codex 컨텍스트 compaction은 라우팅된 모델에서도 동작합니다. `server/responses/compact.ts`는 `POST /v1/responses/compact`를 내부 라우팅 요약 턴으로 처리해 압축된 히스토리를 반환합니다. -`responses/parser.ts`와 `bridge.ts`는 remote compaction v2의 `compaction_trigger` 턴을 처리해 +`responses/parser.ts`와 `bridge/sse.ts`는 remote compaction v2의 `compaction_trigger` 턴을 처리해 합성 `compaction` 출력 항목을 정확히 하나 내보냅니다. ## 캐싱과 카탈로그 diff --git a/docs-site/src/content/docs/reference/architecture.md b/docs-site/src/content/docs/reference/architecture.md index a9bdf48978..c04f647b72 100644 --- a/docs-site/src/content/docs/reference/architecture.md +++ b/docs-site/src/content/docs/reference/architecture.md @@ -23,7 +23,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -34,17 +35,19 @@ src/ └── index.ts # public entry ``` -Three formerly large entry files now preserve compatibility as facades: `codex/catalog.ts` exports -the seven focused `codex/catalog/*.ts` modules, `server/management-api.ts` dispatches to the nine -`server/management/*.ts` modules, and `server/responses.ts` exports the five -`server/responses/*.ts` modules. +Several formerly large entry files now preserve compatibility as facades: `codex/catalog.ts` exports +its focused `codex/catalog/*.ts` modules, `server/management-api.ts` dispatches to +`server/management/*.ts`, `server/responses.ts` exports `server/responses/*.ts`, and `bridge.ts` +re-exports `bridge/*.ts`. A facade is the stable import path, not the implementation: each step +below names the module that owns the code, and `structure/transports/responses.md` carries the +full owner inventory for the Responses surface. ## Request flow -`server/index.ts` owns the HTTP boundary and delegates the Responses data plane to +`server/index/serve-options.ts` owns the HTTP boundary and delegates the Responses data plane to the `server/responses.ts` facade and its `server/responses/*.ts` modules: -1. `server/index.ts` applies CORS and API authentication, rejects new work while draining, and +1. `server/index/serve-options.ts` applies CORS and API authentication, rejects new work while draining, and records request lifecycle metadata. It serves `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST /v1/images/edits` (relayed to an OpenAI-family upstream by `server/images.ts` for codex's built-in `image_gen` @@ -52,7 +55,7 @@ the `server/responses.ts` facade and its `server/responses/*.ts` modules: Realtime call-create, relayed by `server/live.ts`), sideband WebSocket joins on `/v1/live/{callId}` (and `/v1/realtime?call_id=`), and the optional WebSocket upgrade on `/v1/responses`. -2. `server/responses/core.ts` decompresses and parses JSON, expands locally remembered +2. `server/responses/request-prepare.ts` decompresses and parses JSON, expands locally remembered `previous_response_id` input when available, then calls `responses/parser.ts`. 3. `router.ts` resolves a bare or `provider/model` id. The server then resolves Codex account affinity, refreshes provider OAuth when needed, and applies the selected credential to the route. @@ -65,7 +68,7 @@ the `server/responses.ts` facade and its `server/responses/*.ts` modules: executes the real search through the configured backend (the OpenAI/ChatGPT sidecar or Anthropic), feeds results back to the routed model, and repeats within the configured loop limit. This loop supports only the standard HTTP path; adapters that implement `runTurn`, such as Cursor, bypass it. -7. `bridge.ts` produces Responses SSE or JSON. `server/request-log.ts` and `usage/` collect terminal +7. `bridge/sse.ts` / `bridge/response-json.ts` produces Responses SSE or JSON. `server/request-log.ts` and `usage/` collect terminal status, latency, provider/model labels, and best-effort token usage without changing the response. ## The parser @@ -86,7 +89,7 @@ the `server/responses.ts` facade and its `server/responses/*.ts` modules: ## The bridge -`bridge.ts` turns the adapter's internal `AdapterEvent` stream back into Responses SSE that Codex +`bridge/sse.ts` turns the adapter's internal `AdapterEvent` stream back into Responses SSE that Codex understands: | AdapterEvent | Responses SSE emitted | @@ -138,7 +141,7 @@ diagnostics. ## Transport and compaction -`server/index.ts` serves HTTP/SSE on `/v1/responses` by default. If Codex attempts a Responses +`server/index/serve-options.ts` serves HTTP/SSE on `/v1/responses` by default. If Codex attempts a Responses WebSocket upgrade while `websockets` is `false`, opencodex returns `426 upgrade_required`; Codex then falls back to HTTP for that session. When `"websockets": true` is set, the same endpoint accepts the upgrade and uses the WebSocket bridge. @@ -174,7 +177,7 @@ retry after compaction. Non-streaming API callers continue to receive the provid Codex context compaction works for routed models. `server/responses/compact.ts` handles `POST /v1/responses/compact` by running an internal routed summarization turn and returning compacted -history, while `responses/parser.ts` and `bridge.ts` handle remote compaction v2 +history, while `responses/parser.ts` and `bridge/sse.ts` handle remote compaction v2 `compaction_trigger` turns by emitting exactly one synthetic `compaction` output item. ## Caching & the catalog diff --git a/docs-site/src/content/docs/ru/reference/architecture.md b/docs-site/src/content/docs/ru/reference/architecture.md index cd3f776efb..43db27e8fb 100644 --- a/docs-site/src/content/docs/ru/reference/architecture.md +++ b/docs-site/src/content/docs/ru/reference/architecture.md @@ -24,7 +24,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -35,17 +36,20 @@ src/ └── index.ts # public entry ``` -Три прежних крупных входных файла теперь служат фасадами совместимости: `codex/catalog.ts` -экспортирует семь модулей `codex/catalog/*.ts`, `server/management-api.ts` направляет запросы в -девять модулей `server/management/*.ts`, а `server/responses.ts` экспортирует пять модулей -`server/responses/*.ts`. +Прежние крупные входные файлы теперь служат фасадами совместимости: `codex/catalog.ts` +экспортирует модули `codex/catalog/*.ts`, `server/management-api.ts` направляет запросы в +модули `server/management/*.ts`, `server/responses.ts` экспортирует модули +`server/responses/*.ts`, а `bridge.ts` реэкспортирует модули `bridge/*.ts`. Фасад — это +стабильный путь импорта, а не реализация: каждый шаг ниже называет модуль, которому +принадлежит код, а полный перечень владельцев поверхности Responses находится в +`structure/transports/responses.md`. ## Поток запроса -`server/index.ts` владеет HTTP-границей и делегирует плоскость данных Responses в +`server/index/serve-options.ts` владеет HTTP-границей и делегирует плоскость данных Responses в фасад `server/responses.ts` и его модули `server/responses/*.ts`: -1. `server/index.ts` применяет CORS и аутентификацию API, отклоняет новую работу во время +1. `server/index/serve-options.ts` применяет CORS и аутентификацию API, отклоняет новую работу во время завершения (drain) и записывает метаданные жизненного цикла запроса. Он обслуживает `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST /v1/images/edits` @@ -54,7 +58,7 @@ src/ (создание голосового/Realtime-вызова ChatGPT / Codex App, ретранслируется `server/live.ts`), sideband WebSocket на `/v1/live/{callId}`, а также необязательный WebSocket-апгрейд на `/v1/responses`. -2. `server/responses/core.ts` распаковывает и парсит JSON, разворачивает локально запомненный вход +2. `server/responses/request-prepare.ts` распаковывает и парсит JSON, разворачивает локально запомненный вход `previous_response_id`, когда он доступен, затем вызывает `responses/parser.ts`. 3. `router.ts` разрешает «голый» id или id вида `provider/model`. Затем сервер определяет привязку (affinity) аккаунта Codex, при необходимости обновляет OAuth провайдера и применяет @@ -70,7 +74,7 @@ src/ предоставляет синтетическую функцию, выполняет настоящий поиск через сайдкар ChatGPT, возвращает результаты маршрутизируемой модели и повторяет это в пределах настроенного лимита цикла. -7. `bridge.ts` формирует Responses SSE или JSON. `server/request-log.ts` и `usage/` собирают +7. `bridge/sse.ts` / `bridge/response-json.ts` формирует Responses SSE или JSON. `server/request-log.ts` и `usage/` собирают итоговый статус, задержку, метки провайдера/модели и оценку использования токенов, не изменяя ответ. @@ -95,7 +99,7 @@ src/ ## Мост -`bridge.ts` превращает поток внутренних событий `AdapterEvent` адаптера обратно в Responses SSE, +`bridge/sse.ts` превращает поток внутренних событий `AdapterEvent` адаптера обратно в Responses SSE, понятный Codex: | AdapterEvent | Responses SSE emitted | @@ -146,7 +150,7 @@ loopback; настроенные записи `corsAllowOrigins` расширя ## Транспорт и compaction -`server/index.ts` по умолчанию обслуживает HTTP/SSE на `/v1/responses`. Если Codex пытается +`server/index/serve-options.ts` по умолчанию обслуживает HTTP/SSE на `/v1/responses`. Если Codex пытается выполнить WebSocket-апгрейд Responses, пока `websockets` равно `false`, opencodex возвращает `426 upgrade_required`; Codex тогда откатывается на HTTP для этой сессии. Когда установлено `"websockets": true`, та же конечная точка принимает апгрейд и использует WebSocket-мост. @@ -162,7 +166,7 @@ loopback; настроенные записи `corsAllowOrigins` расширя Compaction контекста Codex работает для маршрутизируемых моделей. `server/responses/compact.ts` обрабатывает `POST /v1/responses/compact`, выполняя внутренний маршрутизируемый ход суммаризации -и возвращая сжатую историю, а `responses/parser.ts` и `bridge.ts` обрабатывают ходы +и возвращая сжатую историю, а `responses/parser.ts` и `bridge/sse.ts` обрабатывают ходы `compaction_trigger` из remote compaction v2, генерируя ровно один синтетический выходной элемент `compaction`. diff --git a/docs-site/src/content/docs/tr/reference/architecture.md b/docs-site/src/content/docs/tr/reference/architecture.md index 5dd9b99957..f3350af415 100644 --- a/docs-site/src/content/docs/tr/reference/architecture.md +++ b/docs-site/src/content/docs/tr/reference/architecture.md @@ -24,7 +24,8 @@ src/ ├── vision/ # vizyon sidecar'ı (açıklama + plan) ├── config.ts # ~/.opencodex/config.json, varsayılanlar, PID, ortam çözümleme ├── router.ts # model kimliği → sağlayıcı + adaptör -├── bridge.ts # AdapterEvent akışı → Responses SSE / JSON +├── bridge.ts # bridge/ üzerinde cephe +├── bridge/ # AdapterEvent akışı → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # akıl yürütme çabası çevirisi, sabitleme ve katalog seviyeleri ├── responses/ │ ├── parser.ts # Responses isteği → OcxParsedRequest @@ -35,19 +36,22 @@ src/ └── index.ts # genel giriş noktası ``` -Eskiden büyük olan üç giriş dosyası artık cepheler (facades) olarak uyumluluğu -korur: `codex/catalog.ts` odaklanmış yedi `codex/catalog/*.ts` modülünü dışa -aktarır, `server/management-api.ts` dokuz `server/management/*.ts` modülüne -dağıtır ve `server/responses.ts` beş `server/responses/*.ts` modülünü dışa -aktarır. +Eskiden büyük olan giriş dosyaları artık cepheler (facades) olarak uyumluluğu +korur: `codex/catalog.ts` `codex/catalog/*.ts` modüllerini dışa aktarır, +`server/management-api.ts` `server/management/*.ts` modüllerine dağıtır, +`server/responses.ts` `server/responses/*.ts` modüllerini dışa aktarır ve `bridge.ts` +`bridge/*.ts` modüllerini yeniden dışa aktarır. Cephe, uygulamanın kendisi değil +kararlı içe aktarma yoludur: aşağıdaki her adım kodun sahibi olan modülü +adlandırır ve Responses yüzeyinin tam sahiplik envanteri +`structure/transports/responses.md` dosyasındadır. ## İstek akışı -`server/index.ts` HTTP sınırına sahiptir ve Responses veri düzlemini +`server/index/serve-options.ts` HTTP sınırına sahiptir ve Responses veri düzlemini `server/responses.ts` cephesine ve onun `server/responses/*.ts` modüllerine devreder: -1. `server/index.ts` CORS ve API kimlik doğrulamasını uygular, boşaltma +1. `server/index/serve-options.ts` CORS ve API kimlik doğrulamasını uygular, boşaltma sırasında yeni işleri reddeder ve istek yaşam döngüsü meta verilerini kaydeder. `GET /v1/models`, `POST /v1/responses`, `POST /v1/responses/compact`, `POST /v1/images/generations` / `POST @@ -58,7 +62,7 @@ devreder: `/v1/live/{callId}` (ve `/v1/realtime?call_id=`) üzerindeki yan bant WebSocket katılımlarını ve `/v1/responses` üzerindeki isteğe bağlı WebSocket yükseltmesini sunar. -2. `server/responses/core.ts` JSON'ı açar ve ayrıştırır, kullanılabilir +2. `server/responses/request-prepare.ts` JSON'ı açar ve ayrıştırır, kullanılabilir olduğunda yerel olarak hatırlanan `previous_response_id` girdisini genişletir, ardından `responses/parser.ts`'yi çağırır. 3. `router.ts` yalın veya `sağlayıcı/model` kimliğini çözer. Sunucu daha sonra @@ -75,7 +79,7 @@ devreder: `web-search/` sentetik bir fonksiyon sunar, gerçek aramayı ChatGPT sidecar'ı aracılığıyla yürütür, sonuçları yönlendirilen modele geri besler ve yapılandırılmış döngü sınırı içinde tekrarlar. -7. `bridge.ts` Responses SSE veya JSON üretir. `server/request-log.ts` ve +7. `bridge/sse.ts` / `bridge/response-json.ts` Responses SSE veya JSON üretir. `server/request-log.ts` ve `usage/` yanıtı değiştirmeden uç durumu, gecikmeyi, sağlayıcı/model etiketlerini ve en iyi çaba belirteç kullanımını toplar. @@ -102,7 +106,7 @@ ardından bir `OcxParsedRequest` oluşturur: ## Köprü (Bridge) -`bridge.ts`, adaptörün dahili `AdapterEvent` akışını Codex'in anladığı Responses +`bridge/sse.ts`, adaptörün dahili `AdapterEvent` akışını Codex'in anladığı Responses SSE'ye dönüştürür: | AdapterEvent | Yayınlanan Responses SSE | @@ -164,7 +168,7 @@ tanılamaları için `usage/` tarafından toplanır. ## Aktarım ve sıkıştırma -`server/index.ts` varsayılan olarak `/v1/responses` üzerinde HTTP/SSE sunar. +`server/index/serve-options.ts` varsayılan olarak `/v1/responses` üzerinde HTTP/SSE sunar. Codex `websockets` `false` iken bir Responses WebSocket yükseltmesi denerse opencodex `426 upgrade_required` döndürür; Codex daha sonra bu oturum için HTTP'ye geri döner. `"websockets": true` ayarlandığında aynı uç nokta @@ -182,7 +186,7 @@ değiştirilmeden HTTP'ye geri dönülmeye devam edilir. Codex bağlam sıkıştırması yönlendirilen modeller için çalışır. `server/responses/compact.ts`, dahili bir yönlendirilen özetleme turu çalıştırarak ve sıkıştırılmış geçmişi döndürerek `POST /v1/responses/compact`'ı -işlerken, `responses/parser.ts` ve `bridge.ts` tam olarak bir sentetik +işlerken, `responses/parser.ts` ve `bridge/sse.ts` tam olarak bir sentetik `compaction` çıktı öğesi yayarak uzak sıkıştırma v2 `compaction_trigger` turlarını işler. diff --git a/docs-site/src/content/docs/zh-cn/reference/architecture.md b/docs-site/src/content/docs/zh-cn/reference/architecture.md index b1edbd1e8b..8bf59e184b 100644 --- a/docs-site/src/content/docs/zh-cn/reference/architecture.md +++ b/docs-site/src/content/docs/zh-cn/reference/architecture.md @@ -23,7 +23,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -34,24 +35,26 @@ src/ └── index.ts # public entry ``` -原先的三个大型入口文件现在是兼容性 facade:`codex/catalog.ts` 导出 7 个 -`codex/catalog/*.ts` 模块,`server/management-api.ts` 分派到 9 个 -`server/management/*.ts` 模块,而 `server/responses.ts` 导出 5 个 -`server/responses/*.ts` 模块。 +原先的大型入口文件现在是兼容性 facade:`codex/catalog.ts` 导出 +`codex/catalog/*.ts` 模块,`server/management-api.ts` 分派到 +`server/management/*.ts` 模块,`server/responses.ts` 导出 `server/responses/*.ts` +模块,而 `bridge.ts` 重新导出 `bridge/*.ts` 模块。facade 只是稳定的导入路径,而不是实现: +下面每一步都指向真正拥有代码的模块,Responses 面的完整归属清单见 +`structure/transports/responses.md`。 ## 请求流程 -`server/index.ts` 负责 HTTP 边界,并把 Responses data plane 交给 `server/responses.ts` facade +`server/index/serve-options.ts` 负责 HTTP 边界,并把 Responses data plane 交给 `server/responses.ts` facade 及其 `server/responses/*.ts` 模块: -1. `server/index.ts` 应用 CORS 和 API 认证,在 drain 期间拒绝新请求,并记录请求生命周期 +1. `server/index/serve-options.ts` 应用 CORS 和 API 认证,在 drain 期间拒绝新请求,并记录请求生命周期 metadata。它提供 `GET /v1/models`、`POST /v1/responses`、 `POST /v1/responses/compact`、`POST /v1/images/generations` / `POST /v1/images/edits` (供 Codex 内置 `image_gen` 工具使用——由 `server/images.ts` 中继到 OpenAI 系上游)、 `POST /v1/live` / `POST /v1/realtime/calls`(ChatGPT / Codex App 语音与 OpenAI Realtime 建连,由 `server/live.ts` 中继)、`/v1/live/{callId}` 旁路 WebSocket, 以及 `/v1/responses` 上可选的 WebSocket upgrade。 -2. `server/responses/core.ts` 解压并解析 JSON;如果本地记住了对应输入,则展开 +2. `server/responses/request-prepare.ts` 解压并解析 JSON;如果本地记住了对应输入,则展开 `previous_response_id`,随后调用 `responses/parser.ts`。 3. `router.ts` 解析 bare id 或 `provider/model` id。server 随后确定 Codex account affinity, 必要时刷新 provider OAuth,并把选中的 credential 应用到 route。 @@ -62,7 +65,7 @@ src/ 则构建、获取并解析上游请求。 6. 路由模型请求托管的 `web_search` 工具时,`web-search/` 会暴露一个合成函数,经 ChatGPT sidecar 执行真实搜索,把结果送回路由模型,并在配置的循环上限内重复。 -7. `bridge.ts` 生成 Responses SSE 或 JSON。`server/request-log.ts` 与 `usage/` 在不改变响应的 +7. `bridge/sse.ts` / `bridge/response-json.ts` 生成 Responses SSE 或 JSON。`server/request-log.ts` 与 `usage/` 在不改变响应的 前提下收集终止状态、延迟、provider/model 标签和尽力估算的 token usage。 ## 解析器 @@ -85,7 +88,7 @@ src/ ## 桥接器 -`bridge.ts` 把 adapter 的内部 `AdapterEvent` 流转换回 Codex 能理解的 Responses SSE: +`bridge/sse.ts` 把 adapter 的内部 `AdapterEvent` 流转换回 Codex 能理解的 Responses SSE: | AdapterEvent | 发出的 Responses SSE | | --- | --- | @@ -129,7 +132,7 @@ thread affinity 位于 `codex/` 下,不会出现在管理 API 响应中。请 ## 传输与 compaction -`server/index.ts` 默认在 `/v1/responses` 上提供 HTTP/SSE。当 `websockets` 为 `false` 而 Codex +`server/index/serve-options.ts` 默认在 `/v1/responses` 上提供 HTTP/SSE。当 `websockets` 为 `false` 而 Codex 尝试 Responses WebSocket upgrade 时,opencodex 会返回 `426 upgrade_required`,Codex 随后在该 session 中回退到 HTTP。设置 `"websockets": true` 后,同一 endpoint 会接受 upgrade 并使用 WebSocket bridge。 @@ -143,7 +146,7 @@ WebSocket bridge。 Codex context compaction 同样适用于路由模型。`server/responses/compact.ts` 处理 `POST /v1/responses/compact`,运行一次内部路由 summarization turn 并返回压缩后的历史; -`responses/parser.ts` 与 `bridge.ts` 则处理 remote compaction v2 的 `compaction_trigger` turn, +`responses/parser.ts` 与 `bridge/sse.ts` 则处理 remote compaction v2 的 `compaction_trigger` turn, 准确发出一个合成的 `compaction` 输出 item。 ## 缓存与目录 diff --git a/docs-site/src/content/docs/zh-tw/reference/architecture.md b/docs-site/src/content/docs/zh-tw/reference/architecture.md index be0b2c5003..cb246c8bd0 100644 --- a/docs-site/src/content/docs/zh-tw/reference/architecture.md +++ b/docs-site/src/content/docs/zh-tw/reference/architecture.md @@ -23,7 +23,8 @@ src/ ├── vision/ # vision sidecar (describe + plan) ├── config.ts # ~/.opencodex/config.json, defaults, PID, env resolution ├── router.ts # model id → provider + adapter -├── bridge.ts # AdapterEvent stream → Responses SSE / JSON +├── bridge.ts # facade over bridge/ +├── bridge/ # AdapterEvent stream → Responses SSE (sse.ts) / JSON (response-json.ts) ├── reasoning-effort.ts # reasoning-effort translation, clamping, and catalog levels ├── responses/ │ ├── parser.ts # Responses request → OcxParsedRequest @@ -34,24 +35,26 @@ src/ └── index.ts # public entry ``` -原先的三個大型入口檔案現在是相容性 facade:`codex/catalog.ts` 匯出 7 個 -`codex/catalog/*.ts` 模組,`server/management-api.ts` 分派到 9 個 -`server/management/*.ts` 模組,而 `server/responses.ts` 匯出 5 個 -`server/responses/*.ts` 模組。 +原先的大型入口檔案現在是相容性 facade:`codex/catalog.ts` 匯出 +`codex/catalog/*.ts` 模組,`server/management-api.ts` 分派到 +`server/management/*.ts` 模組,`server/responses.ts` 匯出 `server/responses/*.ts` +模組,而 `bridge.ts` 重新匯出 `bridge/*.ts` 模組。facade 只是穩定的匯入路徑,而不是實作: +下面每一步都指向真正擁有程式碼的模組,Responses 面的完整歸屬清單見 +`structure/transports/responses.md`。 ## 請求流程 -`server/index.ts` 負責 HTTP 邊界,並把 Responses data plane 交給 `server/responses.ts` facade +`server/index/serve-options.ts` 負責 HTTP 邊界,並把 Responses data plane 交給 `server/responses.ts` facade 及其 `server/responses/*.ts` 模組: -1. `server/index.ts` 應用 CORS 和 API 認證,在 drain 期間拒絕新請求,並記錄請求生命週期 +1. `server/index/serve-options.ts` 應用 CORS 和 API 認證,在 drain 期間拒絕新請求,並記錄請求生命週期 metadata。它提供 `GET /v1/models`、`POST /v1/responses`、 `POST /v1/responses/compact`、`POST /v1/images/generations` / `POST /v1/images/edits` (供 Codex 內建 `image_gen` 工具使用——由 `server/images.ts` 中繼到 OpenAI 繫上遊)、 `POST /v1/live` / `POST /v1/realtime/calls`(ChatGPT / Codex App 語音與 OpenAI Realtime 建連,由 `server/live.ts` 中繼)、`/v1/live/{callId}` 旁路 WebSocket, 以及 `/v1/responses` 上可選的 WebSocket upgrade。 -2. `server/responses/core.ts` 解壓並解析 JSON;如果本機記住了對應輸入,則展開 +2. `server/responses/request-prepare.ts` 解壓並解析 JSON;如果本機記住了對應輸入,則展開 `previous_response_id`,隨後呼叫 `responses/parser.ts`。 3. `router.ts` 解析 bare id 或 `provider/model` id。server 隨後確定 Codex account affinity, 必要時重新整理 provider OAuth,並把選中的 credential 應用到 route。 @@ -62,7 +65,7 @@ src/ 則建置、取得並解析上游請求。 6. 路由模型請求託管的 `web_search` 工具時,`web-search/` 會暴露一個合成函式,經 ChatGPT sidecar 執行真實搜尋,把結果送回路由模型,並在設定的迴圈上限內重複。 -7. `bridge.ts` 生成 Responses SSE 或 JSON。`server/request-log.ts` 與 `usage/` 在不改變回應的 +7. `bridge/sse.ts` / `bridge/response-json.ts` 生成 Responses SSE 或 JSON。`server/request-log.ts` 與 `usage/` 在不改變回應的 前提下收集終止狀態、延遲、provider/model 標籤和盡力估算的 token usage。 ## 解析器 @@ -85,7 +88,7 @@ src/ ## 橋接器 -`bridge.ts` 把 adapter 的內部 `AdapterEvent` 流轉換回 Codex 能理解的 Responses SSE: +`bridge/sse.ts` 把 adapter 的內部 `AdapterEvent` 流轉換回 Codex 能理解的 Responses SSE: | AdapterEvent | 發出的 Responses SSE | | --- | --- | @@ -129,7 +132,7 @@ thread affinity 位於 `codex/` 下,不會出現在管理 API 回應中。請 ## 傳輸與 compaction -`server/index.ts` 預設在 `/v1/responses` 上提供 HTTP/SSE。當 `websockets` 為 `false` 而 Codex +`server/index/serve-options.ts` 預設在 `/v1/responses` 上提供 HTTP/SSE。當 `websockets` 為 `false` 而 Codex 嘗試 Responses WebSocket upgrade 時,opencodex 會回傳 `426 upgrade_required`,Codex 隨後在該 session 中回退到 HTTP。設定 `"websockets": true` 後,同一 endpoint 會接受 upgrade 並使用 WebSocket bridge。 @@ -144,7 +147,7 @@ WebSocket bridge。 Codex context compaction 同樣適用於路由模型。`server/responses/compact.ts` 處理 `POST /v1/responses/compact`,執行一次內部路由 summarization turn 並回傳壓縮後的歷史; -`responses/parser.ts` 與 `bridge.ts` 則處理 remote compaction v2 的 `compaction_trigger` turn, +`responses/parser.ts` 與 `bridge/sse.ts` 則處理 remote compaction v2 的 `compaction_trigger` turn, 準確發出一個合成的 `compaction` 輸出 item。 ## 快取與目錄 diff --git a/structure/runtime.md b/structure/runtime.md index 40fe7301ae..695985f22f 100644 --- a/structure/runtime.md +++ b/structure/runtime.md @@ -49,7 +49,7 @@ The prefilter is only an optimization, not final process-membership authority. | `bin/ocx.mjs` | Published npm `bin` entry (Node shim). Resolves the bundled or explicit Bun binary before project dotenv can load, stamps its runtime provenance plus a proof-bound Anthropic parent-env snapshot, lazy-runs `bun/install.js` if only the placeholder stub is present, then execs `src/cli/index.ts` under Bun. Lets `npm install -g` work without a separately-installed Bun. The exact `system codex-cli-update` inspection namespace skips both boot repair and lazy Bun installation; missing runtime support fails closed instead of mutating state. | | `src/lib/bun-runtime.ts` | Bundled-Bun resolution: `isRealBunBinary()` (size gate vs the ~450-byte placeholder stub), `bundledBunPath()`, and `durableBunPath()` (path baked into service/shim artifacts). Durable selection accepts only the source/path pair already stamped for the running executable; it never re-reads a project-dotenv `OPENCODEX_BUN_PATH`. | | `src/cli/index.ts` | `ocx` / `opencodex` CLI. Lifecycle: init, start, stop, restart, status, sync, restore/eject, gui, service, update. `restart` refuses an in-place restart requested by a CLI whose version differs from the attested `/healthz` version, because the replacement respawns from the live installation; placeholder versions (unknown/0.0.0) stay incomparable and keep the restart path. Configuration: provider, account, models, combo/route, access, integrations, v2. Client launchers: Claude, OpenCode, MiniMax Code, and MiniMax CLI text. The MMX launcher owns a child-lifetime loopback path bridge from the client's hard-coded `/anthropic/v1/messages` path to the canonical `/v1/messages` data plane; the server does not expose an extra auth surface. Diagnostics: doctor, debug, observe, health. Windows adds tray. The full command surface is `src/cli/help.ts`; this table names the groups, not every verb. After help/version early exits, ordinary commands run the bounded best-effort Codex-shim auto-restore policy before dispatch. `system codex-cli-update` is the deliberate read-only exception and suppresses auto-restore for its whole namespace, including malformed invocations. Keeps the `#!/usr/bin/env bun` shebang for from-source dev (`bun run src/cli/index.ts`). | -| `src/server/index.ts` | Bun server entrypoint: `startServer`, `/v1/responses` HTTP + WebSocket routing (compact handled before generic Responses), exact `POST /v1/images/generations` and `POST /v1/images/edits` routing, `/v1/models`, the Anthropic-shaped `/v1/messages` and OpenAI-shaped `/v1/chat/completions` compatibility surfaces, the Live/Realtime surface, the hosted-search relay, artifact serving, `/healthz`, the `/api/*` auth gate, the `/v1/*` JSON 404 guard, GUI fallback, the opt-in loopback-only hub-management listener, and facade re-exports for split server modules. | +| `src/server/index.ts` | Bun server entrypoint: `startServer`, `/v1/responses` HTTP + WebSocket routing (compact handled before generic Responses), exact `POST /v1/images/generations` and `POST /v1/images/edits` routing, `/v1/models`, the Anthropic-shaped `/v1/messages` and OpenAI-shaped `/v1/chat/completions` compatibility surfaces, the Live/Realtime surface, the hosted-search relay, artifact serving, `/healthz`, the `/api/*` auth gate, the `/v1/*` JSON 404 guard, GUI fallback, the opt-in loopback-only hub-management listener, and facade re-exports for split server modules. The route table itself is built by `src/server/index/serve-options.ts`; this entry file owns the listener and the startup transaction. | | `src/server/images.ts` | Standalone Images data plane: default OpenAI or explicit custom-provider selection, Codex account affinity, bounded opaque request relay, single-attempt upstream fetch, pool health recording, and safe response/cancellation relay. | | `src/server/audio-transcriptions.ts` | Standalone multipart transcription; audio-specific key admission, bounded upload/response, stored OpenAI credential resolution and lease-bound cancellation. See [audio contracts](data-planes/inbound-compat.md#standalone-file-transcription). | | `src/server/audio-live.ts`, `src/server/audio-dictation.ts` | External voice/dictation orchestration using the existing bounded socket relay, server-owned credentials, cancellation and opaque call ownership. See [streaming audio](data-planes/inbound-compat.md#streaming-audio). | @@ -80,8 +80,10 @@ there. Feature code is grouped by responsibility: `src/generated/` is build output committed for the runtime; it is not edited by hand. -`src/server/` is split by responsibility: `index.ts` owns the listener and route ordering; -`responses.ts` owns Responses handling and compaction; `images.ts` owns the standalone Images relay; +`src/server/` is split by responsibility: `index.ts` owns the listener and the startup transaction +while `index/serve-options.ts` owns route ordering; `responses.ts` and `responses/core.ts` compose +Responses handling from the owners inventoried in [Responses transport](transports/responses.md), +and `responses/compact.ts` owns compaction; `images.ts` owns the standalone Images relay; `responses/codex-auth-error.ts` owns the shared Responses/compact Codex auth-context HTTP mapping. Model entitlement denial is a 400 request error and temporary exhaustion of every model-capable account is a retryable 429; neither is reported as an invalid API key. Images, Live, and Search @@ -216,8 +218,9 @@ The server exposes `POST /api/stop` which restores native Codex config, stops an | `src/adapters/image.ts`, `src/adapters/anthropic-image-guard.ts`, `src/adapters/anthropic-image-normalize.ts`, `src/adapters/anthropic-image-codec.ts` | Image conversion for adapter ingress and Anthropic-specific normalization/limits. An image's ladder position is pinned to its own identity (content hash + media type), so appending a newer image cannot re-encode older ones and bust Anthropic's prompt prefix cache (#4532). | | `src/adapters/run-turn-queue.ts`, `src/adapters/tool-catalog-nudge.ts`, `src/adapters/identity.ts`, `src/adapters/upstream-http-error.ts` | Shared adapter execution support: turn queueing, tool-catalog nudging, client identity, upstream error normalization. | -Adapter output must stay in internal `AdapterEvent` form until `bridge.ts` converts it back to -Responses SSE or WebSocket frames. +Adapter output must stay in internal `AdapterEvent` form until `src/bridge/sse.ts` converts it back +to Responses SSE or WebSocket frames, or `src/bridge/response-json.ts` buffers it into a JSON +response. `src/bridge.ts` is the compatibility facade that re-exports both. The image/video loop bounds each hidden iteration before replay or fulfillment; see [media iteration retention](transports/inventory.md#media-iteration-retention). @@ -265,7 +268,7 @@ The shared Responses path follows the [bounded multipart recovery contract](suba ### Hosted-search continuation binding -The opt-in key-auth Responses hosted-search bridge in `src/server/responses/core.ts` captures the +The opt-in key-auth Responses hosted-search bridge in `src/server/responses/passthrough-delivery.ts` captures the request binding that served the first leg, after any permitted initial reselection. Before every continuation dispatch, after provider pacing, that binding must remain an API-key selection matching the configured entry, reference, revision, resolved key, authentication mode, and base URL; a @@ -357,7 +360,7 @@ The shared atomic replacement publisher also identifies explicit Remote Workspac Remote Workspace uses a separate, explicitly enabled server surface with structural WebSocket callbacks and awaited per-server cleanup; [its contract](remote-workspace.md) owns that integration. -Chat helper admission in `src/server/responses/core.ts` follows the +Chat helper admission in `src/server/responses/request-sidecar-auth.ts` follows the [deferred stored-main contract](providers/openai-tiers.md): only a needed Direct OpenAI helper claims stored main, after terminal vision, routed vision and search exclusions. @@ -393,7 +396,7 @@ Responses route normalization resolves provider summary defaults from the origin ## Live sideband handshake -`src/server/index.ts` establishes the authorized upstream live sideband before accepting the client WebSocket upgrade. `openLiveSidebandUpstream` bounds the handshake to ten seconds and retains at most 32 frames and 1 MiB of preamble within the frame limit. `src/server/ws-bridge.ts` defines the runtime handoff carrying captured frames or terminal state. Failed handshakes return 502/504 and client cancellation returns 499; exact upstream 404/410 status is unavailable from Bun's client WebSocket. Admission ownership lasts until upstream close/CLOSED, including failed upgrades and failed attachment. The ordinary Responses WebSocket exchange remains separate. +`src/server/index/serve-options.ts` establishes the authorized upstream live sideband before accepting the client WebSocket upgrade, and `src/server/index/live-sideband.ts` implements the bounded upstream dial. `openLiveSidebandUpstream` bounds the handshake to ten seconds and retains at most 32 frames and 1 MiB of preamble within the frame limit. `src/server/ws-bridge.ts` defines the runtime handoff carrying captured frames or terminal state. Failed handshakes return 502/504 and client cancellation returns 499; exact upstream 404/410 status is unavailable from Bun's client WebSocket. Admission ownership lasts until upstream close/CLOSED, including failed upgrades and failed attachment. The ordinary Responses WebSocket exchange remains separate. The relay is transparent in both directions, and that includes the close: a downstream client's close code and reason are carried to the upstream through `clientCloseForUpstream`, which only substitutes 1000 for a code no endpoint may send and truncates the reason to the 123-byte control-frame limit. This matters to the caller, because a Frameless v3 client reads upstream 1000 as the session completing and any other code as a transport loss to reconnect.