Commit Graph

10 Commits

  • 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
  • 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>
  • 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
  • Split features into codex-features crate (#15253)
    - Split the feature system into a new `codex-features` crate.
    - Cut `codex-core` and workspace consumers over to the new config and
    warning APIs.
    
    Co-authored-by: Ahmed Ibrahim <219906144+aibrahim-oai@users.noreply.github.com>
    Co-authored-by: Codex <noreply@openai.com>
  • Revert "fix: harden plugin feature gating" (#15102)
    Reverts openai/codex#15020
    
    I messed up the commit in my PR and accidentally merged changes that
    were still under review.
  • fix: harden plugin feature gating (#15020)
    1. Use requirement-resolved config.features as the plugin gate.
    2. Guard plugin/list, plugin/read, and related flows behind that gate.
    3. Skip bad marketplace.json files instead of failing the whole list.
    4. Simplify plugin state and caching.
  • 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.
  • Start TUI on embedded app server (#14512)
    This PR is part of the effort to move the TUI on top of the app server.
    In a previous PR, we introduced an in-process app server and moved
    `exec` on top of it.
    
    For the TUI, we want to do the migration in stages. The app server
    doesn't currently expose all of the functionality required by the TUI,
    so we're going to need to support a hybrid approach as we make the
    transition.
    
    This PR changes the TUI initialization to instantiate an in-process app
    server and access its `AuthManager` and `ThreadManager` rather than
    constructing its own copies. It also adds a placeholder TUI event
    handler that will eventually translate app server events into TUI
    events. App server notifications are accepted but ignored for now. It
    also adds proper shutdown of the app server when the TUI terminates.
  • fix(bazel) add missing app-server-client BUILD.bazel (#14027)
    ## Summary
    Adds missing BUILD.bazel file for the new app-server-client crate
    
    ## Testing
    - [x] 🤞 that this gets bazel ci to pass
  • Add in-process app server and wire up exec to use it (#14005)
    This is a subset of PR #13636. See that PR for a full overview of the
    architectural change.
    
    This PR implements the in-process app server and modifies the
    non-interactive "exec" entry point to use the app server.
    
    ---------
    
    Co-authored-by: Felipe Coury <felipe.coury@gmail.com>