Commit Graph

2382 Commits

  • Elevated Sandbox 3 (#7809)
    dedicated sandbox command runner exe.
  • Chore: limit find family visability (#7891)
    a little bit more code quality of life
  • fix: omit reasoning summary when ReasoningSummary::None (#7845)
    ```
    {
      "error": {
        "message": "Invalid value: 'none'. Supported values are: 'concise', 'detailed', and 'auto'.",
        "type": "invalid_request_error",
        "param": "reasoning.summary",
        "code": "invalid_value"
      }
    }
    ```
  • fix: drop stale filedescriptor output hash for nix (#7865)
    Fixes: #7863 
    
    - Remove the `filedescriptor-0.8.3` entry from `codex-rs/default.nix`
    output hashes because the crate now comes from crates.io.
  • fix: dont quit on 'q' in onboarding ApiKeyEntry state (#7869)
    ### What
    
    Don't treat `q` as a special quit character on the API key paste page in
    the onboarding flow.
    
    This addresses #7413, where pasting API keys with `q` would cause codex
    to quit on Windows.
    
    ### Test Plan
    
    Tested on Windows and MacOS.
  • feat: robin (#7882)
    <img width="554" height="554" alt="image"
    src="https://github.com/user-attachments/assets/aa86f4c8-fb34-4b0e-8b03-3a9980dfdb08"
    />
    
    ---------
    
    Co-authored-by: Dylan Hurd <dylan.hurd@openai.com>
  • fix(stuff) (#7855)
    Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com>
  • Elevated Sandbox 2 (#7792)
    - DPAPI helpers for storing Sandbox user passwords securely
    - creation of Offline/Online sandbox users
    - ACL setup for sandbox users
    - firewall rule setup
  • Fixed regression that broke fuzzy matching for slash commands (#7859)
    This addresses bug #7857 which was introduced recently as part of PR
    #7704.
  • fix: add a hopefully-temporary sleep to reduce test flakiness (#7848)
    Let's see if this `sleep()` call is good enough to fix the test
    flakiness we currently see in CI. It will take me some time to upstream
    a proper fix, and I would prefer not to disable this test in the
    interim.
  • [app-server] make app server not throw error when login id is not found (#7831)
    Our previous design of cancellation endpoint is not idempotent, which
    caused a bunch of flaky tests. Make app server just returned a not_found
    status instead of throwing an error if the login id is not found. Keep
    V1 endpoint behavior the same.
  • fix: ensure accept_elicitation_for_prompt_rule() test passes locally (#7832)
    When I originally introduced `accept_elicitation_for_prompt_rule()` in
    https://github.com/openai/codex/pull/7617, it worked for me locally
    because I had run `codex-rs/exec-server/tests/suite/bash` once myself,
    which had the side-effect of installing the corresponding DotSlash
    artifact.
    
    In CI, I added explicit logic to do this as part of
    `.github/workflows/rust-ci.yml`, which meant the test also passed in CI,
    but this logic should have been done as part of the test so that it
    would work locally for devs who had not installed the DotSlash artifact
    for `codex-rs/exec-server/tests/suite/bash` before. This PR updates the
    test to do this (and deletes the setup logic from `rust-ci.yml`),
    creating a new `DOTSLASH_CACHE` in a temp directory so that this is
    handled independently for each test.
    
    While here, also added a check to ensure that the `codex` binary has
    been built prior to running the test, as we have to ensure it is
    symlinked as `codex-linux-sandbox` on Linux in order for the integration
    test to work on that platform.
  • fix: thread/list returning fewer than the requested amount due to filtering CXA-293 (#7509)
    This caused some conversations to not appear when they otherwise should.
    
    Prior to this change, `thread/list`/`list_conversations_common` would:
    - Fetch N conversations from `RolloutRecorder::list_conversations`
    - Then it would filter those (like by the provided `model_providers`)
    - This would make it potentially return less than N items.
    
    With this change:
    - `list_conversations_common` now continues fetching more conversations
    from `RolloutRecorder::list_conversations` until it "fills up" the
    `requested_page_size`.
    - Ultimately this means that clients can rely on getting eg 20
    conversations if they request 20 conversations.
  • feat(tui2): copy tui crate and normalize snapshots (#7833)
    Introduce a full codex-tui source snapshot under the new codex-tui2
    crate so viewport work can be replayed in isolation.
    
    This change copies the entire codex-rs/tui/src tree into
    codex-rs/tui2/src in one atomic step, rather than piecemeal, to keep
    future diffs vs the original viewport bookmark easy to reason about.
    
    The goal is for codex-tui2 to render identically to the existing TUI
    behind the `features.tui2` flag while we gradually port the
    viewport/history commits from the joshka/viewport bookmark onto this
    forked tree.
    
    While on this baseline change, we also ran the codex-tui2 snapshot test
    suite and accepted all insta snapshots for the new crate, so the
    snapshot files now use the codex-tui2 naming scheme and encode the
    unmodified legacy TUI behavior. This keeps later viewport commits
    focused on intentional behavior changes (and their snapshots) rather
    than on mechanical snapshot renames.
  • Inject SKILL.md when it's explicitly mentioned. (#7763)
    1. Skills load once in core at session start; the cached outcome is
    reused across core and surfaced to TUI via SessionConfigured.
    2. TUI detects explicit skill selections, and core injects the matching
    SKILL.md content into the turn when a selected skill is present.
  • [app-server-protocol] Add types for config (#7658)
    Currently the config returned by `config/read` in untyped. Add types so
    it's easier for client to parse the config. Since currently configs are
    all defined in snake case we'll keep that instead of using camel case
    like the rest of V2.
    
    Sample output by testing using the app server test client:
    ```
    {
    <   "id": "f28449f4-b015-459b-b07b-eef06980165d",
    <   "result": {
    <     "config": {
    <       "approvalPolicy": null,
    <       "compactPrompt": null,
    <       "developerInstructions": null,
    <       "features": {
    <         "experimental_use_rmcp_client": true
    <       },
    <       "forcedChatgptWorkspaceId": null,
    <       "forcedLoginMethod": null,
    <       "instructions": null,
    <       "model": "gpt-5.1-codex-max",
    <       "modelAutoCompactTokenLimit": null,
    <       "modelContextWindow": null,
    <       "modelProvider": null,
    <       "modelReasoningEffort": null,
    <       "modelReasoningSummary": null,
    <       "modelVerbosity": null,
    <       "model_providers": {
    <         "local": {
    <           "base_url": "http://localhost:8061/api/codex",
    <           "env_http_headers": {
    <             "ChatGPT-Account-ID": "OPENAI_ACCOUNT_ID"
    <           },
    <           "env_key": "CHATGPT_TOKEN_STAGING",
    <           "name": "local",
    <           "wire_api": "responses"
    <         }
    <       },
    <       "model_reasoning_effort": "medium",
    <       "notice": {
    <         "hide_gpt-5.1-codex-max_migration_prompt": true,
    <         "hide_gpt5_1_migration_prompt": true
    <       },
    <       "profile": null,
    <       "profiles": {},
    <       "projects": {
    <         "/Users/celia/code": {
    <           "trust_level": "trusted"
    <         },
    <         "/Users/celia/code/codex": {
    <           "trust_level": "trusted"
    <         },
    <         "/Users/celia/code/openai": {
    <           "trust_level": "trusted"
    <         }
    <       },
    <       "reviewModel": null,
    <       "sandboxMode": null,
    <       "sandboxWorkspaceWrite": null,
    <       "tools": {
    <         "viewImage": null,
    <         "webSearch": null
    <       }
    <     },
    <     "origins": {
    <       "features.experimental_use_rmcp_client": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.base_url": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.env_http_headers.ChatGPT-Account-ID": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.env_key": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.name": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_providers.local.wire_api": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "model_reasoning_effort": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "notice.hide_gpt-5.1-codex-max_migration_prompt": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "notice.hide_gpt5_1_migration_prompt": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code/codex.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "projects./Users/celia/code/openai.trust_level": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       },
    <       "tools.web_search": {
    <         "name": "user",
    <         "source": "/Users/celia/.codex/config.toml",
    <         "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c"
    <       }
    <     }
    <   }
    < }
    ```
  • Error when trying to push a release while another release is in progress (#7834)
    <img width="995" height="171" alt="image"
    src="https://github.com/user-attachments/assets/7bab541a-a933-4064-a968-26e9566360ec"
    />
    
    Currently, we just cancel the in progress release which can be annoying
  • fix: Prevent slash command popup from activating on invalid inputs (#7704)
    ## Slash Command popup issue
    
    #7659
    
    When recalling history, the
    composer(`codex_tui::bottom_pane::chat_composer`) restores the previous
    prompt text (which may start with `/`) and then calls
    `sync_command_popup`. The logic in `sync_command_popup` treats any first
    line that starts with `/` and has the caret inside the initial `/name`
    token as an active slash command name:
    
    ```rust
    let is_editing_slash_command_name = if first_line.starts_with('/') && caret_on_first_line {
        let token_end = first_line
            .char_indices()
            .find(|(_, c)| c.is_whitespace())
            .map(|(i, _)| i)
            .unwrap_or(first_line.len());
        cursor <= token_end
    } else {
        false
    };
    ```
    
    This detection does not distinguish between an actual interactive slash
    command being typed and a normal historical prompt that happens to begin
    with `/`. As a result, after history recall, the restored prompt like `/
    test` is interpreted as an "editing command name" context and the
    slash-command popup is (re)activated. Once `active_popup` is
    `ActivePopup::Command`, subsequent `Up` key presses are handled by
    `handle_key_event_with_slash_popup` instead of
    `handle_key_event_without_popup`, so they no longer trigger
    `history.navigate_up(...)` and the session prompt history cannot be
    scrolled.
  • make model optional in config (#7769)
    - Make Config.model optional and centralize default-selection logic in
    ModelsManager, including a default_model helper (with
    codex-auto-balanced when available) so sessions now carry an explicit
    chosen model separate from the base config.
    - Resolve `model` once in `core` and `tui` from config. Then store the
    state of it on other structs.
    - Move refreshing models to be before resolving the default model
  • [app-server] Make sure that config writes preserve comments & order or configs (#7789)
    Make sure that config writes preserve comments and order of configs by
    utilizing the ConfigEditsBuilder in core.
    
    Tested by running a real example and made sure that nothing in the
    config file changes other than the configs to edit.
  • fix: remove duplicated parallel FeatureSpec (#7823)
    regression: #7589
    
    Signed-off-by: Koichi Shiraishi <zchee.io@gmail.com>
  • fix: Upgrade @modelcontextprotocol/sdk to ^1.24.0 (#7817)
    ## What?
    Upgrades @modelcontextprotocol/sdk from ^1.20.2 to ^1.24.0 in the
    TypeScript SDK's devDependencies.
    
    ## Why?
    Related to #7737 - keeping development dependencies up to date with the
    latest MCP SDK version that includes the fix for CVE-2025-66414.
    
    Note: This change does not address the CVE for Codex users, as the MCP
    SDK is only in devDependencies here. The actual MCP integration that
    would be affected by the CVE is in the Rust codebase.
    
    ## How?
    •  Updated dependency version in sdk/typescript/package.json
    •  Ran pnpm install to update lockfile
    •  Fixed formatting (added missing newline in package.json)
    
    ## Related Issue
    Related to #7737
    
    ## Test Status
    ⚠️ After this upgrade, 2 additional tests timeout (1 test was already
    failing on main):
    •  tests/run.test.ts: "sends previous items when run is called twice" 
    •  tests/run.test.ts: "resumes thread by id"
    • tests/runStreamed.test.ts: "sends previous items when runStreamed is
    called twice"
    
    Marking as draft to investigate test timeouts. Maintainer guidance would
    be appreciated.
    
    Co-authored-by: HalfonA <amit@miggo.io>
  • Removed experimental "command risk assessment" feature (#7799)
    This experimental feature received lukewarm reception during internal
    testing. Removing from the code base.
  • refactoring with_escalated_permissions to use SandboxPermissions instead (#7750)
    helpful in the future if we want more granularity for requesting
    escalated permissions:
    e.g when running in readonly sandbox, model can request to escalate to a
    sandbox that allows writes
  • Express rate limit warning as % remaining (#7795)
    <img width="342" height="264" alt="image"
    src="https://github.com/user-attachments/assets/f1e932ff-c550-47b3-9035-0299ada4998d"
    />
    
    Earlier, the warning was expressed as consumed% whereas status was
    expressed as remaining%. This change brings the two into sync to
    minimize confusion and improve visual consistency.
  • Revert "Revert "feat: windows codesign with Azure trusted signing"" (#7757)
    Reverts openai/codex#7753
    
    Updated the tag ref matching at
    https://github.com/openai/openai/pull/594858 so that release with tag
    change can be picked up correctly.
  • Elevated Sandbox 1 (#7788)
    - updating helpers, refactoring some functions that will be used in the
    elevated sandbox
    - better logging
    - better and faster handling of ACL checks/writes
    - No functional change—legacy restricted-token sandbox
    remains the only path.
  • feat: support mcp in-session login (#7751)
    ### Summary
    * Added `mcpServer/oauthLogin` in app server for supporting in session
    MCP server login
    * Added `McpServerOauthLoginParams` and `McpServerOauthLoginResponse` to
    support above method with response returning the auth URL for consumer
    to open browser or display accordingly.
    * Added `McpServerOauthLoginCompletedNotification` which the app server
    would emit on MCP server login success or failure (i.e. timeout).
    * Refactored rmcp-client oath_login to have the ability on starting a
    auth server which the codex_message_processor uses for in-session auth.
  • fix: introduce AbsolutePathBuf and resolve relative paths in config.toml (#7796)
    This PR attempts to solve two problems by introducing a
    `AbsolutePathBuf` type with a special deserializer:
    
    - `AbsolutePathBuf` attempts to be a generally useful abstraction, as it
    ensures, by constructing, that it represents a value that is an
    absolute, normalized path, which is a stronger guarantee than an
    arbitrary `PathBuf`.
    - Values in `config.toml` that can be either an absolute or relative
    path should be resolved against the folder containing the `config.toml`
    in the relative path case. This PR makes this easy to support: the main
    cost is ensuring `AbsolutePathBufGuard` is used inside
    `deserialize_config_toml_with_base()`.
    
    While `AbsolutePathBufGuard` may seem slightly distasteful because it
    relies on thread-local storage, this seems much cleaner to me than using
    than my various experiments with
    https://docs.rs/serde/latest/serde/de/trait.DeserializeSeed.html.
    Further, since the `deserialize()` method from the `Deserialize` trait
    is not async, we do not really have to worry about the deserialization
    work being spread across multiple threads in a way that would interfere
    with `AbsolutePathBufGuard`.
    
    To start, this PR introduces the use of `AbsolutePathBuf` in
    `OtelTlsConfig`. Note how this simplifies `otel_provider.rs` because it
    no longer requires `settings.codex_home` to be threaded through.
    Furthermore, this sets us up better for a world where multiple
    `config.toml` files from different folders could be loaded and then
    merged together, as the absolutifying of the paths must be done against
    the correct parent folder.