Die Codex-app-server-Integration
Wie der Desktop den Codex-Kindprozess startet, steuert und überwacht: die JSON-RPC-Pipe, der Handshake, Zeitlimits, Benachrichtigungen und Freigaben, die Tool-Injektion pro Run und Clients, die an Profilpaare gebunden sind.
Gegen den Quellcode geprüft am 17. September 2026
Auf dieser Seite
Ein überwachter Kindprozess
Der Startpfad löst den mitgelieferten Befehl auf, wendet die app-eigene Laufzeitkonfiguration an und öffnet stdin, stdout und stderr als Pipes. Zuerst beendet er die in app-server.pid im Profilstamm vermerkte Waise, falls dieser Prozess noch ein codex-app-server ist, leert stderr separat, vermerkt die neue Prozess-ID und nutzt kill-on-drop. Die Initialisierung sendet initialize mit Client-Informationen und aktiviertem experimentalApi, dann initialized; ein Initialisierungsfehler fährt das Kind herunter.
-c features.local_thread_store_compression=false
-c features.background_paginated_rollout_migration=false
-c features.multi_agent_v2.tool_namespace="plantocode"
-c sqlite_home=<storage-profile-home>
--allowed-storage-root <storage-profile-home>
--auth-home <execution-profile-home>
--listen stdio:// --session-source app-serverDie initialize-Antwort muss alle 15 erforderlichen Protokollerweiterungen auflisten, darunter threadItem.createdAtMs, threadItem.commandOutputSource, threadItemsList.path, threadUnload und threadTurn.executionMetadata. Ein fehlender Eintrag fährt das Kind als inkompatibel mit diesem Build herunter. Dieses Gate macht ein beliebiges Upstream-Binary unbrauchbar.
{"id":42,"method":"initialize","params":{"capabilities":{"experimentalApi":true},"clientInfo":{"name":"plantocode","version":"<build-version>"}}}- Antwortid
Wird der Anfrage zugeordnet, die auf sie wartet. Die Antwort auf turn/start trägt die Turn-ID, die den Kanal des Turns öffnet.
- EventthreadId · turnId
Wird in den Kanal dieses Turns geleitet. Solange ein turn/start für den Thread wartet, werden seine Events zurückgehalten, bis zu 4.096, und vor den Live-Events eingespielt.
- Anfrage des Kindsitem/tool/call · …/requestApproval
Ein Tool-Aufruf läuft in einem eigenen Task und bekommt nur den Tool-Namen und die Argumente, die Antwort schreibt der Actor. Eine Freigabe ohne aktiven Empfänger wird abgelehnt.
Das Kind läuft in einem app-eigenen Codex-Profil-Home mit stabiler opaker UUID, das der Desktop unterhalb seiner Anwendungsdaten anlegt. Die Einrichtung der eigenen Laufzeit leitet dieses Home ab und prüft es, bereinigt geerbte Speicherkonfiguration und übergibt das gewählte Home an das Kind, und das mitgelieferte Kind weigert sich, eine Datenbank zu öffnen, sofern --allowed-storage-root, CODEX_HOME und sqlite_home nicht auf dasselbe Verzeichnis kanonisieren.
| Frist | Wert |
|---|---|
| Kindstart | 35 Sekunden. |
| Antwort auf eine Anfrage | 30 Sekunden nach dem Schreiben, fest. Der Aufrufer gibt nach 31 Sekunden auf. Nur initialize startet seine 30 Sekunden jedes Mal neu, wenn der Kindprozess vor der Antwort eine Anfrage sendet. |
| stdin-Schreiben | 5 Sekunden. |
| Reservierung in der Befehlswarteschlange | 5 Sekunden. |
| Sauberes Herunterfahren vor dem Kill | 2 Sekunden. |
| Nicht beanspruchte Freigabe | Wird nach 30 Sekunden automatisch abgelehnt. |
Auf einem Telefon angezeigte Freigaben werden über run.codexChatResolveApproval aufgelöst, das einen Idempotenzschlüssel verlangt und die Entscheidung an den maßgeblichen app-server-Resolver weitergibt.
Der Tool-Namespace plantocode
Wenn ein Run seinen Thread mit thread/start oder thread/resume öffnet, übergibt der Desktop dynamicTools und developerInstructions, die einen Namensraum namens plantocode neben die Shell- und Dateiwerkzeuge stellen, die Codex bereits hat. Das Kind wird mit features.multi_agent_v2.tool_namespace auf denselben Namen gestartet, sodass Codex’ eigene Multi-Agent-Werkzeuge ihn teilen. Die Menge wird pro Run neu aufgebaut: use_user_browser, maintain_sessions und create_html_document sind immer vorhanden, send_mobile_notification erscheint, wenn die Einstellung Desktop- und Telefon-Benachrichtigungen eingeschaltet ist, und synthesize_speech und extract_video_context erscheinen, wenn ein Gemini-API-Schlüssel gespeichert ist. Jede Spezifikation ist als deferLoading markiert und bettet appSessionId, runId und Projektverzeichnis ein, und die Namensraumbeschreibung mit ihren Anweisungen bleibt unter 600 Zeichen. Der Aufruf eines Tool-Namens, den der Desktop nicht kennt, bekommt ein result mit success: false und dem Text „Unsupported PlanToCode app tool.“ statt eines Protokollfehlers.
Clients pro Profilpaar
- SpeicherprofilCODEX_HOME · sqlite_home
Ein PlanToCode-eigenes Codex-Home, benannt nach einer opaken UUID. Eine neue Session wird mit dem Home des Kontos verknüpft, das bei ihrem ersten Turn aktiv ist, und ein Wechsel kopiert, verschiebt oder verknüpft das Transkript nie neu.
- Konto--auth-home
Das angemeldete ChatGPT-Profil, Ausführungsprofil genannt, das bei der Zulassung eines Turns aktiv ist. Der Turn behält es bis zu seinem Ende.
- Codex-KindCodexRuntimePair
Einer pro Paar aus Speicher und Konto, bei Bedarf gestartet. Bevor ein Kindprozess einen Thread fortsetzt, entlädt jeder andere seine untätige Kopie, daher wandert ein laufender Turn nie.
Der Quellenlink speichert eine Thread-ID und den exakten Rollout-Pfad. thread/start liefert nur die ID, deshalb liest der Desktop den absoluten Pfad mit einem separaten thread/read, bevor er den Link veröffentlicht und bevor turn/start folgt; der Pfad eines Kind-Threads kommt mit dessen thread/started-Benachrichtigung. Ein Wechsel der Zugangsdaten ändert nie die Unterhaltungsquelle.
Die Obergrenze von drei stoppt nie einen beschäftigten Kindprozess, sind also alle beschäftigt, wächst die Registry, statt zu blockieren. Jeder Anmeldeversuch, der endet, auch durch Zeitüberschreitung oder Abbruch, erhöht die Auth-Generation des Ausführungsprofils, und ein unter der alten Generation gestarteter Kindprozess beendet seine Arbeit und tritt in den Ruhestand, sobald er untätig ist. Nach jedem Run entlädt der Desktop den Thread mit thread/unload, und ein fehlgeschlagenes Entladen nimmt diesen Kindprozess außer Dienst, weil die Prozessgrenze der einzige Beweis ist, dass der JSONL-Schreiber weg ist. Bevor sich der Quellenlink eines Threads ändert, wird ebenfalls jede untätige Kopie auf jedem laufenden Kindprozess entladen.
Der mitgelieferte Sidecar
- Geholtes mainrefs/remotes/origin/main
Wird nur von reconcile:codex-source in den lokalen Spiegel geschrieben. Der Sync vergleicht mit diesem Snapshot, daher ändert ein neuerer Commit auf dem offiziellen main nichts bis zum nächsten Reconcile.
- Akzeptierte Revisionvendor/codex/upstream-revision
Ändert sich nur durch accept:codex-source, sobald der abgeglichene Kandidat dem geholten main entspricht, keine Konflikte hat und seine Tests besteht. Die vollständigen Override-Dateien wechseln mit ihr.
- Syncsync:codex-sidecars
Stoppt vor dem Bauen, wenn die akzeptierte Revision nicht dem geholten main entspricht. Sonst checkt er diese Revision aus, kopiert die Overrides darüber, baut mit --locked und prüft das Manifest.
tauri:dev führt zuerst sync:codex-sidecars aus, sodass das Kind aus der mitgelieferten Quelle gebaut wird statt aus einem global installierten Codex. Rechnen Sie mit einem Rust-Build und dem in desktop/BUILD.md beschriebenen Netzwerkzugriff.
Der Sync ist ein Frische-Gate. Er scheitert, sofern desktop/vendor/codex/upstream-revision nicht dem main entspricht, das das letzte reconcile:codex-source in den lokalen Spiegel geholt hat, daher ist die akzeptierte Revision so aktuell wie dieser Abruf. Die 309 Override-Dateien unter desktop/vendor/codex/source implementieren die Protokollerweiterungen und die Speichergrenze, auf die sich der Desktop verlässt, weshalb ein fremdes Upstream-Binary am initialize-Gate scheitert. Behalten Sie den Protokolltransport als Verlaufsgrenze bei, statt einen weiteren Transkript-Parser hinzuzufügen.
pnpm -C desktop sync:codex-sidecars:verify