Commit Graph

1727 Commits

  • fix: increase timeout for tests that have been flaking with timeout issues (#8932)
    I have seen this test flake out sometimes when running the macOS build
    using Bazel in CI: https://github.com/openai/codex/pull/8875. Perhaps
    Bazel runs with greater parallelism, inducing a heavier load, causing an
    issue?
  • 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.
  • Update models.json (#8792)
    Automated update of models.json.
    
    Co-authored-by: aibrahim-oai <219906144+aibrahim-oai@users.noreply.github.com>
  • 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,
    }
    ```
  • 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>
  • 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: 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.
  • 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.
  • 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"
    />
  • 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`
  • 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
  • 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"
    />
  • 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.
  • 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.
  • feat: agent controller (#8783)
    Added an agent control plane that lets sessions spawn or message other
    conversations via `AgentControl`.
    
    `AgentBus` (core/src/agent/bus.rs) keeps track of the last known status
    of a conversation.
    
    ConversationManager now holds shared state behind an Arc so AgentControl
    keeps only a weak back-reference, the goal is just to avoid explicit
    cycle reference.
    
    Follow-ups:
    * Build a small tool in the TUI to be able to see every agent and send
    manual message to each of them
    * Handle approval requests in this TUI
    * Add tools to spawn/communicate between agents (see related design)
    * Define agent types
  • Use ConfigLayerStack for skills discovery. (#8497)
    Use ConfigLayerStack to get all folders while loading skills.
  • feat: add justification arg to prefix_rule() in *.rules (#8751)
    Adds an optional `justification` parameter to the `prefix_rule()`
    execpolicy DSL so policy authors can attach human-readable rationale to
    a rule. That justification is propagated through parsing/matching and
    can be surfaced to the model (or approval UI) when a command is blocked
    or requires approval.
    
    When a command is rejected (or gated behind approval) due to policy, a
    generic message makes it hard for the model/user to understand what went
    wrong and what to do instead. Allowing policy authors to supply a short
    justification improves debuggability and helps guide the model toward
    compliant alternatives.
    
    Example:
    
    ```python
    prefix_rule(
        pattern = ["git", "push"],
        decision = "forbidden",
        justification = "pushing is blocked in this repo",
    )
    ```
    
    If Codex tried to run `git push origin main`, now the failure would
    include:
    
    ```
    `git push origin main` rejected: pushing is blocked in this repo
    ```
    
    whereas previously, all it was told was:
    
    ```
    execpolicy forbids this command
    ```
  • chore: improve skills render section (#8459)
    This change improves the skills render section
    - Separate the skills list from usage rules with clear subheadings
    - Define skill more clearly upfront
    - Remove confusing trigger/discovery wording and make reference-following guidance more actionable