mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
ae8a3be9585d0918fe38fa199c963aeb80ee4f55
4935 Commits
-
bazel: refresh the expired macOS SDK pin (#16128)
## Why macOS BuildBuddy started failing before target analysis because the Apple CDN object pinned in [`MODULE.bazel`](https://github.com/openai/codex/blob/fce0f76d577b5070f1e2b4a2abaa8350acfc38ff/MODULE.bazel#L28-L36) now returns `403 Forbidden`. The failure report that triggered this change was this [BuildBuddy invocation](https://app.buildbuddy.io/invocation/c57590e0-1bdb-4e19-a86f-74d4a7ded228). This repo uses `@llvm//extensions:osx.bzl` via `osx.from_archive(...)`, and that API does not discover a current SDK URL for us. It fetches exactly the `urls`, `sha256`, and `strip_prefix` we pin. Once Apple retires that `swcdn.apple.com` object, `@macos_sdk` stops resolving and every downstream macOS build fails during external repository fetch. This is the same basic failure mode we hit in [
b9fa08ec61](https://github.com/openai/codex/commit/b9fa08ec619c96617a9ae2041c9ddb02d2c02434): the pin itself aged out. ## How I tracked it down 1. I started from the BuildBuddy error and copied the exact `swcdn.apple.com/.../CLTools_macOSNMOS_SDK.pkg` URL from the failure. 2. I reproduced the issue outside CI by opening that URL directly in a browser and by running `curl -I` against it locally. Both returned `403 Forbidden`, which ruled out BuildBuddy as the root cause. 3. I searched the repo for that URL and found it hardcoded in `MODULE.bazel`. 4. I inspected the `llvm` Bzlmod `osx` extension implementation to confirm that `osx.from_archive(...)` is just a literal fetch of the pinned archive metadata. There is no automatic fallback or catalog lookup behind it. 5. I queried Apple's software update catalogs to find the current Command Line Tools package for macOS 26.x. The useful catalog was: - `https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz` This is scriptable; it does not require opening a website in a browser. The catalog is a gzip-compressed plist served over HTTP, so the workflow is just: 1. fetch the catalog, 2. decompress it, 3. search or parse the plist for `CLTools_macOSNMOS_SDK.pkg` entries, 4. inspect the matching product metadata. The quick shell version I used was: ```shell curl -L <catalog-url> \ | gzip -dc \ | rg -n -C 6 'CLTools_macOSNMOS_SDK\.pkg|PostDate|English\.dist' ``` That is enough to surface the current product id, package URL, post date, and the matching `.dist` file. If we want something less grep-driven next time, the same catalog can be parsed structurally. For example: ```python import gzip import plistlib import urllib.request url = "https://swscan.apple.com/content/catalogs/others/index-26-15-14-13-12-10.16-10.15-10.14-10.13-10.12-10.11-10.10-10.9-mountainlion-lion-snowleopard-leopard.merged-1.sucatalog.gz" with urllib.request.urlopen(url) as resp: catalog = plistlib.loads(gzip.decompress(resp.read())) for product_id, product in catalog["Products"].items(): for package in product.get("Packages", []): package_url = package.get("URL", "") if package_url.endswith("CLTools_macOSNMOS_SDK.pkg"): print(product_id) print(product.get("PostDate")) print(package_url) print(product.get("Distributions", {}).get("English")) ``` In practice, `curl` was only the transport. The important part is that the catalog itself is a machine-readable plist, so this can be automated. 6. That catalog contains the newer `047-96692` Command Line Tools release, and its distribution file identifies it as [Command Line Tools for Xcode 26.4](https://swdist.apple.com/content/downloads/32/53/047-96692-A_OAHIHT53YB/ybtshxmrcju8m2qvw3w5elr4rajtg1x3y3/047-96692.English.dist). 7. I downloaded that package locally, computed its SHA-256, expanded it with `pkgutil --expand-full`, and verified that it contains `Payload/Library/Developer/CommandLineTools/SDKs/MacOSX26.4.sdk`, which is the correct new `strip_prefix` for this pin. The core debugging loop looked like this: ```shell curl -I <stale swcdn URL> rg 'swcdn\.apple\.com|osx\.from_archive' MODULE.bazel curl -L <apple 26.x sucatalog> | gzip -dc | rg 'CLTools_macOSNMOS_SDK.pkg' pkgutil --expand-full CLTools_macOSNMOS_SDK.pkg expanded find expanded/Payload/Library/Developer/CommandLineTools/SDKs -maxdepth 1 -mindepth 1 ``` ## What changed - Updated `MODULE.bazel` to point `osx.from_archive(...)` at the currently live `047-96692` `CLTools_macOSNMOS_SDK.pkg` object. - Updated the pinned `sha256` to match that package. - Updated the `strip_prefix` from `MacOSX26.2.sdk` to `MacOSX26.4.sdk`. ## Verification - `bazel --output_user_root="$(mktemp -d /tmp/codex-bazel-sdk-fetch.XXXXXX)" build @macos_sdk//sysroot` ## Notes for next time As long as we pin raw `swcdn.apple.com` objects, this will likely happen again. When it does, the expected recovery path is: 1. Reproduce the `403` against the exact URL from CI. 2. Find the stale pin in `MODULE.bazel`. 3. Look up the current CLTools package in the relevant Apple software update catalog for that macOS major version. 4. Download the replacement package and refresh both `sha256` and `strip_prefix`. 5. Validate the new pin with a fresh `@macos_sdk` fetch, not just an incremental Bazel build. The important detail is that the non-`26` catalog did not surface the macOS 26.x SDK package here; the `index-26-15-14-...` catalog was the one that exposed the currently live replacement.Michael Bolin ·
2026-03-28 21:08:19 +00:00 -
codex-tools: extract tool spec models (#16047)
## Why This continues the `codex-tools` migration by moving another passive tool-definition layer out of `codex-core`. After `ResponsesApiTool` and the lower-level schema adapters moved into `codex-tools`, `core/src/client_common.rs` was still owning `ToolSpec` and the web-search request wire types even though they are serialized data models rather than runtime orchestration. Keeping those types in `codex-core` makes the crate boundary look smaller than it really is and leaves non-runtime tool-shape code coupled to core. ## What changed - moved `ToolSpec`, `ResponsesApiWebSearchFilters`, and `ResponsesApiWebSearchUserLocation` into `codex-rs/tools/src/tool_spec.rs` - added focused unit tests in `codex-rs/tools/src/tool_spec_tests.rs` for: - `ToolSpec::name()` - web-search config conversions - `ToolSpec` serialization for `web_search` and `tool_search` - kept `codex-rs/tools/src/lib.rs` exports-only by re-exporting the new module from `lib.rs` - reduced `core/src/client_common.rs` to a compatibility shim that re-exports the extracted tool-spec types for current core call sites - updated `core/src/tools/spec_tests.rs` to consume the extracted web-search types directly from `codex-tools` - updated `codex-rs/tools/README.md` so the crate contract reflects that `codex-tools` now owns the passive tool-spec request models in addition to the lower-level Responses API structs ## Test plan - `cargo test -p codex-tools` - `cargo test -p codex-core --lib tools::spec::` - `cargo test -p codex-core --lib client_common::` - `just fix -p codex-tools -p codex-core` - `just argument-comment-lint` ## References - #15923 - #15928 - #15944 - #15953 - #16031
Michael Bolin ·
2026-03-28 13:37:00 -07:00 -
Remove the codex-tui app-server originator workaround (#16116)
## Summary - remove the temporary `codex-tui` special-case when setting the default originator during app-server initialization
Eric Traut ·
2026-03-28 13:53:33 -06:00 -
Remove remaining custom prompt support (#16115)
## Summary - remove protocol and core support for discovering and listing custom prompts - simplify the TUI slash-command flow and command popup to built-in commands only - delete obsolete custom prompt tests, helpers, and docs references - clean up downstream event handling for the removed protocol events
Eric Traut ·
2026-03-28 13:49:37 -06:00 -
build: migrate argument-comment-lint to a native Bazel aspect (#16106)
## Why `argument-comment-lint` had become a PR bottleneck because the repo-wide lane was still effectively running a `cargo dylint`-style flow across the workspace instead of reusing Bazel's Rust dependency graph. That kept the lint enforced, but it threw away the main benefit of moving this job under Bazel in the first place: metadata reuse and cacheable per-target analysis in the same shape as Clippy. This change moves the repo-wide lint onto a native Bazel Rust aspect so Linux and macOS can lint `codex-rs` without rebuilding the world crate-by-crate through the wrapper path. ## What Changed - add a nightly Rust toolchain with `rustc-dev` for Bazel and a dedicated crate-universe repo for `tools/argument-comment-lint` - add `tools/argument-comment-lint/driver.rs` and `tools/argument-comment-lint/lint_aspect.bzl` so Bazel can run the lint as a custom `rustc_driver` - switch repo-wide `just argument-comment-lint` and the Linux/macOS `rust-ci` lanes to `bazel build --config=argument-comment-lint //codex-rs/...` - keep the Python/DotSlash wrappers as the package-scoped fallback path and as the current Windows CI path - gate the Dylint entrypoint behind a `bazel_native` feature so the Bazel-native library avoids the `dylint_*` packaging stack - update the aspect runtime environment so the driver can locate `rustc_driver` correctly under remote execution - keep the dedicated `tools/argument-comment-lint` package tests and wrapper unit tests in CI so the source and packaged entrypoints remain covered ## Verification - `python3 -m unittest discover -s tools/argument-comment-lint -p 'test_*.py'` - `cargo test` in `tools/argument-comment-lint` - `bazel build //tools/argument-comment-lint:argument-comment-lint-driver --@rules_rust//rust/toolchain/channel=nightly` - `bazel build --config=argument-comment-lint //codex-rs/utils/path-utils:all` - `bazel build --config=argument-comment-lint //codex-rs/rollout:rollout` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/16106). * #16120 * __->__ #16106
Michael Bolin ·
2026-03-28 12:41:56 -07:00 -
fix: fix comment linter lint violations in Linux-only code (#16118)
https://github.com/openai/codex/pull/16071 took care of this for Windows, so this takes care of things for Linux. We don't touch the CI jobs in this PR because https://github.com/openai/codex/pull/16106 is going to be the real fix there (including a major speedup!).
Michael Bolin ·
2026-03-28 11:09:41 -07:00 -
Rename tui_app_server to tui (#16104)
This is a follow-up to https://github.com/openai/codex/pull/15922. That previous PR deleted the old `tui` directory and left the new `tui_app_server` directory in place. This PR renames `tui_app_server` to `tui` and fixes up all references.
Eric Traut ·
2026-03-28 11:23:07 -06:00 -
Update PR babysitter skill for review replies and resolution (#16112)
This PR updates the "PR Babysitter" skill to clarify that non-actionable review comments should receive a direct reply explaining why no change is needed, and actionable review comments should be marked "resolved" after they are addressed.
Eric Traut ·
2026-03-28 10:35:20 -06:00 -
fix(tui): refresh footer on collaboration mode changes (#16026)
## Summary - Moves status surface refresh (`refresh_status_surfaces` / `refresh_status_line`) from `App` event handlers into `ChatWidget` setters via a new `refresh_model_dependent_surfaces()` method - Ensures model-dependent UI stays in sync whenever collaboration mode, model, or reasoning effort changes, including the footer and terminal title in both `tui` and `tui_app_server` - Applies the fix to both `tui` and `tui_app_server` widgets #15961 ## Test plan - [x] Added snapshot test `status_line_model_with_reasoning_plan_mode_footer` verifying footer renders correctly in plan mode - [x] Added `terminal_title_model_updates_on_model_change_without_manual_refresh` in `tui_app_server` - [ ] Verify switching collaboration modes updates the footer in real TUI - [ ] Verify model/reasoning effort changes reflect in the status bar and terminal title --------- Co-authored-by: Eric Traut <etraut@openai.com>
Felipe Coury ·
2026-03-28 08:55:32 -06:00 -
bazel: add Windows gnullvm stack flags to unit test binaries (#16074)
## Summary Add the Windows gnullvm stack-reserve flags to the `*-unit-tests-bin` path in `codex_rust_crate()`. ## Why This is the narrow code fix behind the earlier review comment on [#16067](https://github.com/openai/codex/pull/16067). That comment was stale relative to the workflow-only PR it landed on, but it pointed at a real gap in `defs.bzl`. Today, `codex_rust_crate()` already appends `WINDOWS_GNULLVM_RUSTC_STACK_FLAGS` for: - `rust_binary()` targets - integration-test `rust_test()` targets But the unit-test binary path still omitted those flags. That meant the generated `*-unit-tests-bin` executables were not built the same way as the rest of the Windows gnullvm executables in the macro. ## What Changed - Added `WINDOWS_GNULLVM_RUSTC_STACK_FLAGS` to the `unit_test_binary` `rust_test()` rule in `defs.bzl` - Added a short comment explaining why unit-test binaries need the same stack-reserve treatment as binaries and integration tests on Windows gnullvm ## Testing - `bazel query '//codex-rs/core:*'` - `bazel query '//codex-rs/shell-command:*'` Those queries load packages that exercise `codex_rust_crate()`, including `*-unit-tests-bin` targets. The actual runtime effect is Windows-specific, so the real end-to-end confirmation still comes from Windows CI.
Michael Bolin ·
2026-03-27 22:11:49 -07:00 -
ci: split fast PR Rust CI from full post-merge Cargo CI (#16072)
## Summary Split the old all-in-one `rust-ci.yml` into: - a PR-time Cargo workflow in `rust-ci.yml` - a full post-merge Cargo workflow in `rust-ci-full.yml` This keeps the PR path focused on fast Cargo-native hygiene plus the Bazel `build` / `test` / `clippy` coverage in `bazel.yml`, while moving the heavyweight Cargo-native matrix to `main`. ## Why `bazel.yml` is now the main Rust verification workflow for pull requests. It already covers the Bazel build, test, and clippy signal we care about pre-merge, and it also runs on pushes to `main` to re-verify the merged tree and help keep the BuildBuddy caches warm. What was still missing was a clean split for the Cargo-native checks that Bazel does not replace yet. The old `rust-ci.yml` mixed together: - fast hygiene checks such as `cargo fmt --check` and `cargo shear` - `argument-comment-lint` - the full Cargo clippy / nextest / release-build matrix That made every PR pay for the full Cargo matrix even though most of that coverage is better treated as post-merge verification. The goal of this change is to leave PRs with the checks we still want before merge, while moving the heavier Cargo-native matrix off the review path. ## What Changed - Renamed the old heavyweight workflow to `rust-ci-full.yml` and limited it to `push` on `main` plus `workflow_dispatch`. - Added a new PR-only `rust-ci.yml` that runs: - changed-path detection - `cargo fmt --check` - `cargo shear` - `argument-comment-lint` on Linux, macOS, and Windows - `tools/argument-comment-lint` package tests when the lint itself or its workflow wiring changes - Kept the PR workflow's gatherer as the single required Cargo-native status so branch protection can stay simple. - Added `.github/workflows/README.md` to document the intended split between `bazel.yml`, `rust-ci.yml`, and `rust-ci-full.yml`. - Preserved the recent Windows `argument-comment-lint` behavior from `e02fd6e1d3` in `rust-ci-full.yml`, and mirrored cross-platform lint coverage into the PR workflow. A few details are deliberate: - The PR workflow still keeps the Linux lint lane on the default-targets-only invocation for now, while macOS and Windows use the broader released-linter path. - This PR does not change `bazel.yml`; it changes the Cargo-native workflow around the existing Bazel PR path. ## Testing - Rebasing this change onto `main` after `e02fd6e1d3` - `ruby -e 'require "yaml"; %w[.github/workflows/rust-ci.yml .github/workflows/rust-ci-full.yml .github/workflows/bazel.yml].each { |f| YAML.load_file(f) }'`Michael Bolin ·
2026-03-27 21:08:08 -07:00 -
fix: clean up remaining Windows argument-comment-lint violations (#16071)
## Why The initial `argument-comment-lint` rollout left Windows on default-target coverage because there were still Windows-only callsites failing under `--all-targets`. This follow-up cleans up those remaining Windows-specific violations so the Windows CI lane can enforce the same stricter coverage, leaving Linux as the remaining platform-specific follow-up. ## What changed - switched the Windows `rust-ci` argument-comment-lint step back to the default wrapper invocation so it runs full-target coverage again - added the required `/*param_name*/` annotations at Windows-gated literal callsites in: - `codex-rs/windows-sandbox-rs/src/lib.rs` - `codex-rs/windows-sandbox-rs/src/elevated_impl.rs` - `codex-rs/tui_app_server/src/multi_agents.rs` - `codex-rs/network-proxy/src/proxy.rs` ## Validation - Windows `argument comment lint` CI on this PR
Michael Bolin ·
2026-03-27 20:48:21 -07:00 -
ci: run Bazel clippy on Windows gnullvm (#16067)
## Why We want more of the pre-merge Rust signal to come from `bazel.yml`, especially on Windows. The Bazel test workflow already exercises `x86_64-pc-windows-gnullvm`, but the Bazel clippy job still only ran on Linux x64 and macOS arm64. That left a gap where Windows-only Bazel lint breakages could slip through until the Cargo-based workflow ran. This change keeps the fix narrow. Rather than expanding the Bazel clippy target set or changing the shared setup logic, it extends the existing clippy matrix to the same Windows GNU toolchain that the Bazel test job already uses. ## What Changed - add `windows-latest` / `x86_64-pc-windows-gnullvm` to the `clippy` job matrix in `.github/workflows/bazel.yml` - update the nearby workflow comment to explain that the goal is to get Bazel-native Windows lint coverage on the same toolchain as the Bazel test lane - leave the Bazel clippy scope unchanged at `//codex-rs/... -//codex-rs/v8-poc:all` ## Verification - parsed `.github/workflows/bazel.yml` successfully with Ruby `YAML.load_file`
Michael Bolin ·
2026-03-27 20:47:22 -07:00 -
bazel: enable the full Windows gnullvm CI path (#15952)
## Why This PR is the current, consolidated follow-up to the earlier Windows Bazel attempt in #11229. The goal is no longer just to get a tiny Windows smoke job limping along: it is to make the ordinary Bazel CI path usable on `windows-latest` for `x86_64-pc-windows-gnullvm`, with the same broad `//...` test shape that macOS and Linux already use. The earlier smoke-list version of this work was useful as a foothold, but it was not a good long-term landing point. Windows Bazel kept surfacing real issues outside that allowlist: - GitHub's Windows runner exposed runfiles-manifest bugs such as `FINDSTR: Cannot open D:MANIFEST`, which broke Bazel test launchers even when the manifest file existed. - `rules_rs`, `rules_rust`, LLVM extraction, and Abseil still needed `windows-gnullvm`-specific fixes for our hermetic toolchain. - the V8 path needed more work than just turning the Windows matrix entry back on: `rusty_v8` does not ship Windows GNU artifacts in the same shape we need, and Bazel's in-tree V8 build needed a set of Windows GNU portability fixes. Windows performance pressure also pushed this toward a full solution instead of a permanent smoke suite. During this investigation we hit targets such as `//codex-rs/shell-command:shell-command-unit-tests` that were much more expensive on Windows because they repeatedly spawn real PowerShell parsers (see #16057 for one concrete example of that pressure). That made it much more valuable to get the real Windows Bazel path working than to keep iterating on a narrowly curated subset. The net result is that this PR now aims for the same CI contract on Windows that we already expect elsewhere: keep standalone `//third_party/v8:all` out of the ordinary Bazel lane, but allow V8 consumers under `//codex-rs/...` to build and test transitively through `//...`. ## What Changed ### CI and workflow wiring - re-enable the `windows-latest` / `x86_64-pc-windows-gnullvm` Bazel matrix entry in `.github/workflows/bazel.yml` - move the Windows Bazel output root to `D:\b` and enable `git config --global core.longpaths true` in `.github/actions/setup-bazel-ci/action.yml` - keep the ordinary Bazel target set on Windows aligned with macOS and Linux by running `//...` while excluding only standalone `//third_party/v8:all` targets from the normal lane ### Toolchain and module support for `windows-gnullvm` - patch `rules_rs` so `windows-gnullvm` is modeled as a distinct Windows exec/toolchain platform instead of collapsing into the generic Windows shape - patch `rules_rust` build-script environment handling so llvm-mingw build-script probes do not inherit unsupported `-fstack-protector*` flags - patch the LLVM module archive so it extracts cleanly on Windows and provides the MinGW libraries this toolchain needs - patch Abseil so its thread-local identity path matches the hermetic `windows-gnullvm` toolchain instead of taking an incompatible MinGW pthread path - keep both MSVC and GNU Windows targets in the generated Cargo metadata because the current V8 release-asset story still uses MSVC-shaped names in some places while the Bazel build targets the GNU ABI ### Windows test-launch and binary-behavior fixes - update `workspace_root_test_launcher.bat.tpl` to read the runfiles manifest directly instead of shelling out to `findstr`, which was the source of the `D:MANIFEST` failures on the GitHub Windows runner - thread a larger Windows GNU stack reserve through `defs.bzl` so Bazel-built binaries that pull in V8 behave correctly both under normal builds and under `bazel test` - remove the no-longer-needed Windows bootstrap sh-toolchain override from `.bazelrc` ### V8 / `rusty_v8` Windows GNU support - export and apply the new Windows GNU patch set from `patches/BUILD.bazel` / `MODULE.bazel` - patch the V8 module/rules/source layers so the in-tree V8 build can produce Windows GNU archives under Bazel - teach `third_party/v8/BUILD.bazel` to build Windows GNU static archives in-tree instead of aliasing them to the MSVC prebuilts - reuse the Linux release binding for the experimental Windows GNU path where `rusty_v8` does not currently publish a Windows GNU binding artifact ## Testing - the primary end-to-end validation for this work is the `Bazel` workflow plus `v8-canary`, since the hard parts are Windows-specific and depend on real GitHub runner behavior - before consolidation back onto this PR, the same net change passed the full Bazel matrix in [run 23675590471](https://github.com/openai/codex/actions/runs/23675590471) and passed `v8-canary` in [run 23675590453](https://github.com/openai/codex/actions/runs/23675590453) - those successful runs included the `windows-latest` / `x86_64-pc-windows-gnullvm` Bazel job with the ordinary `//...` path, not the earlier Windows smoke allowlist --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15952). * #16067 * __->__ #15952
Michael Bolin ·
2026-03-27 20:37:03 -07:00 -
refactor: rewrite argument-comment lint wrappers in Python (#16063)
## Why The `argument-comment-lint` entrypoints had grown into two shell wrappers with duplicated parsing, environment setup, and Cargo forwarding logic. The recent `--` separator regression was a good example of the problem: the behavior was subtle, easy to break, and hard to verify. This change rewrites those wrappers in Python so the control flow is easier to follow, the shared behavior lives in one place, and the tricky argument/defaulting paths have direct test coverage. ## What changed - replaced `tools/argument-comment-lint/run.sh` and `tools/argument-comment-lint/run-prebuilt-linter.sh` with Python entrypoints: `run.py` and `run-prebuilt-linter.py` - moved shared wrapper behavior into `tools/argument-comment-lint/wrapper_common.py`, including: - splitting lint args from forwarded Cargo args after `--` - defaulting repo runs to `--manifest-path codex-rs/Cargo.toml --workspace --no-deps` - defaulting non-`--fix` runs to `--all-targets` unless the caller explicitly narrows the target set - setting repo defaults for `DYLINT_RUSTFLAGS` and `CARGO_INCREMENTAL` - kept the prebuilt wrapper thin: it still just resolves the packaged DotSlash entrypoint, keeps `rustup` shims first on `PATH`, infers `RUSTUP_HOME` when needed, and then launches the packaged `cargo-dylint` path - updated `justfile`, `rust-ci.yml`, and `tools/argument-comment-lint/README.md` to use the Python entrypoints - updated `rust-ci` so the package job runs Python syntax checks plus the new wrapper unit tests, and the OS-specific lint jobs invoke the wrappers through an explicit Python interpreter This is a follow-up to #16054: it keeps the current lint semantics while making the wrapper logic maintainable enough to iterate on safely. ## Validation - `python3 -m py_compile tools/argument-comment-lint/wrapper_common.py tools/argument-comment-lint/run.py tools/argument-comment-lint/run-prebuilt-linter.py tools/argument-comment-lint/test_wrapper_common.py` - `python3 -m unittest discover -s tools/argument-comment-lint -p 'test_*.py'` - `python3 ./tools/argument-comment-lint/run-prebuilt-linter.py -p codex-terminal-detection -- --lib` - `python3 ./tools/argument-comment-lint/run.py -p codex-terminal-detection -- --lib`
Michael Bolin ·
2026-03-27 19:42:30 -07:00 -
shell-command: reuse a PowerShell parser process on Windows (#16057)
## Why `//codex-rs/shell-command:shell-command-unit-tests` became a real bottleneck in the Windows Bazel lane because repeated calls to `is_safe_command_windows()` were starting a fresh PowerShell parser process for every `powershell.exe -Command ...` assertion. PR #16056 was motivated by that same bottleneck, but its test-only shortcut was the wrong layer to optimize because it weakened the end-to-end guarantee that our runtime path really asks PowerShell to parse the command the way we expect. This PR attacks the actual cost center instead: it keeps the real PowerShell parser in the loop, but turns that parser into a long-lived helper process so both tests and the runtime safe-command path can reuse it across many requests. ## What Changed - add `shell-command/src/command_safety/powershell_parser.rs`, which keeps one mutex-protected parser process per PowerShell executable path and speaks a simple JSON-over-stdio request/response protocol - turn `shell-command/src/command_safety/powershell_parser.ps1` into a long-running parser server with comments explaining the protocol, the AST-shape restrictions, and why unsupported constructs are rejected conservatively - keep request ids and a one-time respawn path so a dead or desynchronized cached child fails closed instead of silently returning mixed parser output - preserve separate parser processes for `powershell.exe` and `pwsh.exe`, since they do not accept the same language surface - avoid a direct `PipelineChainAst` type reference in the PowerShell script so the parser service still runs under Windows PowerShell 5.1 as well as newer `pwsh` - make `shell-command/src/command_safety/windows_safe_commands.rs` delegate to the new parser utility instead of spawning a fresh PowerShell process for every parse - add a Windows-only unit test that exercises multiple sequential requests against the same parser process ## Testing - adds a Windows-only parser-reuse unit test in `powershell_parser.rs` - the main end-to-end verification for this change is the Windows CI lane, because the new service depends on real `powershell.exe` / `pwsh.exe` behavior
Michael Bolin ·
2026-03-27 19:33:41 -07:00 -
Support Codex CLI stdin piping for
codex exec(#15917)# Summary Claude Code supports a useful prompt-plus-stdin workflow: ```bash echo "complex input..." | claude -p "summarize concisely" ``` Codex previously did not support the equivalent `codex exec` form. While `codex exec` could read the prompt from stdin, it could not combine piped input with an explicit prompt argument. This change adds that missing workflow: ```bash echo "complex input..." | codex exec "summarize concisely" ``` With this change, when `codex exec` receives both a positional prompt and piped stdin, the prompt remains the instruction and stdin is passed along as structured `<stdin>...</stdin>` context. Example: ```bash curl https://jsonplaceholder.typicode.com/comments \ | ./target/debug/codex exec --skip-git-repo-check "format the top 20 items into a markdown table" \ > table.md ``` This PR also adds regression coverage for: - prompt argument + piped stdin - legacy stdin-as-prompt behavior - `codex exec -` forced-stdin behavior - empty-stdin error cases --------- Co-authored-by: Codex <noreply@openai.com>
Joe Liccini ·
2026-03-28 02:21:22 +00:00 -
chore: clean up argument-comment lint and roll out all-target CI on macOS (#16054)
## Why `argument-comment-lint` was green in CI even though the repo still had many uncommented literal arguments. The main gap was target coverage: the repo wrapper did not force Cargo to inspect test-only call sites, so examples like the `latest_session_lookup_params(true, ...)` tests in `codex-rs/tui_app_server/src/lib.rs` never entered the blocking CI path. This change cleans up the existing backlog, makes the default repo lint path cover all Cargo targets, and starts rolling that stricter CI enforcement out on the platform where it is currently validated. ## What changed - mechanically fixed existing `argument-comment-lint` violations across the `codex-rs` workspace, including tests, examples, and benches - updated `tools/argument-comment-lint/run-prebuilt-linter.sh` and `tools/argument-comment-lint/run.sh` so non-`--fix` runs default to `--all-targets` unless the caller explicitly narrows the target set - fixed both wrappers so forwarded cargo arguments after `--` are preserved with a single separator - documented the new default behavior in `tools/argument-comment-lint/README.md` - updated `rust-ci` so the macOS lint lane keeps the plain wrapper invocation and therefore enforces `--all-targets`, while Linux and Windows temporarily pass `-- --lib --bins` That temporary CI split keeps the stricter all-targets check where it is already cleaned up, while leaving room to finish the remaining Linux- and Windows-specific target-gated cleanup before enabling `--all-targets` on those runners. The Linux and Windows failures on the intermediate revision were caused by the wrapper forwarding bug, not by additional lint findings in those lanes. ## Validation - `bash -n tools/argument-comment-lint/run.sh` - `bash -n tools/argument-comment-lint/run-prebuilt-linter.sh` - shell-level wrapper forwarding check for `-- --lib --bins` - shell-level wrapper forwarding check for `-- --tests` - `just argument-comment-lint` - `cargo test` in `tools/argument-comment-lint` - `cargo test -p codex-terminal-detection` ## Follow-up - Clean up remaining Linux-only target-gated callsites, then switch the Linux lint lane back to the plain wrapper invocation. - Clean up remaining Windows-only target-gated callsites, then switch the Windows lint lane back to the plain wrapper invocation.
Michael Bolin ·
2026-03-27 19:00:44 -07:00 -
Fix tui_app_server agent picker closed-state regression (#16014)
Addresses #15992 The app-server TUI was treating tracked agent threads as closed based on listener-task bookkeeping that does not reflect live thread state during normal thread switching. That caused the `/agent` picker to gray out live agents and could show a false "Agent thread ... is closed" replay message after switching branches. This PR fixes the picker refresh path to query the app server for each tracked thread and derive closed vs loaded state from `thread/read` status, while preserving cached agent metadata for replay-only threads.
Eric Traut ·
2026-03-27 19:05:43 -06:00 -
Fix tui_app_server resume-by-name lookup regression (#16050)
Addresses #16049 `codex resume <name>` and `/resume <name>` could fail in the app-server TUI path because name lookup pre-filtered `thread/list` with the backend `search_term`, but saved thread names are hydrated after listing and are not part of that search index. Resolve names by scanning listed threads client-side instead, and add a regression test for saved sessions whose rollout title does not match the thread name.
Eric Traut ·
2026-03-27 19:04:48 -06:00 -
ci: run SDK tests with a Bazel-built codex (#16046)
## Why Before this change, the SDK CI job built `codex` with Cargo before running the TypeScript package tests. That step has been getting more expensive as the Rust workspace grows, while the repo already has a Bazel-backed build path for the CLI. The SDK tests also need a normal executable path they can spawn repeatedly. Moving the job to Bazel exposed an extra CI detail: a plain `bazel-bin/...` lookup is not reliable under the Linux config because top-level outputs may stay remote and the wrapper emits status lines around `cquery` output. ## What Changed - taught `sdk/typescript/tests/testCodex.ts` to honor `CODEX_EXEC_PATH` before falling back to the local Cargo-style `target/debug/codex` path - added `--remote-download-toplevel` to `.github/scripts/run-bazel-ci.sh` so workflows can force Bazel to materialize top-level outputs on disk after a build - switched `.github/workflows/sdk.yml` from `cargo build --bin codex` to the shared Bazel CI setup and `//codex-rs/cli:codex` build target - changed the SDK workflow to resolve the built CLI with wrapper-backed `cquery --output=files`, stage the binary into `${GITHUB_WORKSPACE}/.tmp/sdk-ci/codex`, and point the SDK tests at that path via `CODEX_EXEC_PATH` - kept the warm-up step before Jest and the Bazel repository-cache save step ## Verification - `bash -n .github/scripts/run-bazel-ci.sh` - `./.github/scripts/run-bazel-ci.sh -- cquery --output=files -- //codex-rs/cli:codex | grep -E '^(/|bazel-out/)' | tail -n 1` - `./.github/scripts/run-bazel-ci.sh --remote-download-toplevel -- build --build_metadata=TAG_job=sdk -- //codex-rs/cli:codex` - `CODEX_EXEC_PATH="$PWD/.tmp/sdk-ci/codex" pnpm --dir sdk/typescript test --runInBand` - `pnpm --dir sdk/typescript lint`Michael Bolin ·
2026-03-27 17:17:22 -07:00 -
[codex] Pin GitHub Actions workflow references (#15828)
Pin floating external GitHub Actions workflow refs to immutable SHAs. Why are we doing this? Please see the rationale doc: https://docs.google.com/document/d/1qOURCNx2zszQ0uWx7Fj5ERu4jpiYjxLVWBWgKa2wTsA/edit?tab=t.0 Did this break you? Please roll back and let hintz@ know
Drew Hintz ·
2026-03-27 23:00:05 +00:00 -
Remove the legacy TUI split (#15922)
This is the part 1 of 2 PRs that will delete the `tui` / `tui_app_server` split. This part simply deletes the existing `tui` directory and marks the `tui_app_server` feature flag as removed. I left the `tui_app_server` feature flag in place for now so its presence doesn't result in an error. It is simply ignored. Part 2 will rename the `tui_app_server` directory `tui`. I did this as two parts to reduce visible code churn.
Eric Traut ·
2026-03-27 22:56:44 +00:00 -
don't include redundant write roots in apply_patch (#16030)
apply_patch sometimes provides additional parent dir as a writable root when it is already writable. This is mostly a no-op on Mac/Linux but causes actual ACL churn on Windows that is best avoided. We are also seeing some actual failures with these ACLs in the wild, which I haven't fully tracked down, but it's safe/best to avoid doing it altogether.
iceweasel-oai ·
2026-03-27 15:41:51 -07:00 -
[mcp] Bypass read-only tool checks. (#16044)
- [x] Auto / unspecified approval mode: read-only tools now skip before guardian routing. - [x] Approve / always-allow mode: read-only tools still skip, now via the shared early return. - [x] Prompt mode: read-only tools no longer skip; they continue to approval.
Matthew Zeng ·
2026-03-27 15:22:04 -07:00 -
Fix /copy regression in tui_app_server turn completion (#16021)
Addresses #16019 `tui_app_server` renders completed assistant messages from item notifications, but it only updated `/copy` state from `turn/completed`. After the app-server migration, turn completion no longer repeats the final assistant text, so `/copy` could stay unavailable even after the first normal response. This PR track the last completed final-answer agent message during an active app-server turn and promote it into the `/copy` cache when the turn completes. This restores the pre-migration behavior without changing rollback handling.
Eric Traut ·
2026-03-27 16:00:24 -06:00 -
Fix tui_app_server hook notification rendering and replay (#16013)
Addresses #15984 HookStarted/HookCompleted notifications were being translated through a fragile JSON bridge, so hook status/output never reached the renderer. Early hook notifications could also be dropped during session refresh before replay. This PR fixes `tui_app_server` by mapping app-server hook notifications into TUI hook events explicitly and preserving buffered hook notifications across refresh, so cold-start and resumed sessions render the same hook UI as the legacy TUI.
Eric Traut ·
2026-03-27 15:33:51 -06:00 -
codex-tools: extract responses API tool models (#16031)
## Why The previous extraction steps moved shared tool-schema parsing into `codex-tools`, but `codex-core` still owned the generic Responses API tool models and the last adapter layer that turned parsed tool definitions into `ResponsesApiTool` values. That left `core/src/tools/spec.rs` and `core/src/client_common.rs` holding a chunk of tool-shaping code that does not need session state, runtime plumbing, or any other `codex-core`-specific dependency. As a result, `codex-tools` owned the parsed tool definition, but `codex-core` still owned the generic wire model that those definitions are converted into. This change moves that boundary one step further. `codex-tools` now owns the reusable Responses/tool wire structs and the shared conversion helpers for dynamic tools, MCP tools, and deferred MCP aliases. `codex-core` continues to own `ToolSpec` orchestration and the remaining web-search-specific request shapes. ## What changed - added `tools/src/responses_api.rs` to own `ResponsesApiTool`, `FreeformTool`, `ToolSearchOutputTool`, namespace output types, and the shared `ToolDefinition -> ResponsesApiTool` adapter helpers - added `tools/src/responses_api_tests.rs` for deferred-loading behavior, adapter coverage, and namespace serialization coverage - rewired `core/src/tools/spec.rs` to use the extracted dynamic/MCP adapter helpers instead of defining those conversions locally - rewired `core/src/tools/handlers/tool_search.rs` to use the extracted deferred MCP adapter and namespace output types directly - slimmed `core/src/client_common.rs` so it now keeps `ToolSpec` and the web-search-specific wire types, while reusing the extracted tool models from `codex-tools` - moved the extracted seam tests out of `core` and updated `codex-rs/tools/README.md` plus `tools/src/lib.rs` to reflect the expanded `codex-tools` boundary ## Test plan - `cargo test -p codex-tools` - `cargo test -p codex-core --lib tools::spec::` - `cargo test -p codex-core --lib tools::handlers::tool_search::` - `just fix -p codex-tools -p codex-core` - `just argument-comment-lint` ## References - [#15923](https://github.com/openai/codex/pull/15923) `codex-tools: extract shared tool schema parsing` - [#15928](https://github.com/openai/codex/pull/15928) `codex-tools: extract MCP schema adapters` - [#15944](https://github.com/openai/codex/pull/15944) `codex-tools: extract dynamic tool adapters` - [#15953](https://github.com/openai/codex/pull/15953) `codex-tools: introduce named tool definitions`
Michael Bolin ·
2026-03-27 14:26:54 -07:00 -
Add usage-based business plan types (#15934)
## Summary - add `self_serve_business_usage_based` and `enterprise_cbp_usage_based` to the public/internal plan enums and regenerate the app-server + Python SDK artifacts - map both plans through JWT login and backend rate-limit payloads, then bucket them with the existing Team/Business entitlement behavior in cloud requirements, usage-limit copy, tooltips, and status display - keep the earlier display-label remap commit on this branch so the new Team-like and Business-like plans render consistently in the UI ## Testing - `just write-app-server-schema` - `uv run --project sdk/python python sdk/python/scripts/update_sdk_artifacts.py generate-types` - `just fix -p codex-protocol -p codex-login -p codex-core -p codex-backend-client -p codex-cloud-requirements -p codex-tui -p codex-tui-app-server -p codex-backend-openapi-models` - `just fmt` - `just argument-comment-lint` - `cargo test -p codex-protocol usage_based_plan_types_use_expected_wire_names` - `cargo test -p codex-login usage_based` - `cargo test -p codex-backend-client usage_based` - `cargo test -p codex-cloud-requirements usage_based` - `cargo test -p codex-core usage_limit_reached_error_formats_` - `cargo test -p codex-tui plan_type_display_name_remaps_display_labels` - `cargo test -p codex-tui remapped` - `cargo test -p codex-tui-app-server plan_type_display_name_remaps_display_labels` - `cargo test -p codex-tui-app-server remapped` - `cargo test -p codex-tui-app-server preserves_usage_based_plan_type_wire_name` ## Notes - a broader multi-crate `cargo test` run still hits unrelated existing guardian-approval config failures in `codex-rs/core/src/config/config_tests.rs`
bwanner-oai ·
2026-03-27 14:25:13 -07:00 -
plugins: Clean up stale curated plugin sync temp dirs and add sync metrics (#16035)
1. Keep curated plugin staging directories under TempDir ownership until activation succeeds, so failed git/HTTP sync attempts do not leak plugins-clone-*. 2. Best-effort clean up stale plugins-clone-* directories before creating a new staged repo, using a conservative age threshold. 3. Emit OTEL counters for curated plugin startup sync transport attempts and final outcome across git and HTTP paths.
xl-openai ·
2026-03-27 14:21:18 -07:00 -
Normalize /mcp tool grouping for hyphenated server names (#15946)
Fix display for servers with special characters.
pakrym-oai ·
2026-03-27 14:58:29 -06:00 -
fix: disable plugins in SDK integration tests (#16036)
## Why The TypeScript SDK tests create a fresh `CODEX_HOME` for each Jest case and delete it during teardown. That cleanup has been flaking because the real `codex` binary can still be doing background curated-plugin startup sync under `.tmp/plugins-clone-*`, which races the test harness's recursive delete and leaves `ENOTEMPTY` failures behind. This path is unrelated to what the SDK tests are exercising, so letting plugin startup run during these tests only adds nondeterministic filesystem activity. This showed up recently in the `sdk` CI lane for [#16031](https://github.com/openai/codex/pull/16031). ## What Changed - updated `sdk/typescript/tests/testCodex.ts` to merge test config through a single helper - disabled `features.plugins` unconditionally for SDK integration tests so the CLI does not start curated-plugin sync in the temporary `CODEX_HOME` - preserved other explicit feature overrides from individual tests while forcing `plugins` back to `false` - kept the existing mock-provider override behavior intact for SSE-backed tests ## Verification - `pnpm test --runInBand` - `pnpm lint`
Michael Bolin ·
2026-03-27 13:04:34 -07:00 -
fix: fix Windows CI regression introduced in #15999 (#16027)
#15999 introduced a Windows-only `\r\n` mismatch in review-exit template handling. This PR normalizes those template newlines and separates that fix from [#16014](https://github.com/openai/codex/pull/16014) so it can be reviewed independently.
Michael Bolin ·
2026-03-27 12:06:07 -07:00 -
codex-tools: introduce named tool definitions (#15953)
## Why This continues the `codex-tools` migration by moving one more piece of generic tool-definition bookkeeping out of `codex-core`. The earlier extraction steps moved shared schema parsing into `codex-tools`, but `core/src/tools/spec.rs` still had to supply tool names separately and perform ad hoc rewrites for deferred MCP aliases. That meant the crate boundary was still awkward: the parsed shape coming back from `codex-tools` was missing part of the definition that `codex-core` ultimately needs to assemble a `ResponsesApiTool`. This change introduces a named `ToolDefinition` in `codex-tools` so both MCP tools and dynamic tools cross the crate boundary in the same reusable model. `codex-core` still owns the final `ResponsesApiTool` assembly, but less of the generic tool-definition shaping logic stays behind in `core`. ## What changed - replaced `ParsedToolDefinition` with a named `ToolDefinition` in `codex-rs/tools/src/tool_definition.rs` - added `codex-rs/tools/src/tool_definition_tests.rs` for `renamed()` and `into_deferred()` - updated `parse_dynamic_tool()` and `parse_mcp_tool()` to return `ToolDefinition` - simplified `codex-rs/core/src/tools/spec.rs` so it adapts `ToolDefinition` into `ResponsesApiTool` instead of rewriting names and deferred fields inline - updated parser tests and `codex-rs/tools/README.md` to reflect the named tool-definition model ## Test plan - `cargo test -p codex-tools` - `cargo test -p codex-core --lib tools::spec::`
Michael Bolin ·
2026-03-27 12:02:55 -07:00 -
ci: add Bazel clippy workflow for codex-rs (#15955)
## Why `bazel.yml` already builds and tests the Bazel graph, but `rust-ci.yml` still runs `cargo clippy` separately. This PR starts the transition to a Bazel-backed lint lane for `codex-rs` so we can eventually replace the duplicate Rust build, test, and lint work with Bazel while explicitly keeping the V8 Bazel path out of scope for now. To make that lane practical, the workflow also needs to look like the Bazel job we already trust. That means sharing the common Bazel setup and invocation logic instead of hand-copying it, and covering the arm64 macOS path in addition to Linux. Landing the workflow green also required fixing the first lint findings that Bazel surfaced and adding the matching local entrypoint. ## What changed - add a reusable `build:clippy` config to `.bazelrc` and export `codex-rs/clippy.toml` from `codex-rs/BUILD.bazel` so Bazel can run the repository's existing Clippy policy - add `just bazel-clippy` so the local developer entrypoint matches the new CI lane - extend `.github/workflows/bazel.yml` with a dedicated Bazel clippy job for `codex-rs`, scoped to `//codex-rs/... -//codex-rs/v8-poc:all` - run that clippy job on Linux x64 and arm64 macOS - factor the shared Bazel workflow setup into `.github/actions/setup-bazel-ci/action.yml` and the shared Bazel invocation logic into `.github/scripts/run-bazel-ci.sh` so the clippy and build/test jobs stay aligned - fix the first Bazel-clippy findings needed to keep the lane green, including the cross-target `cmsghdr::cmsg_len` normalization in `codex-rs/shell-escalation/src/unix/socket.rs` and the no-`voice-input` dead-code warnings in `codex-rs/tui` and `codex-rs/tui_app_server` ## Verification - `just bazel-clippy` - `RUNNER_OS=macOS ./.github/scripts/run-bazel-ci.sh -- build --config=clippy --build_metadata=COMMIT_SHA=local-check --build_metadata=TAG_job=clippy -- //codex-rs/... -//codex-rs/v8-poc:all` - `bazel build --config=clippy //codex-rs/shell-escalation:shell-escalation` - `CARGO_TARGET_DIR=/tmp/codex4-shell-escalation-test cargo test -p codex-shell-escalation` - `ruby -e 'require "yaml"; YAML.load_file(".github/workflows/bazel.yml"); YAML.load_file(".github/actions/setup-bazel-ci/action.yml")'` ## Notes - `CARGO_TARGET_DIR=/tmp/codex4-tui-app-server-test cargo test -p codex-tui-app-server` still hits existing guardian-approvals test and snapshot failures unrelated to this PR's Bazel-clippy changes. Related: #15954Michael Bolin ·
2026-03-27 12:02:41 -07:00 -
codex-tools: extract dynamic tool adapters (#15944)
## Why `codex-tools` already owned the shared JSON schema parser and the MCP tool schema adapter, but `core/src/tools/spec.rs` still parsed dynamic tools directly. That left the tool-schema boundary split in two different ways: - MCP tools flowed through `codex-tools`, while dynamic tools were still parsed in `codex-core` - the extracted dynamic-tool path initially introduced a dynamic-specific parsed shape even though `codex-tools` already had very similar MCP adapter output This change finishes that extraction boundary in one step. `codex-core` still owns `ResponsesApiTool` assembly, but both MCP tools and dynamic tools now enter that layer through `codex-tools` using the same parsed tool-definition shape. ## What changed - added `tools/src/dynamic_tool.rs` and sibling `tools/src/dynamic_tool_tests.rs` - introduced `parse_dynamic_tool()` in `codex-tools` and switched `core/src/tools/spec.rs` to use it for dynamic tools - added `tools/src/parsed_tool_definition.rs` so both MCP and dynamic adapters return the same `ParsedToolDefinition` - updated `core/src/tools/spec.rs` to build `ResponsesApiTool` through a shared local adapter helper instead of separate MCP and dynamic assembly paths - expanded `core/src/tools/spec_tests.rs` so the dynamic-tool adapter test asserts the full converted `ResponsesApiTool`, including `defer_loading` - updated `codex-rs/tools/README.md` to reflect the shared parsed tool-definition boundary ## Test plan - `cargo test -p codex-tools` - `cargo test -p codex-core --lib tools::spec::` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15944). * #15953 * __->__ #15944
Michael Bolin ·
2026-03-27 09:12:36 -07:00 -
fix(sandbox): fix bwrap lookup for multi-entry PATH (#15973)
## Summary - split the joined `PATH` before running system `bwrap` lookup - keep the existing workspace-local `bwrap` skip behavior intact - add regression tests that exercise real multi-entry search paths ## Why The PATH-based lookup added in #15791 still wrapped the raw `PATH` environment value as a single `PathBuf` before passing it through `join_paths()`. On Unix, a normal multi-entry `PATH` contains `:`, so that wrapper path is invalid as one path element and the lookup returns `None`. That made Codex behave as if no system `bwrap` was installed even when `bwrap` was available on `PATH`, which is what users in #15340 were still hitting on `0.117.0-alpha.25`. ## Impact System `bwrap` discovery now works with normal multi-entry `PATH` values instead of silently falling back to the vendored binary. Fixes #15340. ## Validation - `just fmt` - `cargo test -p codex-sandboxing` - `cargo test -p codex-linux-sandbox` - `just fix -p codex-sandboxing` - `just argument-comment-lint`
viyatb-oai ·
2026-03-27 08:41:06 -07:00 -
feat: spawn v2 as inter agent communication (#15985)
Co-authored-by: Codex <noreply@openai.com>
jif-oai ·
2026-03-27 15:45:19 +01:00 -
jif-oai ·
2026-03-27 15:30:28 +01:00 -
jif-oai ·
2026-03-27 15:08:24 +01:00 -
jif-oai ·
2026-03-27 14:51:07 +01:00 -
jif-oai ·
2026-03-27 14:50:36 +01:00 -
jif-oai ·
2026-03-27 14:50:01 +01:00 -
jif-oai ·
2026-03-27 14:49:45 +01:00 -
jif-oai ·
2026-03-27 11:30:22 +01:00 -
chore: move pty and windows sandbox to Rust 2024 (#15954)
## Why `codex-utils-pty` and `codex-windows-sandbox` were the remaining crates in `codex-rs` that still overrode the workspace's Rust 2024 edition. Moving them forward in a separate PR keeps the baseline edition update isolated from the follow-on Bazel clippy workflow in #15955, while making linting and formatting behavior consistent with the rest of the workspace. This PR also needs Cargo and Bazel to agree on the edition for `codex-windows-sandbox`. Without the Bazel-side sync, the experimental Bazel app-server builds fail once they compile `windows-sandbox-rs`. ## What changed - switch `codex-rs/utils/pty` and `codex-rs/windows-sandbox-rs` to `edition = "2024"` - update `codex-utils-pty` callsites and tests to use the collapsed `if let` form that Clippy expects under the new edition - fix the Rust 2024 fallout in `windows-sandbox-rs`, including the reserved `gen` identifier, `unsafe extern` requirements, and new Clippy findings that surfaced under the edition bump - keep the edition bump separate from a larger unsafe cleanup by temporarily allowing `unsafe_op_in_unsafe_fn` in the Windows entrypoint modules that now report it under Rust 2024 - update `codex-rs/windows-sandbox-rs/BUILD.bazel` to `crate_edition = "2024"` so Bazel compiles the crate with the same edition as Cargo --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15954). * #15976 * #15955 * __->__ #15954
Michael Bolin ·
2026-03-27 02:31:08 -07:00 -
jif-oai ·
2026-03-27 09:41:47 +01:00 -
Add ChatGPT device-code login to app server (#15525)
## Problem App-server clients could only initiate ChatGPT login through the browser callback flow, even though the shared login crate already supports device-code auth. That left VS Code, Codex App, and other app-server clients without a first-class way to use the existing device-code backend when browser redirects are brittle or when the client UX wants to own the login ceremony. ## Mental model This change adds a second ChatGPT login start path to app-server: clients can now call `account/login/start` with `type: "chatgptDeviceCode"`. App-server immediately returns a `loginId` plus the device-code UX payload (`verificationUrl` and `userCode`), then completes the login asynchronously in the background using the existing `codex_login` polling flow. Successful device-code login still resolves to ordinary `chatgpt` auth, and completion continues to flow through the existing `account/login/completed` and `account/updated` notifications. ## Non-goals This does not introduce a new auth mode, a new account shape, or a device-code eligibility discovery API. It also does not add automatic fallback to browser login in core; clients remain responsible for choosing when to request device code and whether to retry with a different UX if the backend/admin policy rejects it. ## Tradeoffs We intentionally keep `login_chatgpt_common` as a local validation helper instead of turning it into a capability probe. Device-code eligibility is checked by actually calling `request_device_code`, which means policy-disabled cases surface as an immediate request error rather than an async completion event. We also keep the active-login state machine minimal: browser and device-code logins share the same public cancel contract, but device-code cancellation is implemented with a local cancel token rather than a larger cross-crate refactor. ## Architecture The protocol grows a new `chatgptDeviceCode` request/response variant in app-server v2. On the server side, the new handler reuses the existing ChatGPT login precondition checks, calls `request_device_code`, returns the device-code payload, and then spawns a background task that waits on either cancellation or `complete_device_code_login`. On success, it reuses the existing auth reload and cloud-requirements refresh path before emitting `account/login/completed` success and `account/updated`. On failure or cancellation, it emits only `account/login/completed` failure. The existing `account/login/cancel { loginId }` contract remains unchanged and now works for both browser and device-code attempts. ## Tests Added protocol serialization coverage for the new request/response variant, plus app-server tests for device-code success, failure, cancel, and start-time rejection behavior. Existing browser ChatGPT login coverage remains in place to show that the callback-based flow is unchanged.daniel-oai ·
2026-03-27 00:27:15 -07:00 -
chore: refactor network permissions to use explicit domain and unix socket rule maps (#15120)
## Summary This PR replaces the legacy network allow/deny list model with explicit rule maps for domains and unix sockets across managed requirements, permissions profiles, the network proxy config, and the app server protocol. Concretely, it: - introduces typed domain (`allow` / `deny`) and unix socket permission (`allow` / `none`) entries instead of separate `allowed_domains`, `denied_domains`, and `allow_unix_sockets` lists - updates config loading, managed requirements merging, and exec-policy overlays to read and upsert rule entries consistently - exposes the new shape through protocol/schema outputs, debug surfaces, and app-server config APIs - rejects the legacy list-based keys and updates docs/tests to reflect the new config format ## Why The previous representation split related network policy across multiple parallel lists, which made merging and overriding rules harder to reason about. Moving to explicit keyed permission maps gives us a single source of truth per host/socket entry, makes allow/deny precedence clearer, and gives protocol consumers access to the full rule state instead of derived projections only. ## Backward Compatibility ### Backward compatible - Managed requirements still accept the legacy `experimental_network.allowed_domains`, `experimental_network.denied_domains`, and `experimental_network.allow_unix_sockets` fields. They are normalized into the new canonical `domains` and `unix_sockets` maps internally. - App-server v2 still deserializes legacy `allowedDomains`, `deniedDomains`, and `allowUnixSockets` payloads, so older clients can continue reading managed network requirements. - App-server v2 responses still populate `allowedDomains`, `deniedDomains`, and `allowUnixSockets` as legacy compatibility views derived from the canonical maps. - `managed_allowed_domains_only` keeps the same behavior after normalization. Legacy managed allowlists still participate in the same enforcement path as canonical `domains` entries. ### Not backward compatible - Permissions profiles under `[permissions.<profile>.network]` no longer accept the legacy list-based keys. Those configs must use the canonical `[domains]` and `[unix_sockets]` tables instead of `allowed_domains`, `denied_domains`, or `allow_unix_sockets`. - Managed `experimental_network` config cannot mix canonical and legacy forms in the same block. For example, `domains` cannot be combined with `allowed_domains` or `denied_domains`, and `unix_sockets` cannot be combined with `allow_unix_sockets`. - The canonical format can express explicit `"none"` entries for unix sockets, but those entries do not round-trip through the legacy compatibility fields because the legacy fields only represent allow/deny lists. ## Testing `/target/debug/codex sandbox macos --log-denials /bin/zsh -c 'curl https://www.example.com' ` gives 200 with config ``` [permissions.workspace.network.domains] "www.example.com" = "allow" ``` and fails when set to deny: `curl: (56) CONNECT tunnel failed, response 403`. Also tested backward compatibility path by verifying that adding the following to `/etc/codex/requirements.toml` works: ``` [experimental_network] allowed_domains = ["www.example.com"] ```
Celia Chen ·
2026-03-27 06:17:59 +00:00 -
[app-server-protocol] introduce generic ClientResponse for app-server-protocol (#15921)
- introduces `ClientResponse` as the symmetrical typed response union to `ClientRequest` for app-server-protocol - enables scalable event stream ingestion for use cases such as analytics - no runtime behavior changes, protocol/schema plumbing only
rhan-oai ·
2026-03-26 21:33:25 -07:00