Commit Graph

1780 Commits

  • Reuse websocket connection (#9127)
    Reuses the connection but still sends full requests.
  • Add model client sessions (#9102)
    Maintain a long-running session.
  • Assemble sandbox/approval/network prompts dynamically (#8961)
    - Add a single builder for developer permissions messaging that accepts
    SandboxPolicy and approval policy. This builder now drives the developer
    “permissions” message that’s injected at session start and any time
    sandbox/approval settings change.
    - Trim EnvironmentContext to only include cwd, writable roots, and
    shell; removed sandbox/approval/network duplication and adjusted XML
    serialization and tests accordingly.
    
    Follow-up: adding a config value to replace the developer permissions
    message for custom sandboxes.
  • feat: hot reload mcp servers (#8957)
    ### Summary
    * Added `mcpServer/refresh` command to inform app servers and active
    threads to refresh mcpServer on next turn event.
    * Added `pending_mcp_server_refresh_config` to codex core so that if the
    value is populated, we reinitialize the mcp server manager on the thread
    level.
    * The config is updated on `mcpServer/refresh` command which we iterate
    through threads and provide with the latest config value after last
    write.
  • nit: add docstring (#9099)
    Add docstring on `ToolHandler` trait
  • Add static mcp callback uri support (#8971)
    Currently the callback URI for MCP authentication is dynamically
    generated. More specifically, the callback URI is dynamic because the
    port part of it is randomly chosen by the OS. This is not ideal as
    callback URIs are recommended to be static and many authorization
    servers do not support dynamic callback URIs.
    
    This PR fixes that issue by exposing a new config option named
    `mcp_oauth_callback_port`. When it is set, the callback URI is
    constructed using this port rather than a random one chosen by the OS,
    thereby making callback URI static.
    
    Related issue: https://github.com/openai/codex/issues/8827
  • feat: add close tool implementation for collab (#9090)
    Pretty straight forward. A known follow-up will be to drop it from the
    AgentControl
  • feat: add wait tool implementation for collab (#9088)
    Add implementation for the `wait` tool.
    
    For this we consider all status different from `PendingInit` and
    `Running` as terminal. The `wait` tool call will return either after a
    given timeout or when the tool reaches a non-terminal status.
    
    A few points to note:
    * The usage of a channel is preferred to prevent some races (just
    looping on `get_status()` could "miss" a terminal status)
    * The order of operations is very important, we need to first subscribe
    and then check the last known status to prevent race conditions
    * If the channel gets dropped, we return an error on purpose
  • Label attached images so agent can understand in-message labels (#8950)
    Agent wouldn't "see" attached images and would instead try to use the
    view_file tool:
    <img width="1516" height="504" alt="image"
    src="https://github.com/user-attachments/assets/68a705bb-f962-4fc1-9087-e932a6859b12"
    />
    
    In this PR, we wrap image content items in XML tags with the name of
    each image (now just a numbered name like `[Image #1]`), so that the
    model can understand inline image references (based on name). We also
    put the image content items above the user message which the model seems
    to prefer (maybe it's more used to definitions being before references).
    
    We also tweak the view_file tool description which seemed to help a bit
    
    Results on a simple eval set of images:
    
    Before
    <img width="980" height="310" alt="image"
    src="https://github.com/user-attachments/assets/ba838651-2565-4684-a12e-81a36641bf86"
    />
    
    After
    <img width="918" height="322" alt="image"
    src="https://github.com/user-attachments/assets/10a81951-7ee6-415e-a27e-e7a3fd0aee6f"
    />
    
    ```json
    [
      {
        "id": "single_describe",
        "prompt": "Describe the attached image in one sentence.",
        "images": ["image_a.png"]
      },
      {
        "id": "single_color",
        "prompt": "What is the dominant color in the image? Answer with a single color word.",
        "images": ["image_b.png"]
      },
      {
        "id": "orientation_check",
        "prompt": "Is the image portrait or landscape? Answer in one sentence.",
        "images": ["image_c.png"]
      },
      {
        "id": "detail_request",
        "prompt": "Look closely at the image and call out any small details you notice.",
        "images": ["image_d.png"]
      },
      {
        "id": "two_images_compare",
        "prompt": "I attached two images. Are they the same or different? Briefly explain.",
        "images": ["image_a.png", "image_b.png"]
      },
      {
        "id": "two_images_captions",
        "prompt": "Provide a short caption for each image (Image 1, Image 2).",
        "images": ["image_c.png", "image_d.png"]
      },
      {
        "id": "multi_image_rank",
        "prompt": "Rank the attached images from most colorful to least colorful.",
        "images": ["image_a.png", "image_b.png", "image_c.png"]
      },
      {
        "id": "multi_image_choice",
        "prompt": "Which image looks more vibrant? Answer with 'Image 1' or 'Image 2'.",
        "images": ["image_b.png", "image_d.png"]
      }
    ]
    ```
  • Add URL to responses error messages (#8984)
    Put the URL in error messages, to aid debugging Codex pointing at wrong
    endpoints.
    
    <img width="759" height="164" alt="Screenshot 2026-01-09 at 16 32 49"
    src="https://github.com/user-attachments/assets/77a0622c-955d-426d-86bb-c035210a4ecc"
    />
  • fix: add tui.alternate_screen config and --no-alt-screen CLI flag for Zellij scrollback (#8555)
    Fixes #2558
    
    Codex uses alternate screen mode (CSI 1049) which, per xterm spec,
    doesn't support scrollback. Zellij follows this strictly, so users can't
    scroll back through output.
    
    **Changes:**
    - Add `tui.alternate_screen` config: `auto` (default), `always`, `never`
    - Add `--no-alt-screen` CLI flag
    - Auto-detect Zellij and skip alt screen (uses existing `ZELLIJ` env var
    detection)
    
    **Usage:**
    ```bash
    # CLI flag
    codex --no-alt-screen
    
    # Or in config.toml
    [tui]
    alternate_screen = "never"
    ```
    
    With default `auto` mode, Zellij users get working scrollback without
    any config changes.
    
    ---------
    
    Co-authored-by: Josh McKinney <joshka@openai.com>
  • Add config to disable /feedback (#8909)
    Some enterprises do not want their users to be able to `/feedback`.
    
    <img width="395" height="325" alt="image"
    src="https://github.com/user-attachments/assets/2dae9c0b-20c3-4a15-bcd3-0187857ebbd8"
    />
    
    Adds to `config.toml`:
    
    ```toml
    [feedback]
    enabled = false
    ```
    
    I've deliberately decided to:
    1. leave other references to `/feedback` (e.g. in the interrupt message,
    tips of the day) unchanged. I think we should continue to promote the
    feature even if it is not usable currently.
    2. leave the `/feedback` menu item selectable and display an error
    saying it's disabled, rather than remove the menu item (which I believe
    would raise more questions).
    
    but happy to discuss these.
    
    This will be followed by a change to requirements.toml that admins can
    use to force the value of feedback.enabled.
  • fix(app-server): set originator header from initialize JSON-RPC request (#8873)
    **Motivation**
    The `originator` header is important for codex-backend’s Responses API
    proxy because it identifies the real end client (codex cli, codex vscode
    extension, codex exec, future IDEs) and is used to categorize requests
    by client for our enterprise compliance API.
    
    Today the `originator` header is set by either:
    - the `CODEX_INTERNAL_ORIGINATOR_OVERRIDE` env var (our VSCode extension
    does this)
    - calling `set_default_originator()` which sets a global immutable
    singleton (`codex exec` does this)
    
    For `codex app-server`, we want the `initialize` JSON-RPC request to set
    that header because it is a natural place to do so. Example:
    ```json
    {
      "method": "initialize",
      "id": 0,
      "params": {
        "clientInfo": {
          "name": "codex_vscode",
          "title": "Codex VS Code Extension",
          "version": "0.1.0"
        }
      }
    }
    ```
    and when app-server receives that request, it can call
    `set_default_originator()`. This is a much more natural interface than
    asking third party developers to set an env var.
    
    One hiccup is that `originator()` reads the global singleton and locks
    in the value, preventing a later `set_default_originator()` call from
    setting it. This would be fine but is brittle, since any codepath that
    calls `originator()` before app-server can process an `initialize`
    JSON-RPC call would prevent app-server from setting it. This was
    actually the case with OTEL initialization which runs on boot, but I
    also saw this behavior in certain tests.
    
    Instead, what we now do is:
    - [unchanged] If `CODEX_INTERNAL_ORIGINATOR_OVERRIDE` env var is set,
    `originator()` would return that value and `set_default_originator()`
    with some other value does NOT override it.
    - [new] If no env var is set, `originator()` would return the default
    value which is `codex_cli_rs` UNTIL `set_default_originator()` is called
    once, in which case it is set to the new value and becomes immutable.
    Later calls to `set_default_originator()` returns
    `SetOriginatorError::AlreadyInitialized`.
    
    **Other notes**
    - I updated `codex_core::otel_init::build_provider` to accepts a service
    name override, and app-server sends a hardcoded `codex_app_server`
    service name to distinguish it from `codex_cli_rs` used by default (e.g.
    TUI).
    
    **Next steps**
    - Update VSCE to set the proper value for `clientInfo.name` on
    `initialize` and drop the `CODEX_INTERNAL_ORIGINATOR_OVERRIDE` env var.
    - Delete support for `CODEX_INTERNAL_ORIGINATOR_OVERRIDE` in codex-rs.
  • [device-auth] When headless environment is detected, show device login flow instead. (#8756)
    When headless environment is detected, show device login flow instead.
  • Add 5s timeout to models list call + integration test (#8942)
    - Enforce a 5s timeout around the remote models refresh to avoid hanging
    /models calls.
  • fix: treat null MCP resource args as empty (#8917)
    Handle null tool arguments in the MCP resource handler so optional
    resource tools accept null without failing, preserving normal JSON
    parsing for non-null payloads and improving robustness when models emit
    null; this avoids spurious argument parse errors for list/read MCP
    resource calls.
  • Elevated sandbox NUX (#8789)
    Elevated Sandbox NUX:
    
    * prompt for elevated sandbox setup when agent mode is selected (via
    /approvals or at startup)
    * prompt for degraded sandbox if elevated setup is declined or fails
    * introduce /elevate-sandbox command to upgrade from degraded
    experience.
  • Attempt to reload auth as a step in 401 recovery (#8880)
    When authentication fails, first attempt to reload the auth from file
    and then attempt to refresh it.
  • feat: fork conversation/thread (#8866)
    ## Summary
    - add thread/conversation fork endpoints to the protocol (v1 + v2)
    - implement fork handling in app-server using thread manager and config
    overrides
    - add fork coverage in app-server tests and document `thread/fork` usage
  • Immutable CodexAuth (#8857)
    Historically we started with a CodexAuth that knew how to refresh it's
    own tokens and then added AuthManager that did a different kind of
    refresh (re-reading from disk).
    
    I don't think it makes sense for both `CodexAuth` and `AuthManager` to
    be mutable and contain behaviors.
    
    Move all refresh logic into `AuthManager` and keep `CodexAuth` as a data
    object.
  • Add read-only when backfilling requirements from managed_config (#8913)
    When a user has a managed_config which doesn't specify read-only, Codex
    fails to launch.
  • fix: preserve core env vars on Windows (#8897)
    This updates core shell environment policy handling to match Windows
    case-insensitive variable names and adds a Windows-only regression test,
    so Path/TEMP are no longer dropped when inherit=core.
  • config requirements: improve requirement error messages (#8843)
    **Before:**
    ```
    Error loading configuration: value `Never` is not in the allowed set [OnRequest]
    ```
    
    **After:**
    ```
    Error loading configuration: invalid value for `approval_policy`: `Never` is not in the
    allowed set [OnRequest] (set by MDM com.openai.codex:requirements_toml_base64)
    ```
    
    Done by introducing a new struct `ConfigRequirementsWithSources` onto
    which we `merge_unset_fields` now. Also introduces a pair of requirement
    value and its `RequirementSource` (inspired by `ConfigLayerSource`):
    
    ```rust
    pub struct Sourced<T> {
        pub value: T,
        pub source: RequirementSource,
    }
    ```
  • Avoid setpgid for inherited stdio on macOS (#8691)
    ## Summary
    - avoid setting a new process group when stdio is inherited (keeps child
    in foreground PG)
    - keep process-group isolation when stdio is redirected so killpg
    cleanup still works
    - prevents macOS job-control SIGTTIN stops that look like hangs after
    output
    
    ## Testing
    - `cargo build -p codex-cli`
    - `GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_NOSYSTEM=1
    CARGO_BIN_EXE_codex=/Users/denis/Code/codex/codex-rs/target/debug/codex
    /opt/homebrew/bin/timeout 30m cargo test -p codex-core -p codex-exec`
    
    ## Context
    This fixes macOS sandbox hangs for commands like `elixir -v` / `erl
    -noshell`, where the child was moved into a new process group while
    still attached to the controlling TTY. See issue #8690.
    
    ## Authorship & collaboration
    - This change and analysis were authored by **Codex** (AI coding agent).
    - Human collaborator: @seeekr provided repro environment, context, and
    review guidance.
    - CLI used: `codex-cli 0.77.0`.
    - Model: `gpt-5.2-codex (xhigh)`.
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • fix: include project instructions in /review subagent (#8899)
    Include project-level AGENTS.md and skills in /review sessions so the
    review sub-agent uses the same instruction pipeline as standard runs,
    keeping reviewer context aligned with normal sessions.
  • chore: drop metrics exporter config (#8892)
    Dropped for now as enterprises should not be able to use it
  • fix: stabilize list_dir pagination order (#8826)
    Sort list_dir entries before applying offset/limit so pagination matches
    the displayed order, update pagination/truncation expectations, and add
    coverage for sorted pagination. This ensures stable, predictable
    directory pages when list_dir is enabled.
  • feat: metrics capabilities (#8318)
    Add metrics capabilities to Codex. The `README.md` is up to date.
    
    This will not be merged with the metrics before this PR of course:
    https://github.com/openai/codex/pull/8350
  • Feat: appServer.requirementList for requirement.toml (#8800)
    ### Summary
    We are exposing requirements via `requirement/list` method from
    app-server so that we can conditionally disable the agent mode dropdown
    selection in VSCE and correctly setting the default value.
    
    ### Sample output
    #### `etc/codex/requirements.toml`
    <img width="497" height="49" alt="Screenshot 2026-01-06 at 11 32 06 PM"
    src="https://github.com/user-attachments/assets/fbd9402e-515f-4b9e-a158-2abb23e866a0"
    />
    
    #### App server response
    <img width="1107" height="79" alt="Screenshot 2026-01-06 at 11 30 18 PM"
    src="https://github.com/user-attachments/assets/c0d669cd-54ef-4789-a26c-adb2c41950af"
    />
  • Support symlink for skills discovery. (#8801)
    Skills discovery now follows symlink entries for SkillScope::User
    ($CODEX_HOME/skills) and SkillScope::Admin (e.g. /etc/codex/skills).
    
    Added cycle protection: directories are canonicalized and tracked in a
    visited set to prevent infinite traversal from circular links.
    
    Added per-root traversal limits to avoid accidentally scanning huge
    trees:
    - max depth: 6
    - max directories: 2000 (logs a warning if truncated)
    
    For now, symlink stat failures and traversal truncation are logged
    rather than surfaced as UI “invalid SKILL.md” warnings.