mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
dev
14 Commits
-
Support
openai/formextended form elicitations (#27500)# Summary Allow App Server clients to opt into `openai/form` MCP elicitations.
Gabriel Peal ·
2026-06-18 11:54:49 -07:00 -
[1 of 3] Support long raw TUI goal objectives (#27508)
## Stack 1. **[1 of 3] Support long raw TUI goal objectives** - this PR 2. [2 of 3] Support long pasted text in TUI goals - #27509 3. [3 of 3] Support images in TUI goals - #27510 ## Why `thread/goal/set` limits persisted objective text to 4000 characters. The TUI used to reject raw `/goal` objectives above that limit, even though the client can make them usable by writing the long text to a file and storing a short objective that points at that file. This also needs to work for remote app-server sessions: filesystem API calls must create files on the app-server host, and the stored path must be meaningful to the agent on that host. ## What Changed - Adds an app-server-host path helper so TUI code can build paths that are resolved on the app-server host rather than the TUI host. - Adds TUI app-server session helpers for `fs/createDirectory`, `fs/writeFile`, `fs/readFile`, and `fs/remove` that work for embedded and remote app-server sessions without changing the app-server protocol. - Materializes oversized raw `/goal` objectives into `$CODEX_HOME/attachments/<uuid>/goal-objective.md` through the app-server filesystem APIs, then stores a short, readable objective that directs the agent to that file. - Reads managed objective files back for `/goal edit`. Other goal UI renders the readable stored objective normally, without managed-file-specific presentation logic. - Recognizes managed references only when they name the expected generated file under the app server's reported `$CODEX_HOME`, and cleans up newly materialized files when goal replacement or setting does not complete. ## Verification - Added/updated TUI tests for raw oversized `/goal` submission, large inline-paste expansion, queued oversized goals, app-facing materialization before `thread/goal/set`, managed-path validation, editing, and cleanup. - Added/updated app-server-client remote coverage for initialized remote Codex home handling. ## Manual Testing - Ran the real TUI against a Unix-socket app server with different local and server `$CODEX_HOME` directories. Oversized goals wrote only under the server home, and persisted references used the server-canonical path rather than the TUI path. - Exercised 3,999-, 4,000-, and 4,001-character raw objectives. The first two stayed inline without new files; the 4,001-character objective became a managed objective file. - Submitted a larger 8,275-character objective, verified its full contents on the app-server host, and observed the goal continuation open the referenced server-side file. - Opened `/goal edit` for a managed objective and verified the full text was restored through remote `fs/readFile`. - Submitted an oversized replacement while a goal was active, verified no file was written before confirmation, then canceled and confirmed that the existing goal and attachment count were unchanged.
Eric Traut ·
2026-06-11 22:26:31 -07:00 -
Show remote connection details in /status (#24420)
## Summary Fixes #24411. `/status` currently has no way to show when the TUI is talking to Codex through a remote transport. That makes embedded local sessions, local daemon sessions, and true remote sessions look the same, and it hides the remote server version when debugging connection-specific behavior. This PR adds a single `Remote` row for non-embedded connections only. The row shows the sanitized connection address and a dimmed version parenthetical, preserving the existing status output for embedded local sessions. <img width="791" height="144" alt="image" src="https://github.com/user-attachments/assets/529d7940-1c45-4586-8b06-f20a1f04b771" /> ## Verification - Manually validated when connecting remotely (either implicitly to local daemon or explicitly)
Eric Traut ·
2026-05-25 09:42:42 -07:00 -
Add support for UDS in
codex --remote(#22414)## Why Added support for UDS connections in `codex --remote`. TUI also now connects to local app-server using UDS by default if it is running and set to listen to UDS connection. ## What Changed - Introduced `RemoteAppServerEndpoint` with `WebSocket` and `UnixSocket` variants. - Reused the existing JSON-RPC-over-WebSocket protocol over either a TCP WebSocket stream or a UDS stream. - Updated `codex --remote` to accept `ws://host:port`, `wss://host:port`, `unix://`, and `unix://PATH`. - Kept `--remote-auth-token-env` restricted to `wss://` and loopback `ws://` remotes. - Added a fast TUI startup probe for the default daemon socket, falling back to the embedded app server when the daemon is absent or unresponsive. ## Verification - Manually verified that the updated remote flow works. - Added coverage for UDS remote round trips, WebSocket auth headers, auth-token transport policy, remote address parsing, and missing-daemon fallback. - Ran focused remote test coverage locally.
Eric Traut ·
2026-05-12 21:17:20 -07:00 -
[codex] request desktop attestation from app (#20619)
## Summary TL;DR: teaches `codex-rs` / app-server to request a desktop-provided attestation token and attach it as `x-oai-attestation` on the scoped ChatGPT Codex request paths.  ## Details This PR teaches the Codex app-server runtime how to request and attach an attestation token. It does not generate DeviceCheck tokens directly; instead, it relies on the connected desktop app to advertise that it can generate attestation and then asks that app for a fresh header value when needed. The flow is: 1. The Codex desktop app connects to app-server. 2. During `initialize`, the app can advertise that it supports `requestAttestation`. 3. Before app-server calls selected ChatGPT Codex endpoints, it sends the internal server request `attestation/generate` to the app. 4. app-server receives a pre-encoded header value back. 5. app-server forwards that value as `x-oai-attestation` on the scoped outbound requests. The code in this repo is mostly protocol and runtime plumbing: it adds the app-server request/response shape, introduces an attestation provider in core, wires that provider into Responses / compaction / realtime setup paths, and covers the intended scoping with tests. The signed macOS DeviceCheck generation remains owned by the desktop app PR. ## Related PR - Codex desktop app implementation: https://github.com/openai/openai/pull/878649 ## Validation <details> <summary>Tests run</summary> ```sh cargo test -p codex-app-server-protocol cargo test -p codex-core attestation --lib cargo test -p codex-app-server --lib attestation ``` Also ran: ```sh just fix -p codex-core just fix -p codex-app-server just fix -p codex-app-server-protocol just fmt just write-app-server-schema ``` </details> <details> <summary>E2E DeviceCheck validation</summary> First validated the signed desktop app boundary directly: launched a packaged signed `Codex.app`, sent `attestation/generate`, decoded the returned `v1.` attestation header, and validated the extracted DeviceCheck token with `personal/jm/verify_devicecheck_token.py` using bundle ID `com.openai.codex`. Apple returned `status_code: 200` and `is_ok: true`. Then ran the fuller app + app-server flow. The packaged `Codex.app` launched a current-branch app-server via `CODEX_CLI_PATH`, and a local MITM proxy intercepted outbound `chatgpt.com` traffic. The app-server requested `attestation/generate` from the real Electron app process, and the intercepted `/backend-api/codex/responses` traffic included `x-oai-attestation` on both routes: ```text GET /backend-api/codex/responses Upgrade: websocket x-oai-attestation: present POST /backend-api/codex/responses Upgrade: none x-oai-attestation: present ``` The captured header decoded to a DeviceCheck token that also validated with Apple for `com.openai.codex` (`status_code: 200`, `is_ok: true`, team `2DC432GLL2`). </details> --------- Co-authored-by: Codex <noreply@openai.com>
Jiaming Zhang ·
2026-05-08 12:36:02 -07:00 -
Allow large remote app-server resume responses (#19920)
## Why Remote TUI resume uses the app-server websocket client. That client inherited tungstenite's default `16 MiB` frame limit, so a large saved session could make `thread/resume` return a single JSON-RPC response frame that the client rejected before the TUI could deserialize or render it. Fixes #19837 ## What Changed - Configure the remote app-server websocket client with a bounded `128 MiB` max frame/message size. - Preserve the concrete remote worker exit reason when completing pending requests after a transport/read failure instead of replacing it with a generic channel-closed error. - Add a regression test that sends a single `>16 MiB` JSON-RPC response frame and verifies the typed request succeeds. Note: This isn't a perfect fix. It really just moves the limit to a much larger value. I looked at a bunch of other potential fixes (both server-side and client-side), and they all involved significant complexity, had backward-compatibility impact, or impacted performance of common use cases. This simple fix should address the vast majority of remote use cases. ## Verification I reproed the problem locally using a long rollout. Verified that fix addresses connection drop.
Eric Traut ·
2026-04-27 22:44:10 -07:00 -
TUI: Keep remote app-server events draining (#18932)
Addresses #18860 Problem: Remote app-server clients could stop draining websocket events when their bounded local event channel filled, leaving clients stuck on stale in-progress turns after a disconnect. Solution: Use an unbounded local event channel for the remote client so the websocket reader can keep forwarding disconnect and progress events instead of blocking or dropping them. Why this is reasonable: This does not make the remote websocket itself unbounded. The changed queue lives inside the remote client, between the task that reads the remote websocket and the API consumer in the same client process. Once an event has been received from the remote server, preserving it is preferable to blocking websocket reads or dropping disconnect/lifecycle events; network-level backpressure still happens at the websocket boundary if the remote side outpaces the client.
Eric Traut ·
2026-04-22 09:29:34 -07:00 -
Fix remote app-server shutdown race (#18936)
## Why A Mac Bazel CI run saw `remote_notifications_arrive_over_websocket` fail during shutdown with `remote app-server shutdown channel is closed` (https://app.buildbuddy.io/invocation/9dac05d6-ae20-40f9-b627-fca6e91cf127). The remote websocket worker can legitimately finish while `shutdown()` is waiting for the shutdown acknowledgement: after the test server sends a notification and exits, the worker may deliver the required disconnect event, observe that the caller has dropped the event receiver, and exit before it sends the shutdown one-shot. That state is already terminal cleanup, not a failed shutdown, so callers should not see a `BrokenPipe` from the acknowledgement channel. ## What Changed - Treat a closed remote shutdown acknowledgement as an already-exited worker while still propagating websocket close errors when the worker returns them. - Added a deterministic regression test for the interleaving where the shutdown command is received and the worker exits before replying. ## Verification - `cargo test -p codex-app-server-client` - New test: `remote::tests::shutdown_tolerates_worker_exit_after_command_is_queued`
Michael Bolin ·
2026-04-22 02:41:19 +00:00 -
Install rustls provider for remote websocket client (#17288)
Addresses #17283 Problem: `codex --remote wss://...` could panic because app-server-client did not install rustls' process-level crypto provider before opening TLS websocket connections. Solution: Add the existing rustls provider utility dependency and install it before the remote websocket connect.
Eric Traut ·
2026-04-09 20:29:12 -07:00 -
Remove the legacy TUI split (#15922)
This is the part 1 of 2 PRs that will delete the `tui` / `tui_app_server` split. This part simply deletes the existing `tui` directory and marks the `tui_app_server` feature flag as removed. I left the `tui_app_server` feature flag in place for now so its presence doesn't result in an error. It is simply ignored. Part 2 will rename the `tui_app_server` directory `tui`. I did this as two parts to reduce visible code churn.
Eric Traut ·
2026-03-27 22:56:44 +00:00 -
Wire remote app-server auth through the client (#14853)
For app-server websocket auth, support the two server-side mechanisms from PR #14847: - `--ws-auth capability-token --ws-token-file /abs/path` - `--ws-auth signed-bearer-token --ws-shared-secret-file /abs/path` with optional `--ws-issuer`, `--ws-audience`, and `--ws-max-clock-skew-seconds` On the client side, add interactive remote support via: - `--remote ws://host:port` or `--remote wss://host:port` - `--remote-auth-token-env <ENV_VAR>` Codex reads the bearer token from the named environment variable and sends it as `Authorization: Bearer <token>` during the websocket handshake. Remote auth tokens are only allowed for `wss://` URLs or loopback `ws://` URLs. Testing: - tested both auth methods manually to confirm connection success and rejection for both auth types
Eric Traut ·
2026-03-25 22:17:03 -06:00 -
fix(tui_app_server): preserve transcript events under backpressure (#15759)
## TL;DR When running codex with `-c features.tui_app_server=true` we see corruption when streaming large amounts of data. This PR marks other event types as _critical_ by making them _must-deliver_. ## Problem When the TUI consumer falls behind the app-server event stream, the bounded `mpsc` channel fills up and the forwarding layer drops events via `try_send`. Previously only `TurnCompleted` was marked as must-deliver. Streamed assistant text (`AgentMessageDelta`) and the authoritative final item (`ItemCompleted`) were treated as droppable — the same as ephemeral command output deltas. Because the TUI renders markdown incrementally from these deltas, dropping any of them produces permanently corrupted or incomplete paragraphs that persist for the rest of the session. ## Mental model The app-server event stream has two tiers of importance: 1. **Lossless (transcript + terminal):** Events that form the authoritative record of what the assistant said or that signal turn lifecycle transitions. Losing any of these corrupts the visible output or leaves surfaces waiting forever. These are: `AgentMessageDelta`, `PlanDelta`, `ReasoningSummaryTextDelta`, `ReasoningTextDelta`, `ItemCompleted`, and `TurnCompleted`. 2. **Best-effort (everything else):** Ephemeral status events like `CommandExecutionOutputDelta` and progress notifications. Dropping these under load causes cosmetic gaps but no permanent corruption. The forwarding layer uses `try_send` for best-effort events (dropping on backpressure) and blocking `send().await` for lossless events (applying back-pressure to the producer until the consumer catches up). ## Non-goals - Eliminating backpressure entirely. The bounded queue is intentional; this change only widens the set of events that survive it. - Changing the event protocol or adding new notification types. - Addressing root causes of consumer slowness (e.g. TUI render cost). ## Tradeoffs Blocking on transcript events means a slow consumer can now stall the producer for the duration of those events. This is acceptable because: (a) the alternative is permanently broken output, which is worse; (b) the consumer already had to keep up with `TurnCompleted` blocking sends; and (c) transcript events arrive at model-output speed, not burst speed, so sustained saturation is unlikely in practice. ## Architecture Two parallel changes, one per transport: - **In-process path** (`lib.rs`): The inline forwarding logic was extracted into `forward_in_process_event`, a standalone async function that encapsulates the lag-marker / must-deliver / try-send decision tree. The worker loop now delegates to it. A new `server_notification_requires_delivery` function (shared `pub(crate)`) centralizes the notification classification. - **Remote path** (`remote.rs`): The local `event_requires_delivery` now delegates to the same shared `server_notification_requires_delivery`, keeping both transports in sync. ## Observability No new metrics or log lines. The existing `warn!` on event drops continues to fire for best-effort events. Lossless events that block will not produce a log line (they simply wait). ## Tests - `event_requires_delivery_marks_transcript_and_terminal_events`: unit test confirming the expanded classification covers `AgentMessageDelta`, `ItemCompleted`, `TurnCompleted`, and excludes `CommandExecutionOutputDelta` and `Lagged`. - `forward_in_process_event_preserves_transcript_notifications_under_backpressure`: integration-style test that fills a capacity-1 channel, verifies a best-effort event is dropped (skipped count increments), then sends lossless transcript events and confirms they all arrive in order with the correct lag marker preceding them. - `remote_backpressure_preserves_transcript_notifications`: end-to-end test over a real websocket that verifies the remote transport preserves transcript events under the same backpressure scenario. - `event_requires_delivery_marks_transcript_and_disconnect_events` (remote): unit test confirming the remote-side classification covers transcript events and `Disconnected`. --------- Co-authored-by: Eric Traut <etraut@openai.com>
Felipe Coury ·
2026-03-25 13:50:39 -06:00 -
Finish moving codex exec to app-server (#15424)
This PR completes the conversion of non-interactive `codex exec` to use app server rather than directly using core events and methods. ### Summary - move `codex-exec` off exec-owned `AuthManager` and `ThreadManager` state - route exec bootstrap, resume, and auth refresh through existing app-server paths - replace legacy `codex/event/*` decoding in exec with typed app-server notification handling - update human and JSONL exec output adapters to translate existing app-server notifications only - clean up "app server client" layer by eliminating support for legacy notifications; this is no longer needed - remove exposure of `authManager` and `threadManager` from "app server client" layer ### Testing - `exec` has pretty extensive unit and integration tests already, and these all pass - In addition, I asked Codex to put together a comprehensive manual set of tests to cover all of the `codex exec` functionality (including command-line options), and it successfully generated and ran these tests
Eric Traut ·
2026-03-24 08:51:32 -06:00 -
Move TUI on top of app server (parallel code) (#14717)
This PR replicates the `tui` code directory and creates a temporary parallel `tui_app_server` directory. It also implements a new feature flag `tui_app_server` to select between the two tui implementations. Once the new app-server-based TUI is stabilized, we'll delete the old `tui` directory and feature flag.
Eric Traut ·
2026-03-16 10:49:19 -06:00