Commit Graph

2689 Commits

  • 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.
  • Clear copy pill background and add snapshot test (#8777)
    ### Motivation
    - Fix a visual bug where transcript text could bleed through the
    on-screen copy "pill" overlay.
    - Ensure the copy affordance fully covers the underlying buffer so the
    pill background is solid and consistent with styling.
    - Document the approach in-code to make the background-clearing
    rationale explicit.
    
    ### Description
    - Clear the pill area before drawing by iterating `Rect::positions()`
    and calling `cell.set_symbol(" ")` and `cell.set_style(base_style)` in
    `render_copy_pill` in `transcript_copy_ui.rs`.
    - Added an explanatory comment for why the pill background is explicitly
    cleared.
    - Added a unit test `copy_pill_clears_background` and committed the
    corresponding snapshot file to validate the rendering behavior.
    
    ### Testing
    - Ran `just fmt` (formatting completed; non-blocking environment warning
    may appear).
    - Ran `just fix -p codex-tui2` to apply lints/fixes (completed). 
    - Ran `cargo test -p codex-tui2` and all tests passed (snapshot updated
    and tests succeeded).
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_695c9b23e9b8832997d5a457c4d83410)
  • 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
  • feat: forced tool tips (#8752)
    Force an announcement tooltip in the CLI. This query the gh repo on this
    [file](https://raw.githubusercontent.com/openai/codex/main/announcement_tip.toml)
    which contains announcements in TOML looking like this:
    ```
    # Example announcement tips for Codex TUI.
    # Each [[announcements]] entry is evaluated in order; the last matching one is shown.
    # Dates are UTC, formatted as YYYY-MM-DD. The from_date is inclusive and the to_date is exclusive.
    # version_regex matches against the CLI version (env!("CARGO_PKG_VERSION")); omit to apply to all versions.
    # target_app specify which app should display the announcement (cli, vsce, ...).
    
    [[announcements]]
    content = "Welcome to Codex! Check out the new onboarding flow."
    from_date = "2024-10-01"
    to_date = "2024-10-15"
    version_regex = "^0\\.0\\.0$"
    target_app = "cli"
    ``` 
    
    To make this efficient, the announcement is queried on a best effort
    basis at the launch of the CLI (no refresh made after this).
    This is done in an async way and we display the announcement (with 100%
    probability) iff the announcement is available, the cache is correctly
    warmed and there is a matching announcement (matching is recomputed for
    each new session).
  • chore: add model/list call to app-server-test-client (#8331)
    Allows us to run `cargo run -p codex-app-server-test-client --
    model-list` to return the list of models over app-server.
  • fix: update model examples to gpt-5.2 (#8566)
    The models are outdated and sometime get used by GPT when it to try
    delegate.
    
    I have read the CLA Document and I hereby sign the CLA
  • fix: fix readiness subscribe token wrap-around (#8770)
    Fixes ReadinessFlag::subscribe to avoid handing out token 0 or duplicate
    tokens on i32 wrap-around, adds regression tests, and prevents readiness
    gates from getting stuck waiting on an unmarkable or mis-authorized
    token.
  • fix: render cwd-relative paths in tui (#8771)
    Display paths relative to the cwd before checking git roots so view
    image tool calls keep project-local names in jj/no-.git workspaces.
  • tui2: stop baking streaming wraps; reflow agent markdown (#8761)
    Background
    Streaming assistant prose in tui2 was being rendered with viewport-width
    wrapping during streaming, then stored in history cells as already split
    `Line`s. Those width-derived breaks became indistinguishable from hard
    newlines, so the transcript could not "un-split" on resize. This also
    degraded copy/paste, since soft wraps looked like hard breaks.
    
    What changed
    - Introduce width-agnostic `MarkdownLogicalLine` output in
    `tui2/src/markdown_render.rs`, preserving markdown wrap semantics:
    initial/subsequent indents, per-line style, and a preformatted flag.
    - Update the streaming collector (`tui2/src/markdown_stream.rs`) to emit
    logical lines (newline-gated) and remove any captured viewport width.
    - Update streaming orchestration (`tui2/src/streaming/*`) to queue and
    emit logical lines, producing `AgentMessageCell::new_logical(...)`.
    - Make `AgentMessageCell` store logical lines and wrap at render time in
    `HistoryCell::transcript_lines_with_joiners(width)`, emitting joiners so
    copy/paste can join soft-wrap continuations correctly.
    
    Overlay deferral
    When an overlay is active, defer *cells* (not rendered `Vec<Line>`) and
    render them at overlay close time. This avoids baking width-derived
    wraps based on a stale width.
    
    Tests + docs
    - Add resize/reflow regression tests + snapshots for streamed agent
    output.
    - Expand module/API docs for the new logical-line streaming pipeline and
    clarify joiner semantics.
    - Align scrollback-related docs/comments with current tui2 behavior
    (main draw loop does not flush queued "history lines" to the terminal).
    
    More details
    See `codex-rs/tui2/docs/streaming_wrapping_design.md` for the full
    problem statement and solution approach, and
    `codex-rs/tui2/docs/tui_viewport_and_history.md` for viewport vs printed
    output behavior.
  • fix: accept whitespace-padded patch markers (#8746)
    Trim whitespace when validating '*** Begin Patch'/'*** End Patch'
    markers in codex-apply-patch so padded marker lines parse as intended,
    and add regression coverage (unit + fixture scenario); this avoids
    apply_patch failures when models include extra spacing. Tested with
    cargo test -p codex-apply-patch.
  • chore(apply-patch) additional scenarios (#8230)
    ## Summary
    More apply-patch scenarios
    
    ## Testing
    - [x] This pr only adds tests
  • Allow global exec flags after resume and fix CI codex build/timeout (#8440)
    **Motivation**
    - Bring `codex exec resume` to parity with top‑level flags so global
    options (git check bypass, json, model, sandbox toggles) work after the
    subcommand, including when outside a git repo.
    
    **Description**
    - Exec CLI: mark `--skip-git-repo-check`, `--json`, `--model`,
    `--full-auto`, and `--dangerously-bypass-approvals-and-sandbox` as
    global so they’re accepted after `resume`.
    - Tests: add `exec_resume_accepts_global_flags_after_subcommand` to
    verify those flags work when passed after `resume`.
    
    **Testing**
    - `just fmt`
    - `cargo test -p codex-exec` (pass; ran with elevated perms to allow
    network/port binds)
    - Manual: exercised `codex exec resume` with global flags after the
    subcommand to confirm behavior.