Commit Graph

2707 Commits

  • fix: leverage codex_utils_cargo_bin() in codex-rs/core/tests/suite (#8887)
    This eliminates our dependency on the `escargot` crate and better
    prepares us for Bazel builds: https://github.com/openai/codex/pull/8875.
  • 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>
  • chore: add small debug client (#8894)
    Small debug client, do not use in production
  • 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
  • fix: windows can now paste non-ascii multiline text (#8774)
    ## Summary
    This PR builds _heavily_ on the work from @occurrent in #8021 - I've
    only added a small fix, added additional tests, and propagated the
    changes to tui2.
    
    From the original PR:
    
    > On Windows, Codex relies on PasteBurst for paste detection because
    bracketed paste is not reliably available via crossterm.
    > 
    > When pasted content starts with non-ASCII characters, input is routed
    through handle_non_ascii_char, which bypasses the normal paste burst
    logic. This change extends the paste burst window for that path, which
    should ensure that Enter is correctly grouped as part of the paste.
    
    
    ## Testing
    - [x] tested locally cross-platform
    - [x] added regression tests
    
    ---------
    
    Co-authored-by: occur <occurring@outlook.com>
  • fix: make the find_resource! macro responsible for the absolutize() call (#8884)
    https://github.com/openai/codex/pull/8879 introduced the
    `find_resource!` macro, but now that I am about to use it in more
    places, I realize that it should take care of this normalization case
    for callers.
    
    Note the `use $crate::path_absolutize::Absolutize;` line is there so
    that users of `find_resource!` do not have to explicitly include
    `path-absolutize` to their own `Cargo.toml`.
  • add ability to disable input temporarily in the TUI. (#8876)
    We will disable input while the elevated sandbox setup is running.
  • Support UserInput::Skill in V2 API. (#8864)
    Allow client to specify explicit skill invocation in v2 API.
  • feat: introduce find_resource! macro that works with Cargo or Bazel (#8879)
    To support Bazelification in https://github.com/openai/codex/pull/8875,
    this PR introduces a new `find_resource!` macro that we use in place of
    our existing logic in tests that looks for resources relative to the
    compile-time `CARGO_MANIFEST_DIR` env var.
    
    To make this work, we plan to add the following to all `rust_library()`
    and `rust_test()` Bazel rules in the project:
    
    ```
    rustc_env = {
        "BAZEL_PACKAGE": native.package_name(),
    },
    ```
    
    Our new `find_resource!` macro reads this value via
    `option_env!("BAZEL_PACKAGE")` so that the Bazel package _of the code
    using `find_resource!`_ is injected into the code expanded from the
    macro. (If `find_resource()` were a function, then
    `option_env!("BAZEL_PACKAGE")` would always be
    `codex-rs/utils/cargo-bin`, which is not what we want.)
    
    Note we only consider the `BAZEL_PACKAGE` value when the `RUNFILES_DIR`
    environment variable is set at runtime, indicating that the test is
    being run by Bazel. In this case, we have to concatenate the runtime
    `RUNFILES_DIR` with the compile-time `BAZEL_PACKAGE` value to build the
    path to the resource.
    
    In testing this change, I discovered one funky edge case in
    `codex-rs/exec-server/tests/common/lib.rs` where we have to _normalize_
    (but not canonicalize!) the result from `find_resource!` because the
    path contains a `common/..` component that does not exist on disk when
    the test is run under Bazel, so it must be semantically normalized using
    the [`path-absolutize`](https://crates.io/crates/path-absolutize) crate
    before it is passed to `dotslash fetch`.
    
    Because this new behavior may be non-obvious, this PR also updates
    `AGENTS.md` to make humans/Codex aware that this API is preferred.
  • add footer note to TUI (#8867)
    This will be used by the elevated sandbox NUX to give a hint on how to
    run the elevated sandbox when in the non-elevated mode.
  • fix: use tokio for I/O in an async function (#8868)
    I thought this might solve a bug I'm working on, but it turned out to be
    a red herring. Nevertheless, this seems like the right thing to do here.
  • fix: update resource path resolution logic so it works with Bazel (#8861)
    The Bazelification work in-flight over at
    https://github.com/openai/codex/pull/8832 needs this fix so that Bazel
    can find the path to the DotSlash file for `bash`.
    
    With this change, the following almost works:
    
    ```
    bazel test --test_output=errors //codex-rs/exec-server:exec-server-all-test
    ```
    
    That is, now the `list_tools` test passes, but
    `accept_elicitation_for_prompt_rule` still fails because it runs
    Seatbelt itself, so it needs to be run outside Bazel's local sandboxing.
  • 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.
  • Warn in /model if BASE_URL set (#8847)
    <img width="763" height="349" alt="Screenshot 2026-01-07 at 18 37 59"
    src="https://github.com/user-attachments/assets/569d01cb-ea91-4113-889b-ba74df24adaf"
    />
    
    It may not make sense to use the `/model` menu with a custom
    OPENAI_BASE_URL. But some model proxies may support it, so we shouldn't
    disable it completely. A warning is a reasonable compromise.
  • Clarify YAML frontmatter formatting in skill-creator (#8610)
    Fixes #8609
    
    # Summary
    
    Emphasize single-line name/description values and quoting when values
    could be interpreted as YAML syntax.
    
    # Testing
    
    Not run (skill-only change.)
  • Add feature for optional request compression (#8767)
    Adds a new feature
    `enable_request_compression` that will compress using zstd requests to
    the codex-backend. Currently only enabled for codex-backend so only enabled for openai providers when using chatgpt::auth even when the feature is enabled
    
    Added a new info log line too for evaluating the compression ratio and
    overhead off compressing before requesting. You can enable with
    `RUST_LOG=$RUST_LOG,codex_client::transport=info`
    
    ```
    2026-01-06T00:09:48.272113Z  INFO codex_client::transport: Compressed request body with zstd pre_compression_bytes=28914 post_compression_bytes=11485 compression_duration_ms=0
    ```
  • Override truncation policy at model info level (#8856)
    We used to override truncation policy by comparing model info vs config
    value in context manager. A better way to do it is to construct model
    info using the config value
  • fix: implement 'Allow this session' for apply_patch approvals (#8451)
    **Summary**
    This PR makes “ApprovalDecision::AcceptForSession / don’t ask again this
    session” actually work for `apply_patch` approvals by caching approvals
    based on absolute file paths in codex-core, properly wiring it through
    app-server v2, and exposing the choice in both TUI and TUI2.
    - This brings `apply_patch` calls to be at feature-parity with general
    shell commands, which also have a "Yes, and don't ask again" option.
    - This also fixes VSCE's "Allow this session" button to actually work.
    
    While we're at it, also split the app-server v2 protocol's
    `ApprovalDecision` enum so execpolicy amendments are only available for
    command execution approvals.
    
    **Key changes**
    - Core: per-session patch approval allowlist keyed by absolute file
    paths
    - Handles multi-file patches and renames/moves by recording both source
    and destination paths for `Update { move_path: Some(...) }`.
    - Extend the `Approvable` trait and `ApplyPatchRuntime` to work with
    multiple keys, because an `apply_patch` tool call can modify multiple
    files. For a request to be auto-approved, we will need to check that all
    file paths have been approved previously.
    - App-server v2: honor AcceptForSession for file changes
    - File-change approval responses now map AcceptForSession to
    ReviewDecision::ApprovedForSession (no longer downgraded to plain
    Approved).
    - Replace `ApprovalDecision` with two enums:
    `CommandExecutionApprovalDecision` and `FileChangeApprovalDecision`
    - TUI / TUI2: expose “don’t ask again for these files this session”
    - Patch approval overlays now include a third option (“Yes, and don’t
    ask again for these files this session (s)”).
        - Snapshot updates for the approval modal.
    
    **Tests added/updated**
    - Core:
    - Integration test that proves ApprovedForSession on a patch skips the
    next patch prompt for the same file
    - App-server:
    - v2 integration test verifying
    FileChangeApprovalDecision::AcceptForSession works properly
    
    **User-visible behavior**
    - When the user approves a patch “for session”, future patches touching
    only those previously approved file(s) will no longer prompt gain during
    that session (both via app-server v2 and TUI/TUI2).
    
    **Manual testing**
    Tested both TUI and TUI2 - see screenshots below.
    
    TUI:
    <img width="1082" height="355" alt="image"
    src="https://github.com/user-attachments/assets/adcf45ad-d428-498d-92fc-1a0a420878d9"
    />
    
    
    TUI2:
    <img width="1089" height="438" alt="image"
    src="https://github.com/user-attachments/assets/dd768b1a-2f5f-4bd6-98fd-e52c1d3abd9e"
    />
  • Fix app-server write_models_cache to treat models with less priority number as higher priority. (#8844)
    Rank models with p0 higher than p1. This shouldn't result in any
    behavioral changes. Just reordering.
  • remove unnecessary todos (#8842)
    > // todo(aibrahim): why are we passing model here while it can change?
    
    we update it on each turn with `.with_model`
    
    > //TODO(aibrahim): run CI in release mode.
    
    although it's good to have, release builds take double the time tests
    take.
    
    > // todo(aibrahim): make this async function
    
    we figured out another way of doing this sync
  • Merge Modelfamily into modelinfo (#8763)
    - Merge ModelFamily into ModelInfo
    - Remove logic for adding instructions to apply patch
    - Add compaction limit and visible context window to `ModelInfo`
  • fix: upgrade lru crate to 0.16.3 (#8845)
    See https://rustsec.org/advisories/RUSTSEC-2026-0002.
    
    Though our `ratatui` fork has a transitive dep on an older version of
    the `lru` crate, so to get CI green ASAP, this PR also adds an exception
    to `deny.toml` for `RUSTSEC-2026-0002`, but hopefully this will be
    short-lived.
  • Move tests below auth manager (#8840)
    To simplify future diffs
  • chore: unify conversation with thread name (#8830)
    Done and verified by Codex + refactor feature of RustRover
  • fix: handle early codex exec exit (#8825)
    Fixes CodexExec to avoid missing early process exits by registering the
    exit handler up front and deferring the error until after stdout is
    drained, and adds a regression test that simulates a fast-exit child
    while still producing output so hangs are caught.
  • fix: handle /review arguments in TUI (#8823)
    Handle /review <instructions> in the TUI and TUI2 by routing it as a
    custom review command instead of plain text, wiring command dispatch and
    adding composer coverage so typing /review text starts a review directly
    rather than posting a message. User impact: /review with arguments now
    kicks off the review flow, previously it would just forward as a plain
    command and not actually start a review.
  • fix: parse git apply paths correctly (#8824)
    Fixes apply.rs path parsing so 
    - quoted diff headers are tokenized and extracted correctly, 
    - /dev/null headers are ignored before prefix stripping to avoid bogus
    dev/null paths, and
    - git apply output paths are unescaped from C-style quoting.
    
    **Why**
    This prevents potentially missed staging and misclassified paths when
    applying or reverting patches, which could lead to incorrect behavior
    for repos with spaces or escaped characters in filenames.
    
    **Impact**
    I checked and this is only used in the cloud tasks support and `codex
    apply <task_id>` flow.
  • chore: silent just fmt (#8820)
    Done to avoid spammy warnings to end up in the model context without
    having to switch to nightly
    ```
    Warning: can't set `imports_granularity = Item`, unstable features are only available in nightly channel.
    ```
  • chore: stabilize core tool parallelism test (#8805)
    Set login=false for the shell tool in the timing-based parallelism test
    so it does not depend on slow user login shells, making the test
    deterministic without user-facing changes. This prevents occasional
    flakes when running locally.
  • Enable model upgrade popup even when selected model is no longer in picker (#8802)
    With `config.toml`:
    ```
    model = "gpt-5.1-codex"
    ```
    (where `gpt-5.1-codex` has `show_in_picker: false` in
    [`model_presets.rs`](https://github.com/openai/codex/blob/main/codex-rs/core/src/models_manager/model_presets.rs);
    this happens if the user hasn't used codex in a while so they didn't see
    the popup before their model was changed to `show_in_picker: false`)
    
    The upgrade picker used to not show (because `gpt-5.1-codex` was
    filtered out of the model list in code). Now, the filtering is done
    downstream in tui and app-server, so the model upgrade popup shows:
    
    <img width="1503" height="227" alt="Screenshot 2026-01-06 at 5 04 37 PM"
    src="https://github.com/user-attachments/assets/26144cc2-0b3f-4674-ac17-e476781ec548"
    />
  • fix: truncate long approval prefixes when rendering (#8734)
    Fixes inscrutable multiline approval requests:
    <img width="686" height="844" alt="image"
    src="https://github.com/user-attachments/assets/cf9493dc-79e6-4168-8020-0ef0fe676d5e"
    />
  • fix: populate the release notes when the release is created (#8799)
    Use the contents of the commit message from the commit associated with
    the tag (that contains the version bump) as the release notes by writing
    them to a file and then specifying the file as the `body_path` of
    `softprops/action-gh-release@v2`.
  • add web_search_cached flag (#8795)
    Add `web_search_cached` feature to config. Enables `web_search` tool
    with access only to cached/indexed results (see
    [docs](https://platform.openai.com/docs/guides/tools-web-search#live-internet-access)).
    
    This takes precedence over the existing `web_search_request`, which
    continues to enable `web_search` over live results as it did before.
    
    `web_search_cached` is disabled for review mode, as `web_search_request`
    is.
  • [app-server] fix config loading for conversations (#8765)
    Currently we don't load config properly for app server conversations.
    see:
    https://linear.app/openai/issue/CODEX-3956/config-flags-not-respected-in-codex-app-server.
    This PR fixes that by respecting the config passed in.
    
    Tested by running `cargo build -p codex-cli &&
    RUST_LOG=codex_app_server=debug CODEX_BIN=target/debug/codex cargo run
    -p codex-app-server-test-client -- \
    --config
    model_providers.mock_provider.base_url=\"http://localhost:4010/v2\" \
        --config model_provider=\"mock_provider\" \
        --config model_providers.mock_provider.name="hello" \
        send-message-v2 "hello"`
    and verified that the mock_provider is called instead of default
    provider.
    
    #closes
    https://linear.app/openai/issue/CODEX-3956/config-flags-not-respected-in-codex-app-server
    
    ---------
    
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • feat(app-server): thread/rollback API (#8454)
    Add `thread/rollback` to app-server to support IDEs undo-ing the last N
    turns of a thread.
    
    For context, an IDE partner will be supporting an "undo" capability
    where the IDE (the app-server client) will be responsible for reverting
    the local changes made during the last turn. To support this well, we
    also need a way to drop the last turn (or more generally, the last N
    turns) from the agent's context. This is what `thread/rollback` does.
    
    **Core idea**: A Thread rollback is represented as a persisted event
    message (EventMsg::ThreadRollback) in the rollout JSONL file, not by
    rewriting history. On resume, both the model's context (core replay) and
    the UI turn list (app-server v2's thread history builder) apply these
    markers so the pruned history is consistent across live conversations
    and `thread/resume`.
    
    Implementation notes:
    - Rollback only affects agent context and appends to the rollout file;
    clients are responsible for reverting files on disk.
    - If a thread rollback is currently in progress, subsequent
    `thread/rollback` calls are rejected.
    - Because we use `CodexConversation::submit` and codex core tracks
    active turns, returning an error on concurrent rollbacks is communicated
    via an `EventMsg::Error` with a new variant
    `CodexErrorInfo::ThreadRollbackFailed`. app-server watches for that and
    sends the BAD_REQUEST RPC response.
    
    Tests cover thread rollbacks in both core and app-server, including when
    `num_turns` > existing turns (which clears all turns).
    
    **Note**: this explicitly does **not** behave like `/undo` which we just
    removed from the CLI, which does the opposite of what `thread/rollback`
    does. `/undo` reverts local changes via ghost commits/snapshots and does
    not modify the agent's context / conversation history.