Commit Graph

2282 Commits

  • cloud: status, diff, apply (#7614)
    Adds cli commands for getting the status of cloud tasks, and for
    getting/applying the diffs from same.
  • Fix unified_exec on windows (#7620)
    Fix unified_exec on windows
    
    Requires removal of PSUEDOCONSOLE_INHERIT_CURSOR flag so child processed
    don't attempt to wait for cursor position response (and timeout).
    
    
    https://github.com/wezterm/wezterm/compare/main...pakrym:wezterm:PSUEDOCONSOLE_INHERIT_CURSOR?expand=1
    
    ---------
    
    Co-authored-by: pakrym-oai <pakrym@openai.com>
  • feat(core) Add login to shell_command tool (#6846)
    ## Summary
    Adds the `login` parameter to the `shell_command` tool - optional,
    defaults to true.
    
    ## Testing
    - [x] Tested locally
  • Wire with_remote_overrides to construct model families (#7621)
    - This PR wires `with_remote_overrides` and make the
    `construct_model_families` an async function
    - Moves getting model family a level above to keep the function `sync`
    - Updates the tests to local, offline, and `sync` helper for model
    families
  • fix: taking plan type from usage endpoint instead of thru auth token (#7610)
    pull plan type from the usage endpoint, persist it in session state /
    tui state, and propagate through rate limit snapshots
  • feat: exec policy integration in shell mcp (#7609)
    adding execpolicy support into the `posix` mcp
    
    Co-authored-by: Michael Bolin <mbolin@openai.com>
  • Call models endpoint in models manager (#7616)
    - Introduce `with_remote_overrides` and update
    `refresh_available_models`
    - Put `auth_manager` instead of `auth_mode` on `models_manager`
    - Remove `ShellType` and `ReasoningLevel` to use already existing
    structs
  • chore(apply-patch) scenarios for e2e testing (#7567)
    ## Summary
    This PR introduces an End to End test suite for apply-patch, so we can
    easily validate behavior against other implementations as well.
    
    ## Testing
    - [x] These are tests
  • chore: refactor to move Arc<RwLock> concern outside exec_policy_for (#7615)
    The caller should decide whether wrapping the policy in `Arc<RwLock>` is
    necessary. This should make https://github.com/openai/codex/pull/7609 a
    bit smoother.
    
    - `exec_policy_for()` -> `load_exec_policy_for_features()`
    - introduce `load_exec_policy()` that does not take `Features` as an arg
    - both return `Result<Policy, ExecPolicyError>` instead of
    Result<Arc<RwLock<Policy>>, ExecPolicyError>`
    
    This simplifies the tests as they have no need for `Arc<RwLock>`.
  • Fix handle_shortcut_overlay_key for cross-platform consistency (#7583)
    **Summary**
    - Shortcut toggle using `?` in `handle_shortcut_overlay_key` fails to
    trigger on some platforms (notably Windows). Current match requires
    `KeyCode::Char('?')` with `KeyModifiers::NONE`. Some terminals set
    `SHIFT` when producing `?` (since it is typically `Shift + /`), so the
    strict `NONE` check prevents toggling.
    
    **Impact**
    - On Windows consoles/terminals, pressing `?` with an empty composer
    often does nothing, leading to inconsistent UX compared to macOS/Linux.
    
    **Root Cause**
    - Crossterm/terminal backends report modifiers inconsistently across
    platforms. Generating `?` may include `SHIFT`. The code enforces
    `modifiers == NONE`, so valid `?` presses with `SHIFT` are ignored.
    AltGr keyboards may also surface as `ALT`.
    
    **Repro Steps**
    - Open the TUI, ensure the composer is empty.
    - Press `?`.
    - Expected: Shortcut overlay toggles.
    - Actual (Windows frequently): No toggle occurs.
    
    **Fix Options**
    - Option 1 (preferred): Accept `?` regardless of `SHIFT`, but reject
    `CONTROL` and `ALT`.
    - Rationale: Keeps behavior consistent across platforms with minimal
    code change.
    	- Example change:
    		- Before: matching `KeyModifiers::NONE` only.
    		- After: allow `SHIFT`, disallow `CONTROL | ALT`.
    		- Suggested condition:
    			```rust
    			let toggles = matches!(key_event.code, KeyCode::Char('?'))
    && !key_event.modifiers.intersects(KeyModifiers::CONTROL |
    KeyModifiers::ALT)
    					&& self.is_empty();
    			```
    
    - Option 2: Platform-specific handling (Windows vs non-Windows).
    - Implement two variants or conditional branches using `#[cfg(target_os
    = "windows")]`.
    - On Windows, accept `?` with `SHIFT`; on other platforms, retain
    current behavior.
    - Trade-off: Higher maintenance burden and code divergence for limited
    benefit.
    
    ---
    
    close #5495
  • fix(app-server): add will_retry to ErrorNotification (#7611)
    VSCE renders `codex/event/stream_error` (automatically retried, e.g.
    `"Reconnecting... 1/n"`) and `codex/event/error` (terminal errors)
    differently, so add `will_retry` on ErrorNotification to indicate this.
  • fix(app-server): add duration_ms to McpToolCallItem (#7605)
    Seems like a nice field to have, and also VSCE does render this one.
  • Add models endpoint (#7603)
    - Use the codex-api crate to introduce models endpoint. 
    - Add `models` to codex core tests helpers
    - Add `ModelsInfo` for the endpoint return type
  • Inline response recording and remove process_items indirection (#7310)
    - Inline response recording during streaming: `run_turn` now records
    items as they arrive instead of building a `ProcessedResponseItem` list
    and post‑processing via `process_items`.
    - Simplify turn handling: `handle_output_item_done` returns the
    follow‑up signal + optional tool future; `needs_follow_up` is set only
    there, and in‑flight tool futures are drained once at the end (errors
    logged, no extra state writes).
    - Flattened stream loop: removed `process_items` indirection and the
    extra output queue
    - - Tests: relaxed `tool_parallelism::tool_results_grouped` to allow any
    completion order while still requiring matching call/output IDs.
  • add --branch to codex cloud exec (#7602)
    Adds `--branch` to `codex cloud exec` to set base branch.
  • remove model_family from `config (#7571)
    - Remove `model_family` from `config`
    - Make sure to still override config elements related to `model_family`
    like supporting reasoning
  • FIX: WSL Paste image does not work (#6793)
    ## Related issues:  
    - https://github.com/openai/codex/issues/3939  
    - https://github.com/openai/codex/issues/2292  
    - https://github.com/openai/codex/issues/7528 (After correction
    https://github.com/openai/codex/pull/3990)
    
    **Area:** `codex-cli` (image handling / clipboard & file uploads)  
    **Platforms affected:** WSL (Ubuntu on Windows 10/11). No behavior
    change on native Linux/macOS/Windows.
    
    ## Summary
    
    This PR fixes image pasting and file uploads when running `codex-cli`
    inside WSL. Previously, image operations failed silently or with
    permission errors because paths weren't properly mapped between Windows
    and WSL filesystems.
    
    ## Visual Result
    
    <img width="1118" height="798" alt="image"
    src="https://github.com/user-attachments/assets/14e10bc4-6b71-4d1f-b2a6-52c0a67dd069"
    />
    
    ## Last Rust-Cli
    
    <img width="1175" height="859" alt="image"
    src="https://github.com/user-attachments/assets/7ef41e29-9118-42c9-903c-7116d21e1751"
    />
    
    ## Root cause
    
    The CLI assumed native Linux/Windows environments and didn't handle the
    WSL↔Windows boundary:
    
    - Used Linux paths for files that lived on the Windows host
    - Missing path normalization between Windows (`C:\...`) and WSL
    (`/mnt/c/...`)
    - Clipboard access failed under WSL
    
    ### Why `Ctrl+V` doesn't work in WSL terminals
    
    Most WSL terminal emulators (Windows Terminal, ConEmu, etc.) intercept
    `Ctrl+V` at the terminal level to paste text from the Windows clipboard.
    This keypress never reaches the CLI application itself, so our clipboard
    image handler never gets triggered. Users need `Ctrl+Alt+V`.
    
    ## Changes
    
    ### WSL detection & path mapping
    
    - Detects WSL by checking `/proc/sys/kernel/osrelease` and the
    `WSL_INTEROP` env var
    - Maps Windows drive paths to WSL mount paths (`C:\...` → `/mnt/c/...`)
    
    ### Clipboard fallback for WSL
    
    - When clipboard access fails under WSL, falls back to PowerShell to
    extract images from the Windows clipboard
    - Saves to a temp file and maps the path back to WSL
    
    ### UI improvements
    
    - Shows `Ctrl+Alt+V` hint on WSL (many terminals intercept plain
    `Ctrl+V`)
    - Better error messages for unreadable images
    
    ## Performance
    
    - Negligible overhead. The fallback adds a single FS copy to a temp file
    only when needed.
    - Direct streaming remains the default.
    
    ## Files changed
    
    - `protocol/src/lib.rs` – Added platform detection module  
    - `protocol/src/models.rs` – Added WSL path mapping for local images  
    - `protocol/src/platform.rs` – New module with WSL detection utilities  
    - `tui/src/bottom_pane/chat_composer.rs` – Added base64 data URL support
    and WSL path mapping
    - `tui/src/bottom_pane/footer.rs` – WSL-aware keyboard shortcuts  
    - `tui/src/clipboard_paste.rs` – PowerShell clipboard fallback
    
    ## How to reproduce the original bug (pre-fix)
    
    1. Run `codex-cli` inside WSL2 on Windows.  
    2. Paste an image from the Windows clipboard or drag an image from
    `C:\...` into the terminal.
    3. Observe that the image is not attached (silent failure) or an error
    is logged; no artifact reaches the tool.
    
    ## How to verify the fix
    
    1. Build this branch and run `codex-cli` inside WSL2.  
    2. Paste from clipboard and drag from both Windows and WSL paths.  
    3. Confirm that the image appears in the tool and the CLI shows a single
    concise info line (no warning unless fallback was used).
    
    I’m happy to adjust paths, naming, or split helpers into a separate
    module if you prefer.
    
    ## How to try this branch
    
    If you want to try this before it’s merged, you can use my Git branch:
    
    Repository: https://github.com/Waxime64/codex.git  
    Branch: `wsl-image-2`
    
    1. Start WSL on your Windows machine.
    2. Clone the repository and switch to the branch:
       ```bash
       git clone https://github.com/Waxime64/codex.git
       cd codex
       git checkout wsl-image-2
       # then go into the Rust workspace root, e.g.:
       cd codex-rs
    3. Build the TUI binary:
      cargo build -p codex-tui --bin codex-tui --release
    4. Install the binary:
       sudo install -m 0755 target/release/codex-tui /usr/local/bin/codex
    5. From the project directory where you want to use Codex, start it
    with:
       cd /path/to/your/project
       /usr/local/bin/codex
    
    On WSL, use CTRL+ALT+V to paste an image from the Windows clipboard into
    the chat.
  • chore(core): test apply_patch_cli on Windows (#7554)
    ## Summary
    These tests pass on windows, let's enable them.
    
    ## Testing
    - [x] These are more tests
  • feat: update sandbox policy to allow TTY (#7580)
    **Change**: Seatbelt now allows file-ioctl on /dev/ttys[0-9]+ even
    without the sandbox extension so pre-created PTYs remain interactive
    (Python REPL, shells).
    
    **Risk**: A seatbelted process that already holds a PTY fd (including
    one it shouldn’t) could issue tty ioctls like TIOCSTI or termios changes
    on that fd. This doesn’t allow opening new PTYs or reading/writing them;
    it only broadens ioctl capability on existing fds.
    
    **Why acceptable**: We already hand the child its PTY for interactive
    use; restoring ioctls is required for isatty() and prompts to work. The
    attack requires being given or inheriting a sensitive PTY fd; by design
    we don’t hand untrusted processes other users’ PTYs (we don't hand them
    any PTYs actually), so the practical exposure is limited to the PTY
    intentionally allocated for the session.
    
    **Validation**:
    Running
    ```
    start a python interpreter and keep it running
    ```
    Followed by:
    * `calculate 1+1 using it` -> works as expected
    * `Use this Python session to run the command just fix in
    /Users/jif/code/codex/codex-rs` -> does not work as expected
  • execpolicy tui flow (#7543)
    ## Updating the `execpolicy` TUI flow
    
    In the TUI, when going through the command approval flow, codex will now
    ask the user if they would like to whitelist the FIRST unmatched command
    among a chain of commands.
    
    For example, let's say the agent wants to run `apple | pear` with an
    empty `execpolicy`
    
    Neither apple nor pear will match to an `execpolicy` rule. Thus, when
    prompting the user, codex tui will ask the user if they would like to
    whitelist `apple`.
    
    If the agent wants to run `apple | pear` again, they would be prompted
    again because pear is still unknown. when prompted, the user will now be
    asked if they'd like to whitelist `pear`.
    
    Here's a demo video of this flow:
    
    
    https://github.com/user-attachments/assets/fd160717-f6cb-46b0-9f4a-f0a974d4e710
    
    This PR also removed the `allow for this session` option from the TUI.
  • Add Enterprise plan to ChatGPT login description (#6918)
    ## Summary
    - update ChatGPT onboarding login description to mention Enterprise
    plans alongside Plus, Pro, and Team
    
    ## Testing
    - just fmt
    
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_691e088daf20832c88d8b667adf45128)
  • Refactor execpolicy fallback evaluation (#7544)
    ## Refactor of the `execpolicy` crate
    
    To illustrate why we need this refactor, consider an agent attempting to
    run `apple | rm -rf ./`. Suppose `apple` is allowed by `execpolicy`.
    Before this PR, `execpolicy` would consider `apple` and `pear` and only
    render one rule match: `Allow`. We would skip any heuristics checks on
    `rm -rf ./` and immediately approve `apple | rm -rf ./` to run.
    
    To fix this, we now thread a `fallback` evaluation function into
    `execpolicy` that runs when no `execpolicy` rules match a given command.
    In our example, we would run `fallback` on `rm -rf ./` and prevent
    `apple | rm -rf ./` from being run without approval.
  • whitelist command prefix integration in core and tui (#7033)
    this PR enables TUI to approve commands and add their prefixes to an
    allowlist:
    <img width="708" height="605" alt="Screenshot 2025-11-21 at 4 18 07 PM"
    src="https://github.com/user-attachments/assets/56a19893-4553-4770-a881-becf79eeda32"
    />
    
    note: we only show the option to whitelist the command when 
    1) command is not multi-part (e.g `git add -A && git commit -m 'hello
    world'`)
    2) command is not already matched by an existing rule
  • use markdown for rendering tips (#7557)
    ## Summary
    - render tooltip content through the markdown renderer and prepend a
    bold Tip label
    - wrap tooltips at the available width using the indent’s measured width
    before adding the indent
    
    ## Testing
    - `/root/.cargo/bin/just fmt`
    - `RUSTFLAGS="--cfg tokio_unstable" TOKIO_UNSTABLE=1
    /root/.cargo/bin/just fix -p codex-tui` *(fails: codex-tui tests
    reference tokio::time::advance/start_paused gated behind the tokio
    test-util feature)*
    - `RUSTFLAGS="--cfg tokio_unstable" TOKIO_UNSTABLE=1 cargo test -p
    codex-tui` *(fails: codex-tui tests reference
    tokio::time::advance/start_paused gated behind the tokio test-util
    feature)*
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_693081406050832c9772ae9fa5dd77ca)
  • Migrate codex max (#7566)
    - make codex max the default
    - fix: we were doing some async work in sync function which caused tui
    to panic
  • [app-server] make file_path for config optional (#7560)
    When we are writing to config using `config/value/write` or
    `config/batchWrite`, it always require a `config/read` before it right
    now in order to get the correct file path to write to. make this
    optional so we read from the default user config file if this is not
    passed in.
  • Migrate model family to models manager (#7565)
    This PR moves `ModelsFamily` to `openai_models`. It also propagates
    `ModelsManager` to session services and use it to drive model family. We
    also make `derive_default_model_family` private because it's a step
    towards what we want: one place that gives model configuration.
    
    This is a second step at having one source of truth for models
    information and config: `ModelsManager`.
    
    Next steps would be to remove `ModelsFamily` from config. That's massive
    because it's being used in 41 occasions mostly pre launching `codex`.
    Also, we need to make `find_family_for_model` private. It's also big
    because it's being used in 21 occasions ~ all tests.
  • Migrate tui to use models manager (#7555)
    - This PR treats the `ModelsManager` like `AuthManager` and propagate it
    into the tui, replacing the `builtin_model_presets`
    - We are also decreasing the visibility of `builtin_model_presets`
    
    based on https://github.com/openai/codex/pull/7552
  • fix: wrap long exec lines in transcript overlay (#7481)
    What
    -----
    - Fix the Ctrl+T transcript overlay so that very long exec output lines
    are soft‑wrapped to the viewport width instead of being rendered as a
    single truncated row.
    - Add a regression test to `TranscriptOverlay` to ensure long exec
    outputs are rendered on multiple lines in the overlay.
    
    Why
    ----
    - Previously, the transcript overlay rendered extremely long single exec
    lines as one on‑screen row and simply cut them off at the right edge,
    with no horizontal scrolling.
    - This made it impossible to inspect the full content of long tool/exec
    outputs in the transcript view, even though the main TUI view already
    wrapped those lines.
    - Fixes #7454.
    
    How
    ----
    - Update `ExecCell::transcript_lines` to wrap exec output lines using
    the existing `RtOptions`/`word_wrap_line` helpers so that transcript
    rendering is width‑aware.
    - Reuse the existing line utilities to expand the wrapped `Line` values
    into the transcript overlay, preserving styling while respecting the
    current viewport width.
    - Add `transcript_overlay_wraps_long_exec_output_lines` test in
    `pager_overlay.rs` that constructs a long single‑line exec output,
    renders the transcript overlay into a small buffer, and asserts that the
    long marker string spans multiple rendered lines.
  • fix: Features should be immutable over the lifetime of a session/thread (#7540)
    I noticed that `features: Features` was defined on `struct
    SessionConfiguration`, which is commonly owned by `SessionState`, which
    is in turn owned by `Session`.
    
    Though I do not believe that `Features` should be allowed to be modified
    over the course of a session (if the feature state is not invariant, it
    makes it harder to reason about), which argues that it should live on
    `Session` rather than `SessionState` or `SessionConfiguration`.
    
    This PR moves `Features` to `Session` and updates all call sites. It
    appears the only place we were mutating `Features` was:
    
    - in tests
    - the sub-agent config for a review task:
    
    
    https://github.com/openai/codex/blob/3ef76ff29d5eed258fb6b8550e0e2b973d0dca21/codex-rs/core/src/tasks/review.rs#L86-L89
    
    Note this change also means it is no longer an `async` call to check the
    state of a feature, eliminating the possibility of a
    [TOCTTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use)
    error between checking the state of a feature and acting on it:
    
    
    https://github.com/openai/codex/blob/3ef76ff29d5eed258fb6b8550e0e2b973d0dca21/codex-rs/core/src/codex.rs#L1069-L1076
  • feat: Support listing and selecting skills via $ or /skills (#7506)
    List/Select skills with $-mention or /skills
  • [app-server] fix: add thread_id to turn/plan/updated (#7553)
    Realized we're missing this while migrating VSCE.
  • feat(tui): map Ctrl-P/N to arrow navigation in textarea (#7530)
    - Treat Ctrl-P/N (and their C0 fallbacks) the same as Up/Down so cursor
    movement matches popup/history behavior and control bytes never land in
    the buffer
    
    Fixes #7529
    
    Signed-off-by: Aofei Sheng <aofei@aofeisheng.com>
  • fix(tui): limit user shell output by screen lines (#7448)
    What
    - Limit the TUI "user shell" output panel by the number of visible
    screen lines rather than by the number of logical lines.
    - Apply middle truncation after wrapping, so a few extremely long lines
    cannot expand into hundreds of visible lines.
    - Add a regression test to guard this behavior.
    
    Why
    When the `ExecCommandSource::UserShell` tool returns a small number of
    very long logical lines, the TUI wraps those lines into many visual
    lines. The existing truncation logic applied
    `USER_SHELL_TOOL_CALL_MAX_LINES` to the number of logical lines *before*
    wrapping.
    
    As a result, a command like:
    
    - `Ran bash -lc "grep -R --line-number 'maskAssetId' ."`
    
    or a synthetic command that prints a single ~50,000‑character line, can
    produce hundreds of screen lines and effectively flood the viewport. The
    intended middle truncation for user shell output does not take effect in
    this scenario.
    
    How
    - In `codex-rs/tui/src/exec_cell/render.rs`, change the `ExecCell`
    rendering path for `ExecCommandSource::UserShell` so that:
    - Each logical line from `CommandOutput::aggregated_output` is first
    wrapped via `word_wrap_line` into multiple screen lines using the
    appropriate `RtOptions` and width from the `EXEC_DISPLAY_LAYOUT`
    configuration.
    - `truncate_lines_middle` is then applied to the wrapped screen lines,
    with `USER_SHELL_TOOL_CALL_MAX_LINES` as the limit. This means the limit
    is enforced on visible screen lines, not logical lines.
    - The existing layout struct (`ExecDisplayLayout`) continues to provide
    `output_max_lines`, so user shell output is subject to both
    `USER_SHELL_TOOL_CALL_MAX_LINES` and the layout-specific
    `output_max_lines` constraint.
    - Keep using `USER_SHELL_TOOL_CALL_MAX_LINES` as the cap, but interpret
    it as a per‑tool‑call limit on screen lines.
    - Add a regression test `user_shell_output_is_limited_by_screen_lines`
    in `codex-rs/tui/src/exec_cell/render.rs` that:
    - Constructs two extremely long logical lines containing a short marker
    (`"Z"`), so each wrapped screen line still contains the marker.
      - Wraps them at a narrow width to generate many screen lines.
    - Asserts that the unbounded wrapped output would exceed
    `USER_SHELL_TOOL_CALL_MAX_LINES` screen lines.
    - Renders an `ExecCell` for `ExecCommandSource::UserShell` at the same
    width and counts rendered lines containing the marker.
    - Asserts `output_screen_lines <= USER_SHELL_TOOL_CALL_MAX_LINES`,
    guarding against regressions where truncation happens before wrapping.
    
    This change keeps user shell output readable while ensuring it cannot
    flood the TUI, even when the tool emits a few extremely long lines.
    
    Tests
    - `cargo test -p codex-tui`
    
    Issue
    - Fixes #7447
  • Migrate model preset (#7542)
    - Introduce `openai_models` in `/core`
    - Move `PRESETS` under it
    - Move `ModelPreset`, `ModelUpgrade`, `ReasoningEffortPreset`,
    `ReasoningEffortPreset`, and `ReasoningEffortPreset` to `protocol`
    - Introduce `Op::ListModels` and `EventMsg::AvailableModels`
    
    Next steps:
    - migrate `app-server` and `tui` to use the introduced Operation