mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
49c2b66ece0d1c19245cdc78a94036313b8eaacc
92 Commits
-
Apply argument comment lint across codex-rs (#14652)
## Why Once the repo-local lint exists, `codex-rs` needs to follow the checked-in convention and CI needs to keep it from drifting. This commit applies the fallback `/*param*/` style consistently across existing positional literal call sites without changing those APIs. The longer-term preference is still to avoid APIs that require comments by choosing clearer parameter types and call shapes. This PR is intentionally the mechanical follow-through for the places where the existing signatures stay in place. After rebasing onto newer `main`, the rollout also had to cover newly introduced `tui_app_server` call sites. That made it clear the first cut of the CI job was too expensive for the common path: it was spending almost as much time installing `cargo-dylint` and re-testing the lint crate as a representative test job spends running product tests. The CI update keeps the full workspace enforcement but trims that extra overhead from ordinary `codex-rs` PRs. ## What changed - keep a dedicated `argument_comment_lint` job in `rust-ci` - mechanically annotate remaining opaque positional literals across `codex-rs` with exact `/*param*/` comments, including the rebased `tui_app_server` call sites that now fall under the lint - keep the checked-in style aligned with the lint policy by using `/*param*/` and leaving string and char literals uncommented - cache `cargo-dylint`, `dylint-link`, and the relevant Cargo registry/git metadata in the lint job - split changed-path detection so the lint crate's own `cargo test` step runs only when `tools/argument-comment-lint/*` or `rust-ci.yml` changes - continue to run the repo wrapper over the `codex-rs` workspace, so product-code enforcement is unchanged Most of the code changes in this commit are intentionally mechanical comment rewrites or insertions driven by the lint itself. ## Verification - `./tools/argument-comment-lint/run.sh --workspace` - `cargo test -p codex-tui-app-server -p codex-tui` - parsed `.github/workflows/rust-ci.yml` locally with PyYAML --- * -> #14652 * #14651
Michael Bolin ·
2026-03-16 16:48:15 -07:00 -
windows-sandbox: add runner IPC foundation for future unified_exec (#14139)
# Summary This PR introduces the Windows sandbox runner IPC foundation that later unified_exec work will build on. The key point is that this is intentionally infrastructure-only. The new IPC transport, runner plumbing, and ConPTY helpers are added here, but the active elevated Windows sandbox path still uses the existing request-file bootstrap. In other words, this change prepares the transport and module layout we need for unified_exec without switching production behavior over yet. Part of this PR is also a source-layout cleanup: some Windows sandbox files are moved into more explicit `elevated/`, `conpty/`, and shared locations so it is clearer which code is for the elevated sandbox flow, which code is legacy/direct-spawn behavior, and which helpers are shared between them. That reorganization is intentional in this first PR so later behavioral changes do not also have to carry a large amount of file-move churn. # Why This Is Needed For unified_exec Windows elevated sandboxed unified_exec needs a long-lived, bidirectional control channel between the CLI and a helper process running under the sandbox user. That channel has to support: - starting a process and reporting structured spawn success/failure - streaming stdout/stderr back incrementally - forwarding stdin over time - terminating or polling a long-lived process - supporting both pipe-backed and PTY-backed sessions The existing elevated one-shot path is built around a request-file bootstrap and does not provide those primitives cleanly. Before we can turn on Windows sandbox unified_exec, we need the underlying runner protocol and transport layer that can carry those lifecycle events and streams. # Why Windows Needs More Machinery Than Linux Or macOS Linux and macOS can generally build unified_exec on top of the existing sandbox/process model: the parent can spawn the child directly, retain normal ownership of stdio or PTY handles, and manage the lifetime of the sandboxed process without introducing a second control process. Windows elevated sandboxing is different. To run inside the sandbox boundary, we cross into a different user/security context and then need to manage a long-lived process from outside that boundary. That means we need an explicit helper process plus an IPC transport to carry spawn, stdin, output, and exit events back and forth. The extra code here is mostly that missing Windows sandbox infrastructure, not a conceptual difference in unified_exec itself. # What This PR Adds - the framed IPC message types and transport helpers for parent <-> runner communication - the renamed Windows command runner with both the existing request-file bootstrap and the dormant IPC bootstrap - named-pipe helpers for the elevated runner path - ConPTY helpers and process-thread attribute plumbing needed for PTY-backed sessions - shared sandbox/process helpers that later PRs will reuse when switching live execution paths over - early file/module moves so later PRs can focus on behavior rather than layout churn # What This PR Does Not Yet Do - it does not switch the active elevated one-shot path over to IPC yet - it does not enable Windows sandbox unified_exec yet - it does not remove the existing request-file bootstrap yet So while this code compiles and the new path has basic validation, it is not yet the exercised production path. That is intentional for this first PR: the goal here is to land the transport and runner foundation cleanly before later PRs start routing real command execution through it. # Follow-Ups Planned follow-up PRs will: 1. switch elevated one-shot Windows sandbox execution to the new runner IPC path 2. layer Windows sandbox unified_exec sessions on top of the same transport 3. remove the legacy request-file path once the IPC-based path is live # Validation - `cargo build -p codex-windows-sandbox`
iceweasel-oai ·
2026-03-16 19:45:06 +00:00 -
fix: preserve zsh-fork escalation fds across unified-exec spawn paths (#13644)
## Why `zsh-fork` sessions launched through unified-exec need the escalation socket to survive the wrapper -> server -> child handoff so later intercepted `exec()` calls can still reach the escalation server. The inherited-fd spawn path also needs to avoid closing Rust's internal exec-error pipe, and the shell-escalation handoff needs to tolerate the receive-side case where a transferred fd is installed into the same stdio slot it will be mapped onto. ## What Changed - Added `SpawnLifecycle::inherited_fds()` in `codex-rs/core/src/unified_exec/process.rs` and threaded inherited fds through `codex-rs/core/src/unified_exec/process_manager.rs` so unified-exec can preserve required descriptors across both PTY and no-stdin pipe spawn paths. - Updated `codex-rs/core/src/tools/runtimes/shell/zsh_fork_backend.rs` to expose the escalation socket fd through the spawn lifecycle. - Added inherited-fd-aware spawn helpers in `codex-rs/utils/pty/src/pty.rs` and `codex-rs/utils/pty/src/pipe.rs`, including Unix pre-exec fd pruning that preserves requested inherited fds while leaving `FD_CLOEXEC` descriptors alone. The pruning helper is now named `close_inherited_fds_except()` to better describe that behavior. - Updated `codex-rs/shell-escalation/src/unix/escalate_client.rs` to duplicate local stdio before transfer and send destination stdio numbers in `SuperExecMessage`, so the wrapper keeps using its own `stdin`/`stdout`/`stderr` until the escalated child takes over. - Updated `codex-rs/shell-escalation/src/unix/escalate_server.rs` so the server accepts the overlap case where a received fd reuses the same stdio descriptor number that the child setup will target with `dup2`. - Added comments around the PTY stdio wiring and the overlap regression helper to make the fd handoff and controlling-terminal setup easier to follow. ## Verification - `cargo test -p codex-utils-pty` - covers preserved-fd PTY spawn behavior, PTY resize, Python REPL continuity, exec-failure reporting, and the no-stdin pipe path - `cargo test -p codex-shell-escalation` - covers duplicated-fd transfer on the client side and verifies the overlap case by passing a pipe-backed stdin payload through the server-side `dup2` path --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/13644). * #14624 * __->__ #13644
Michael Bolin ·
2026-03-13 20:25:31 +00:00 -
refactor: make bubblewrap the default Linux sandbox (#13996)
## Summary - make bubblewrap the default Linux sandbox and keep `use_legacy_landlock` as the only override - remove `use_linux_sandbox_bwrap` from feature, config, schema, and docs surfaces - update Linux sandbox selection, CLI/config plumbing, and related tests/docs to match the new default - fold in the follow-up CI fixes for request-permissions responses and Linux read-only sandbox error text
viyatb-oai ·
2026-03-11 23:31:18 -07:00 -
Stabilize pipe process stdin round-trip test (#14013)
## What changed - keep the explicit stdin-close behavior after writing so the child still receives EOF deterministically - on Windows, stop using `python -c` for the round-trip assertion and instead run a native `cmd.exe` pipeline that reads one line from stdin with `set /p` and echoes it back - send ` ` on Windows so the stdin payload matches the platform-native line ending the shell reader expects ## Why this fixes flakiness The failing branch-local flake was not in `spawn_pipe_process` itself. The child exited cleanly, but the Windows ARM runner sometimes produced an empty stdout string when the test used Python as the stdin consumer. That makes the test sensitive to Python startup and stdin-close timing rather than the pipe primitive we actually want to validate. Switching the Windows path to a native `cmd.exe` reader keeps the assertion focused on our pipe behavior: bytes written to stdin should come back on stdout before EOF closes the process. The explicit ` ` write removes line-ending ambiguity on Windows. ## Scope - test-only - no production logic change
Ahmed Ibrahim ·
2026-03-11 12:33:09 -07:00 -
Stabilize split PTY output on Windows (#14003)
## Summary - run the split stdout/stderr PTY test through the normal shell helper on every platform - use a Windows-native command string instead of depending on Python to emit split streams - assert CRLF line endings on Windows explicitly ## Why this fixes the flake The earlier PTY split-output test used a Python one-liner on Windows while the rest of the file exercised shell-command behavior. That made the test depend on runner-local Python availability and masked the real Windows shell output shape. Using a native cmd-compatible command and asserting the actual CRLF output makes the split stdout/stderr coverage deterministic on Windows runners.
Ahmed Ibrahim ·
2026-03-11 12:33:07 -07:00 -
start of hooks engine (#13276)
(Experimental) This PR adds a first MVP for hooks, with SessionStart and Stop The core design is: - hooks live in a dedicated engine under codex-rs/hooks - each hook type has its own event-specific file - hook execution is synchronous and blocks normal turn progression while running - matching hooks run in parallel, then their results are aggregated into a normalized HookRunSummary On the AppServer side, hooks are exposed as operational metadata rather than transcript-native items: - new live notifications: hook/started, hook/completed - persisted/replayed hook results live on Turn.hookRuns - we intentionally did not add hook-specific ThreadItem variants Hooks messages are not persisted, they remain ephemeral. The context changes they add are (they get appended to the user's prompt)
Andrei Eternal ·
2026-03-10 04:11:31 +00:00 -
Stabilize PTY Python REPL test (#13883)
## What changed - The PTY Python REPL test now starts Python with a startup marker already embedded in argv. - The test waits for that marker in PTY output before making assertions. ## Why this fixes the flake - The old version tried to probe the live REPL almost immediately after spawn. - That races PTY initialization, Python startup, and prompt buffering, all of which vary across platforms and CI load. - By having the child process emit a known marker as part of its own startup path, the test gets a deterministic synchronization point that comes from the process under test rather than from guessed timing. ## Scope - Test-only change.
Ahmed Ibrahim ·
2026-03-09 10:08:36 -07:00 -
fix(ci): restore guardian coverage and bazel unit tests (#13912)
## Summary - restore the guardian review request snapshot test and its tracked snapshot after it was dropped from `main` - make Bazel Rust unit-test wrappers resolve runfiles correctly on manifest-only platforms like macOS and point Insta at the real workspace root - harden the shell-escalation socket-closure assertion so the musl Bazel test no longer depends on fd reuse behavior ## Verification - cargo test -p codex-core guardian_review_request_layout_matches_model_visible_request_snapshot - cargo test -p codex-shell-escalation - bazel test //codex-rs/exec:exec-unit-tests //codex-rs/shell-escalation:shell-escalation-unit-tests Supersedes #13894. --------- Co-authored-by: Ahmed Ibrahim <aibrahim@openai.com> Co-authored-by: viyatb-oai <viyatb@openai.com> Co-authored-by: Codex <noreply@openai.com>
Charley Cunningham ·
2026-03-08 12:05:19 -07:00 -
Fix inverted Windows PTY
TerminateProcesshandling (#13989)Addresses #13945 The vendored WezTerm ConPTY backend in `codex-rs/utils/pty/src/win/mod.rs` treated `TerminateProcess` return values backwards: nonzero success was handled as failure, and `0` failure was handled as success. This is likely causing a number of bugs reported against Codex running on Windows native where processes are not cleaned up.
Eric Traut ·
2026-03-08 11:52:16 -06:00 -
utils/pty: add streaming spawn and terminal sizing primitives (#13695)
Enhance pty utils: * Support closing stdin * Separate stderr and stdout streams to allow consumers differentiate them * Provide compatibility helper to merge both streams back into combined one * Support specifying terminal size for pty, including on-demand resizes while process is already running * Support terminating the process while still consuming its outputs
Ruslan Nigmatullin ·
2026-03-06 15:13:12 -08:00 -
jif-oai ·
2026-03-04 10:17:29 +00:00 -
Feat: Preserve network access on read-only sandbox policies (#13409)
## Summary `PermissionProfile.network` could not be preserved when additional or compiled permissions resolved to `SandboxPolicy::ReadOnly`, because `ReadOnly` had no network_access field. This change makes read-only + network enabled representable directly and threads that through the protocol, app-server v2 mirror, and permission- merging logic. ## What changed - Added `network_access: bool` to `SandboxPolicy::ReadOnly` in the core protocol and app-server v2 protocol. - Kept backward compatibility by defaulting the new field to false, so legacy read-only payloads still deserialize unchanged. - Updated `has_full_network_access()` and sandbox summaries to respect read-only network access. - Preserved PermissionProfile.network when: - compiling skill permission profiles into sandbox policies - normalizing additional permissions - merging additional permissions into existing sandbox policies - Updated the approval overlay to show network in the rendered permission rule when requested. - Regenerated app-server schema fixtures for the new v2 wire shape.Celia Chen ·
2026-03-04 02:41:57 +00:00 -
Add under-development original-resolution view_image support (#13050)
## Summary Add original-resolution support for `view_image` behind the under-development `view_image_original_resolution` feature flag. When the flag is enabled and the target model is `gpt-5.3-codex` or newer, `view_image` now preserves original PNG/JPEG/WebP bytes and sends `detail: "original"` to the Responses API instead of using the legacy resize/compress path. ## What changed - Added `view_image_original_resolution` as an under-development feature flag. - Added `ImageDetail` to the protocol models and support for serializing `detail: "original"` on tool-returned images. - Added `PromptImageMode::Original` to `codex-utils-image`. - Preserves original PNG/JPEG/WebP bytes. - Keeps legacy behavior for the resize path. - Updated `view_image` to: - use the shared `local_image_content_items_with_label_number(...)` helper in both code paths - select original-resolution mode only when: - the feature flag is enabled, and - the model slug parses as `gpt-5.3-codex` or newer - Kept local user image attachments on the existing resize path; this change is specific to `view_image`. - Updated history/image accounting so only `detail: "original"` images use the docs-based GPT-5 image cost calculation; legacy images still use the old fixed estimate. - Added JS REPL guidance, gated on the same feature flag, to prefer JPEG at 85% quality unless lossless is required, while still allowing other formats when explicitly requested. - Updated tests and helper code that construct `FunctionCallOutputContentItem::InputImage` to carry the new `detail` field. ## Behavior ### Feature off - `view_image` keeps the existing resize/re-encode behavior. - History estimation keeps the existing fixed-cost heuristic. ### Feature on + `gpt-5.3-codex+` - `view_image` sends original-resolution images with `detail: "original"`. - PNG/JPEG/WebP source bytes are preserved when possible. - History estimation uses the GPT-5 docs-based image-cost calculation for those `detail: "original"` images. #### [git stack](https://github.com/magus/git-stack-cli) - 👉 `1` https://github.com/openai/codex/pull/13050 - ⏳ `2` https://github.com/openai/codex/pull/13331 - ⏳ `3` https://github.com/openai/codex/pull/13049Curtis 'Fjord' Hawthorne ·
2026-03-03 15:56:54 -08:00 -
Use model catalog default for reasoning summary fallback (#12873)
## Summary - make `Config.model_reasoning_summary` optional so unset means use model default - resolve the optional config value to a concrete summary when building `TurnContext` - add protocol support for `default_reasoning_summary` in model metadata ## Validation - `cargo test -p codex-core --lib client::tests -- --nocapture` --------- Co-authored-by: Codex <noreply@openai.com>
pakrym-oai ·
2026-02-26 09:31:13 -08:00 -
tui: restore visible line numbers for hidden file links (#12870)
we recently changed file linking so the model uses markdown links when it wants something to be clickable. This works well across the GUI surfaces because they can render markdown cleanly and use the full absolute path in the anchor target. A previous pass hid the absolute path in the TUI (and only showed the label), but that also meant we could lose useful location info when the model put the line number or range in the anchor target instead of the label. This follow-up keeps the TUI behavior simple while making local file links feel closer to the old TUI file reference style. key changes: - Local markdown file links in the TUI keep the old file-ref feel: code styling, no underline, no visible absolute path. - If the hidden local anchor target includes a location suffix and the label does not already include one, we append that suffix to the visible label. - This works for single lines, line/column references, and ranges. - If the label already includes the location, we leave it alone. - normal web links keep the old TUI markdown-link behavior some examples: - `[foo.rs](/abs/path/foo.rs)` renders as `foo.rs` - `[foo.rs](/abs/path/foo.rs:45)` renders as `foo.rs:45` - `[foo.rs](/abs/path/foo.rs:45:3-48:9)` renders as `foo.rs:45:3-48:9` - `[foo.rs:45](/abs/path/foo.rs:45)` stays `foo.rs:45` - `[docs](https://example.com/docs)` still renders like a normal web link how it looks: <img width="732" height="813" alt="Screenshot 2026-02-26 at 9 27 55 AM" src="https://github.com/user-attachments/assets/d51bf236-653a-4e83-96e4-9427f0804471" />
pash-openai ·
2026-02-26 10:29:54 +00:00 -
feat: adding stream parser (#12666)
Add a stream parser to extract citations (and others) from a stream. This support cases where markers are split in differen tokens. Codex never manage to make this code work so everything was done manually. Please review correctly and do not touch this part of the code without a very clear understanding of it
jif-oai ·
2026-02-25 13:27:58 +00:00 -
feat(sleep-inhibitor): add Linux and Windows idle-sleep prevention (#11766)
## Background - follow-up to previous macOS-only PR: https://github.com/openai/codex/pull/11711 - follow-up macOS refactor PR (current structural approach used here): https://github.com/openai/codex/pull/12340 ## Summary - extend `codex-utils-sleep-inhibitor` with Linux and Windows backends while preserving existing macOS behavior - Linux backend: - use `systemd-inhibit` (`--what=idle --mode=block`) when available - fall back to `gnome-session-inhibit` (`--inhibit idle`) when available - keep no-op behavior if neither backend exists on host - Windows backend: - use Win32 power request handles (`PowerCreateRequest` + `PowerSetRequest` / `PowerClearRequest`) with `PowerRequestSystemRequired` - make `prevent_idle_sleep` Experimental on macOS/Linux/Windows; keep under development on other targets ## Testing - `just fmt` - `cargo test -p codex-utils-sleep-inhibitor` - `cargo test -p codex-core features::tests::` - `cargo test -p codex-tui chatwidget::tests::` - `just fix -p codex-utils-sleep-inhibitor` - `just fix -p codex-core` ## Semantics and API references - Goal remains: prevent idle system sleep while a turn is running. - Linux: - `systemd-inhibit` / login1 inhibitor model: - https://www.freedesktop.org/software/systemd/man/latest/systemd-inhibit.html - https://www.freedesktop.org/software/systemd/man/org.freedesktop.login1.html - https://systemd.io/INHIBITOR_LOCKS/ - xdg-desktop-portal Inhibit (relevant for sandboxed apps): - https://flatpak.github.io/xdg-desktop-portal/docs/doc-org.freedesktop.portal.Inhibit.html - Windows: - `PowerCreateRequest`: - https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powercreaterequest - `PowerSetRequest`: - https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powersetrequest - `PowerClearRequest`: - https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-powerclearrequest - `SetThreadExecutionState` (alternative baseline API): - https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate ## Chromium vs this PR - Chromium Linux backend: - https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc - Chromium Windows backend: - https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc - Electron powerSaveBlocker entry point: - https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc ## Why we differ from Chromium - Linux implementation mechanism: - Chromium uses in-process D-Bus APIs plus UI-integrated screen-saver suspension. - This PR uses command-based inhibitor backends (`systemd-inhibit`, `gnome-session-inhibit`) instead of linking a Linux D-Bus client in this crate. - Reason: keep `codex-utils-sleep-inhibitor` dependency-light and avoid Linux CI/toolchain fragility from new native D-Bus linkage, while preserving the same runtime intent (hold an inhibitor while a turn runs). - Linux UI integration scope: - Chromium also uses `display::Screen::SuspendScreenSaver()` in its UI stack. - Codex `codex-rs` does not have that display abstraction in this crate, so this PR scopes Linux behavior to process-level sleep inhibition only. - Windows wake-lock type breadth: - Chromium supports both display/system wake-lock types and extra display-specific handling for some pre-Win11 scenarios. - Codex’s feature is scoped to turn execution continuity (not forcing display on), so this PR uses `PowerRequestSystemRequired` only.
Yaroslav Volovich ·
2026-02-24 11:51:44 -08:00 -
feat: use process group to kill the PTY (#12688)
Use the process group kill logic to kill the PTY
jif-oai ·
2026-02-24 16:55:23 +00:00 -
Avoid
AbsolutePathBuf::parent()panic underEMFILEby skipping re-absolutization (#12647)Fixes #12216 Fixes a panic in `AbsolutePathBuf::parent()` when the process hits file descriptor exhaustion (`EMFILE` / "Too many open files"). ### Root cause `AbsolutePathBuf::parent()` was re-validating the parent path via `from_absolute_path(...).expect(...)`. `from_absolute_path()` calls `path_absolutize::absolutize()`, which can depend on `std::env::current_dir()`. Under `EMFILE`, that can fail, causing `parent()` to panic even though the parent of an absolute path is already known. ### Change - Stop re-absolutizing the result of `self.0.parent()` - Construct `AbsolutePathBuf` directly from the known parent path - Keep an invariant check with `debug_assert!(p.is_absolute())` ### Why this is safe `self` is already an `AbsolutePathBuf`, so `self.0` is absolute/normalized. The parent of an absolute path is expected to be absolute, so re-running fallible normalization here is unnecessary and can introduce unrelated panics.
Eric Traut ·
2026-02-23 21:59:33 -08:00 -
jif-oai ·
2026-02-23 14:14:36 +00:00 -
chore: remove codex-core public protocol/shell re-exports (#12432)
## Why `codex-rs/core/src/lib.rs` re-exported a broad set of types and modules from `codex-protocol` and `codex-shell-command`. That made it easy for workspace crates to import those APIs through `codex-core`, which in turn hides dependency edges and makes it harder to reduce compile-time coupling over time. This change removes those public re-exports so call sites must import from the source crates directly. Even when a crate still depends on `codex-core` today, this makes dependency boundaries explicit and unblocks future work to drop `codex-core` dependencies where possible. ## What Changed - Removed public re-exports from `codex-rs/core/src/lib.rs` for: - `codex_protocol::protocol` and related protocol/model types (including `InitialHistory`) - `codex_protocol::config_types` (`protocol_config_types`) - `codex_shell_command::{bash, is_dangerous_command, is_safe_command, parse_command, powershell}` - Migrated workspace Rust call sites to import directly from: - `codex_protocol::protocol` - `codex_protocol::config_types` - `codex_protocol::models` - `codex_shell_command` - Added explicit `Cargo.toml` dependencies (`codex-protocol` / `codex-shell-command`) in crates that now import those crates directly. - Kept `codex-core` internal modules compiling by using `pub(crate)` aliases in `core/src/lib.rs` (internal-only, not part of the public API). - Updated the two utility crates that can already drop a `codex-core` dependency edge entirely: - `codex-utils-approval-presets` - `codex-utils-cli` ## Verification - `cargo test -p codex-utils-approval-presets` - `cargo test -p codex-utils-cli` - `cargo check --workspace --all-targets` - `just clippy`Michael Bolin ·
2026-02-20 23:45:35 -08:00 -
Move sanitizer into codex-secrets (#12306)
## Summary - move the sanitizer implementation into `codex-secrets` (`secrets/src/sanitizer.rs`) and re-export `redact_secrets` - switch `codex-core` to depend on/import `codex-secrets` for sanitizer usage - remove the old `utils/sanitizer` crate wiring and refresh lockfiles ## Testing - `just fmt` - `cargo test -p codex-secrets` - `cargo test -p codex-core --no-run` - `cargo clippy -p codex-secrets -p codex-core --all-targets --all-features -- -D warnings` - `just bazel-lock-update` - `just bazel-lock-check` ## Notes - not run: `cargo test --all-features` (full workspace suite)
viyatb-oai ·
2026-02-20 22:47:54 +00:00 -
fix: simplify macOS sleep inhibitor FFI (#12340)
Summary - simplify the macOS sleep inhibitor FFI by replacing `dlopen` / `dlsym` / `transmute` with normal IOKit extern calls and `SAFETY` comments - switch to cfg-selected platform implementations (`imp::SleepInhibitor`) instead of `Box<dyn ...>` - check in minimal IOKit bindings generated with `bindgen` and include them from the macOS backend - enable direct IOKit linkage in Bazel macOS builds by registering `IOKit` in the Bazel `osx.framework(...)` toolchain extension list - update `Cargo.lock` and `MODULE.bazel.lock` after removing the build-time `bindgen` dependency path Testing - `just fmt` - `cargo clippy -p codex-utils-sleep-inhibitor --all-targets -- -D warnings` - `cargo test -p codex-utils-sleep-inhibitor` - `bazel test //codex-rs/utils/sleep-inhibitor:all --test_output=errors` - `just bazel-lock-update` - `just bazel-lock-check` Context - follow-up to #11711 addressing Ryan's review comments - `bindgen` is used to generate the checked-in bindings file, but not at build time
Yaroslav Volovich ·
2026-02-20 09:52:21 -08:00 -
feat(tui): prevent macOS idle sleep while turns run (#11711)
## Summary - add a shared `codex-core` sleep inhibitor that uses native macOS IOKit assertions (`IOPMAssertionCreateWithName` / `IOPMAssertionRelease`) instead of spawning `caffeinate` - wire sleep inhibition to turn lifecycle in `tui` (`TurnStarted` enables; `TurnComplete` and abort/error finalization disable) - gate this behavior behind a `/experimental` feature toggle (`[features].prevent_idle_sleep`) instead of a dedicated `[tui]` config flag - expose the toggle in `/experimental` on macOS; keep it under development on other platforms - keep behavior no-op on non-macOS targets <img width="1326" height="577" alt="image" src="https://github.com/user-attachments/assets/73fac06b-97ae-46a2-800a-30f9516cf8a3" /> ## Testing - `cargo check -p codex-core -p codex-tui` - `cargo test -p codex-core sleep_inhibitor::tests -- --nocapture` - `cargo test -p codex-core tui_config_missing_notifications_field_defaults_to_enabled -- --nocapture` - `cargo test -p codex-core prevent_idle_sleep_is_ -- --nocapture` ## Semantics and API references - This PR targets `caffeinate -i` semantics: prevent *idle system sleep* while allowing display idle sleep. - `caffeinate -i` mapping in Apple open source (`assertionMap`): - `kIdleAssertionFlag -> kIOPMAssertionTypePreventUserIdleSystemSleep` - Source: https://github.com/apple-oss-distributions/PowerManagement/blob/PowerManagement-1846.60.12/caffeinate/caffeinate.c#L52-L54 - Apple IOKit docs for assertion types and API: - https://developer.apple.com/documentation/iokit/iopmlib_h/iopmassertiontypes - https://developer.apple.com/documentation/iokit/1557092-iopmassertioncreatewithname - https://developer.apple.com/library/archive/qa/qa1340/_index.html ## Codex Electron vs this PR (full stack path) - Codex Electron app requests sleep blocking with `powerSaveBlocker.start("prevent-app-suspension")`: - https://github.com/openai/codex/blob/main/codex/codex-vscode/electron/src/electron-message-handler.ts - Electron maps that string to Chromium wake lock type `kPreventAppSuspension`: - https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_power_save_blocker.cc - Chromium macOS backend maps wake lock types to IOKit assertion constants and calls IOKit: - `kPreventAppSuspension -> kIOPMAssertionTypeNoIdleSleep` - `kPreventDisplaySleep / kPreventDisplaySleepAllowDimming -> kIOPMAssertionTypeNoDisplaySleep` - https://github.com/chromium/chromium/blob/main/services/device/wake_lock/power_save_blocker/power_save_blocker_mac.cc ## Why this PR uses a different macOS constant name - This PR uses `"PreventUserIdleSystemSleep"` directly, via `IOPMAssertionCreateWithName`, in `codex-rs/core/src/sleep_inhibitor.rs`. - Apple’s IOKit header documents `kIOPMAssertionTypeNoIdleSleep` as deprecated and recommends `kIOPMAssertPreventUserIdleSystemSleep` / `kIOPMAssertionTypePreventUserIdleSystemSleep`: - https://github.com/apple-oss-distributions/IOKitUser/blob/IOKitUser-100222.60.2/pwr_mgt.subproj/IOPMLib.h#L1000-L1030 - So Chromium and this PR are using different constant names, but semantically equivalent idle-system-sleep prevention behavior. ## Future platform support The architecture is intentionally set up for multi-platform extensions: - UI code (`tui`) only calls `SleepInhibitor::set_turn_running(...)` on turn lifecycle boundaries. - Platform-specific behavior is isolated in `codex-rs/core/src/sleep_inhibitor.rs` behind `cfg(...)` blocks. - Feature exposure is centralized in `core/src/features.rs` and surfaced via `/experimental`. - Adding new OS backends should not require additional TUI wiring; only the backend internals and feature stage metadata need to change. Potential follow-up implementations: - Windows: - Add a backend using Win32 power APIs (`SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED)` as baseline). - Optionally move to `PowerCreateRequest` / `PowerSetRequest` / `PowerClearRequest` for richer assertion semantics. - Linux: - Add a backend using logind inhibitors over D-Bus (`org.freedesktop.login1.Manager.Inhibit` with `what="sleep"`). - Keep a no-op fallback where logind/D-Bus is unavailable. This PR keeps the cross-platform API surface minimal so future PRs can add Windows/Linux support incrementally with low churn. --------- Co-authored-by: jif-oai <jif@openai.com>
Yaroslav Volovich ·
2026-02-13 10:31:39 -08:00 -
feat: introduce Permissions (#11633)
## Why We currently carry multiple permission-related concepts directly on `Config` for shell/unified-exec behavior (`approval_policy`, `sandbox_policy`, `network`, `shell_environment_policy`, `windows_sandbox_mode`). Consolidating these into one in-memory struct makes permission handling easier to reason about and sets up the next step: supporting named permission profiles (`[permissions.PROFILE_NAME]`) without changing behavior now. This change is mostly mechanical: it updates existing callsites to go through `config.permissions`, but it does not yet refactor those callsites to take a single `Permissions` value in places where multiple permission fields are still threaded separately. This PR intentionally **does not** change the on-disk `config.toml` format yet and keeps compatibility with legacy config keys. ## What Changed - Introduced `Permissions` in `core/src/config/mod.rs`. - Added `Config::permissions` and moved effective runtime permission fields under it: - `approval_policy` - `sandbox_policy` - `network` - `shell_environment_policy` - `windows_sandbox_mode` - Updated config loading/building so these effective values are still derived from the same existing config inputs and constraints. - Updated Windows sandbox helpers/resolution to read/write via `permissions`. - Threaded the new field through all permission consumers across core runtime, app-server, CLI/exec, TUI, and sandbox summary code. - Updated affected tests to reference `config.permissions.*`. - Renamed the struct/field from `EffectivePermissions`/`effective_permissions` to `Permissions`/`permissions` and aligned variable naming accordingly. ## Verification - `just fix -p codex-core -p codex-tui -p codex-cli -p codex-app-server -p codex-exec -p codex-utils-sandbox-summary` - `cargo build -p codex-core -p codex-tui -p codex-cli -p codex-app-server -p codex-exec -p codex-utils-sandbox-summary`
Michael Bolin ·
2026-02-12 14:42:54 -08:00 -
chore(core) Deprecate approval_policy: on-failure (#11631)
## Summary In an effort to start simplifying our sandbox setup, we're announcing this approval_policy as deprecated. In general, it performs worse than `on-request`, and we're focusing on making fewer sandbox configurations perform much better. ## Testing - [x] Tested locally - [x] Existing tests pass
Dylan Hurd ·
2026-02-12 13:23:30 -08:00 -
chore: drop and clean from phase 1 (#11605)
This PR is mostly cleaning and simplifying phase 1 of memories
jif-oai ·
2026-02-12 17:23:00 +00:00 -
feat: add sanitizer to redact secrets (#11600)
Adding a sanitizer crate that can redact API keys and other secret with known pattern from a String
jif-oai ·
2026-02-12 16:44:01 +00:00 -
feat: make sandbox read access configurable with
ReadOnlyAccess(#11387)`SandboxPolicy::ReadOnly` previously implied broad read access and could not express a narrower read surface. This change introduces an explicit read-access model so we can support user-configurable read restrictions in follow-up work, while preserving current behavior today. It also ensures unsupported backends fail closed for restricted-read policies instead of silently granting broader access than intended. ## What - Added `ReadOnlyAccess` in protocol with: - `Restricted { include_platform_defaults, readable_roots }` - `FullAccess` - Updated `SandboxPolicy` to carry read-access configuration: - `ReadOnly { access: ReadOnlyAccess }` - `WorkspaceWrite { ..., read_only_access: ReadOnlyAccess }` - Preserved existing behavior by defaulting current construction paths to `ReadOnlyAccess::FullAccess`. - Threaded the new fields through sandbox policy consumers and call sites across `core`, `tui`, `linux-sandbox`, `windows-sandbox`, and related tests. - Updated Seatbelt policy generation to honor restricted read roots by emitting scoped read rules when full read access is not granted. - Added fail-closed behavior on Linux and Windows backends when restricted read access is requested but not yet implemented there (`UnsupportedOperation`). - Regenerated app-server protocol schema and TypeScript artifacts, including `ReadOnlyAccess`. ## Compatibility / rollout - Runtime behavior remains unchanged by default (`FullAccess`). - API/schema changes are in place so future config wiring can enable restricted read access without another policy-shape migration.Michael Bolin ·
2026-02-11 18:31:14 -08:00 -
feat: split codex-common into smaller utils crates (#11422)
We are removing feature-gated shared crates from the `codex-rs` workspace. `codex-common` grouped several unrelated utilities behind `[features]`, which made dependency boundaries harder to reason about and worked against the ongoing effort to eliminate feature flags from workspace crates. Splitting these utilities into dedicated crates under `utils/` aligns this area with existing workspace structure and keeps each dependency explicit at the crate boundary. ## What changed - Removed `codex-rs/common` (`codex-common`) from workspace members and workspace dependencies. - Added six new utility crates under `codex-rs/utils/`: - `codex-utils-cli` - `codex-utils-elapsed` - `codex-utils-sandbox-summary` - `codex-utils-approval-presets` - `codex-utils-oss` - `codex-utils-fuzzy-match` - Migrated the corresponding modules out of `codex-common` into these crates (with tests), and added matching `BUILD.bazel` targets. - Updated direct consumers to use the new crates instead of `codex-common`: - `codex-rs/cli` - `codex-rs/tui` - `codex-rs/exec` - `codex-rs/app-server` - `codex-rs/mcp-server` - `codex-rs/chatgpt` - `codex-rs/cloud-tasks` - Updated workspace lockfile entries to reflect the new dependency graph and removal of `codex-common`.
Michael Bolin ·
2026-02-11 12:59:24 +00:00 -
chore: put crypto provider logic in a shared crate (#11294)
Ensures a process-wide rustls crypto provider is installed. Both the `codex-network-proxy` and `codex-api` crates need this.
Michael Bolin ·
2026-02-10 01:04:31 -08:00 -
adding image support for gif and webp (#11237)
Adds image support for gif and webp images. Tested using webp and gif (both single and multi image gif files)
natea-oai ·
2026-02-09 14:47:22 -08:00 -
Fix flaky windows CI test (#10993)
Hardens PTY Python REPL test and make MCP test startup deterministic **Summary** - `utils/pty/src/tests.rs` - Added a REPL readiness handshake (`wait_for_python_repl_ready`) that repeatedly sends a marker and waits for it in PTY output before sending test commands. - Updated `pty_python_repl_emits_output_and_exits` to: - wait for readiness first, - preserve startup output, - append output collected through process exit. - Reduces Windows/ConPTY flakiness from early stdin writes racing REPL startup. - `mcp-server/tests/suite/codex_tool.rs` - Avoid remote model refresh during MCP test startup, reducing timeout-prone nondeterminism.Eric Traut ·
2026-02-07 08:55:42 -08:00 -
Process-group cleanup for stdio MCP servers to prevent orphan process storms (#10710)
This PR changes stdio MCP child processes to run in their own process group * Add guarded teardown in codex-rmcp-client: send SIGTERM to the group first, then SIGKILL after a short grace period. * Add terminate_process_group helper in process_group.rs. * Add Unix regression test in process_group_cleanup.rs to verify wrapper + grandchild are reaped on client drop. Addresses reported MCP process/thread storm: #10581
Eric Traut ·
2026-02-06 21:26:36 -08:00 -
Include real OS info in metrics. (#10425)
calculated a hashed user ID from either auth user id or API key Also correctly populates OS. These will make our metrics more useful and powerful for analysis.
iceweasel-oai ·
2026-02-05 06:30:31 -08:00 -
feat: experimental flags (#10231)
## Problem being solved - We need a single, reliable way to mark app-server API surface as experimental so that: 1. the runtime can reject experimental usage unless the client opts in 2. generated TS/JSON schemas can exclude experimental methods/fields for stable clients. Right now that’s easy to drift or miss when done ad-hoc. ## How to declare experimental methods and fields - **Experimental method**: add `#[experimental("method/name")]` to the `ClientRequest` variant in `client_request_definitions!`. - **Experimental field**: on the params struct, derive `ExperimentalApi` and annotate the field with `#[experimental("method/name.field")]` + set `inspect_params: true` for the method variant so `ClientRequest::experimental_reason()` inspects params for experimental fields. ## How the macro solves it - The new derive macro lives in `codex-rs/codex-experimental-api-macros/src/lib.rs` and is used via `#[derive(ExperimentalApi)]` plus `#[experimental("reason")]` attributes. - **Structs**: - Generates `ExperimentalApi::experimental_reason(&self)` that checks only annotated fields. - The “presence” check is type-aware: - `Option<T>`: `is_some_and(...)` recursively checks inner. - `Vec`/`HashMap`/`BTreeMap`: must be non-empty. - `bool`: must be `true`. - Other types: considered present (returns `true`). - Registers each experimental field in an `inventory` with `(type_name, serialized field name, reason)` and exposes `EXPERIMENTAL_FIELDS` for that type. Field names are converted from `snake_case` to `camelCase` for schema/TS filtering. - **Enums**: - Generates an exhaustive `match` returning `Some(reason)` for annotated variants and `None` otherwise (no wildcard arm). - **Wiring**: - Runtime gating uses `ExperimentalApi::experimental_reason()` in `codex-rs/app-server/src/message_processor.rs` to reject requests unless `InitializeParams.capabilities.experimental_api == true`. - Schema/TS export filters use the inventory list and `EXPERIMENTAL_CLIENT_METHODS` from `client_request_definitions!` to strip experimental methods/fields when `experimental_api` is false.jif-oai ·
2026-02-02 11:06:50 +00:00 -
Validate CODEX_HOME before resolving (#10249)
Summary - require `CODEX_HOME` to point to an existing directory before canonicalizing and surface clear errors otherwise - share the same helper logic in both `core` and `rmcp-client` and add unit tests that cover missing, non-directory, valid, and default paths This addresses #9222
Eric Traut ·
2026-01-30 15:46:33 -08:00 -
[bazel] Improve runfiles handling (#10098)
we can't use runfiles directory on Windows due to path lengths, so swap to manifest strategy. Parsing the manifest is a bit complex and the format is changing in Bazel upstream, so pull in the official Rust library (via a small hack to make it importable...) and cleanup all the associated logic to work cleanly in both bazel and cargo without extra confusion
zbarsky-openai ·
2026-01-29 00:15:44 +00:00 -
fix: Fix tilde expansion to avoid absolute-path escape (#9621)
### Motivation - Prevent inputs like `~//` or `~///etc` from expanding to arbitrary absolute paths (e.g. `/`) because `Path::join` discards the left side when the right side is absolute, which could allow config values to escape `HOME` and broaden writable roots. ### Description - In `codex-rs/utils/absolute-path/src/lib.rs` update `maybe_expand_home_directory` to trim leading separators from the suffix and return `home` when the remainder is empty so tilde expansion stays rooted under `HOME`. - Add a non-Windows unit test `home_directory_double_slash_on_non_windows_is_expanded_in_deserialization` that validates `"~//code"` expands to `home.join("code")`. ### Testing - Ran `just fmt` successfully. - Ran `just fix -p codex-utils-absolute-path` (Clippy autofix) successfully. - Ran `cargo test -p codex-utils-absolute-path` and all tests passed. ------ [Codex Task](https://chatgpt.com/codex/tasks/task_i_697007481cac832dbeb1ee144d1e4cbe)Tiffany Citra ·
2026-01-21 10:43:10 -08:00 -
fix:
writable_rootsdoesn't recognize home directory symbol in non-windows OS (#9193)Fixes: ``` [sandbox_workspace_write] writable_roots = ["~/code/"] ``` translates to ``` /Users/ccunningham/.codex/~/code ``` (i.e. the home dir symbol isn't recognized)
Tiffany Citra ·
2026-01-20 10:55:01 -08:00 -
feat: detach non-tty childs (#9477)
Thanks to the investigations made by * @frantic-openai https://github.com/openai/codex/pull/9403 * @kfiramar https://github.com/openai/codex/pull/9388
jif-oai ·
2026-01-19 11:35:34 +00:00 -
jif-oai ·
2026-01-16 17:24:41 +01:00 -
chore: close pipe on non-pty processes (#9369)
Closing the STDIN of piped process when starting them to avoid commands like `rg` to wait for content on STDIN and hangs for ever
jif-oai ·
2026-01-16 15:54:32 +01:00 -
jif-oai ·
2026-01-14 18:44:04 +00:00 -
feat: add support for building with Bazel (#8875)
This PR configures Codex CLI so it can be built with [Bazel](https://bazel.build) in addition to Cargo. The `.bazelrc` includes configuration so that remote builds can be done using [BuildBuddy](https://www.buildbuddy.io). If you are familiar with Bazel, things should work as you expect, e.g., run `bazel test //... --keep-going` to run all the tests in the repo, but we have also added some new aliases in the `justfile` for convenience: - `just bazel-test` to run tests locally - `just bazel-remote-test` to run tests remotely (currently, the remote build is for x86_64 Linux regardless of your host platform). Note we are currently seeing the following test failures in the remote build, so we still need to figure out what is happening here: ``` failures: suite::compact::manual_compact_twice_preserves_latest_user_messages suite::compact_resume_fork::compact_resume_after_second_compaction_preserves_history suite::compact_resume_fork::compact_resume_and_fork_preserve_model_history_view ``` - `just build-for-release` to build release binaries for all platforms/architectures remotely To setup remote execution: - [Create a buildbuddy account](https://app.buildbuddy.io/) (OpenAI employees should also request org access at https://openai.buildbuddy.io/join/ with their `@openai.com` email address.) - [Copy your API key](https://app.buildbuddy.io/docs/setup/) to `~/.bazelrc` (add the line `build --remote_header=x-buildbuddy-api-key=YOUR_KEY`) - Use `--config=remote` in your `bazel` invocations (or add `common --config=remote` to your `~/.bazelrc`, or use the `just` commands) ## CI In terms of CI, this PR introduces `.github/workflows/bazel.yml`, which uses Bazel to run the tests _locally_ on Mac and Linux GitHub runners (we are working on supporting Windows, but that is not ready yet). Note that the failures we are seeing in `just bazel-remote-test` do not occur on these GitHub CI jobs, so everything in `.github/workflows/bazel.yml` is green right now. The `bazel.yml` uses extra config in `.github/workflows/ci.bazelrc` so that macOS CI jobs build _remotely_ on Linux hosts (using the `docker://docker.io/mbolin491/codex-bazel` Docker image declared in the root `BUILD.bazel`) using cross-compilation to build the macOS artifacts. Then these artifacts are downloaded locally to GitHub's macOS runner so the tests can be executed natively. This is the relevant config that enables this: ``` common:macos --config=remote common:macos --strategy=remote common:macos --strategy=TestRunner=darwin-sandbox,local ``` Because of the remote caching benefits we get from BuildBuddy, these new CI jobs can be extremely fast! For example, consider these two jobs that ran all the tests on Linux x86_64: - Bazel 1m37s https://github.com/openai/codex/actions/runs/20861063212/job/59940545209?pr=8875 - Cargo 9m20s https://github.com/openai/codex/actions/runs/20861063192/job/59940559592?pr=8875 For now, we will continue to run both the Bazel and Cargo jobs for PRs, but once we add support for Windows and running Clippy, we should be able to cutover to using Bazel exclusively for PRs, which should still speed things up considerably. We will probably continue to run the Cargo jobs post-merge for commits that land on `main` as a sanity check. Release builds will also continue to be done by Cargo for now. Earlier attempt at this PR: https://github.com/openai/codex/pull/8832 Earlier attempt to add support for Buck2, now abandoned: https://github.com/openai/codex/pull/8504 --------- Co-authored-by: David Zbarsky <dzbarsky@gmail.com> Co-authored-by: Michael Bolin <mbolin@openai.com>
zbarsky-openai ·
2026-01-09 11:09:43 -08:00 -
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`.
Michael Bolin ·
2026-01-07 23:03:43 -08:00 -
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.
Michael Bolin ·
2026-01-07 18:06:08 -08:00 -
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" />Owen Lin ·
2026-01-07 20:11:12 +00:00 -
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.
Thibault Sottiaux ·
2026-01-07 13:00:31 +00:00