Commit Graph

12 Commits

  • Preserve persisted thread git info in resume (#13504)
    ## Summary
    - ensure `thread.resume` reuses the stored `gitInfo` instead of
    rebuilding it from the live working tree
    - persist and apply thread git metadata through the resume flow and add
    a regression test covering branch mismatch cases
    
    ## Testing
    - Not run (not requested)
  • chore(app-server): delete v1 RPC methods and notifications (#13375)
    ## Summary
    This removes the old app-server v1 methods and notifications we no
    longer need, while keeping the small set the main codex app client still
    depends on for now.
    
    The remaining legacy surface is:
    - `initialize`
    - `getConversationSummary`
    - `getAuthStatus`
    - `gitDiffToRemote`
    - `fuzzyFileSearch`
    - `fuzzyFileSearch/sessionStart`
    - `fuzzyFileSearch/sessionUpdate`
    - `fuzzyFileSearch/sessionStop`
    
    And the raw `codex/event/*` notifications emitted from core. These
    notifications will be removed in a followup PR.
    
    ## What changed
    - removed deprecated v1 request variants from the protocol and
    app-server dispatcher
    - removed deprecated typed notifications: `authStatusChange`,
    `loginChatGptComplete`, and `sessionConfigured`
    - updated the app-server test client to use v2 flows instead of deleted
    v1 flows
    - deleted legacy-only app-server test suites and added focused coverage
    for `getConversationSummary`
    - regenerated app-server schema fixtures and updated the MCP interface
    docs to match the remaining compatibility surface
    
    ## Testing
    - `just write-app-server-schema`
    - `cargo test -p codex-app-server-protocol`
    - `cargo test -p codex-app-server`
  • fix(app-server): make thread/start non-blocking (#13033)
    Stop `thread/start` from blocking other app-server requests.
    
    Before this change, `thread/start ran` inline on the request loop, so
    slow startup paths like MCP auth checks could hold up unrelated requests
    on the same connection, including `thread/loaded/list`. This moves
    `thread/start` into a background task.
    
    While doing so, it revealed an issue where we were doing nested locking
    (and there were some race conditions possible that could introduce a
    "phantom listener"). This PR also refactors the listener/subscription
    bookkeeping - listener/subscription state is now centralized in
    `ThreadStateManager` instead of being split across multiple lock
    domains. That makes late auto-attach on `thread/start` race-safe and
    avoids reintroducing disconnected clients as phantom subscribers.
  • app-server: Replay pending item requests on thread/resume (#12560)
    Replay pending client requests after `thread/resume` and emit resolved
    notifications when those requests clear so approval/input UI state stays
    in sync after reconnects and across subscribed clients.
    
    Affected RPCs:
    - `item/commandExecution/requestApproval`
    - `item/fileChange/requestApproval`
    - `item/tool/requestUserInput`
    
    Motivation:
    - Resumed clients need to see pending approval/input requests that were
    already outstanding before the reconnect.
    - Clients also need an explicit signal when a pending request resolves
    or is cleared so stale UI can be removed on turn start, completion, or
    interruption.
    
    Implementation notes:
    - Use pending client requests from `OutgoingMessageSender` in order to
    replay them after `thread/resume` attaches the connection, using
    original request ids.
    - Emit `serverRequest/resolved` when pending requests are answered
    or cleared by lifecycle cleanup.
    - Update the app-server protocol schema, generated TypeScript bindings,
    and README docs for the replay/resolution flow.
    
    High-level test plan:
    - Added automated coverage for replaying pending command execution and
    file change approval requests on `thread/resume`.
    - Added automated coverage for resolved notifications in command
    approval, file change approval, request_user_input, turn start, and turn
    interrupt flows.
    - Verified schema/docs updates in the relevant protocol and app-server
    tests.
    
    Manual testing:
    - Tested reconnect/resume with multiple connections.
    - Confirmed state stayed in sync between connections.
  • feat(app-server): thread/unsubscribe API (#10954)
    Adds a new v2 app-server API for a client to be able to unsubscribe to a
    thread:
    - New RPC method: `thread/unsubscribe`
    - New server notification: `thread/closed`
    
    Today clients can start/resume/archive threads, but there wasn’t a way
    to explicitly unload a live thread from memory without archiving it.
    With `thread/unsubscribe`, a client can indicate it is no longer
    actively working with a live Thread. If this is the only client
    subscribed to that given thread, the thread will be automatically closed
    by app-server, at which point the server will send `thread/closed` and
    `thread/status/changed` with `status: notLoaded` notifications.
    
    This gives clients a way to prevent long-running app-server processes
    from accumulating too many thread (and related) objects in memory.
    
    Closed threads will also be removed from `thread/loaded/list`.
  • app-server: retain thread listener across disconnects (#12373)
    - keep the per-thread app-server listener alive when the last client
    unsubscribes or disconnects
    - preserve listener-side active turn history so running `thread/resume`
    can merge an in-progress turn snapshot after reconnect
    - add `ThreadStateManager` regressions for disconnect/unsubscribe
    retention and explicit thread teardown cleanup
    
    Added unit tests, and I manually tested to confirm the fix
    
    ---------
    
    Co-authored-by: Codex <noreply@openai.com>
  • app-server: harden disconnect cleanup paths (#12218)
    Hardens codex-rs/app-server connection lifecycle and outbound routing
    for websocket clients. Fixes some FUD I was having
    
    - Added per-connection disconnect signaling (CancellationToken) for
    websocket transports.
    - Split websocket handling into independent inbound/outbound tasks
    coordinated by cancellation.
    - Changed outbound routing so websocket connections use non-blocking
    try_send; slow/full websocket writers are disconnected instead of
    stalling broadcast delivery.
    - Kept stdio behavior blocking-on-send (no forced disconnect) so local
    stdio clients are not dropped when queues are temporarily full.
    - Simplified outbound router flow by removing deferred
    pending_closed_connections handling.
    - Added guards to drop incoming response/notification/error messages
    from unknown connections.
    - Fixed listener teardown race in thread listener tasks using a
    listener_generation check so stale tasks do not clear newer listeners.
    
    Fixes
    https://linear.app/openai/issue/CODEX-4966/multiclient-handle-slow-notification-consumers
    
      ## Tests
    
      Added/updated transport tests covering:
    
      - broadcast does not block on a slow/full websocket connection
      - stdio connection waits instead of disconnecting on full queue
    
    I (maxj) have tested manually and will retest before landing
  • app-server: improve thread resume rejoin flow (#11776)
    thread/resume response includes latest turn with all items, in band so
    no events are stale or lost
    
    Testing
    - e2e tested using app-server-test-client using flow described in
    "Testing Thread Rejoin Behavior" in
    codex-rs/app-server-test-client/README.md
    - e2e tested in codex desktop by reconnecting to a running turn
  • app-server: expose loaded thread status via read/list and notifications (#11786)
    Motivation
    - Today, a newly connected client has no direct way to determine the
    current runtime status of threads from read/list responses alone.
    - This forces clients to infer state from transient events, which can
    lead to stale or inconsistent UI when reconnecting or attaching late.
    
    Changes
    - Add `status` to `thread/read` responses.
    - Add `statuses` to `thread/list` responses.
    - Emit `thread/status/changed` notifications with `threadId` and the new
    status.
    - Track runtime status for all loaded threads and default unknown
    threads to `idle`.
    - Update protocol/docs/tests/schema fixtures for the revised API.
    
    Testing
    - Validated protocol API changes with automated protocol tests and
    regenerated schema/type fixtures.
    - Validated app-server behavior with unit and integration test suites,
    including status transitions and notifications.
  • feat(core): plumb distinct approval ids for command approvals (#12051)
    zsh fork PR stack:
    - https://github.com/openai/codex/pull/12051 👈 
    - https://github.com/openai/codex/pull/12052
    
    With upcoming support for a fork of zsh that allows us to intercept
    `execve` and run execpolicy checks for each subcommand as part of a
    `CommandExecution`, it will be possible for there to be multiple
    approval requests for a shell command like `/path/to/zsh -lc 'git status
    && rg \"TODO\" src && make test'`.
    
    To support that, this PR introduces a new `approval_id` field across
    core, protocol, and app-server so that we can associate approvals
    properly for subcommands.
  • app-server: thread resume subscriptions (#11474)
    This stack layer makes app-server thread event delivery connection-aware
    so resumed/attached threads only emit notifications and approval prompts
    to subscribed connections.
    
    - Added per-thread subscription tracking in `ThreadState`
    (`subscribed_connections`) and mapped subscription ids to `(thread_id,
    connection_id)`.
    - Updated listener lifecycle so removing a subscription or closing a
    connection only removes that connection from the thread’s subscriber
    set; listener shutdown now happens when the last subscriber is gone.
    - Added `connection_closed(connection_id)` plumbing (`lib.rs` ->
    `message_processor.rs` -> `codex_message_processor.rs`) so disconnect
    cleanup happens immediately.
    - Scoped bespoke event handling outputs through `TargetedOutgoing` to
    send requests/notifications only to subscribed connections.
    - Kept existing threadresume behavior while aligning with the latest
    split-loop transport structure.
  • refactor: codex app-server ThreadState (#11419)
    this is a no-op functionality wise. consolidates thread-specific message
    processor / event handling state in ThreadState