Commit Graph

29 Commits

  • Cleanup experimentalFeature/enablement/set (#26312)
    ## Why
    
    `experimentalFeature/enablement/set` still allowed several keys that no
    longer need to be managed through this API. Keeping those keys also
    preserved corresponding special-case logic, including refreshing the
    apps list when the `apps` key was enabled.
    
    The endpoint also rejected an entire request when any key was invalid or
    unsupported. That makes clients brittle when they send a mix of current
    and stale keys, even when the valid entries can still be applied safely.
    
    ## What changed
    
    - remove the feature keys that no longer need to be supported by
    `experimentalFeature/enablement/set`
    - remove the corresponding apps-list refresh path and its auth/config
    plumbing
    - ignore and warn on invalid or unsupported keys while still applying
    valid keys from the same request
    - update the app-server documentation and integration coverage for the
    reduced key set and partial-acceptance behavior
    
    ## Test plan
    
    - `just test -p codex-app-server experimental_feature_enablement_set` (6
    passed)
    - `just test -p codex-app-server` exercised the changed tests
    successfully; unrelated sandbox-dependent and watcher/timing tests
    failed locally
  • fix: rename McpServer to TestAppServer (#25701)
    This PR brought to you via VS Code rather than Codex...
    
    - opened `codex-rs/app-server/tests/common/mcp_process.rs`
    - put the cursor on `McpServer`
    - hit `F2` and renamed the symbol to `TestAppServer`
    - went to the file tree
    - hit enter and renamed `mcp_process.rs` to `test_app_server.rs`
    - ran **Save All Files** from the Command Palette
    - ran `just fmt`
    
    The End
    
    (Admittedly, most of the local variables for `TestAppServer` are still
    named `mcp`, though.)
  • Update rmcp to 1.7.0 (#24763)
    WIll make it easier to uprev when the new draft spec is supported.
    
    Also updates reqwest where needed for compatibility but doesn't update
    it everywhere since this is already a large diff.
    
    The new version of rmcp handles certain kinds of authentication failures
    differently, this patch includes support for identifying the failing scope
    in a WWW-Authenticate header.
  • respect workspace option for disabling plugins (#18907)
    Respects the workspace setting for plugins in Codex
    
    Plugins menu disappears
    Plugins do not load
    Plugins do not load in composer
    
    no plugins loaded
    <img width="809" height="226" alt="Screenshot 2026-04-23 at 3 20 45 PM"
    src="https://github.com/user-attachments/assets/3a4dba8e-69c3-4046-a77e-f13ab77f84b4"
    />
    
    
    no plugins in menu
    <img width="293" height="204" alt="Screenshot 2026-04-23 at 3 20 35 PM"
    src="https://github.com/user-attachments/assets/5cb9bf52-ad72-488f-b90c-5eb457da09a3"
    />
  • feat: add explicit AgentIdentity auth mode (#18785)
    ## Summary
    
    This PR adds `CodexAuth::AgentIdentity` as an explicit auth mode.
    
    An AgentIdentity auth record is a standalone `auth.json` mode. When
    `AuthManager::auth().await` loads that mode, it registers one
    process-scoped task and stores it in runtime-only state on the auth
    value. Header creation stays synchronous after that because the task is
    initialized before callers receive the auth object.
    
    This PR also removes the old feature flag path. AgentIdentity is
    selected by explicit auth mode, not by a hidden flag or lazy mutation of
    ChatGPT auth records.
    
    Reference old stack: https://github.com/openai/codex/pull/17387/changes
    
    ## Design Decisions
    
    - AgentIdentity is a real auth enum variant because it can be the only
    credential in `auth.json`.
    - The process task is ephemeral runtime state. It is not serialized and
    is not stored in rollout/session data.
    - Account/user metadata needed by existing Codex backend checks lives on
    the AgentIdentity record for now.
    - `is_chatgpt_auth()` remains token-specific.
    - `uses_codex_backend()` is the broader predicate for ChatGPT-token auth
    and AgentIdentity auth.
    
    ## Stack
    
    1. https://github.com/openai/codex/pull/18757: full revert
    2. https://github.com/openai/codex/pull/18871: isolated Agent Identity
    crate
    3. This PR: explicit AgentIdentity auth mode and startup task allocation
    4. https://github.com/openai/codex/pull/18811: migrate Codex backend
    auth callsites through AuthProvider
    5. https://github.com/openai/codex/pull/18904: accept AgentIdentity JWTs
    and load `CODEX_AGENT_IDENTITY`
    
    ## Testing
    
    Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
  • fix: fully revert agent identity runtime wiring (#18757)
    ## Summary
    
    This PR fully reverts the previously merged Agent Identity runtime
    integration from the old stack:
    https://github.com/openai/codex/pull/17387/changes
    
    It removes the Codex-side task lifecycle wiring, rollout/session
    persistence, feature flag plumbing, lazy `auth.json` mutation,
    background task auth paths, and request callsite changes introduced by
    that stack.
    
    This leaves the repo in a clean pre-AgentIdentity integration state so
    the follow-up PRs can reintroduce the pieces in smaller reviewable
    layers.
    
    ## Stack
    
    1. This PR: full revert
    2. https://github.com/openai/codex/pull/18871: move Agent Identity
    business logic into a crate
    3. https://github.com/openai/codex/pull/18785: add explicit
    AgentIdentity auth mode and startup task allocation
    4. https://github.com/openai/codex/pull/18811: migrate auth callsites
    through AuthProvider
    
    ## Testing
    
    Tests: targeted Rust checks, cargo-shear, Bazel lock check, and CI.
  • Register agent identities behind use_agent_identity (#17386)
    ## Summary
    
    Stack PR 2 of 4 for feature-gated agent identity support.
    
    This PR adds agent identity registration behind
    `features.use_agent_identity`. It keeps the app-server protocol
    unchanged and starts registration after ChatGPT auth exists rather than
    requiring a client restart.
    
    ## Stack
    
    - PR1: https://github.com/openai/codex/pull/17385 - add
    `features.use_agent_identity`
    - PR2: https://github.com/openai/codex/pull/17386 - this PR
    - PR3: https://github.com/openai/codex/pull/17387 - register agent tasks
    when enabled
    - PR4: https://github.com/openai/codex/pull/17388 - use `AgentAssertion`
    downstream when enabled
    
    ## Validation
    
    Covered as part of the local stack validation pass:
    
    - `just fmt`
    - `cargo test -p codex-core --lib agent_identity`
    - `cargo test -p codex-core --lib agent_assertion`
    - `cargo test -p codex-core --lib websocket_agent_task`
    - `cargo test -p codex-api api_bridge`
    - `cargo build -p codex-cli --bin codex`
    
    ## Notes
    
    The full local app-server E2E path is still being debugged after PR
    creation. The current branch stack is directionally ready for review
    while that follow-up continues.
  • Refactor config types into a separate crate (#16962)
    Move config types into a separate crate because their macros expand into
    a lot of new code.
  • core: remove cross-crate re-exports from lib.rs (#16512)
    ## Why
    
    `codex-core` was re-exporting APIs owned by sibling `codex-*` crates,
    which made downstream crates depend on `codex-core` as a proxy module
    instead of the actual owner crate.
    
    Removing those forwards makes crate boundaries explicit and lets leaf
    crates drop unnecessary `codex-core` dependencies. In this PR, this
    reduces the dependency on `codex-core` to `codex-login` in the following
    files:
    
    ```
    codex-rs/backend-client/Cargo.toml
    codex-rs/mcp-server/tests/common/Cargo.toml
    ```
    
    ## What
    
    - Remove `codex-rs/core/src/lib.rs` re-exports for symbols owned by
    `codex-login`, `codex-mcp`, `codex-rollout`, `codex-analytics`,
    `codex-protocol`, `codex-shell-command`, `codex-sandboxing`,
    `codex-tools`, and `codex-utils-path`.
    - Delete the `default_client` forwarding shim in `codex-rs/core`.
    - Update in-crate and downstream callsites to import directly from the
    owning `codex-*` crate.
    - Add direct Cargo dependencies where callsites now target the owner
    crate, and remove `codex-core` from `codex-rs/backend-client`.
  • [mcp] Improve custom MCP elicitation (#15800)
    - [x] Support don't ask again for custom MCP tool calls.
    - [x] Don't run arc in yolo mode.
    - [x] Run arc for custom MCP tools in always allow mode.
  • [apps] Fix apps enablement condition. (#14011)
    - [x] Fix apps enablement condition to check both the feature flag and
    that the user is not an API key user.
  • Stabilize app list update ordering test (#14052)
    ## Summary
    - make
    `list_apps_waits_for_accessible_data_before_emitting_directory_updates`
    accept the two valid notification paths the server can emit
    - keep rejecting the real bug this test is meant to catch: a
    directory-only `app/list/updated` notification before accessible app
    data is available
    
    ## Why this fixes the flake
    The old test used a fixed `150ms` silence window and assumed the first
    notification after that window had to be the fully merged final update.
    In CI, scheduling occasionally lets accessible app data arrive before
    directory data, so the first valid notification can be an
    accessible-only interim update. That made the test fail even though the
    server behavior was correct.
    
    This change makes the test deterministic by reading notifications until
    the final merged payload arrives. Any interim update is only accepted if
    it contains accessible apps only; if the server ever emits inaccessible
    directory data before accessible data is ready, the test still fails
    immediately.
    
    ## Change type
    - test-only; no production app-list logic changes
  • add @plugin mentions (#13510)
    ## Note-- added plugin mentions via @, but that conflicts with file
    mentions
    
    depends and builds upon #13433.
    
    - introduces explicit `@plugin` mentions. this injects the plugin's mcp
    servers, app names, and skill name format into turn context as a dev
    message.
    - we do not yet have UI for these mentions, so we currently parse raw
    text (as opposed to skills and apps which have UI chips, autocomplete,
    etc.) this depends on a `plugins/list` app-server endpoint we can feed
    the UI with, which is upcoming
    - also annotate mcp and app tool descriptions with the plugin(s) they
    come from. this gives the model a first class way of understanding what
    tools come from which plugins, which will help implicit invocation.
    
    ### Tests
    Added and updated tests, unit and integration. Also confirmed locally a
    raw `@plugin` injects the dev message, and the model knows about its
    apps, mcps, and skills.
  • [apps] Stablize app list updated event. (#13067)
    Stablize app list updated event so that we only send 2 updates: 1 when
    installed apps become available, one when all directory apps are
    available. Previously it also updates when directory apps become
    available before installed apps, which cuts off installed apps.
  • [apps] Improve app/list with force_fetch=true (#12745)
    - [x] Improve app/list with force_fetch=true, we now keep cached
    snapshot until both install apps and directory apps load.
  • [apps] Enforce simple logo url format. (#12374)
    - [x] Enforce simple logo url format when loading apps directory to save
    bandwidth.
  • app-server: fix flaky list_apps_returns_connectors_with_accessible_flags test (#12286)
    ## Why
    
    `app/list` emits `app/list/updated` after whichever async load finishes
    first (directory connectors or accessible tools). This test assumed the
    directory-backed update always arrived first because it injected a tools
    delay, but that assumption is not stable when the process-global Codex
    Apps tools cache is already warm. In that case the accessible-tools path
    can return immediately and the first notification shape flips, which
    makes the assertion flaky.
    
    Relevant code paths:
    
    -
    [`codex-rs/app-server/src/codex_message_processor.rs`](https://github.com/openai/codex/blob/13ec97d72e3482f16c62e0a22025a0542133e623/codex-rs/app-server/src/codex_message_processor.rs#L4949-L5034)
    (concurrent loads + per-load `app/list/updated` notifications)
    -
    [`codex-rs/core/src/mcp_connection_manager.rs`](https://github.com/openai/codex/blob/13ec97d72e3482f16c62e0a22025a0542133e623/codex-rs/core/src/mcp_connection_manager.rs#L1182-L1197)
    (Codex Apps tools cache hit path)
    
    ## What Changed
    
    Updated
    `suite::v2::app_list::list_apps_returns_connectors_with_accessible_flags`
    in `codex-rs/app-server/tests/suite/v2/app_list.rs` to accept either
    valid first `app/list/updated` payload:
    
    - the directory-first snapshot
    - the accessible-tools-first snapshot
    
    The test still keeps the later assertions strict:
    
    - the second `app/list/updated` notification must be the fully merged
    result
    - the final `app/list` response must match the same merged result
    
    I also added an inline comment explaining why the first notification is
    intentionally order-insensitive.
    
    ## Verification
    
    - `cargo test -p codex-app-server`
  • [apps] Expose more fields from apps listing endpoints. (#11706)
    - [x] Expose app_metadata, branding, and labels in AppInfo.
  • [apps] Fix app loading logic. (#11518)
    When `app/list` is called with `force_refetch=True`, we should seed the
    results with what is already cached instead of starting from an empty
    list. Otherwise when we send app/list/updated events, the client will
    first see an empty list of accessible apps and then get the updated one.
  • [apps] Add is_enabled to app info. (#11417)
    - [x] Add is_enabled to app info and the response of `app/list`.
    - [x] Update TUI to have Enable/Disable button on the app detail page.
  • test(app-server): stabilize app/list thread feature-flag test by using file-backed MCP OAuth creds (#11521)
    ## Why
    
    `suite::v2::app_list::list_apps_uses_thread_feature_flag_when_thread_id_is_provided`
    has been flaky in CI. The test exercises `thread/start`, which
    initializes `codex_apps`. In CI/Linux, that path can reach OS
    keyring-backed MCP OAuth credential lookup (`Codex MCP Credentials`) and
    intermittently abort the MCP process (observed stack overflow in
    `zbus`), causing the test to fail before the assertion logic runs.
    
    ## What Changed
    
    - Updated the test config in
    `codex-rs/app-server/tests/suite/v2/app_list.rs` to set
    `mcp_oauth_credentials_store = "file"` in both relevant config-writing
    paths:
    - The in-test config override inside
    `list_apps_uses_thread_feature_flag_when_thread_id_is_provided`
    - `write_connectors_config(...)`, which is used by the v2 `app_list`
    test suite
    - This keeps test coverage focused on thread-scoped app feature flags
    while removing OS keyring/DBus dependency from this test path.
    
    ## How It Was Verified
    
    - `cargo test -p codex-app-server`
    - `cargo test -p codex-app-server
    list_apps_uses_thread_feature_flag_when_thread_id_is_provided --
    --nocapture`
  • [apps] Add thread_id param to optionally load thread config for apps feature check. (#11279)
    - [x] Add thread_id param to optionally load thread config for apps
    feature check
  • [apps] Improve app loading. (#10994)
    There are two concepts of apps that we load in the harness:
    
    - Directory apps, which is all the apps that the user can install.
    - Accessible apps, which is what the user actually installed and can be
    $ inserted and be used by the model. These are extracted from the tools
    that are loaded through the gateway MCP.
    
    Previously we wait for both sets of apps before returning the full apps
    list. Which causes many issues because accessible apps won't be
    available to the UI or the model if directory apps aren't loaded or
    failed to load.
    
    In this PR we are separating them so that accessible apps can be loaded
    separately and are instantly available to be shown in the UI and to be
    provided in model context. We also added an app-server event so that
    clients can subscribe to also get accessible apps without being blocked
    on the full app list.
    
    - [x] Separate accessible apps and directory apps loading.
    - [x] `app/list` request will also emit `app/list/updated` notifications
    that app-server clients can subscribe. Which allows clients to get
    accessible apps list to render in the $ menu without being blocked by
    directory apps.
    - [x] Cache both accessible and directory apps with 1 hour TTL to avoid
    reloading them when creating new threads.
    - [x] TUI improvements to redraw $ menu and /apps menu when app list is
    updated.
  • Upgrade rmcp to 0.14 (#10718)
    - [x] Upgrade rmcp to 0.14
  • [connectors] Support connectors part 2 - slash command and tui (#9728)
    - [x] Support `/apps` slash command to browse the apps in tui.
    - [x] Support inserting apps to prompt using `$`.
    - [x] Lots of simplification/renaming from connectors to apps.
  • [connectors] Support connectors part 1 - App server & MCP (#9667)
    In order to make Codex work with connectors, we add a built-in gateway
    MCP that acts as a transparent proxy between the client and the
    connectors. The gateway MCP collects actions that are accessible to the
    user and sends them down to the user, when a connector action is chosen
    to be called, the client invokes the action through the gateway MCP as
    well.
    
     - [x] Add the system built-in gateway MCP to list and run connectors.
     - [x] Add the app server methods and protocol