Termux rust-v0.143.0-alpha.32#280
Merged
Merged
Conversation
Termux rust-v0.134.0
…nt/wallentx_termux-target_from_release_0.134.0_04e72fc5230f
…et_from_release_0.134.0_04e72fc5230f checkpoint: into wallentx/termux-target from release/0.134.0 @ 04e72fc
Termux rust-v0.135.0-alpha.2
…nt/wallentx_termux-target_from_release_0.135.0_e3957436d89a
…et_from_release_0.135.0_e3957436d89a checkpoint: into wallentx/termux-target from release/0.135.0 @ e395743
- `codex doctor` now reports richer environment, Git, terminal, app-server, and thread inventory diagnostics for support cases. (openai#24261, openai#24311, openai#24305) - `/status` shows remote connection details and server version when the TUI is connected over a remote transport. (openai#24420) - Vim mode gained text-object editing, improved word/line-end behavior, and a configurable interrupt-turn binding. (openai#24382, openai#24380, openai#24766) - `/permissions` now understands named permission profiles and displays configured custom profiles. (openai#21559) - Packaged Codex builds can discover and use the bundled patched zsh helper across supported macOS and Linux targets. (openai#23756, openai#24171) - The Python SDK now exposes friendly `Sandbox` presets for thread and turn APIs. (openai#24772) ## Bug Fixes - Markdown tables and multiline lists render more readably in the TUI, with better column sizing and app-style table formatting. (openai#24489, openai#24346, openai#24351) - TUI output is more stable on macOS and Zellij, avoiding stderr/composer corruption and raw-output overlap. (openai#24459, openai#24479, openai#24593) - Slash-command completion now preserves existing draft text for commands that accept inline arguments. (openai#23950) - Older tmux/iTerm control-mode sessions no longer lose normal `Ctrl-C` handling from unsupported keyboard enhancement setup. (openai#24371) - App mentions now exclude inaccessible or disabled apps instead of offering unusable `$` suggestions. (openai#24625) - Resume flows now include non-interactive exec sessions when requested and honor cwd overrides for idle cached threads. (openai#24503, openai#24528) ## Documentation - Clarified image-viewing tool detail behavior and removed stale TUI composer documentation references. (openai#23949, openai#24641) - Updated Python SDK docs, examples, and notebook content to use the new sandbox preset API. (openai#24772) ## Chores - Updated Rust toolchain pins and SQLx/SQLite dependencies. (openai#24684, openai#24728) - Moved memory runtime state into a dedicated SQLite database. (openai#24591) - Removed remaining legacy config-profile consumers and routed more TUI config/plugin state through app-server-owned APIs. (openai#24076, openai#24254, openai#24255, openai#24265, openai#24266, openai#24257) - Centralized Responses retry handling and MCP tool naming logic to reduce duplicated internal plumbing. (openai#24131, openai#21576) ## Changelog Full Changelog: openai/codex@rust-v0.134.0...rust-v0.135.0 - openai#24164 fix(remote-control): cap reconnect backoff @apanasenko-oai - openai#23756 package: include zsh fork in Codex package @bolinfest - openai#23757 Default function tools into tool hooks @abhinav-oai - openai#24171 package: add x64 macOS codex-zsh artifact @bolinfest - openai#24159 code-mode: merge stored values by key @cconger - openai#23983 fix: plugin bundle archive handling for upload and install @xl-openai - openai#24261 feat(doctor): add environment diagnostics @fcoury-oai - openai#24311 Report app-server version in codex doctor @etraut-openai - openai#24314 tui: label compact rate-limit percentages @etraut-openai - openai#24420 Show remote connection details in /status @etraut-openai - openai#24317 Respect hook trust bypass during TUI startup @etraut-openai - openai#24254 TUI config cleanup: oss_provider @etraut-openai - openai#24255 TUI config cleanup: trusted projects @etraut-openai - openai#24265 TUI config cleanup: MCP inventory @etraut-openai - openai#24305 Add doctor thread inventory audit @etraut-openai - openai#24346 fix(tui): improve markdown table column allocation @fcoury-oai - openai#24351 fix(tui): improve multiline markdown list readability @fcoury-oai - openai#24459 fix(tui): prevent macos stderr from corrupting composer @fcoury-oai - openai#24479 fix(process-hardening): preserve macos malloc diagnostics @fcoury-oai - openai#24474 Log rollout writer OS errors @etraut-openai - openai#24076 chore: stop consuming legacy config profiles @jif-oai - openai#24131 centralize Responses retry policy @rhan-oai - openai#23858 [wip] goal shift @jif-oai - openai#24555 chore: drop orphaned codex memories MCP crate @jif-oai - openai#24558 chore: move memory prompt builder into extension @jif-oai - openai#24562 Add ad-hoc memory note tool @jif-oai - openai#24567 Wire metrics client into memories extension @jif-oai - openai#24588 fix: drop flake @jif-oai - openai#24583 Add memory tool call metrics to memories extension @jif-oai - openai#24586 Wire app-server extension event sink @jif-oai - openai#24532 Use thread config for TUI MCP inventory @etraut-openai - openai#24105 [codex] Make active turn task singular @pakrym-oai - openai#21576 Move MCP tool naming mode into manager @pakrym-oai - openai#24503 tui: include exec sessions in resume list @etraut-openai - openai#24600 feat: gate dedicated memories tools in config @jif-oai - openai#21559 tui: add named permission profile picker @viyatb-oai - openai#24608 feat: add manual and remote_v2 tags to compaction metric @jif-oai - openai#24611 test: clean up apply_patch allow-session artifact @jif-oai - openai#24609 Remove reserved namespaces dedup @pakrym-oai - openai#23964 Move slash input logic out of chat composer @canvrno-oai - openai#24615 Add goal extension telemetry parity @jif-oai - openai#24371 fix(tui): avoid modifyOtherKeys for unknown tmux formats @fcoury-oai - openai#24626 fix: restore goal accounting after thread resume @jif-oai - openai#24591 Move memory state to a dedicated SQLite DB @jif-oai - openai#23823 standalone websearch extension @sayan-oai - openai#24593 fix(tui): keep raw output above composer in zellij @fcoury-oai - openai#24625 tui: keep inaccessible apps out of mentions @canvrno-oai - openai#24154 Add experimental turn additional context @pakrym-oai - openai#24473 fix(remote-control): surface websocket task stalls @apanasenko-oai - openai#24528 Respect resume cwd overrides for idle cached threads @etraut-openai - openai#24160 Add forked_from_thread_id turn metadata @owenlin0 - openai#24646 make direct only allowed caller for standalone websearch @sayan-oai - openai#23949 Clarify view_image tool description @fjord-oai - openai#24266 TUI config cleanup: plugin mentions @etraut-openai - openai#24320 Avoid repeated marketplace upgrades for alternate layouts @etraut-openai - openai#23813 windows-sandbox: remove SandboxPolicy runner plumbing @bolinfest - openai#24652 [codex] remove plain image wrapper spans @pakrym-oai - openai#24623 Attach Windows sandbox log to feedback reports @iceweasel-oai - openai#24644 Restore legacy image detail values @rhan-oai - openai#24655 [codex-analytics] add grouped session id to runtime events @marksteinbrick-oai - openai#24658 [codex] Remove obsolete goal continuation turn marker @pakrym-oai - openai#24660 fix: dont compact standalone websearch schema @sayan-oai - openai#24667 fix(core): instrument stalled tool-listing handoff @apanasenko-oai - openai#24684 Uprev Rust toolchain pins to 1.95.0 @anp-oai - openai#21567 fix: add noninteractive install script mode @efrazer-oai - openai#24707 Allow runtime enablement for remote plugins @xl-openai - openai#24714 fix(auto-review) skip legacy notify for auto review threads @dylan-hurd-oai - openai#24690 Revert "Add Bedrock Mantle GovCloud region (openai#23860)" @celia-oai - openai#24628 feat: handle goal usage limits in goal extension @jif-oai - openai#24746 Fix guardian review test user input @jif-oai - openai#24744 feat: add thread idle lifecycle hook @jif-oai - openai#24751 Drop startup context when truncating forked rollouts @jif-oai - openai#24257 TUI config cleanup: plugin marketplace @etraut-openai - openai#24380 fix(tui): complete vim word-end and line-end behavior @fcoury-oai - openai#24728 Bump SQLx to pick up newer bundled SQLite @jif-oai - openai#24637 fix: run standalone updates noninteractively @efrazer-oai - openai#24778 make vercel webhook url an env secret @sayan-oai - openai#23950 fix: Preserve draft text when completing argument-taking slash commands @canvrno-oai - openai#24641 [codex] Remove stale composer narrative doc references @canvrno-oai - openai#24368 [codex] add compaction metadata to turn headers @ningyi-oai - openai#24772 [codex] Add friendly Python SDK sandbox presets @aibrahim-oai - openai#24382 feat(tui): add vim text object bindings @fcoury-oai - openai#24766 feat(tui): make turn interruption keybind configurable @fcoury-oai - openai#24489 feat(tui): render markdown tables in app style [1 of 2] @fcoury-oai - openai#24713 chore: enable namespace tools for Bedrock @celia-oai
Termux rust-v0.135.0
…nt/wallentx_termux-target_from_release_0.135.0_60f36188b99d
…et_from_release_0.135.0_60f36188b99d checkpoint: into wallentx/termux-target from release/0.135.0 @ 60f3618
#176) * fix(linux-sandbox): preserve shell cleanup on interruption (#22729) ## Why Interrupted `shell_command` calls can race with the outer tool-dispatch cancellation path. When that happens, the runtime future may be dropped before the spawned process gets a chance to run `SIGTERM` cleanup. For bwrapd-backed Linux sandbox commands, that can leave synthetic protected-path mount bookkeeping such as `.git/.codex` registrations under `/tmp` behind after a TUI interruption. The relevant cancellation points are the outer dispatch race in [`core/src/tools/parallel.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/parallel.rs#L91-L132) and the process shutdown logic in [`core/src/exec.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/exec.rs#L1367-L1393). ## What changed - Keep `shell_command` dispatch alive long enough for the runtime to finish cancellation cleanup instead of immediately returning the synthetic aborted response. - Fold shell-turn cancellation into the existing `ExecExpiration` path in [`core/src/tools/runtimes/shell.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/runtimes/shell.rs#L267-L274), so cancellation and timeout behavior stay centralized. - On cancellation, send `SIGTERM` first, wait briefly for cleanup to run, then hard-kill any remaining descendants in the original process group. - Treat `ESRCH` as an already-gone process-group cleanup case in `codex-utils-pty`, which keeps best-effort teardown from surfacing a stale-process race as an error. ## Verification - `cargo test -p codex-core cancellation` - Added regression coverage for: - `shell_tool_cancellation_waits_for_runtime_cleanup` - `process_exec_tool_call_cancellation_allows_sigterm_cleanup` * feat(tui): add OSC 8 web links to rich content (#24472) ## Why Wrapped URLs in rich TUI output, especially URLs rendered inside Markdown tables, are split across terminal rows. In terminals that support OSC 8 hyperlinks, treating each visible fragment as part of the complete destination enables reliable open-link and copy-link actions even after table layout wraps the URL. This addresses the semantic-link portion of #12200 and the behavior described in https://github.com/openai/codex/issues/12200#issuecomment-4535452980. It does not change ordinary drag-selection across bordered table rows. ## What Changed - Added shared TUI OSC 8 support that validates `http://` and `https://` destinations, sanitizes terminal payloads, and applies metadata separately from visible line width/layout. - Added semantic web-link annotations to assistant and proposed-plan Markdown, including explicit web links and bare web URLs in prose and table cells while excluding code and non-web Markdown destinations. - Preserved complete URL targets through table wrapping, narrow pipe fallback, streaming, transcript overlay rendering, history insertion, and resize replay. - Routed intentional Codex-owned links in notices, status/setup/app-link, feedback, onboarding, MCP/plugin help, memories, and update surfaces through the shared hyperlink handling. ## How to Test 1. Run Codex in a terminal with OSC 8 link support, such as Ghostty, and request an assistant response containing a Markdown table whose last column contains a long `https://` URL. 2. Make the terminal narrow enough for the URL to wrap across multiple bordered table rows. 3. Use the terminal's open-link or copy-link action on more than one wrapped URL fragment and confirm each fragment resolves to the complete original URL. 4. Resize the terminal after the table is rendered and repeat the link action to confirm the destination survives scrollback replay. 5. Open the transcript overlay while rich output is present and confirm web links remain interactive there. 6. As a regression check, render inline/fenced code containing URL text and a Markdown link such as `[https://example.com](mailto:support@example.com)`; confirm these do not acquire a web OSC 8 destination. Targeted automated coverage exercised Markdown links and exclusions, wrapped and pipe-fallback tables, streaming/transcript overlay propagation, status-link truncation, and rendered word-wrapping cell alignment. `just test -p codex-tui` was also run; it passed the hyperlink coverage and reproduced two unrelated existing guardian feature-flag test failures. * feat(tui): render cramped markdown tables as key-value records [2 of 2] (#24636) ## Stack - **Base: #24489 [1 of 2]** - render markdown tables in app style. - **Current: #24636 [2 of 2]** - render cramped markdown tables as key/value records. Review this PR against `fcoury/app-style-markdown-tables`; it contains only the fallback behavior for cramped tables. ## Why The row-separated markdown table rendering in #24489 remains readable while columns have usable room. Once long links or multiple prose-heavy columns are compressed into narrow allocations, however, the grid can turn words and paths into tall vertical strips that are difficult to scan. In those cases the content matters more than preserving the grid shape. ## What Changed <table> <tr><td> <p align="center"><b> Normal </b></p> <img width="1722" height="619" alt="CleanShot 2026-05-27 at 14 32 57" src="https://github.com/user-attachments/assets/d04f5fbd-6064-4acd-91bd-072d19b983df" /> </td></tr> <tr><td> <p align="center"><b> Narrow </b></p> <img width="863" height="1013" alt="CleanShot 2026-05-27 at 14 33 12" src="https://github.com/user-attachments/assets/6a7d2968-0a68-48fd-ab5d-209b3dbaf03e" /> </td></tr> <tr><td> <p align="center"><b> Very narrow </b></p> <img width="435" height="746" alt="CleanShot 2026-05-27 at 14 33 47" src="https://github.com/user-attachments/assets/f6a59e30-b1d2-4063-9c05-43933abc77d6" /> </td></tr> </table> - Detect tables whose grid allocation causes systemic token fragmentation or starves multiple prose-heavy columns. - Render those tables as repeated key/value records instead of retaining an unreadable grid. - Use aligned label/value records when there is useful horizontal room, and switch to a stacked narrow-record layout where each label is followed by a full-width value when width is especially constrained. - Preserve the themed label color, rich inline formatting, links, and the existing grid presentation for tables that remain readable. - Add snapshot coverage for path-heavy narrow tables, prose-heavy issue tables, systemic compact fragmentation, and a control case that should continue to render as a grid. ## How to Test 1. Start Codex from this branch and render a normal multi-column markdown table at a comfortable terminal width. Confirm it still appears as the styled row-separated grid from #24489. 2. Render a table containing a long linked record identifier or file-like value, then narrow the terminal until the grid would split the value into vertical fragments. Confirm it switches to key/value records, with labels above values at very narrow widths. 3. Render a table with multiple prose-heavy columns, such as an issue summary table with `Issue`, `Activity`, `Complexity`, and `Why start`. Confirm a cramped width switches to records rather than wrapping several columns into hard-to-read strips. 4. Render a compact table where only one value wraps mildly. Confirm it stays in grid form rather than switching prematurely. ## Validation - Ran `just test -p codex-tui` while developing the fallback and reviewed/accepted the intended new markdown-render snapshots. The command still reports two unrelated existing guardian feature-flag test failures outside this diff. - Ran `just fix -p codex-tui` and `just fmt` after the Rust changes were complete. - `just argument-comment-lint` cannot reach source linting locally because Bazel fails while resolving LLVM sanitizer headers; touched positional literal callsites were inspected manually and annotated where needed. * Allow API-key auth for remote exec-server registration (#24666) ## Overview Allow remote `codex exec-server` registration to use existing API-key auth while restricting where those credentials can be sent. - Accept `CodexAuth::ApiKey` for the normal `--remote` registration path. - Restrict API-key remote registration to HTTPS `openai.com` and `openai.org` hosts and subdomains, with explicit HTTP loopback support for local development. - Disable registry registration redirects so credentials cannot be forwarded to an unvalidated destination. - Retain `--use-agent-identity-auth` as the explicit Agent Identity path. - Document remote registration using `CODEX_API_KEY`. ## Big picture Callers can now provide an API key directly to `exec-server` registration without first establishing ChatGPT login state: ```sh CODEX_API_KEY="$OPENAI_API_KEY" \ codex exec-server \ --remote "https://<host>.openai.org/api" \ --environment-id "$ENVIRONMENT_ID" ``` ## Validation - `cargo fmt --all` (`just fmt` is not installed on this host) - `cargo test -p codex-cli -p codex-exec-server` * Update rmcp to 1.7.0 (#24763) WIll make it easier to uprev when the new draft spec is supported. Also updates reqwest where needed for compatibility but doesn't update it everywhere since this is already a large diff. The new version of rmcp handles certain kinds of authentication failures differently, this patch includes support for identifying the failing scope in a WWW-Authenticate header. * [codex] Fix hyperlink-aware key-value table rendering (#24825) ## Why The key/value markdown table renderer added in #24636 still operates on `Line` values, while table cells and rendered table output now carry `HyperlinkLine`. That mismatch breaks `codex-tui` compilation on `main` and would risk losing semantic web-link annotations if corrected by flattening the values. ## What changed - Make key/value record rendering wrap and emit `HyperlinkLine` values consistently with the existing grid renderer. - Remap wrapped hyperlink ranges and shift them when value content is prefixed by record-mode indentation or labels. - Add focused coverage verifying key/value fallback output preserves web-link destinations. ## Verification - `just test -p codex-tui -E 'test(key_value_table_keeps_web_annotations) | test(/table_renders_(key_value_records_when_compact_fragmentation_is_systemic_snapshot|stacked_key_value_records_when_path_column_becomes_too_narrow_snapshot|records_when_multiple_prose_columns_are_starved_snapshot)/)'` * [codex] Rename Python SDK AppServerConfig to CodexConfig (#24800) ## Why `AppServerConfig` is exported as part of the ergonomic Python SDK surface and passed to `Codex(...)` and `AsyncCodex(...)`. That name exposes the underlying app-server transport at the same layer where users are configuring the Codex client. `CodexConfig` makes the common callsite read naturally and names the object it configures. ## What changed - Renamed the public configuration dataclass from `AppServerConfig` to `CodexConfig`. - Updated `Codex`, `AsyncCodex`, and the transport clients to accept `CodexConfig`. - Updated binary-resolution messages, package exports, docs, examples, and related coverage to use the new public name. ## API impact ```python from openai_codex import Codex, CodexConfig with Codex(config=CodexConfig(codex_bin="/path/to/codex")) as codex: ... ``` Callers should now import and construct `CodexConfig`; `AppServerConfig` is no longer part of the Python SDK surface. ## Validation - `uv run --frozen --extra dev ruff check src/openai_codex scripts examples tests` - Tests are deferred to online CI for this PR. * [codex] Remove redundant SQLite dynamic tool storage (#24819) ## Why Dynamic tools are defined at thread start and already stored in rollout `SessionMeta`, which restores resumed and forked sessions. Persisting the same tools through SQLite creates a second runtime persistence path that is unnecessary prework for the explicit namespace refactor. ## What changed - Restore missing thread-start dynamic tools directly from rollout history, including when SQLite is enabled. - Remove SQLite dynamic-tool reads, writes, backfill, and thread metadata patch plumbing. - Add SQLite-enabled resume integration coverage that verifies a rollout-defined dynamic tool is still sent after resume. ## Compatibility The existing `thread_dynamic_tools` table is intentionally not dropped even though it's now unused. Older Codex binaries are allowed to open databases migrated by newer binaries and still reference this table; dropping it would break that mixed-version path. See [here](https://github.com/openai/codex/blob/main/codex-rs/state/src/migrations.rs#L10-L11). ## Verification - `just test -p codex-state -p codex-rollout -p codex-thread-store` - `just test -p codex-core --test all resume_restores_dynamic_tools_from_rollout_with_sqlite_enabled` * [codex] Add independent beta release for the Python SDK (#24828) ## Why `openai-codex` needs a beta release lifecycle without requiring beta releases of its pinned runtime package. Previously, SDK staging rewrote its runtime dependency to the SDK version, which made an SDK-only beta impossible. ## What changed - Set the initial SDK beta version to `0.1.0b1` and pin it to published stable `openai-codex-cli-bin==0.132.0`. - Decoupled SDK release staging from runtime versioning so it preserves the reviewed exact runtime pin. - Added a `python-v*` tag workflow that builds and publishes only `openai-codex` through PyPI trusted publishing. - Removed the Beta classifier from runtime package metadata for future runtime publications. - Regenerated protocol-derived SDK models from the selected stable runtime package. `0.132.0` is the newest stable runtime admitted by the checked-in dependency date fence and retains the Linux wheel family currently used by SDK CI. ## Release setup Before pushing `python-v0.1.0b1`, configure PyPI trusted publishing for the `openai-codex` project with workflow `python-sdk-release.yml`, environment `pypi`, and job `publish-python-sdk`. ## Validation - `uv run --frozen --extra dev ruff check src/openai_codex scripts examples tests` - Parsed `.github/workflows/python-sdk-release.yml` with PyYAML. - Built staged release artifacts locally: `openai_codex-0.1.0b1-py3-none-any.whl` and `openai_codex-0.1.0b1.tar.gz`. - Verified wheel metadata pins `openai-codex-cli-bin==0.132.0`. - Tests are deferred to online CI for this PR. * [codex] Prepare Python SDK beta documentation and package metadata (#24836) ## Why The initial public `openai-codex` beta should read and install like a normal published Python package before a release tag is created. This follows merged PR #24828, which establishes the independent SDK beta release plumbing and exact runtime dependency. ## What changed - Rewrote `sdk/python/README.md` as a compact PyPI-facing beta package page: published installation, one quickstart, short login examples, built-in help, and links to deeper guides. - Updated the getting-started guide, API reference, FAQ, and examples index to present the published beta consistently without repeating onboarding in the package landing page or reference page. - Made `pip install openai-codex` the primary install path while beta releases are the only published SDK releases, with `--pre` documented for opting into prereleases after a stable release exists. - Added curated `help()` / `pydoc` docstrings across the public API and generated public convenience methods through `scripts/update_sdk_artifacts.py`. - Declared the repository `Apache-2.0` license expression and Documentation URL in package metadata, without introducing a duplicated SDK-local license file. - Kept the source distribution focused on installable package material (`src/openai_codex`, `README.md`, and `pyproject.toml`); the repository docs and runnable examples remain linked from the PyPI README. - Built release artifacts in an Alpine container on the Ubuntu runner, matching Python SDK CI and allowing type generation to install the published `musllinux` runtime wheel. - Added `twine check --strict` to the release workflow so malformed PyPI metadata or rendered README content fails before publishing. - Added focused SDK assertions for beta metadata, the exact runtime pin, source distribution contents, and the built-in Python documentation surface. ## Validation - Ran `uv run --frozen --extra dev ruff check scripts/update_sdk_artifacts.py src/openai_codex tests/test_public_api_signatures.py tests/test_artifact_workflow_and_binaries.py` before the final README-only reductions and review-fix follow-ups. - Built `openai_codex-0.1.0b1-py3-none-any.whl` and `openai_codex-0.1.0b1.tar.gz` before the final README-only reductions and review-fix follow-ups. - Ran `python -m twine check --strict` on both built artifacts before the final README-only reductions and review-fix follow-ups. - Verified artifact metadata reports `Apache-2.0` without a duplicated SDK-local license file. - Verified `inspect.getdoc(...)` resolves documentation for the package, `Codex`, `CodexConfig`, and key generated thread methods. - Rebased the documentation/readiness change onto merged PR #24828 without changing the intended SDK or workflow file contents. - Final verification is delegated to online CI for this PR. * Treat refresh_token_reused 400s as relogin-required (#24830) ## Summary - classify known refresh-token terminal failures from `/oauth/token` as permanent even when the backend returns `400` - preserve the existing relogin-required message for `refresh_token_reused` instead of retrying and collapsing into a generic cloud requirements error - add regression coverage for `400 refresh_token_reused` ## Testing - `just fmt` - `cargo test -p codex-login` * [codex] Simplify Python SDK install guidance (#24866) ## Summary - Remove the exact-version install snippet from the PyPI-facing Python SDK README. - Remove the release-selection explanation so the install section presents the standard `pip install openai-codex` path directly. ## Validation - Not run locally; relying on online CI for this documentation-only change. * [codex] Remove Python SDK language classifiers (#24868) ## Summary - Remove the Python language classifiers from the Python SDK package metadata. - Keep `requires-python = ">=3.10"` as the package's interpreter compatibility constraint. - Avoid presenting a curated version-support list in PyPI metadata. ## Validation - Not run locally; relying on online CI for this metadata-only change. ## Release - Land this change before publishing the next Python SDK beta. * [codex] Remove Python SDK beta warning note (#24870) ## Summary - Remove the beta warning callout from the PyPI-facing Python SDK README. - Keep the existing Beta title and install/usage guidance unchanged. ## Validation - Not run locally; relying on online CI for this documentation-only change. ## Release - Land this change before publishing the next Python SDK beta. * [codex] Stage Python SDK beta versions from release tags (#24872) ## Summary - Treat `sdk/python` as a development template with source version `0.0.0-dev`, matching the existing Python runtime packaging pattern. - Have `python-v*` tags supply the published SDK beta version through the existing `stage-sdk --sdk-version` path. - Remove the workflow check requiring a source version bump for each beta release and remove its now-unused host Python setup step. - Keep the reviewed runtime dependency pin at `openai-codex-cli-bin==0.132.0`. - Remove beta-number-specific documentation so it does not need editing for each publish. ## Why The package staging script already writes the release version into the artifact. Requiring the checked-in SDK template version to match every tag adds release-only source churn without changing the package users receive. ## Validation - Not run locally; relying on online CI for this workflow and metadata change. ## Release After this PR lands, publish the next beta by pushing tag `python-v0.1.0b2` from merged `main`. * Move memories root setup out of core config (#24758) ## Why Config loading should not create or write-authorize the memories root just because memory support exists. Memory startup is the code path that actually materializes that tree. ## What - Stop creating the memories root during Config load and remove it from legacy workspace-write projections. - Grant the memories root read access only when the memories feature and use_memories are enabled. - Create the memories root inside memories startup before seeding extension instructions. - Update config and startup tests around the ownership boundary. ## Tests - just fmt - just fix -p codex-core - just fix -p codex-memories-write - just test -p codex-core memory_tool_makes_memories_root_readable_without_creating_or_widening_writes workspace_write_includes_configured_writable_root_once_without_memories_root permission_profile_override_keeps_memories_root_out_of_legacy_projection permissions_profiles_allow_direct_write_roots_outside_workspace_root default_permissions_profile_populates_runtime_sandbox_policy - just test -p codex-memories-write memories_startup_creates_memory_root Note: a broader just test -p codex-core run is not clean in this sandbox; it hit missing test_stdio_server plus seatbelt, realtime, and environment-sensitive failures. The changed config tests above pass. * Stabilize Guardian client cache key handling (#24891) Split from the Guardian prompt cache key change. This PR only updates codex-rs/core/src/client.rs. Validation was not run per request; this branch is expected to rely on the companion split PRs. * Export Guardian prompt cache key helper (#24892) Split from the Guardian prompt cache key change. This PR only updates codex-rs/core/src/guardian/mod.rs. Validation was not run per request; this branch is expected to rely on the companion split PRs. * Add Guardian review prompt cache key (#24893) Split from the Guardian prompt cache key change. This PR only updates codex-rs/core/src/guardian/review_session.rs. Validation was not run per request; this branch is expected to rely on the companion split PRs. * Assert Guardian prompt cache key reuse (#24894) Split from the Guardian prompt cache key change. This PR only updates codex-rs/core/src/guardian/tests.rs. Validation was not run per request; this branch is expected to rely on the companion split PRs. * Thread Guardian cache key through session (#24895) Split from the Guardian prompt cache key change. This PR only updates codex-rs/core/src/session/session.rs. Validation was not run per request; this branch is expected to rely on the companion split PRs. * Use stable Guardian prompt cache keys (#24803) ## Why Guardian review sessions are reusable across forks when their `GuardianReviewSessionReuseKey` is unchanged, but the underlying Responses request was still using the child thread ID as `prompt_cache_key`. That meant forked Guardian reviews that should share cache context produced different cache keys, reducing prompt cache reuse and weakening the reuse invariant. ## What Changed - Adds a `ModelClient` prompt cache key override and uses it for `ResponsesApiRequest.prompt_cache_key`. - Computes Guardian review cache keys as `guardian:<sha1(parent_thread_id:reuse_key)>`, scoped to the parent thread plus the reuse-sensitive Guardian config. - Wires session construction to apply that override only for Guardian sub-agent sessions. ## Testing - Added coverage that Guardian cache keys are stable for the same parent/reuse key, change when either the parent thread or reuse key changes, fit within the Responses API length limit, and are absent for non-Guardian sessions. - Extended the parallel review test to assert forked Guardian reviews send the same `prompt_cache_key`. * [codex] Fix Guardian argument comment lint (#24902) ## Summary - Add the required `/*parent_thread_id*/` argument comment at the Guardian review session test callsite flagged by CI. ## Validation - `just fmt` - Not run: clippy/tests, per request; CI will cover them. * Fix memories namespace for Responses API tools (#24898) ## Why Dedicated memories tools are exposed through a Responses API namespace tool. The namespace itself has to be a valid tool identifier, so `memories/` can fail validation before the model ever gets a chance to call the memory tools. ## What changed - Changed `MEMORY_TOOLS_NAMESPACE` from `memories/` to `memories`. - Added `memory_tool_namespace_matches_responses_api_identifier` so the namespace stays non-empty and limited to Responses-safe identifier characters. ## Verification - Added unit coverage for the namespace identifier shape in `codex-rs/ext/memories/src/tests.rs`. * Add Guardian review metrics (#24897) ## Why Guardian reviews already emit analytics events, but we do not expose aggregate OpenTelemetry metrics for review volume, latency, token usage, or terminal outcomes. That makes it harder to monitor Guardian behavior during rollouts and to compare review outcomes by source, action type, session kind, model, and failure mode. ## What Changed - Added Guardian review metric names for count, total duration, time to first token, and token usage in `codex-rs/otel`. - Added `core/src/guardian/metrics.rs` to convert `GuardianReviewAnalyticsResult` into sanitized metric tags covering decision, terminal status, failure reason, approval request source, reviewed action, session kind, risk/outcome, model, reasoning effort, and context/truncation state. - Emitted the new metrics from `track_guardian_review` for each terminal Guardian review result. ## Testing - Added `guardian_review_metrics_record_counts_durations_and_token_usage`, which verifies the emitted count, duration, TTFT, token usage histograms, and tag set through the in-memory metrics exporter. * [codex-cli] Refresh near-expiry ChatGPT access tokens before requests (#23546) ## Summary - refresh managed ChatGPT auth during auth resolution when its access token is inside ChatGPT web's five-minute near-expiry window - cover refresh-window decisions while preserving the existing expired-token refresh path ## Why Codex already resolves managed ChatGPT auth before outbound requests and refreshes expired access tokens there. This change adjusts the existing predicate to refresh a still-valid access token once it is within the same five-minute refresh window used by ChatGPT web, avoiding a request with a token about to expire. A cross-process serialization follow-up was explored in #24663 and closed for now; we do not currently suspect cross-process refresh races are a root cause of the refresh errors under investigation. External-token, API-key, and Agent Identity auth modes remain unchanged. ## Validation - `bazel test //codex-rs/login:login-all-test` - `just fmt` runs Rust formatting successfully, then its Python SDK Ruff step cannot install `openai-codex-cli-bin==0.131.0a4` on this Linux environment because no compatible wheel is published. * Add thread start contributor facts (#24915) Summary: add session source and persistent-state availability to ThreadStartInput; populate them from session init; update existing goal test harness constructors. Tests: just fmt; git diff --check. No full tests or clippy run per request. * Add turn error lifecycle contributor (#24916) Summary - Add TurnErrorInput and TurnLifecycleContributor::on_turn_error to the extension API. - Emit the turn-error lifecycle from core turn error paths, including usage limit failures. - Add direct lifecycle coverage for the emitted error facts and stores. Tests - just fmt - git diff --check - Not run: full tests or clippy (per instructions) * [codex] Store pending response items directly (#24865) * [codex] Update OpenAI Docs skill (#24914) ## Summary - update the bundled `openai-docs` system skill to match the latest `openai-docs-plus` content from `skills-internal` - add the cached Codex manual fetch helper and expand the skill routing for Codex self-knowledge - keep the stable local skill identity and labels as `openai-docs` ## Why The built-in OpenAI Docs skill needed to reflect the current upstream guidance from `skills-internal` while preserving the local system-skill name used by Codex. ## Impact Codex now ships the newer OpenAI Docs skill behavior for Codex self-knowledge and manual-first documentation lookups. ## Validation - `just test -p codex-skills` - exact directory diff against transformed `skills-internal` `origin/main` was clean * Add app-server startup benchmark crate (#24651) ## Summary - Add a new `app-server-start-bench` crate to measure app-server startup performance - Wire the benchmark into the workspace and Bazel build so it can be run consistently - Update lockfiles and repo automation to account for the new package * Gate goal tools by thread eligibility (#24925) ## Why Goal tools create and update goal state for a persistent thread. The extension was only checking whether goals were enabled before advertising those tools, which meant they could be surfaced in contexts that should not receive thread goal controls: ephemeral threads without persistent thread state and review subagents. Those sessions can still run the goal extension lifecycle, but the thread tools should only be visible when the current thread can safely use them. ## What changed - Adds a `GoalRuntimeConfig` that separates goal enablement from whether goal tools are available for the current thread. - Computes tool eligibility on thread start from `persistent_thread_state_available` and `SessionSource`, hiding tools for review subagents. - Uses `GoalRuntimeHandle::tools_visible()` when contributing thread tools so enabled runtime state does not automatically imply tool exposure. - Adds backend coverage for hiding goal tools on ephemeral threads and review subagents. ## Testing - Added `goal_tools_hidden_for_ephemeral_threads`. - Added `goal_tools_hidden_for_review_subagents`. * Remove libubsan CI workaround (#24782) It seems that this was added to allow rustc to load proc macros that had been compiled with UBSan enabled, which zig does for debug and `ReleaseSafe` builds. When zig drives the link of the final binary it knows to include the ubsan runtime, but our zig-built artifacts are being linked into a binary whose linking rustc drives. This removes the libubsan workaround we have and replaces it with `-fno-sanitize=undefined` passed to zig. The new argument is passed at the end of zig's args so should take precedence over any earlier arguments from the script's caller. * extension-api: add TurnItemEmitter to tool calls (#24813) ## Why Extension-contributed tools need to emit visible turn items through Codex's normal event and persistence pipeline. ## What - Add `TurnItemEmitter` to extension `ToolCall`s and route the core implementation through `Session::emit_turn_item_*`. - Hold weak session and turn references so retained tool calls cannot keep host state alive. - Provide a no-op emitter for extension test callers. ## Test Plan - `just test -p codex-core -E 'test(passes_turn_fields_and_scoped_turn_item_emitter_to_extension_call)'` --------- Co-authored-by: jif-oai <jif@openai.com> * feat(app-server): include turns page on thread resume (#23534) ## Summary The client currently calls `thread/resume` to establish live updates and immediately follows it with `thread/turns/list` to hydrate recent turns. This lets `thread/resume` return that page directly, eliminating a round trip and the ordering/deduplication gap between the two calls. Experimental clients opt in with `initialTurnsPage: { limit, sortDirection, itemsView }`. The response returns `initialTurnsPage` as a `TurnsPage`, including cursors for paging further back in history. Keeping the controls in a nested opt-in object provides the useful `thread/turns/list` knobs without spreading page-specific parameters across `thread/resume`. ## Verification - `just fmt` - `just write-app-server-schema --experimental` - `just write-app-server-schema` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server thread_resume_initial_turns_page_matches_requested_turns_list_page --tests` - `cargo test -p codex-app-server thread_resume_rejoins_running_thread_even_with_override_mismatch --tests` - `just fix -p codex-app-server-protocol -p codex-app-server` * Expose MCP server info as part of server status (#24698) # Summary Expose MCP server info via App Server (when available) so apps can render a richer MCP experience * Reap stale multi-agent slots (#24903) ## Summary - Let `close_agent` clean up an agent that is still registered in `AgentRegistry` even when its underlying thread is already missing. - Preserve the explicit-close boundary: for known stale thread-spawn agents, mark the persisted spawn edge `Closed`, then treat `ThreadNotFound` / `InternalAgentDied` as a successful close so the registry slot can be released. - Add a regression for MultiAgentV2 task-name targets where `close_agent("worker")` succeeds after the worker thread has already disappeared. ## Motivation A worker can disappear from `ThreadManager` while its metadata still exists in the root `AgentRegistry`. Before this change, the close tool failed while trying to subscribe to the missing thread status, so it never reached the cleanup path that releases the registered agent slot. With `agents.max_threads = 1`, an explicit close of that stale task-name agent could fail and leave the session unable to spawn a replacement. ## Scope This PR intentionally does not add automatic stale-agent reaping to `spawn_agent`, `resume_agent`, or `list_agents`. A thread being missing from `ThreadManager` is not the same as an explicit close: persisted open spawn edges are still the durable source of truth for resume and task-name ownership until `close_agent` is called. ## Validation - `just test -p codex-core -E 'test(multi_agent_v2_close_agent_reaps_stale_task_name_target) | test(resume_agent_from_rollout_reopens_open_descendants_after_manager_shutdown)'` - `just fix -p codex-core` * Fix extension turn item emitter test event ordering (#24936) ## Why PR #24813 added extension `TurnItemEmitter` coverage and introduced a test that records a conversation history item before asserting extension-emitted turn item events. `record_conversation_items()` also emits a `RawResponseItem` event to observers. The test was reading from the same event receiver and expected the next event to be `ItemStarted`, so the test failed reliably once the setup history item was present. ## What Changed Update `passes_turn_fields_and_scoped_turn_item_emitter_to_extension_call` to consume and assert the expected setup `RawResponseItem` before checking the extension `ItemStarted`, `WebSearchBegin`, `ItemCompleted`, and `WebSearchEnd` events. This is test-only and does not change extension runtime behavior. ## Verification - `cargo nextest run --no-fail-fast -p codex-core tools::handlers::extension_tools::tests::passes_turn_fields_and_scoped_turn_item_emitter_to_extension_call` * [codex] Support ui visibility meta for tools (#24700) ## Summary Adds support for the same ui.visibility metadata as resources [spec](https://github.com/modelcontextprotocol/ext-apps/blob/main/specification/draft/apps.mdx#resource-discovery) * chore: add GPT-5.5 to the Amazon Bedrock catalog (#24701) ## Summary Amazon Bedrock should expose GPT-5.5 alongside GPT-5.4, and the Bedrock GPT entries should stay aligned with the canonical bundled OpenAI model metadata instead of carrying a separate hand-written copy that can drift over time. This change will be merged when the model is online. This change: - Adds the Bedrock Mantle model id for `openai.gpt-5.5`. - Builds the Bedrock GPT-5.5 and GPT-5.4 catalog entries from the bundled OpenAI model catalog, then overrides the Bedrock-facing slug, explicit priority, and Bedrock-specific context windows. - Hardcodes both `context_window` and `max_context_window` to `272000` for Bedrock GPT-5.5 and GPT-5.4. - Keeps `openai.gpt-5.5` as the default Bedrock model ahead of `openai.gpt-5.4` and the Bedrock OSS models. * TUI: Unified mentions tweaks + polish mentions rendering (#23363) This change keeps unified @mentions behind the mentions_v2 gate, moves the flag to under-development, and polishes mention rendering/history behavior. It also adds a few small improvements to the mentions feature around mention rendering and history round-tripping for plugin/tool mentions in message edit scenarios. Plugin selections now insert `@` mentions with better casing, and saved history preserves the visible sigil so recalled messages look the same as what the user typed. - Preserves `@` sigils when encoding/decoding mention history for tool/plugin paths. - Improves plugin mention insertion so display names/casing are reflected more cleanly in the composer. - Update composer to render user-entered plugin mentions in the same color as the mentions menu. ALso applies to recalled/edited messages. - Left/right arrows no longer switch unified-mention search modes after an @mention has already been accepted (Ex: arrowing left through a composed message that contains @mentions). - Keeps bound mentions stable around punctuation, so accepted `@` mentions do not reopen the popup and punctuated `$` mentions still persist to cross-session history. **Steps to test** - Ensure mentions_v2 is enabled through configuration or `--enable mentions_v2` - Type `@` in the TUI composer and verify filesystem/plugin/skill results are displayed in the unified mentions menu. - Select a plugin mention from the `@` popup and confirm the inserted text is an `@...` mention with casing, then recall/edit the message and confirm it still renders as `@...`. - Mention a skill and verify that skills still insert as `$skill` mentions rather than `@` mentions. - Verify punctuated mentions such as `@plugin.` and `($skill)` keep their bound mention behavior across editing and history recall. * Revert "Add app-server startup benchmark crate" (#24937) Reverts openai/codex#24651, broke musl job https://github.com/openai/codex/actions/runs/26585495205/job/78330166927 * Wire task completion into thread-idle lifecycle (#24928) ## Why #24744 introduced the thread idle lifecycle hook so idle continuation can be owned by lifecycle contributors instead of hard-coded goal runtime plumbing. Task completion still called `goal_runtime_apply(GoalRuntimeEvent::MaybeContinueIfIdle)` directly, so the post-turn idle transition remained goal-specific and did not notify generic thread lifecycle contributors. ## What Changed - Add `Session::emit_thread_idle_lifecycle_if_idle()` to gate idle emission on both no active turn and no queued trigger-turn mailbox work. - Call that helper when a task clears the active turn, replacing the direct `GoalRuntimeEvent::MaybeContinueIfIdle` path. - Cover the behavior with `codex-core` session tests for emitting after task completion and suppressing idle emission while trigger-turn mailbox work is pending. ## Verification - New tests in `core/src/session/tests.rs` exercise the idle lifecycle emission and trigger-turn mailbox guard. * Add feature-gated standalone image generation extension (#24723) ## Why Add a standalone image generation path that can be exercised independently of hosted Responses image generation, while retaining the hosted tool as fallback unless the extension is actually available to the model. ## What changed - Added the `codex-image-generation-extension` crate with standalone generate/edit execution, prior-image selection for edits, model-visible image output, and local generated-image persistence. - Installed the extension in app-server behind the disabled-by-default `imagegenext` feature and backend eligibility checks. - Updated core tool planning so eligible `image_gen.imagegen` exposure replaces hosted `image_generation`, while unavailable configurations retain hosted fallback. - Added coverage for extension behavior, edit history reuse, feature gating, auth eligibility, and hosted-tool replacement. - The extension is installed through app-server only in this PR; other execution paths retain hosted image generation because hosted replacement occurs only when the standalone executor is actually registered and model-visible. - The initial extension contract intentionally fixes the image model to `gpt-image-2` and uses automatic image parameters. - Native generated-image history/card parity and rollout persistence cleanup are intentionally deferred follow-up work. ## Validation - `just test -p codex-image-generation-extension` - `just test -p codex-features` - `just test -p codex-core hosted_tools_follow_provider_auth_model_and_config_gates` - `just test -p codex-app-server` - `just fix -p codex-image-generation-extension -p codex-features -p codex-core -p codex-app-server` - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` --------- Co-authored-by: jif-oai <jif@openai.com> * Move Bazel Windows jobs onto codex-runners (#24952) The codex-windows runner group should be much faster than the default GHA runners. Since bazel jobs on windows are frequently the long pole for PRs checks, this will hopefully get people landing a bit faster. * Add `codex app-server --stdio` alias (#24940) ## Summary - Add `--stdio` as a direct alias for `codex app-server --listen stdio://`. - Keep `--stdio` and `--listen` mutually exclusive. - Update the app-server README to document both forms. * fix(tui): prevent repository-configured code execution in /diff (#24954) ## Why `/diff` is intended to display working-tree changes, but its Git invocations honored repository-selected executable helpers. A repository could configure diff/text conversion helpers, clean/process filters, `core.fsmonitor`, or `post-index-change` hooks that execute when a user runs `/diff`. Fixes [PSEC-4395](https://linear.app/openai/issue/PSEC-4395/codex-cli-diff-executes-repository-selected-diff-helpers). ## What Changed - Pass `--no-textconv` and `--no-ext-diff` for tracked and untracked diff generation. - Discover configured `filter.<driver>.clean` and `.process` entries, then neutralize the selected drivers through structured `GIT_CONFIG_KEY_*` / `GIT_CONFIG_VALUE_*` overrides, including driver names containing `=`. - Run all `/diff` Git probes with `core.fsmonitor=false` and a null `core.hooksPath`. - Use short submodule reporting while ignoring dirty submodule worktrees, since inspecting a checked-out submodule for dirtiness can execute filters from that child repository. This intentionally omits dirty-only submodule markers in order to preserve the non-executing security boundary. - Add real-Git marker tests covering filters, fsmonitor, hooks, and configured helpers inside checked-out submodules. ## How to Test 1. In a repository with ordinary tracked and untracked edits, run `/diff`. 2. Confirm the normal working-tree diff is shown for top-level files. 3. Run the targeted tests below; they configure executable marker helpers for repository filters, fsmonitor, hooks, and a checked-out submodule, then verify `/diff` does not invoke them. 4. Confirm a dirty-only submodule does not cause Codex to enter the submodule and execute its configured helper. Targeted tests: - `just test -p codex-tui get_git_diff_` Validation note: `just test -p codex-tui` runs the new coverage, but this worktree currently also has two unrelated failing guardian tests: `app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default` and `app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`. * [codex] Handle PowerShell UTF-8 setup failures (#24949) Fixes #12496. ## Why Windows sandboxed PowerShell commands can run under `ConstrainedLanguage` on some machines, especially enterprise-managed Windows environments. In that mode, our PowerShell command prelude could fail before every command because it directly assigned `[Console]::OutputEncoding` to UTF-8. The actual user command still ran, but Codex surfaced noisy `Cannot set property. Property setting is supported only on core types in this language mode.` output for every shell call. ## What Changed - Makes the PowerShell UTF-8 output encoding prelude best-effort by wrapping the assignment in `try { ... } catch {}`. - Keeps the existing UTF-8 behavior when PowerShell allows the assignment. - Adds focused tests for adding the prelude and avoiding duplicate prelude insertion. ## Validation - `cargo fmt -p codex-shell-command` - `cargo check -p codex-shell-command` - `git diff --check` - Verified a local `ConstrainedLanguage` PowerShell probe prints only the command output with no property-setting error. - Verified `codex exec` from a temporary `chcp 437` context reports `utf-8` / `65001` and preserves non-ASCII output (`café`, `漢字`). * [codex] Remove Bedrock OSS models from catalog (#24960) Remove the GPT OSS 120B and 20B entries from the Amazon Bedrock static model catalog, as they are no longer supported. * runtime: prepend zsh fork bin dir to PATH (#23768) ## Why #23756 makes packaged Codex builds include and default to the bundled zsh fork. The important reason to put that fork's directory at the front of `PATH` is to keep executable-level escalation working after a command leaves the original shell and later re-enters zsh through `env`. The expected chain is: 1. The zsh fork runs the top-level shell command. 2. That command launches another program, such as `python3`, while inheriting the `EXEC_WRAPPER` environment and the escalation socket fd. 3. That program spawns a shell script whose shebang is `#!/usr/bin/env zsh` rather than `#!/bin/zsh`, and it does not close the escalation fd. 4. `/usr/bin/env` resolves `zsh` through `PATH`, so it must find the packaged zsh fork before the system zsh. 5. Commands inside that nested script are intercepted by the zsh fork and can still request escalation from Codex. If `PATH` resolves `zsh` to the system shell instead, the nested script loses zsh-fork exec interception. Commands that should request escalation can then run only in the original sandbox, or fail there, without Codex ever receiving the approval request. Shell snapshots make this slightly more subtle: a snapshot can restore an older `PATH` after the child shell starts. This PR treats the zsh fork `PATH` prepend as an explicit environment override so snapshot wrapping preserves it. ## What Changed - Added shared zsh-fork runtime helpers that prepend the configured zsh executable parent directory to `PATH` without duplicate entries. - Applied the zsh fork `PATH` prepend to both zsh-fork `shell_command` launches and unified-exec zsh-fork launches before sandbox command construction. - Kept the shell-command zsh-fork backend API narrow: it derives the configured zsh path from session services and rebuilds its sandbox environment from `req.env`, rather than accepting a second, competing environment map or a separately threaded bin dir. - Kept Unix-only zsh-fork `PATH` mutation out of Windows clippy-visible mutability. - Added coverage for duplicate `PATH` entries, for preserving the zsh fork prepend through shell snapshot wrapping, and for the nested `python3` -> `#!/usr/bin/env zsh` escalation flow. ## Testing - `just fmt` - `just fix -p codex-core` I left final test validation to CI after the latest review-comment cleanup. Before that cleanup, `just test -p codex-core zsh_fork` passed locally for the zsh-fork-focused tests. * Release 0.136.0-alpha.1 * Seed Termux release automation * Termux rust-v0.136.0-alpha.1 (#175) * Release 0.132.0-alpha.1 * ## New Features - The Python SDK now supports first-class authentication, including API key login, ChatGPT browser and device-code flows, account inspection, and logout APIs. (#23093) - Python turn APIs are easier to use for text-only workflows: you can pass a plain string as input, and handle-based runs now return a richer `TurnResult` with collected items, timing, and usage data. (#23151, #23162) - `codex exec resume` now accepts `--output-schema`, so resumed automations can keep session context while still enforcing structured JSON output. (#23123) - TUI startup is faster because terminal capability probes are now batched instead of waiting on several serial checks before the first interactive frame. (#23175) - Remote executor registration can now use standard Codex auth instead of a separate registry credential flow. (#22769) - App-server turns can preserve requested image fidelity, including original-resolution local images, across user inputs and image-producing tools. (#20693) ## Bug Fixes - Goal continuations now stop when they hit usage limits or a repeated blocker instead of looping and burning more tokens, and completion responses phrase usage more naturally. (#23094, #22907) - The session picker is easier to trust: renamed threads now show `name (thread-id)` in resume hints, and pasted text works in the picker search box. (#23234, #23338) - Multi-session TUI flows are more reliable: in-progress MCP calls stay marked as active during replay, and elicitation replies are sent back to the thread that requested them. (#23236, #23241) - Remote sessions now keep websocket connections alive and show repo-relative diff paths again instead of `/tmp/...`-prefixed paths. (#23226, #23261) - Windows installs are more robust: `codex doctor` now detects npm-managed installs correctly, and MSVC release binaries no longer depend on separately installed VC++ runtime DLLs. (#22967, #22905) - TUI polish fixes include immediate shutdown feedback on exit, hiding the ChatGPT usage link for non-OpenAI providers, and keeping a cleared Fast tier from reappearing after side-thread resume. (#23323, #23127, #23121) ## Documentation - The Python SDK docs, FAQ, and examples were refreshed around the new auth flow and turn APIs, with clearer setup guidance and simpler text-only examples. (#22941, #23093, #23151, #23162) ## Chores - Memory summaries are now versioned and rebuilt when the stored format is stale, which should keep long-lived memory context leaner and more predictable. (#23148) ## Changelog Full Changelog: https://github.com/openai/codex/compare/rust-v0.131.0...rust-v0.132.0 - #20693 Preserve image detail in app-server inputs @fjord-oai - #22891 tui: pass active permission profiles through app commands @bolinfest - #22924 app-server-protocol: remove PermissionProfile from API @bolinfest - #22941 [codex] Refine Python SDK user-facing docs @aibrahim-oai - #22967 Fix Windows doctor npm root probe @etraut-openai - #22920 core: set permission profiles from snapshots @bolinfest - #22939 [codex] Split Python SDK helper logic @aibrahim-oai - #22907 Improve goal completion usage reporting @etraut-openai - #23030 test: construct permission profiles directly @bolinfest - #22769 exec-server: support auth-backed remote executor registration @miz-openai - #22946 [codex] preserve MCP result meta in McpToolCallItemResult @miaolin-oai - #23069 multiagent: trim model-visible description, cap to 5 models @sayan-oai - #22913 [1 of 4] tui: route primary settings writes through app server @etraut-openai - #23093 sdk/python: add first-class login support @aibrahim-oai - #23151 [codex] Return TurnResult from Python turn handles @aibrahim-oai - #23147 Make multi-agent v2 tool namespace configurable @jif-oai - #23036 test: reduce core sandbox policy test setup @bolinfest - #23162 [codex] Accept string input for Python turns @aibrahim-oai - #23226 Add exec-server websocket keepalive @starr-openai - #23148 Densify and version memory summaries @jif-oai - #22448 [codex] Add installed-plugin mention API @xli-oai - #23288 chore: goal ext skeleton @jif-oai - #23291 Make extension lifecycle hooks async @jif-oai - #23293 feat: add extension event sink capability @jif-oai - #23295 chore: isolate thread goal storage behind GoalStore @jif-oai - #23301 chore: goal resumed metrics @jif-oai - #23305 chore: make token usage async @jif-oai - #23306 Emit goal update events from goal extension tools @jif-oai - #23121 tui: keep cleared Fast tier from reappearing after side-thread resume @etraut-openai - #23123 Support --output-schema for exec resume @etraut-openai - #23128 Fix TUI stream cleanup after turn errors @etraut-openai - #23127 Hide ChatGPT usage link for non-OpenAI status @etraut-openai - #23175 [1 of 2] Optimize TUI startup terminal probes @etraut-openai - #22706 [codex] Remove legacy shell output formatting paths @pakrym-oai - #23332 nit: read prompt @jif-oai - #22905 windows: link MSVC release binaries with static CRT @iceweasel-oai - #23323 fix(tui): show shutdown feedback on exit @fcoury-oai - #23261 Fix remote turn diff display roots @starr-openai - #22569 Simplify legacy Windows sandbox ACL persistence @iceweasel-oai - #23273 Upload rust full CI JUnit reports @starr-openai - #22893 fix: harden plugin creator sharing validation @efrazer-oai - #23094 goal: pause continuation loops on usage limits and blockers @etraut-openai - #23234 Clarify resume hints for renamed threads @etraut-openai - #23241 TUI: route elicitation responses to request thread @etraut-openai - #23236 TUI: replay in-progress MCP calls as started @etraut-openai - #23088 goals: keep pause transitions explicit @etraut-openai - #23338 feat(tui): handle paste in session picker @fcoury-oai - #23335 feat(app-server): add optional thread_id to experimentalFeature/list @owenlin0 * Apply Termux compatibility patch * Disable realtime audio on Android builds (cherry picked from commit 337303c72c5c624386937c5f2aa9dc3a8dcfa2b4) * Update Termux v8 dependency * Release 0.133.0-alpha.1 * Seed Termux release automation * Prepare Termux rust-v0.132.0 * Seed Termux release automation * Prepare Termux rust-v0.133.0-alpha.1 * Release 0.133.0-alpha.3 * Seed Termux release automation * Prepare Termux rust-v0.133.0-alpha.3 * ## New Features - Goals are now enabled by default, backed by dedicated storage, and track progress across active turns. (#23300, #23685, #23696, #23732) - `codex remote-control` now runs like a foreground command, waits for readiness, reports machine status, and keeps explicit daemon-style `start`/`stop` commands. (#22878) - Permission profiles gained list APIs, inheritance, managed `requirements.toml` support, runtime refresh behavior, and stronger Windows sandbox integration. (#22928, #23412, #22270, #23433, #22931, #23715) - Plugin discovery is easier to inspect, with marketplace-aware list output, installed versions, visible marketplace roots, and remote collection support. (#23372, #23584, #23727, #23730) - Extensions can observe more lifecycle events, including subagent start/stop, tool execution, turn metadata, and async approval/turn processing. (#22782, #22873, #23309, #23688, #23690, #23692) ## Bug Fixes - Fixed TUI startup choosing the wrong working directory when reusing a local app-server socket. (#23538) - Fixed plan-mode free-form answers so modified Enter keys, like Shift+Enter, no longer submit unexpectedly. (#23536) - Removed stale background terminal poll events after a process exits. (#23231) - Preserved raw code-mode exec output unless an explicit output token limit is requested. (#23564) - Made AGENTS instruction loading more reliable, including local global reads and warnings for invalid UTF-8 instead of silent drops. (#23343, #23232) - Fixed app-server startup/shutdown races, empty resume/fork paths, plugin upgrade failures, and realtime v1 websocket compatibility. (#23516, #23578, #23400, #23356, #23771) ## Documentation - Added clearer plugin-creator guidance for updating and reinstalling local personal plugins. (#23542) - Expanded app-server/API docs and schema coverage around managed permission profile requirements. (#23433, #23555) ## Chores - Added a canonical Codex package archive pipeline and moved installers, npm packages, DotSlash, and SDK runtimes toward that shared layout. (#23513, #23582, #23586, #23596, #23635, #23636, #23637, #23638, #23786) - Fixed Linux Python runtime wheel tags so glibc-based systems can install the runtime artifacts. (#21812) - Improved release and CI reliability with package-builder tests, prebuilt resource packaging, DotSlash zstd handling, platform-sharded Rust tests, and Codex Linux release runners. (#23760, #23759, #23752, #23358, #23761) ## Changelog Full Changelog: https://github.com/openai/codex/compare/rust-v0.132.0...rust-v0.133.0 - #23343 codex: route global AGENTS reads through LOCAL_FS @starr-openai - #22380 fix: default unknown tool schemas to empty schemas @celia-oai - #23309 Add tool lifecycle extension contributor @jif-oai - #23253 Reduce rust-ci-full Windows nextest timeout flakes @starr-openai - #22878 Improve `codex remote-control` CLI UX @owenlin0 - #21812 Publish Linux runtime wheels with glibc-compatible tags @aibrahim-oai - #22709 [codex] Trim unused TurnContextItem fields @pakrym-oai - #23353 Include plugin id in plugin MCP tool metadata @mzeng-openai - #22728 [codex] Move pending input into input queue @pakrym-oai - #23371 fix(tui): warn on unsupported iTerm2 pet versions @fcoury-oai - #23376 [codex-analytics] preserve user thread source for exec threads @marksteinbrick-oai - #23360 app-server: use profile ids in v2 permission params @bolinfest - #23384 [codex] Remove external websocket session resets @pakrym-oai - #22721 cleanup: Remove skill env var dependency prompting @xl-openai - #23389 Remove ToolSearch feature toggle @sayan-oai - #23080 [1 of 7] Add thread settings to UserInput @etraut-openai - #23081 [2 of 7] Remove UserInputWithTurnContext @etraut-openai - #23075 [3 of 7] Remove UserTurn @etraut-openai - #23396 [codex] Extract turn skill and plugin injections @pakrym-oai - #23356 fix(plugins): keep version upgrades additive @iceweasel-oai - #22508 [5 of 7] Replace OverrideTurnContext with ThreadSettings @etraut-openai - #22086 CI: Customize v8 building @cconger - #23390 Remove explicit connector tool undeferral @sayan-oai - #22928 core: expose permission profile picker metadata @viyatb-oai - #23352 Preserve context baselines for full-history agent forks @jif-oai - #23300 feat: dedicated goal DB @jif-oai - #22835 Remove ToolsConfig from tool planning @jif-oai - #22870 Add `body_after_prefix` auto-compact token limit scope @jif-oai - #23144 Defer v1 multi-agent tools behind tool search @jif-oai - #23409 [codex] Allow empty turn/start requests @pakrym-oai - #23388 [codex] Move hook request plumbing into hook runtime @pakrym-oai - #23405 [codex] Preserve steer input as user input @pakrym-oai - #22914 [2 of 4] tui: route app and skill enablement through app server @etraut-openai - #23397 [codex] Make contextual user fragments dyn-renderable @pakrym-oai - #23475 chore: namespace v1 sub-agent tools @jif-oai - #23493 Make `deny` canonical for filesystem permission entries @viyatb-oai - #22929 Harden CLI rate limit window labels @ase-openai - #22782 Add SubagentStart hook @abhinav-oai - #23513 build: add Codex package builder @bolinfest - #23369 Make local environment optional in EnvironmentManager @starr-openai - #23327 Refactor exec-server websocket pump @starr-openai - #23536 fix(tui): preserve modified enter in plan questions @fcoury-oai - #23400 Fix empty rollout path app-server handling @wiltzius-openai - #23551 Route local-only app-server gating through processors @starr-openai - #23372 Split plugin install discovery into list and request tools @mzeng-openai - #23516 fix: serialize unix app-server startup @efrazer-oai - #22169 [codex] Honor role-defined spawn service tiers @aibrahim-oai - #23555 Add CUA requirements subsection for locked computer use @adams-oai - #23538 Fix: TUI starting in wrong CWD @canvrno-oai - #23526 build: fetch rg for Codex packages @bolinfest - #23573 Remove unused ARC monitor path @mzeng-openai - #23576 test: fix multi-agent service tier assertion @bolinfest - #23541 build: default Codex package target and output @bolinfest - #23358 Fan out rust-ci-full nextest by platform @starr-openai - #23593 feat: expose codex-app-server version flag @bolinfest - #23412 feat: add permission profile list api @viyatb-oai - #23535 Move plugin and skill warmup into session startup @aibrahim-oai - #23231 Fix stale background terminal poll events @etraut-openai - #23564 [codex] Preserve raw code-mode exec output by default @aibrahim-oai - #23232 Warn on invalid UTF-8 in AGENTS.md files @etraut-openai - #23584 feat: Add vertical remote plugin collection support @xl-openai - #23586 build: package prebuilt Codex entrypoints @bolinfest - #23582 ci: build Codex package archives in release workflow @bolinfest - #23596 runtime: detect Codex package layout @bolinfest - #23500 add encryptedcontent to functioncalloutput @sayan-oai - #23633 Migrate exec-server remote registration to environments @richardopenai - #23451 Add timeout for remote compaction requests @jif-oai - #23667 feat: rename 1 @jif-oai - #23669 feat: rename 3 @jif-oai - #23668 feat: rename 2 @jif-oai - #23675 fix: main @jif-oai - #23685 feat: wire goal extension tools to the dedicated goal store @jif-oai - #23690 feat: async approval contrib @jif-oai - #23692 feat: async turn item process @jif-oai - #23688 feat: expose turn-start metadata to extensions @jif-oai - #23605 [codex] Hide deferred tools from code mode prompt @pakrym-oai - #23634 runtime: use install context for bundled bwrap @bolinfest - #23635 release: publish Codex package archive checksums @bolinfest - #23592 feat: Add btw alias for side slash command @anp-oai - #23696 feat: account active goal progress in the goal extension @jif-oai - #23176 [2 of 2] Start fresh TUI thread in background @etraut-openai - #23578 fix(app-server): speed up shutdown @fcoury-oai - #22896 windows-sandbox: add resolved permissions helper @bolinfest - #23502 Add thread/settings/update app-server API @etraut-openai - #23507 Sync TUI thread settings through app server @etraut-openai - #23666 feat: add turn_id and truncation_policy to extension tool calls @jif-oai - #23636 install: consume Codex package archives @bolinfest - #23717 [codex] Preserve failed goal accounting flushes @jif-oai - #23655 add standalone websearch api client @sayan-oai - #23724 Fix thread settings clippy failure @etraut-openai - #23637 npm: ship platform packages in Codex package layout @bolinfest - #23729 fix(config): resolve cloud requirements deny-read globs @viyatb-oai - #23638 dotslash: publish Codex entrypoints from package archives @bolinfest - #22918 windows-sandbox: send permission profiles to elevated runner @bolinfest - #23735 windows-sandbox: share bundled helper lookup @bolinfest - #18868 Add MITM hook config model @evawong-oai - #22270 feat(permissions): resolve permission profile inheritance @viyatb-oai - #23719 cli: add strict config to exec-server @bolinfest - #23542 [skills] Create a personal update flow for plugin creator @caseychow-oai - #21272 Support compact SessionStart hooks @abhinav-oai - #20659 Wire MITM hooks into runtime enforcement @evawong-oai - #23752 release: use DotSlash zstd for package archives @bolinfest - #22923 windows-sandbox: drive write roots from resolved permissions @bolinfest - #23761 chore: use Codex Linux runners for Rust releases @bolinfest - #23759 release: package prebuilt resource binaries @bolinfest - #23167 windows-sandbox: feed setup from resolved permissions @bolinfest - #22931 core: refresh active permission profiles at runtime @viyatb-oai - #22873 Add SubagentStop hook @abhinav-oai - #23727 feat(plugins): tabulate plugin list output @caseychow-oai - #23732 Make goals feature on by default and no longer experimental @etraut-openai - #23537 Honor client-resolved service tier defaults @shijie-oai - #23771 [codex] Fix realtime v1 websocket compatibility @guinness-oai - #23764 Remove Windows sandbox resource stamping @iceweasel-oai - #23730 [codex] List marketplaces considered by plugin discovery @caseychow-oai - #23760 ci: run Codex package builder tests @bolinfest - #23737 [codex] Add plugin id to MCP tool call items @mzeng-openai - #18240 Use named MITM permissions config @evawong-oai - #23774 [codex] Reject read-only fallback with approvals disabled @viyatb-oai - #23714 windows-sandbox: add profile-native elevated APIs @bolinfest - #23433 feat: support managed permission profiles in requirements.toml @viyatb-oai - #23715 core: pass permission profiles to Windows runner @bolinfest - #23786 sdk: launch packaged Codex runtimes @bolinfest * Seed Termux release automation * Prepare Termux rust-v0.133.0 * Release 0.134.0-alpha.2 * Seed Termux release automation * Prepare Termux rust-v0.134.0-alpha.2 * Release 0.134.0-alpha.3 * Seed Termux release automation * Prepare Termux rust-v0.134.0-alpha.3 * ## New Features - Added search across local conversation history, including case-insensitive content matches with result previews. (#23519, #23921) - Made `--profile` the primary profile selector across CLI, TUI permissions, and sandbox flows, with legacy profile configs rejected through migration guidance. (#23708, #23883, #23890, #24051, #24055, #24059, #24067, #24110) - Improved MCP setup with per-server environment targeting and OAuth options for streamable HTTP servers. (#23583, #24120) - Made connector tool sche…
* Release 0.132.0-alpha.1
* ## New Features
- The Python SDK now supports first-class authentication, including API key login, ChatGPT browser and device-code flows, account inspection, and logout APIs. (#23093)
- Python turn APIs are easier to use for text-only workflows: you can pass a plain string as input, and handle-based runs now return a richer `TurnResult` with collected items, timing, and usage data. (#23151, #23162)
- `codex exec resume` now accepts `--output-schema`, so resumed automations can keep session context while still enforcing structured JSON output. (#23123)
- TUI startup is faster because terminal capability probes are now batched instead of waiting on several serial checks before the first interactive frame. (#23175)
- Remote executor registration can now use standard Codex auth instead of a separate registry credential flow. (#22769)
- App-server turns can preserve requested image fidelity, including original-resolution local images, across user inputs and image-producing tools. (#20693)
## Bug Fixes
- Goal continuations now stop when they hit usage limits or a repeated blocker instead of looping and burning more tokens, and completion responses phrase usage more naturally. (#23094, #22907)
- The session picker is easier to trust: renamed threads now show `name (thread-id)` in resume hints, and pasted text works in the picker search box. (#23234, #23338)
- Multi-session TUI flows are more reliable: in-progress MCP calls stay marked as active during replay, and elicitation replies are sent back to the thread that requested them. (#23236, #23241)
- Remote sessions now keep websocket connections alive and show repo-relative diff paths again instead of `/tmp/...`-prefixed paths. (#23226, #23261)
- Windows installs are more robust: `codex doctor` now detects npm-managed installs correctly, and MSVC release binaries no longer depend on separately installed VC++ runtime DLLs. (#22967, #22905)
- TUI polish fixes include immediate shutdown feedback on exit, hiding the ChatGPT usage link for non-OpenAI providers, and keeping a cleared Fast tier from reappearing after side-thread resume. (#23323, #23127, #23121)
## Documentation
- The Python SDK docs, FAQ, and examples were refreshed around the new auth flow and turn APIs, with clearer setup guidance and simpler text-only examples. (#22941, #23093, #23151, #23162)
## Chores
- Memory summaries are now versioned and rebuilt when the stored format is stale, which should keep long-lived memory context leaner and more predictable. (#23148)
## Changelog
Full Changelog: https://github.com/openai/codex/compare/rust-v0.131.0...rust-v0.132.0
- #20693 Preserve image detail in app-server inputs @fjord-oai
- #22891 tui: pass active permission profiles through app commands @bolinfest
- #22924 app-server-protocol: remove PermissionProfile from API @bolinfest
- #22941 [codex] Refine Python SDK user-facing docs @aibrahim-oai
- #22967 Fix Windows doctor npm root probe @etraut-openai
- #22920 core: set permission profiles from snapshots @bolinfest
- #22939 [codex] Split Python SDK helper logic @aibrahim-oai
- #22907 Improve goal completion usage reporting @etraut-openai
- #23030 test: construct permission profiles directly @bolinfest
- #22769 exec-server: support auth-backed remote executor registration @miz-openai
- #22946 [codex] preserve MCP result meta in McpToolCallItemResult @miaolin-oai
- #23069 multiagent: trim model-visible description, cap to 5 models @sayan-oai
- #22913 [1 of 4] tui: route primary settings writes through app server @etraut-openai
- #23093 sdk/python: add first-class login support @aibrahim-oai
- #23151 [codex] Return TurnResult from Python turn handles @aibrahim-oai
- #23147 Make multi-agent v2 tool namespace configurable @jif-oai
- #23036 test: reduce core sandbox policy test setup @bolinfest
- #23162 [codex] Accept string input for Python turns @aibrahim-oai
- #23226 Add exec-server websocket keepalive @starr-openai
- #23148 Densify and version memory summaries @jif-oai
- #22448 [codex] Add installed-plugin mention API @xli-oai
- #23288 chore: goal ext skeleton @jif-oai
- #23291 Make extension lifecycle hooks async @jif-oai
- #23293 feat: add extension event sink capability @jif-oai
- #23295 chore: isolate thread goal storage behind GoalStore @jif-oai
- #23301 chore: goal resumed metrics @jif-oai
- #23305 chore: make token usage async @jif-oai
- #23306 Emit goal update events from goal extension tools @jif-oai
- #23121 tui: keep cleared Fast tier from reappearing after side-thread resume @etraut-openai
- #23123 Support --output-schema for exec resume @etraut-openai
- #23128 Fix TUI stream cleanup after turn errors @etraut-openai
- #23127 Hide ChatGPT usage link for non-OpenAI status @etraut-openai
- #23175 [1 of 2] Optimize TUI startup terminal probes @etraut-openai
- #22706 [codex] Remove legacy shell output formatting paths @pakrym-oai
- #23332 nit: read prompt @jif-oai
- #22905 windows: link MSVC release binaries with static CRT @iceweasel-oai
- #23323 fix(tui): show shutdown feedback on exit @fcoury-oai
- #23261 Fix remote turn diff display roots @starr-openai
- #22569 Simplify legacy Windows sandbox ACL persistence @iceweasel-oai
- #23273 Upload rust full CI JUnit reports @starr-openai
- #22893 fix: harden plugin creator sharing validation @efrazer-oai
- #23094 goal: pause continuation loops on usage limits and blockers @etraut-openai
- #23234 Clarify resume hints for renamed threads @etraut-openai
- #23241 TUI: route elicitation responses to request thread @etraut-openai
- #23236 TUI: replay in-progress MCP calls as started @etraut-openai
- #23088 goals: keep pause transitions explicit @etraut-openai
- #23338 feat(tui): handle paste in session picker @fcoury-oai
- #23335 feat(app-server): add optional thread_id to experimentalFeature/list @owenlin0
* Apply Termux compatibility patch
* Disable realtime audio on Android builds
(cherry picked from commit 337303c72c5c624386937c5f2aa9dc3a8dcfa2b4)
* Update Termux v8 dependency
* Release 0.133.0-alpha.1
* Seed Termux release automation
* Prepare Termux rust-v0.132.0
* Seed Termux release automation
* Prepare Termux rust-v0.133.0-alpha.1
* Release 0.133.0-alpha.3
* Seed Termux release automation
* Prepare Termux rust-v0.133.0-alpha.3
* ## New Features
- Goals are now enabled by default, backed by dedicated storage, and track progress across active turns. (#23300, #23685, #23696, #23732)
- `codex remote-control` now runs like a foreground command, waits for readiness, reports machine status, and keeps explicit daemon-style `start`/`stop` commands. (#22878)
- Permission profiles gained list APIs, inheritance, managed `requirements.toml` support, runtime refresh behavior, and stronger Windows sandbox integration. (#22928, #23412, #22270, #23433, #22931, #23715)
- Plugin discovery is easier to inspect, with marketplace-aware list output, installed versions, visible marketplace roots, and remote collection support. (#23372, #23584, #23727, #23730)
- Extensions can observe more lifecycle events, including subagent start/stop, tool execution, turn metadata, and async approval/turn processing. (#22782, #22873, #23309, #23688, #23690, #23692)
## Bug Fixes
- Fixed TUI startup choosing the wrong working directory when reusing a local app-server socket. (#23538)
- Fixed plan-mode free-form answers so modified Enter keys, like Shift+Enter, no longer submit unexpectedly. (#23536)
- Removed stale background terminal poll events after a process exits. (#23231)
- Preserved raw code-mode exec output unless an explicit output token limit is requested. (#23564)
- Made AGENTS instruction loading more reliable, including local global reads and warnings for invalid UTF-8 instead of silent drops. (#23343, #23232)
- Fixed app-server startup/shutdown races, empty resume/fork paths, plugin upgrade failures, and realtime v1 websocket compatibility. (#23516, #23578, #23400, #23356, #23771)
## Documentation
- Added clearer plugin-creator guidance for updating and reinstalling local personal plugins. (#23542)
- Expanded app-server/API docs and schema coverage around managed permission profile requirements. (#23433, #23555)
## Chores
- Added a canonical Codex package archive pipeline and moved installers, npm packages, DotSlash, and SDK runtimes toward that shared layout. (#23513, #23582, #23586, #23596, #23635, #23636, #23637, #23638, #23786)
- Fixed Linux Python runtime wheel tags so glibc-based systems can install the runtime artifacts. (#21812)
- Improved release and CI reliability with package-builder tests, prebuilt resource packaging, DotSlash zstd handling, platform-sharded Rust tests, and Codex Linux release runners. (#23760, #23759, #23752, #23358, #23761)
## Changelog
Full Changelog: https://github.com/openai/codex/compare/rust-v0.132.0...rust-v0.133.0
- #23343 codex: route global AGENTS reads through LOCAL_FS @starr-openai
- #22380 fix: default unknown tool schemas to empty schemas @celia-oai
- #23309 Add tool lifecycle extension contributor @jif-oai
- #23253 Reduce rust-ci-full Windows nextest timeout flakes @starr-openai
- #22878 Improve `codex remote-control` CLI UX @owenlin0
- #21812 Publish Linux runtime wheels with glibc-compatible tags @aibrahim-oai
- #22709 [codex] Trim unused TurnContextItem fields @pakrym-oai
- #23353 Include plugin id in plugin MCP tool metadata @mzeng-openai
- #22728 [codex] Move pending input into input queue @pakrym-oai
- #23371 fix(tui): warn on unsupported iTerm2 pet versions @fcoury-oai
- #23376 [codex-analytics] preserve user thread source for exec threads @marksteinbrick-oai
- #23360 app-server: use profile ids in v2 permission params @bolinfest
- #23384 [codex] Remove external websocket session resets @pakrym-oai
- #22721 cleanup: Remove skill env var dependency prompting @xl-openai
- #23389 Remove ToolSearch feature toggle @sayan-oai
- #23080 [1 of 7] Add thread settings to UserInput @etraut-openai
- #23081 [2 of 7] Remove UserInputWithTurnContext @etraut-openai
- #23075 [3 of 7] Remove UserTurn @etraut-openai
- #23396 [codex] Extract turn skill and plugin injections @pakrym-oai
- #23356 fix(plugins): keep version upgrades additive @iceweasel-oai
- #22508 [5 of 7] Replace OverrideTurnContext with ThreadSettings @etraut-openai
- #22086 CI: Customize v8 building @cconger
- #23390 Remove explicit connector tool undeferral @sayan-oai
- #22928 core: expose permission profile picker metadata @viyatb-oai
- #23352 Preserve context baselines for full-history agent forks @jif-oai
- #23300 feat: dedicated goal DB @jif-oai
- #22835 Remove ToolsConfig from tool planning @jif-oai
- #22870 Add `body_after_prefix` auto-compact token limit scope @jif-oai
- #23144 Defer v1 multi-agent tools behind tool search @jif-oai
- #23409 [codex] Allow empty turn/start requests @pakrym-oai
- #23388 [codex] Move hook request plumbing into hook runtime @pakrym-oai
- #23405 [codex] Preserve steer input as user input @pakrym-oai
- #22914 [2 of 4] tui: route app and skill enablement through app server @etraut-openai
- #23397 [codex] Make contextual user fragments dyn-renderable @pakrym-oai
- #23475 chore: namespace v1 sub-agent tools @jif-oai
- #23493 Make `deny` canonical for filesystem permission entries @viyatb-oai
- #22929 Harden CLI rate limit window labels @ase-openai
- #22782 Add SubagentStart hook @abhinav-oai
- #23513 build: add Codex package builder @bolinfest
- #23369 Make local environment optional in EnvironmentManager @starr-openai
- #23327 Refactor exec-server websocket pump @starr-openai
- #23536 fix(tui): preserve modified enter in plan questions @fcoury-oai
- #23400 Fix empty rollout path app-server handling @wiltzius-openai
- #23551 Route local-only app-server gating through processors @starr-openai
- #23372 Split plugin install discovery into list and request tools @mzeng-openai
- #23516 fix: serialize unix app-server startup @efrazer-oai
- #22169 [codex] Honor role-defined spawn service tiers @aibrahim-oai
- #23555 Add CUA requirements subsection for locked computer use @adams-oai
- #23538 Fix: TUI starting in wrong CWD @canvrno-oai
- #23526 build: fetch rg for Codex packages @bolinfest
- #23573 Remove unused ARC monitor path @mzeng-openai
- #23576 test: fix multi-agent service tier assertion @bolinfest
- #23541 build: default Codex package target and output @bolinfest
- #23358 Fan out rust-ci-full nextest by platform @starr-openai
- #23593 feat: expose codex-app-server version flag @bolinfest
- #23412 feat: add permission profile list api @viyatb-oai
- #23535 Move plugin and skill warmup into session startup @aibrahim-oai
- #23231 Fix stale background terminal poll events @etraut-openai
- #23564 [codex] Preserve raw code-mode exec output by default @aibrahim-oai
- #23232 Warn on invalid UTF-8 in AGENTS.md files @etraut-openai
- #23584 feat: Add vertical remote plugin collection support @xl-openai
- #23586 build: package prebuilt Codex entrypoints @bolinfest
- #23582 ci: build Codex package archives in release workflow @bolinfest
- #23596 runtime: detect Codex package layout @bolinfest
- #23500 add encryptedcontent to functioncalloutput @sayan-oai
- #23633 Migrate exec-server remote registration to environments @richardopenai
- #23451 Add timeout for remote compaction requests @jif-oai
- #23667 feat: rename 1 @jif-oai
- #23669 feat: rename 3 @jif-oai
- #23668 feat: rename 2 @jif-oai
- #23675 fix: main @jif-oai
- #23685 feat: wire goal extension tools to the dedicated goal store @jif-oai
- #23690 feat: async approval contrib @jif-oai
- #23692 feat: async turn item process @jif-oai
- #23688 feat: expose turn-start metadata to extensions @jif-oai
- #23605 [codex] Hide deferred tools from code mode prompt @pakrym-oai
- #23634 runtime: use install context for bundled bwrap @bolinfest
- #23635 release: publish Codex package archive checksums @bolinfest
- #23592 feat: Add btw alias for side slash command @anp-oai
- #23696 feat: account active goal progress in the goal extension @jif-oai
- #23176 [2 of 2] Start fresh TUI thread in background @etraut-openai
- #23578 fix(app-server): speed up shutdown @fcoury-oai
- #22896 windows-sandbox: add resolved permissions helper @bolinfest
- #23502 Add thread/settings/update app-server API @etraut-openai
- #23507 Sync TUI thread settings through app server @etraut-openai
- #23666 feat: add turn_id and truncation_policy to extension tool calls @jif-oai
- #23636 install: consume Codex package archives @bolinfest
- #23717 [codex] Preserve failed goal accounting flushes @jif-oai
- #23655 add standalone websearch api client @sayan-oai
- #23724 Fix thread settings clippy failure @etraut-openai
- #23637 npm: ship platform packages in Codex package layout @bolinfest
- #23729 fix(config): resolve cloud requirements deny-read globs @viyatb-oai
- #23638 dotslash: publish Codex entrypoints from package archives @bolinfest
- #22918 windows-sandbox: send permission profiles to elevated runner @bolinfest
- #23735 windows-sandbox: share bundled helper lookup @bolinfest
- #18868 Add MITM hook config model @evawong-oai
- #22270 feat(permissions): resolve permission profile inheritance @viyatb-oai
- #23719 cli: add strict config to exec-server @bolinfest
- #23542 [skills] Create a personal update flow for plugin creator @caseychow-oai
- #21272 Support compact SessionStart hooks @abhinav-oai
- #20659 Wire MITM hooks into runtime enforcement @evawong-oai
- #23752 release: use DotSlash zstd for package archives @bolinfest
- #22923 windows-sandbox: drive write roots from resolved permissions @bolinfest
- #23761 chore: use Codex Linux runners for Rust releases @bolinfest
- #23759 release: package prebuilt resource binaries @bolinfest
- #23167 windows-sandbox: feed setup from resolved permissions @bolinfest
- #22931 core: refresh active permission profiles at runtime @viyatb-oai
- #22873 Add SubagentStop hook @abhinav-oai
- #23727 feat(plugins): tabulate plugin list output @caseychow-oai
- #23732 Make goals feature on by default and no longer experimental @etraut-openai
- #23537 Honor client-resolved service tier defaults @shijie-oai
- #23771 [codex] Fix realtime v1 websocket compatibility @guinness-oai
- #23764 Remove Windows sandbox resource stamping @iceweasel-oai
- #23730 [codex] List marketplaces considered by plugin discovery @caseychow-oai
- #23760 ci: run Codex package builder tests @bolinfest
- #23737 [codex] Add plugin id to MCP tool call items @mzeng-openai
- #18240 Use named MITM permissions config @evawong-oai
- #23774 [codex] Reject read-only fallback with approvals disabled @viyatb-oai
- #23714 windows-sandbox: add profile-native elevated APIs @bolinfest
- #23433 feat: support managed permission profiles in requirements.toml @viyatb-oai
- #23715 core: pass permission profiles to Windows runner @bolinfest
- #23786 sdk: launch packaged Codex runtimes @bolinfest
* Seed Termux release automation
* Prepare Termux rust-v0.133.0
* Release 0.134.0-alpha.2
* Seed Termux release automation
* Prepare Termux rust-v0.134.0-alpha.2
* Release 0.134.0-alpha.3
* Seed Termux release automation
* Prepare Termux rust-v0.134.0-alpha.3
* ## New Features
- Added search across local conversation history, including case-insensitive content matches with result previews. (#23519, #23921)
- Made `--profile` the primary profile selector across CLI, TUI permissions, and sandbox flows, with legacy profile configs rejected through migration guidance. (#23708, #23883, #23890, #24051, #24055, #24059, #24067, #24110)
- Improved MCP setup with per-server environment targeting and OAuth options for streamable HTTP servers. (#23583, #24120)
- Made connector tool schemas more reliable by preserving local `$ref`/`$defs` structures and compacting oversized schemas before exposure. (#23357, #23904)
- Let read-only MCP tools run concurrently when they advertise `readOnlyHint`. (#23750)
- Added richer extension and hook context, including conversation history for extension tools and subagent identity in hook inputs. (#22882, #23963)
## Bug Fixes
- Improved remote reliability by reconnecting stale exec-server websocket clients, retrying remote control immediately after auth recovery, and retrying remote compaction v2 streams. (#23867, #23775, #23951)
- Fixed Windows TUI rendering corruption by restoring virtual terminal mode before drawing. (#24082)
- Displayed workspace-specific usage-limit messages for credit and spend-cap failures. (#24114)
- Allowed plugin skills to reuse shared plugin-level icon assets. (#23776)
- Preserved active permission profile metadata when syncing auto-review runtime settings. (#23956)
- Ensured Node-based tools honor Codex’s managed network proxy environment. (#23905)
## Documentation
- Documented the curl and PowerShell installer paths in the README. (#24106)
- Updated developer docs to prefer `just test` over direct `cargo test` for repo-local test runs. (#23910)
- Added profile migration documentation links to relevant config errors. (#23879)
## Chores
- Simplified release packaging around canonical native artifacts, reusable DotSlash fetching, and a new macOS x64 zsh artifact. (#23833, #23836, #24129, #24165)
- Added release-build support for Codex-produced V8 artifacts. (#23934)
- Added image re-encoding benchmarks and connector-style JSON schema policy fixtures. (#23935, #24152)
- Improved tracing and analytics for websocket requests, turn starts, and remote compaction v2. (#23581, #23980, #24146)
## Changelog
Full Changelog: https://github.com/openai/codex/compare/rust-v0.133.0...rust-v0.134.0
- #23581 Trace logical websocket request after untraced warmup @jif-oai
- #23718 [codex] Steer budget-limited goal extension turns @jif-oai
- #23861 fix: cargo lock @jif-oai
- #23728 feat: retain remote compaction truncation parity in v2 @jif-oai
- #23870 Make tool executor specs mandatory @jif-oai
- #23882 [codex] Stabilize subagent start hook test @jif-oai
- #23876 refactor: centralize tool exposure planning @jif-oai
- #23879 chore: link doc in profile error messages @jif-oai
- #23883 cli: rename profile v2 flag to --profile @jif-oai
- #23835 docs: add description to codex-cli/package.json @bolinfest
- #23583 Route MCP servers through explicit environments @starr-openai
- #23886 cli: remove legacy profile v1 plumbing @jif-oai
- #23708 tui: plumb permission profile selection @viyatb-oai
- #23833 packaging: move rg manifest out of npm bin @bolinfest
- #23796 Improve `/goal` error messages for ephemeral sessions @etraut-openai
- #23867 Reconnect disconnected exec-server websocket clients with fresh sessions @starr-openai
- #23792 TUI: skip goal replace prompt for completed goals @etraut-openai
- #23519 [codex] Add rollout-backed thread content search @fc-oai
- #22552 Remove plugin hooks feature flag @abhinav-oai
- #23836 npm: remove legacy package artifact synthesis @bolinfest
- #23921 [codex] Make thread search case-insensitive @fc-oai
- #23775 fix(remote-control): retry after auth recovery @apanasenko-oai
- #22882 Add subagent identity to hook inputs @abhinav-oai
- #22915 [3 of 4] tui: route feature and memory toggles through app server @etraut-openai
- #23776 fix: Allow plugin skills to share plugin-level icon assets @xl-openai
- #23860 Add Bedrock Mantle GovCloud region @CHARLESPALEN-OAI
- #23956 Fix auto-review permission profile override @etraut-openai
- #23357 feat: support local refs and defs in tool input schemas @celia-oai
- #23963 Expose conversation history to extension tools @sayan-oai
- #23904 feat: best-effort compact large tool schemas @celia-oai
- #23750 Allow parallel MCP tool calls when annotated readOnly @anp-oai
- #23905 [codex] Enable Node env proxy for managed network proxy @rreichel3-oai
- #23890 mcp: surface profile migration guidance under --profile @jif-oai
- #24051 config: remove legacy profile v1 resolution @jif-oai
- #24055 config: remove legacy profile write paths @jif-oai
- #24057 Avoid config snapshots in live agent subtree traversal @jif-oai
- #24061 otel: drop legacy profile usage telemetry @jif-oai
- #24059 fix: reject legacy profile selectors @jif-oai
- #23934 ci: Use codex produced v8 artifacts for release builds @cconger
- #24099 fix(app-server): fix optional bool annotations @owenlin0
- #23910 Prefer `just test` over `cargo test` in docs @anp-oai
- #23951 retry remote compaction v2 requests @rhan-oai
- #24081 tui: make `codex-tui.log` opt-in @jif-oai
- #24102 cli: infer host sandbox backend @bolinfest
- #24067 app-server: drop legacy profile config surface @jif-oai
- #23736 Add new enterprise requirement gate @adams-oai
- #24117 [codex] Use rolling files for Windows sandbox logs @iceweasel-oai
- #24106 docs: update README.md to mention curl-based installer @bolinfest
- #24082 fix(tui): restore Windows VT before TUI renders @fcoury-oai
- #24110 cli: support --profile for codex sandbox @bolinfest
- #23980 Add trace_id to TurnStartedEvent @mchen-oai
- #24120 Support OAuth options in codex mcp add @mzeng-openai
- #23989 Add typed Images client to codex-api @won-openai
- #24146 [codex-analytics] split compaction v2 analytics implementation @rhan-oai
- #24129 package: factor DotSlash executable fetching @bolinfest
- #24151 [codex] Use TurnInput for session task input @pakrym-oai
- #23935 [codex] Add image re-encoding benchmarks @anp-oai
- #24152 chore: add JSON schema policy fixture coverage @celia-oai
- #24157 [codex] Remove external client session reset plumbing @pakrym-oai
- #24114 Display workspace usage limit error copy from response header @dhruvgupta-oai
- #24165 release: build macOS x64 zsh artifact @bolinfest
* Seed Termux release automation
* Prepare Termux rust-v0.134.0
* Release 0.135.0-alpha.2
* Seed Termux release automation
* Prepare Termux rust-v0.135.0-alpha.2
* ## New Features
- `codex doctor` now reports richer environment, Git, terminal, app-server, and thread inventory diagnostics for support cases. (#24261, #24311, #24305)
- `/status` shows remote connection details and server version when the TUI is connected over a remote transport. (#24420)
- Vim mode gained text-object editing, improved word/line-end behavior, and a configurable interrupt-turn binding. (#24382, #24380, #24766)
- `/permissions` now understands named permission profiles and displays configured custom profiles. (#21559)
- Packaged Codex builds can discover and use the bundled patched zsh helper across supported macOS and Linux targets. (#23756, #24171)
- The Python SDK now exposes friendly `Sandbox` presets for thread and turn APIs. (#24772)
## Bug Fixes
- Markdown tables and multiline lists render more readably in the TUI, with better column sizing and app-style table formatting. (#24489, #24346, #24351)
- TUI output is more stable on macOS and Zellij, avoiding stderr/composer corruption and raw-output overlap. (#24459, #24479, #24593)
- Slash-command completion now preserves existing draft text for commands that accept inline arguments. (#23950)
- Older tmux/iTerm control-mode sessions no longer lose normal `Ctrl-C` handling from unsupported keyboard enhancement setup. (#24371)
- App mentions now exclude inaccessible or disabled apps instead of offering unusable `$` suggestions. (#24625)
- Resume flows now include non-interactive exec sessions when requested and honor cwd overrides for idle cached threads. (#24503, #24528)
## Documentation
- Clarified image-viewing tool detail behavior and removed stale TUI composer documentation references. (#23949, #24641)
- Updated Python SDK docs, examples, and notebook content to use the new sandbox preset API. (#24772)
## Chores
- Updated Rust toolchain pins and SQLx/SQLite dependencies. (#24684, #24728)
- Moved memory runtime state into a dedicated SQLite database. (#24591)
- Removed remaining legacy config-profile consumers and routed more TUI config/plugin state through app-server-owned APIs. (#24076, #24254, #24255, #24265, #24266, #24257)
- Centralized Responses retry handling and MCP tool naming logic to reduce duplicated internal plumbing. (#24131, #21576)
## Changelog
Full Changelog: https://github.com/openai/codex/compare/rust-v0.134.0...rust-v0.135.0
- #24164 fix(remote-control): cap reconnect backoff @apanasenko-oai
- #23756 package: include zsh fork in Codex package @bolinfest
- #23757 Default function tools into tool hooks @abhinav-oai
- #24171 package: add x64 macOS codex-zsh artifact @bolinfest
- #24159 code-mode: merge stored values by key @cconger
- #23983 fix: plugin bundle archive handling for upload and install @xl-openai
- #24261 feat(doctor): add environment diagnostics @fcoury-oai
- #24311 Report app-server version in codex doctor @etraut-openai
- #24314 tui: label compact rate-limit percentages @etraut-openai
- #24420 Show remote connection details in /status @etraut-openai
- #24317 Respect hook trust bypass during TUI startup @etraut-openai
- #24254 TUI config cleanup: oss_provider @etraut-openai
- #24255 TUI config cleanup: trusted projects @etraut-openai
- #24265 TUI config cleanup: MCP inventory @etraut-openai
- #24305 Add doctor thread inventory audit @etraut-openai
- #24346 fix(tui): improve markdown table column allocation @fcoury-oai
- #24351 fix(tui): improve multiline markdown list readability @fcoury-oai
- #24459 fix(tui): prevent macos stderr from corrupting composer @fcoury-oai
- #24479 fix(process-hardening): preserve macos malloc diagnostics @fcoury-oai
- #24474 Log rollout writer OS errors @etraut-openai
- #24076 chore: stop consuming legacy config profiles @jif-oai
- #24131 centralize Responses retry policy @rhan-oai
- #23858 [wip] goal shift @jif-oai
- #24555 chore: drop orphaned codex memories MCP crate @jif-oai
- #24558 chore: move memory prompt builder into extension @jif-oai
- #24562 Add ad-hoc memory note tool @jif-oai
- #24567 Wire metrics client into memories extension @jif-oai
- #24588 fix: drop flake @jif-oai
- #24583 Add memory tool call metrics to memories extension @jif-oai
- #24586 Wire app-server extension event sink @jif-oai
- #24532 Use thread config for TUI MCP inventory @etraut-openai
- #24105 [codex] Make active turn task singular @pakrym-oai
- #21576 Move MCP tool naming mode into manager @pakrym-oai
- #24503 tui: include exec sessions in resume list @etraut-openai
- #24600 feat: gate dedicated memories tools in config @jif-oai
- #21559 tui: add named permission profile picker @viyatb-oai
- #24608 feat: add manual and remote_v2 tags to compaction metric @jif-oai
- #24611 test: clean up apply_patch allow-session artifact @jif-oai
- #24609 Remove reserved namespaces dedup @pakrym-oai
- #23964 Move slash input logic out of chat composer @canvrno-oai
- #24615 Add goal extension telemetry parity @jif-oai
- #24371 fix(tui): avoid modifyOtherKeys for unknown tmux formats @fcoury-oai
- #24626 fix: restore goal accounting after thread resume @jif-oai
- #24591 Move memory state to a dedicated SQLite DB @jif-oai
- #23823 standalone websearch extension @sayan-oai
- #24593 fix(tui): keep raw output above composer in zellij @fcoury-oai
- #24625 tui: keep inaccessible apps out of mentions @canvrno-oai
- #24154 Add experimental turn additional context @pakrym-oai
- #24473 fix(remote-control): surface websocket task stalls @apanasenko-oai
- #24528 Respect resume cwd overrides for idle cached threads @etraut-openai
- #24160 Add forked_from_thread_id turn metadata @owenlin0
- #24646 make direct only allowed caller for standalone websearch @sayan-oai
- #23949 Clarify view_image tool description @fjord-oai
- #24266 TUI config cleanup: plugin mentions @etraut-openai
- #24320 Avoid repeated marketplace upgrades for alternate layouts @etraut-openai
- #23813 windows-sandbox: remove SandboxPolicy runner plumbing @bolinfest
- #24652 [codex] remove plain image wrapper spans @pakrym-oai
- #24623 Attach Windows sandbox log to feedback reports @iceweasel-oai
- #24644 Restore legacy image detail values @rhan-oai
- #24655 [codex-analytics] add grouped session id to runtime events @marksteinbrick-oai
- #24658 [codex] Remove obsolete goal continuation turn marker @pakrym-oai
- #24660 fix: dont compact standalone websearch schema @sayan-oai
- #24667 fix(core): instrument stalled tool-listing handoff @apanasenko-oai
- #24684 Uprev Rust toolchain pins to 1.95.0 @anp-oai
- #21567 fix: add noninteractive install script mode @efrazer-oai
- #24707 Allow runtime enablement for remote plugins @xl-openai
- #24714 fix(auto-review) skip legacy notify for auto review threads @dylan-hurd-oai
- #24690 Revert "Add Bedrock Mantle GovCloud region (#23860)" @celia-oai
- #24628 feat: handle goal usage limits in goal extension @jif-oai
- #24746 Fix guardian review test user input @jif-oai
- #24744 feat: add thread idle lifecycle hook @jif-oai
- #24751 Drop startup context when truncating forked rollouts @jif-oai
- #24257 TUI config cleanup: plugin marketplace @etraut-openai
- #24380 fix(tui): complete vim word-end and line-end behavior @fcoury-oai
- #24728 Bump SQLx to pick up newer bundled SQLite @jif-oai
- #24637 fix: run standalone updates noninteractively @efrazer-oai
- #24778 make vercel webhook url an env secret @sayan-oai
- #23950 fix: Preserve draft text when completing argument-taking slash commands @canvrno-oai
- #24641 [codex] Remove stale composer narrative doc references @canvrno-oai
- #24368 [codex] add compaction metadata to turn headers @ningyi-oai
- #24772 [codex] Add friendly Python SDK sandbox presets @aibrahim-oai
- #24382 feat(tui): add vim text object bindings @fcoury-oai
- #24766 feat(tui): make turn interruption keybind configurable @fcoury-oai
- #24489 feat(tui): render markdown tables in app style [1 of 2] @fcoury-oai
- #24713 chore: enable namespace tools for Bedrock @celia-oai
* Seed Termux release automation
* Prepare Termux rust-v0.135.0
* checkpoint: into wallentx/termux-target from release/0.136.0 @ 1e6e8b4b5d85 (#176)
* fix(linux-sandbox): preserve shell cleanup on interruption (#22729)
## Why
Interrupted `shell_command` calls can race with the outer tool-dispatch
cancellation path. When that happens, the runtime future may be dropped
before the spawned process gets a chance to run `SIGTERM` cleanup. For
bwrapd-backed Linux sandbox commands, that can leave synthetic
protected-path mount bookkeeping such as `.git/.codex` registrations
under `/tmp` behind after a TUI interruption.
The relevant cancellation points are the outer dispatch race in
[`core/src/tools/parallel.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/parallel.rs#L91-L132)
and the process shutdown logic in
[`core/src/exec.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/exec.rs#L1367-L1393).
## What changed
- Keep `shell_command` dispatch alive long enough for the runtime to
finish cancellation cleanup instead of immediately returning the
synthetic aborted response.
- Fold shell-turn cancellation into the existing `ExecExpiration` path
in
[`core/src/tools/runtimes/shell.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/runtimes/shell.rs#L267-L274),
so cancellation and timeout behavior stay centralized.
- On cancellation, send `SIGTERM` first, wait briefly for cleanup to
run, then hard-kill any remaining descendants in the original process
group.
- Treat `ESRCH` as an already-gone process-group cleanup case in
`codex-utils-pty`, which keeps best-effort teardown from surfacing a
stale-process race as an error.
## Verification
- `cargo test -p codex-core cancellation`
- Added regression coverage for:
- `shell_tool_cancellation_waits_for_runtime_cleanup`
- `process_exec_tool_call_cancellation_allows_sigterm_cleanup`
* feat(tui): add OSC 8 web links to rich content (#24472)
## Why
Wrapped URLs in rich TUI output, especially URLs rendered inside
Markdown tables, are split across terminal rows. In terminals that
support OSC 8 hyperlinks, treating each visible fragment as part of the
complete destination enables reliable open-link and copy-link actions
even after table layout wraps the URL.
This addresses the semantic-link portion of #12200 and the behavior
described in
https://github.com/openai/codex/issues/12200#issuecomment-4535452980. It
does not change ordinary drag-selection across bordered table rows.
## What Changed
- Added shared TUI OSC 8 support that validates `http://` and `https://`
destinations, sanitizes terminal payloads, and applies metadata
separately from visible line width/layout.
- Added semantic web-link annotations to assistant and proposed-plan
Markdown, including explicit web links and bare web URLs in prose and
table cells while excluding code and non-web Markdown destinations.
- Preserved complete URL targets through table wrapping, narrow pipe
fallback, streaming, transcript overlay rendering, history insertion,
and resize replay.
- Routed intentional Codex-owned links in notices,
status/setup/app-link, feedback, onboarding, MCP/plugin help, memories,
and update surfaces through the shared hyperlink handling.
## How to Test
1. Run Codex in a terminal with OSC 8 link support, such as Ghostty, and
request an assistant response containing a Markdown table whose last
column contains a long `https://` URL.
2. Make the terminal narrow enough for the URL to wrap across multiple
bordered table rows.
3. Use the terminal's open-link or copy-link action on more than one
wrapped URL fragment and confirm each fragment resolves to the complete
original URL.
4. Resize the terminal after the table is rendered and repeat the link
action to confirm the destination survives scrollback replay.
5. Open the transcript overlay while rich output is present and confirm
web links remain interactive there.
6. As a regression check, render inline/fenced code containing URL text
and a Markdown link such as
`[https://example.com](mailto:support@example.com)`; confirm these do
not acquire a web OSC 8 destination.
Targeted automated coverage exercised Markdown links and exclusions,
wrapped and pipe-fallback tables, streaming/transcript overlay
propagation, status-link truncation, and rendered word-wrapping cell
alignment. `just test -p codex-tui` was also run; it passed the
hyperlink coverage and reproduced two unrelated existing guardian
feature-flag test failures.
* feat(tui): render cramped markdown tables as key-value records [2 of 2] (#24636)
## Stack
- **Base: #24489 [1 of 2]** - render markdown tables in app style.
- **Current: #24636 [2 of 2]** - render cramped markdown tables as
key/value records.
Review this PR against `fcoury/app-style-markdown-tables`; it contains
only the fallback behavior for cramped tables.
## Why
The row-separated markdown table rendering in #24489 remains readable
while columns have usable room. Once long links or multiple prose-heavy
columns are compressed into narrow allocations, however, the grid can
turn words and paths into tall vertical strips that are difficult to
scan. In those cases the content matters more than preserving the grid
shape.
## What Changed
<table>
<tr><td>
<p align="center"><b>
Normal
</b></p>
<img width="1722" height="619" alt="CleanShot 2026-05-27 at 14 32 57"
src="https://github.com/user-attachments/assets/d04f5fbd-6064-4acd-91bd-072d19b983df"
/>
</td></tr>
<tr><td>
<p align="center"><b>
Narrow
</b></p>
<img width="863" height="1013" alt="CleanShot 2026-05-27 at 14 33 12"
src="https://github.com/user-attachments/assets/6a7d2968-0a68-48fd-ab5d-209b3dbaf03e"
/>
</td></tr>
<tr><td>
<p align="center"><b>
Very narrow
</b></p>
<img width="435" height="746" alt="CleanShot 2026-05-27 at 14 33 47"
src="https://github.com/user-attachments/assets/f6a59e30-b1d2-4063-9c05-43933abc77d6"
/>
</td></tr>
</table>
- Detect tables whose grid allocation causes systemic token
fragmentation or starves multiple prose-heavy columns.
- Render those tables as repeated key/value records instead of retaining
an unreadable grid.
- Use aligned label/value records when there is useful horizontal room,
and switch to a stacked narrow-record layout where each label is
followed by a full-width value when width is especially constrained.
- Preserve the themed label color, rich inline formatting, links, and
the existing grid presentation for tables that remain readable.
- Add snapshot coverage for path-heavy narrow tables, prose-heavy issue
tables, systemic compact fragmentation, and a control case that should
continue to render as a grid.
## How to Test
1. Start Codex from this branch and render a normal multi-column
markdown table at a comfortable terminal width. Confirm it still appears
as the styled row-separated grid from #24489.
2. Render a table containing a long linked record identifier or
file-like value, then narrow the terminal until the grid would split the
value into vertical fragments. Confirm it switches to key/value records,
with labels above values at very narrow widths.
3. Render a table with multiple prose-heavy columns, such as an issue
summary table with `Issue`, `Activity`, `Complexity`, and `Why start`.
Confirm a cramped width switches to records rather than wrapping several
columns into hard-to-read strips.
4. Render a compact table where only one value wraps mildly. Confirm it
stays in grid form rather than switching prematurely.
## Validation
- Ran `just test -p codex-tui` while developing the fallback and
reviewed/accepted the intended new markdown-render snapshots. The
command still reports two unrelated existing guardian feature-flag test
failures outside this diff.
- Ran `just fix -p codex-tui` and `just fmt` after the Rust changes were
complete.
- `just argument-comment-lint` cannot reach source linting locally
because Bazel fails while resolving LLVM sanitizer headers; touched
positional literal callsites were inspected manually and annotated where
needed.
* Allow API-key auth for remote exec-server registration (#24666)
## Overview
Allow remote `codex exec-server` registration to use existing API-key
auth while restricting where those credentials can be sent.
- Accept `CodexAuth::ApiKey` for the normal `--remote` registration
path.
- Restrict API-key remote registration to HTTPS `openai.com` and
`openai.org` hosts and subdomains, with explicit HTTP loopback support
for local development.
- Disable registry registration redirects so credentials cannot be
forwarded to an unvalidated destination.
- Retain `--use-agent-identity-auth` as the explicit Agent Identity
path.
- Document remote registration using `CODEX_API_KEY`.
## Big picture
Callers can now provide an API key directly to `exec-server`
registration without first establishing ChatGPT login state:
```sh
CODEX_API_KEY="$OPENAI_API_KEY" \
codex exec-server \
--remote "https://<host>.openai.org/api" \
--environment-id "$ENVIRONMENT_ID"
```
## Validation
- `cargo fmt --all` (`just fmt` is not installed on this host)
- `cargo test -p codex-cli -p codex-exec-server`
* Update rmcp to 1.7.0 (#24763)
WIll make it easier to uprev when the new draft spec is supported.
Also updates reqwest where needed for compatibility but doesn't update
it everywhere since this is already a large diff.
The new version of rmcp handles certain kinds of authentication failures
differently, this patch includes support for identifying the failing scope
in a WWW-Authenticate header.
* [codex] Fix hyperlink-aware key-value table rendering (#24825)
## Why
The key/value markdown table renderer added in #24636 still operates on
`Line` values, while table cells and rendered table output now carry
`HyperlinkLine`. That mismatch breaks `codex-tui` compilation on `main`
and would risk losing semantic web-link annotations if corrected by
flattening the values.
## What changed
- Make key/value record rendering wrap and emit `HyperlinkLine` values
consistently with the existing grid renderer.
- Remap wrapped hyperlink ranges and shift them when value content is
prefixed by record-mode indentation or labels.
- Add focused coverage verifying key/value fallback output preserves
web-link destinations.
## Verification
- `just test -p codex-tui -E
'test(key_value_table_keeps_web_annotations) |
test(/table_renders_(key_value_records_when_compact_fragmentation_is_systemic_snapshot|stacked_key_value_records_when_path_column_becomes_too_narrow_snapshot|records_when_multiple_prose_columns_are_starved_snapshot)/)'`
* [codex] Rename Python SDK AppServerConfig to CodexConfig (#24800)
## Why
`AppServerConfig` is exported as part of the ergonomic Python SDK
surface and passed to `Codex(...)` and `AsyncCodex(...)`. That name
exposes the underlying app-server transport at the same layer where
users are configuring the Codex client. `CodexConfig` makes the common
callsite read naturally and names the object it configures.
## What changed
- Renamed the public configuration dataclass from `AppServerConfig` to
`CodexConfig`.
- Updated `Codex`, `AsyncCodex`, and the transport clients to accept
`CodexConfig`.
- Updated binary-resolution messages, package exports, docs, examples,
and related coverage to use the new public name.
## API impact
```python
from openai_codex import Codex, CodexConfig
with Codex(config=CodexConfig(codex_bin="/path/to/codex")) as codex:
...
```
Callers should now import and construct `CodexConfig`; `AppServerConfig`
is no longer part of the Python SDK surface.
## Validation
- `uv run --frozen --extra dev ruff check src/openai_codex scripts
examples tests`
- Tests are deferred to online CI for this PR.
* [codex] Remove redundant SQLite dynamic tool storage (#24819)
## Why
Dynamic tools are defined at thread start and already stored in rollout
`SessionMeta`, which restores resumed and forked sessions. Persisting
the same tools through SQLite creates a second runtime persistence path
that is unnecessary prework for the explicit namespace refactor.
## What changed
- Restore missing thread-start dynamic tools directly from rollout
history, including when SQLite is enabled.
- Remove SQLite dynamic-tool reads, writes, backfill, and thread
metadata patch plumbing.
- Add SQLite-enabled resume integration coverage that verifies a
rollout-defined dynamic tool is still sent after resume.
## Compatibility
The existing `thread_dynamic_tools` table is intentionally not dropped
even though it's now unused. Older Codex binaries are allowed to open
databases migrated by newer binaries and still reference this table;
dropping it would break that mixed-version path. See
[here](https://github.com/openai/codex/blob/main/codex-rs/state/src/migrations.rs#L10-L11).
## Verification
- `just test -p codex-state -p codex-rollout -p codex-thread-store`
- `just test -p codex-core --test all
resume_restores_dynamic_tools_from_rollout_with_sqlite_enabled`
* [codex] Add independent beta release for the Python SDK (#24828)
## Why
`openai-codex` needs a beta release lifecycle without requiring beta
releases of its pinned runtime package. Previously, SDK staging rewrote
its runtime dependency to the SDK version, which made an SDK-only beta
impossible.
## What changed
- Set the initial SDK beta version to `0.1.0b1` and pin it to published
stable `openai-codex-cli-bin==0.132.0`.
- Decoupled SDK release staging from runtime versioning so it preserves
the reviewed exact runtime pin.
- Added a `python-v*` tag workflow that builds and publishes only
`openai-codex` through PyPI trusted publishing.
- Removed the Beta classifier from runtime package metadata for future
runtime publications.
- Regenerated protocol-derived SDK models from the selected stable
runtime package.
`0.132.0` is the newest stable runtime admitted by the checked-in
dependency date fence and retains the Linux wheel family currently used
by SDK CI.
## Release setup
Before pushing `python-v0.1.0b1`, configure PyPI trusted publishing for
the `openai-codex` project with workflow `python-sdk-release.yml`,
environment `pypi`, and job `publish-python-sdk`.
## Validation
- `uv run --frozen --extra dev ruff check src/openai_codex scripts
examples tests`
- Parsed `.github/workflows/python-sdk-release.yml` with PyYAML.
- Built staged release artifacts locally:
`openai_codex-0.1.0b1-py3-none-any.whl` and
`openai_codex-0.1.0b1.tar.gz`.
- Verified wheel metadata pins `openai-codex-cli-bin==0.132.0`.
- Tests are deferred to online CI for this PR.
* [codex] Prepare Python SDK beta documentation and package metadata (#24836)
## Why
The initial public `openai-codex` beta should read and install like a
normal published Python package before a release tag is created. This
follows merged PR #24828, which establishes the independent SDK beta
release plumbing and exact runtime dependency.
## What changed
- Rewrote `sdk/python/README.md` as a compact PyPI-facing beta package
page: published installation, one quickstart, short login examples,
built-in help, and links to deeper guides.
- Updated the getting-started guide, API reference, FAQ, and examples
index to present the published beta consistently without repeating
onboarding in the package landing page or reference page.
- Made `pip install openai-codex` the primary install path while beta
releases are the only published SDK releases, with `--pre` documented
for opting into prereleases after a stable release exists.
- Added curated `help()` / `pydoc` docstrings across the public API and
generated public convenience methods through
`scripts/update_sdk_artifacts.py`.
- Declared the repository `Apache-2.0` license expression and
Documentation URL in package metadata, without introducing a duplicated
SDK-local license file.
- Kept the source distribution focused on installable package material
(`src/openai_codex`, `README.md`, and `pyproject.toml`); the repository
docs and runnable examples remain linked from the PyPI README.
- Built release artifacts in an Alpine container on the Ubuntu runner,
matching Python SDK CI and allowing type generation to install the
published `musllinux` runtime wheel.
- Added `twine check --strict` to the release workflow so malformed PyPI
metadata or rendered README content fails before publishing.
- Added focused SDK assertions for beta metadata, the exact runtime pin,
source distribution contents, and the built-in Python documentation
surface.
## Validation
- Ran `uv run --frozen --extra dev ruff check
scripts/update_sdk_artifacts.py src/openai_codex
tests/test_public_api_signatures.py
tests/test_artifact_workflow_and_binaries.py` before the final
README-only reductions and review-fix follow-ups.
- Built `openai_codex-0.1.0b1-py3-none-any.whl` and
`openai_codex-0.1.0b1.tar.gz` before the final README-only reductions
and review-fix follow-ups.
- Ran `python -m twine check --strict` on both built artifacts before
the final README-only reductions and review-fix follow-ups.
- Verified artifact metadata reports `Apache-2.0` without a duplicated
SDK-local license file.
- Verified `inspect.getdoc(...)` resolves documentation for the package,
`Codex`, `CodexConfig`, and key generated thread methods.
- Rebased the documentation/readiness change onto merged PR #24828
without changing the intended SDK or workflow file contents.
- Final verification is delegated to online CI for this PR.
* Treat refresh_token_reused 400s as relogin-required (#24830)
## Summary
- classify known refresh-token terminal failures from `/oauth/token` as
permanent even when the backend returns `400`
- preserve the existing relogin-required message for
`refresh_token_reused` instead of retrying and collapsing into a generic
cloud requirements error
- add regression coverage for `400 refresh_token_reused`
## Testing
- `just fmt`
- `cargo test -p codex-login`
* [codex] Simplify Python SDK install guidance (#24866)
## Summary
- Remove the exact-version install snippet from the PyPI-facing Python
SDK README.
- Remove the release-selection explanation so the install section
presents the standard `pip install openai-codex` path directly.
## Validation
- Not run locally; relying on online CI for this documentation-only
change.
* [codex] Remove Python SDK language classifiers (#24868)
## Summary
- Remove the Python language classifiers from the Python SDK package
metadata.
- Keep `requires-python = ">=3.10"` as the package's interpreter
compatibility constraint.
- Avoid presenting a curated version-support list in PyPI metadata.
## Validation
- Not run locally; relying on online CI for this metadata-only change.
## Release
- Land this change before publishing the next Python SDK beta.
* [codex] Remove Python SDK beta warning note (#24870)
## Summary
- Remove the beta warning callout from the PyPI-facing Python SDK
README.
- Keep the existing Beta title and install/usage guidance unchanged.
## Validation
- Not run locally; relying on online CI for this documentation-only
change.
## Release
- Land this change before publishing the next Python SDK beta.
* [codex] Stage Python SDK beta versions from release tags (#24872)
## Summary
- Treat `sdk/python` as a development template with source version
`0.0.0-dev`, matching the existing Python runtime packaging pattern.
- Have `python-v*` tags supply the published SDK beta version through
the existing `stage-sdk --sdk-version` path.
- Remove the workflow check requiring a source version bump for each
beta release and remove its now-unused host Python setup step.
- Keep the reviewed runtime dependency pin at
`openai-codex-cli-bin==0.132.0`.
- Remove beta-number-specific documentation so it does not need editing
for each publish.
## Why
The package staging script already writes the release version into the
artifact. Requiring the checked-in SDK template version to match every
tag adds release-only source churn without changing the package users
receive.
## Validation
- Not run locally; relying on online CI for this workflow and metadata
change.
## Release
After this PR lands, publish the next beta by pushing tag
`python-v0.1.0b2` from merged `main`.
* Move memories root setup out of core config (#24758)
## Why
Config loading should not create or write-authorize the memories root
just because memory support exists. Memory startup is the code path that
actually materializes that tree.
## What
- Stop creating the memories root during Config load and remove it from
legacy workspace-write projections.
- Grant the memories root read access only when the memories feature and
use_memories are enabled.
- Create the memories root inside memories startup before seeding
extension instructions.
- Update config and startup tests around the ownership boundary.
## Tests
- just fmt
- just fix -p codex-core
- just fix -p codex-memories-write
- just test -p codex-core
memory_tool_makes_memories_root_readable_without_creating_or_widening_writes
workspace_write_includes_configured_writable_root_once_without_memories_root
permission_profile_override_keeps_memories_root_out_of_legacy_projection
permissions_profiles_allow_direct_write_roots_outside_workspace_root
default_permissions_profile_populates_runtime_sandbox_policy
- just test -p codex-memories-write memories_startup_creates_memory_root
Note: a broader just test -p codex-core run is not clean in this
sandbox; it hit missing test_stdio_server plus seatbelt, realtime, and
environment-sensitive failures. The changed config tests above pass.
* Stabilize Guardian client cache key handling (#24891)
Split from the Guardian prompt cache key change. This PR only updates
codex-rs/core/src/client.rs. Validation was not run per request; this
branch is expected to rely on the companion split PRs.
* Export Guardian prompt cache key helper (#24892)
Split from the Guardian prompt cache key change. This PR only updates
codex-rs/core/src/guardian/mod.rs. Validation was not run per request;
this branch is expected to rely on the companion split PRs.
* Add Guardian review prompt cache key (#24893)
Split from the Guardian prompt cache key change. This PR only updates
codex-rs/core/src/guardian/review_session.rs. Validation was not run per
request; this branch is expected to rely on the companion split PRs.
* Assert Guardian prompt cache key reuse (#24894)
Split from the Guardian prompt cache key change. This PR only updates
codex-rs/core/src/guardian/tests.rs. Validation was not run per request;
this branch is expected to rely on the companion split PRs.
* Thread Guardian cache key through session (#24895)
Split from the Guardian prompt cache key change. This PR only updates
codex-rs/core/src/session/session.rs. Validation was not run per
request; this branch is expected to rely on the companion split PRs.
* Use stable Guardian prompt cache keys (#24803)
## Why
Guardian review sessions are reusable across forks when their
`GuardianReviewSessionReuseKey` is unchanged, but the underlying
Responses request was still using the child thread ID as
`prompt_cache_key`. That meant forked Guardian reviews that should share
cache context produced different cache keys, reducing prompt cache reuse
and weakening the reuse invariant.
## What Changed
- Adds a `ModelClient` prompt cache key override and uses it for
`ResponsesApiRequest.prompt_cache_key`.
- Computes Guardian review cache keys as
`guardian:<sha1(parent_thread_id:reuse_key)>`, scoped to the parent
thread plus the reuse-sensitive Guardian config.
- Wires session construction to apply that override only for Guardian
sub-agent sessions.
## Testing
- Added coverage that Guardian cache keys are stable for the same
parent/reuse key, change when either the parent thread or reuse key
changes, fit within the Responses API length limit, and are absent for
non-Guardian sessions.
- Extended the parallel review test to assert forked Guardian reviews
send the same `prompt_cache_key`.
* [codex] Fix Guardian argument comment lint (#24902)
## Summary
- Add the required `/*parent_thread_id*/` argument comment at the
Guardian review session test callsite flagged by CI.
## Validation
- `just fmt`
- Not run: clippy/tests, per request; CI will cover them.
* Fix memories namespace for Responses API tools (#24898)
## Why
Dedicated memories tools are exposed through a Responses API namespace
tool. The namespace itself has to be a valid tool identifier, so
`memories/` can fail validation before the model ever gets a chance to
call the memory tools.
## What changed
- Changed `MEMORY_TOOLS_NAMESPACE` from `memories/` to `memories`.
- Added `memory_tool_namespace_matches_responses_api_identifier` so the
namespace stays non-empty and limited to Responses-safe identifier
characters.
## Verification
- Added unit coverage for the namespace identifier shape in
`codex-rs/ext/memories/src/tests.rs`.
* Add Guardian review metrics (#24897)
## Why
Guardian reviews already emit analytics events, but we do not expose
aggregate OpenTelemetry metrics for review volume, latency, token usage,
or terminal outcomes. That makes it harder to monitor Guardian behavior
during rollouts and to compare review outcomes by source, action type,
session kind, model, and failure mode.
## What Changed
- Added Guardian review metric names for count, total duration, time to
first token, and token usage in `codex-rs/otel`.
- Added `core/src/guardian/metrics.rs` to convert
`GuardianReviewAnalyticsResult` into sanitized metric tags covering
decision, terminal status, failure reason, approval request source,
reviewed action, session kind, risk/outcome, model, reasoning effort,
and context/truncation state.
- Emitted the new metrics from `track_guardian_review` for each terminal
Guardian review result.
## Testing
- Added
`guardian_review_metrics_record_counts_durations_and_token_usage`, which
verifies the emitted count, duration, TTFT, token usage histograms, and
tag set through the in-memory metrics exporter.
* [codex-cli] Refresh near-expiry ChatGPT access tokens before requests (#23546)
## Summary
- refresh managed ChatGPT auth during auth resolution when its access
token is inside ChatGPT web's five-minute near-expiry window
- cover refresh-window decisions while preserving the existing
expired-token refresh path
## Why
Codex already resolves managed ChatGPT auth before outbound requests and
refreshes expired access tokens there. This change adjusts the existing
predicate to refresh a still-valid access token once it is within the
same five-minute refresh window used by ChatGPT web, avoiding a request
with a token about to expire.
A cross-process serialization follow-up was explored in #24663 and
closed for now; we do not currently suspect cross-process refresh races
are a root cause of the refresh errors under investigation.
External-token, API-key, and Agent Identity auth modes remain unchanged.
## Validation
- `bazel test //codex-rs/login:login-all-test`
- `just fmt` runs Rust formatting successfully, then its Python SDK Ruff
step cannot install `openai-codex-cli-bin==0.131.0a4` on this Linux
environment because no compatible wheel is published.
* Add thread start contributor facts (#24915)
Summary: add session source and persistent-state availability to
ThreadStartInput; populate them from session init; update existing goal
test harness constructors. Tests: just fmt; git diff --check. No full
tests or clippy run per request.
* Add turn error lifecycle contributor (#24916)
Summary
- Add TurnErrorInput and TurnLifecycleContributor::on_turn_error to the
extension API.
- Emit the turn-error lifecycle from core turn error paths, including
usage limit failures.
- Add direct lifecycle coverage for the emitted error facts and stores.
Tests
- just fmt
- git diff --check
- Not run: full tests or clippy (per instructions)
* [codex] Store pending response items directly (#24865)
* [codex] Update OpenAI Docs skill (#24914)
## Summary
- update the bundled `openai-docs` system skill to match the latest
`openai-docs-plus` content from `skills-internal`
- add the cached Codex manual fetch helper and expand the skill routing
for Codex self-knowledge
- keep the stable local skill identity and labels as `openai-docs`
## Why
The built-in OpenAI Docs skill needed to reflect the current upstream
guidance from `skills-internal` while preserving the local system-skill
name used by Codex.
## Impact
Codex now ships the newer OpenAI Docs skill behavior for Codex
self-knowledge and manual-first documentation lookups.
## Validation
- `just test -p codex-skills`
- exact directory diff against transformed `skills-internal`
`origin/main` was clean
* Add app-server startup benchmark crate (#24651)
## Summary
- Add a new `app-server-start-bench` crate to measure app-server startup
performance
- Wire the benchmark into the workspace and Bazel build so it can be run
consistently
- Update lockfiles and repo automation to account for the new package
* Gate goal tools by thread eligibility (#24925)
## Why
Goal tools create and update goal state for a persistent thread. The
extension was only checking whether goals were enabled before
advertising those tools, which meant they could be surfaced in contexts
that should not receive thread goal controls: ephemeral threads without
persistent thread state and review subagents.
Those sessions can still run the goal extension lifecycle, but the
thread tools should only be visible when the current thread can safely
use them.
## What changed
- Adds a `GoalRuntimeConfig` that separates goal enablement from whether
goal tools are available for the current thread.
- Computes tool eligibility on thread start from
`persistent_thread_state_available` and `SessionSource`, hiding tools
for review subagents.
- Uses `GoalRuntimeHandle::tools_visible()` when contributing thread
tools so enabled runtime state does not automatically imply tool
exposure.
- Adds backend coverage for hiding goal tools on ephemeral threads and
review subagents.
## Testing
- Added `goal_tools_hidden_for_ephemeral_threads`.
- Added `goal_tools_hidden_for_review_subagents`.
* Remove libubsan CI workaround (#24782)
It seems that this was added to allow rustc to load proc macros that had
been compiled with UBSan enabled, which zig does for debug and
`ReleaseSafe` builds. When zig drives the link of the final binary it
knows to include the ubsan runtime, but our zig-built artifacts are
being linked into a binary whose linking rustc drives. This removes the
libubsan workaround we have and replaces it with
`-fno-sanitize=undefined` passed to zig.
The new argument is passed at the end of zig's args so should take
precedence over any earlier arguments from the script's caller.
* extension-api: add TurnItemEmitter to tool calls (#24813)
## Why
Extension-contributed tools need to emit visible turn items through
Codex's normal event and persistence pipeline.
## What
- Add `TurnItemEmitter` to extension `ToolCall`s and route the core
implementation through `Session::emit_turn_item_*`.
- Hold weak session and turn references so retained tool calls cannot
keep host state alive.
- Provide a no-op emitter for extension test callers.
## Test Plan
- `just test -p codex-core -E
'test(passes_turn_fields_and_scoped_turn_item_emitter_to_extension_call)'`
---------
Co-authored-by: jif-oai <jif@openai.com>
* feat(app-server): include turns page on thread resume (#23534)
## Summary
The client currently calls `thread/resume` to establish live updates and
immediately follows it with `thread/turns/list` to hydrate recent turns.
This lets `thread/resume` return that page directly, eliminating a round
trip and the ordering/deduplication gap between the two calls.
Experimental clients opt in with `initialTurnsPage: { limit,
sortDirection, itemsView }`. The response returns `initialTurnsPage` as
a `TurnsPage`, including cursors for paging further back in history.
Keeping the controls in a nested opt-in object provides the useful
`thread/turns/list` knobs without spreading page-specific parameters
across `thread/resume`.
## Verification
- `just fmt`
- `just write-app-server-schema --experimental`
- `just write-app-server-schema`
- `cargo test -p codex-app-server-protocol`
- `cargo test -p codex-app-server
thread_resume_initial_turns_page_matches_requested_turns_list_page
--tests`
- `cargo test -p codex-app-server
thread_resume_rejoins_running_thread_even_with_override_mismatch
--tests`
- `just fix -p codex-app-server-protocol -p codex-app-server`
* Expose MCP server info as part of server status (#24698)
# Summary
Expose MCP server info via App Server (when available) so apps can
render a richer MCP experience
* Reap stale multi-agent slots (#24903)
## Summary
- Let `close_agent` clean up an agent that is still registered in
`AgentRegistry` even when its underlying thread is already missing.
- Preserve the explicit-close boundary: for known stale thread-spawn
agents, mark the persisted spawn edge `Closed`, then treat
`ThreadNotFound` / `InternalAgentDied` as a successful close so the
registry slot can be released.
- Add a regression for MultiAgentV2 task-name targets where
`close_agent("worker")` succeeds after the worker thread has already
disappeared.
## Motivation
A worker can disappear from `ThreadManager` while its metadata still
exists in the root `AgentRegistry`. Before this change, the close tool
failed while trying to subscribe to the missing thread status, so it
never reached the cleanup path that releases the registered agent slot.
With `agents.max_threads = 1`, an explicit close of that stale task-name
agent could fail and leave the session unable to spawn a replacement.
## Scope
This PR intentionally does not add …
…olve/pr-178 # Conflicts: # codex-rs/Cargo.lock # codex-rs/Cargo.toml # codex-rs/core/src/codex_thread.rs # codex-rs/core/src/exec_tests.rs # codex-rs/core/src/goals.rs # codex-rs/core/src/session/input_queue.rs # codex-rs/core/src/session/tests.rs # codex-rs/core/src/session/turn.rs # codex-rs/core/src/tasks/review.rs # codex-rs/core/src/tools/code_mode/mod.rs # codex-rs/core/src/tools/handlers/extension_tools.rs # codex-rs/core/src/tools/runtimes/shell.rs # codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs # codex-rs/ext/goal/src/extension.rs # codex-rs/ext/image-generation/Cargo.toml # codex-rs/ext/image-generation/src/extension.rs # codex-rs/ext/image-generation/src/tests.rs # codex-rs/ext/image-generation/src/tool.rs # codex-rs/model-provider/src/amazon_bedrock/catalog.rs # codex-rs/tools/src/lib.rs # codex-rs/tools/src/tool_call.rs
…et_from_release_0.136.0_328b1e6d55a9 checkpoint: into wallentx/termux-target from release/0.136.0 @ 328b1e6
- TUI markdown now keeps web links clickable with OSC 8 metadata, and cramped tables switch to readable key/value records without losing link targets. (openai#24472, openai#24636, openai#24825) - Sessions can now be archived from the TUI with `/archive` or from the CLI with `codex archive` / `codex unarchive`; archived sessions are protected from resume/fork until restored. (openai#25027, openai#25021) - App-server integrations can resume a thread with its initial turns page, see richer MCP server status, and launch stdio mode with `codex app-server --stdio`. (openai#23534, openai#24698, openai#24940) - Remote execution setup now supports `CODEX_API_KEY` registration for approved OpenAI hosts, while remote-control websockets use short-lived server tokens instead of ChatGPT access tokens. (openai#24666, openai#24141) - Windows admins get an alpha `codex sandbox setup --elevated` provisioning path, plus requirements support for allowed Windows sandbox implementations. (openai#24831, openai#23766) - A feature-gated standalone image generation extension can run through the native Codex image artifact completion pipeline. (openai#24723, openai#24972) ## Bug Fixes - ChatGPT auth refreshes tokens before the five-minute expiry window and shows a relogin-required path for reused refresh tokens instead of collapsing into a generic cloud error. (openai#23546, openai#24830) - Command-safety hardening prevents `/diff` from running repository-provided Git helpers/hooks, avoids PowerShell parser execution on non-Windows hosts, and rejects browser-origin exec-server websocket handshakes. (openai#24954, openai#24946, openai#24947) - Sandboxed commands clean up more reliably after interruptions or denied Windows network attempts, and `deny` read rules stay enforced for safe-command and approval-bypass paths. (openai#22729, openai#19880, openai#23943) - Resumed TUI sessions seed prompt history from the session transcript, multiline hook output renders as separate rows, and Vim normal-mode editing behaves correctly. (openai#24298, openai#24965, openai#25022) - App-server filesystem watchers debounce later batches correctly, and standalone web search calls now show and restore completed search activity. (openai#24716, openai#24693) - Bedrock auth now falls back to `AWS_REGION` / `AWS_DEFAULT_REGION`, and unsupported Bedrock GPT service tiers are no longer advertised or sent. (openai#25171, openai#25318) ## Documentation - Python SDK beta docs and package metadata now present the standard `pip install openai-codex` path, refreshed quickstarts, API reference, FAQ, and examples. (openai#24836, openai#24866, openai#24868, openai#24870) - Python SDK examples and docs now use the public `CodexConfig` name for configuring `Codex` / `AsyncCodex`. (openai#24800) - The bundled OpenAI Docs skill was updated with current Codex manual routing and a cached manual fetch helper. (openai#24914) - Built-in tool schema descriptions now clarify defaults, optional fields, bounds, and enums across shell, Code Mode, MCP, image, goal, plan, multi-agent, and related tools. (openai#24794) - App-server and exec-server docs now cover API-key remote registration, `--stdio`, runtime extra skill roots, and remote-control server-token behavior. (openai#24666, openai#24940, openai#24977, openai#24141) ## Chores - Python SDK releases can now be staged and published independently from runtime releases using `python-v*` tags while preserving the reviewed runtime dependency pin. (openai#24828, openai#24872) - Updated MCP dependencies to `rmcp` 1.7.0 and refreshed compatibility code. (openai#24763) - Refreshed Amazon Bedrock catalog metadata, including GPT-5.5, removal of unsupported OSS entries, and default-tier-only GPT model behavior. (openai#24701, openai#24960, openai#25318) - Removed the stale app-server debug-client pieces and cleaned up the workspace after deletion. (openai#25063, openai#25064, openai#25065, openai#25066, openai#25067, openai#25068, openai#25069, openai#25070, openai#25075) - Trimmed CI/build maintenance by moving Bazel Windows jobs to Codex runners, removing the libubsan workaround, and reverting the startup benchmark that broke musl builders. (openai#24952, openai#24782, openai#24937) ## Changelog Full Changelog: openai/codex@rust-v0.135.0...rust-v0.136.0 - openai#22729 fix(linux-sandbox): preserve shell cleanup on interruption @viyatb-oai - openai#24472 feat(tui): add OSC 8 web links to rich content @fcoury-oai - openai#24636 feat(tui): render cramped markdown tables as key-value records [2 of 2] @fcoury-oai - openai#24666 Allow API-key auth for remote exec-server registration @sdcoffey - openai#24763 Update rmcp to 1.7.0 @anp-oai - openai#24825 [codex] Fix hyperlink-aware key-value table rendering @sayan-oai - openai#24800 [codex] Rename Python SDK AppServerConfig to CodexConfig @aibrahim-oai - openai#24819 [codex] Remove redundant SQLite dynamic tool storage @sayan-oai - openai#24828 [codex] Add independent beta release for the Python SDK @aibrahim-oai - openai#24836 [codex] Prepare Python SDK beta documentation and package metadata @aibrahim-oai - openai#24830 Treat refresh_token_reused 400s as relogin-required @alexsong-oai - openai#24866 [codex] Simplify Python SDK install guidance @aibrahim-oai - openai#24868 [codex] Remove Python SDK language classifiers @aibrahim-oai - openai#24870 [codex] Remove Python SDK beta warning note @aibrahim-oai - openai#24872 [codex] Stage Python SDK beta versions from release tags @aibrahim-oai - openai#24758 Move memories root setup out of core config @jif-oai - openai#24891 Stabilize Guardian client cache key handling @jif-oai - openai#24892 Export Guardian prompt cache key helper @jif-oai - openai#24893 Add Guardian review prompt cache key @jif-oai - openai#24894 Assert Guardian prompt cache key reuse @jif-oai - openai#24895 Thread Guardian cache key through session @jif-oai - openai#24803 Use stable Guardian prompt cache keys @jif-oai - openai#24902 [codex] Fix Guardian argument comment lint @jif-oai - openai#24898 Fix memories namespace for Responses API tools @jif-oai - openai#24897 Add Guardian review metrics @jif-oai - openai#23546 [codex-cli] Refresh near-expiry ChatGPT access tokens before requests @cooper-oai - openai#24915 Add thread start contributor facts @jif-oai - openai#24916 Add turn error lifecycle contributor @jif-oai - openai#24865 [codex] Store pending response items directly @pakrym-oai - openai#24914 [codex] Update OpenAI Docs skill @vb-openai - openai#24651 Add app-server startup benchmark crate @anp-oai - openai#24925 Gate goal tools by thread eligibility @jif-oai - openai#24782 Remove libubsan CI workaround @anp-oai - openai#24813 extension-api: add TurnItemEmitter to tool calls @sayan-oai - openai#23534 feat(app-server): include turns page on thread resume @btraut-openai - openai#24698 Expose MCP server info as part of server status @gpeal - openai#24903 Reap stale multi-agent slots @jif-oai - openai#24936 Fix extension turn item emitter test event ordering @bolinfest - openai#24700 [codex] Support ui visibility meta for tools @gpeal - openai#24701 chore: add GPT-5.5 to the Amazon Bedrock catalog @celia-oai - openai#23363 TUI: Unified mentions tweaks + polish mentions rendering @canvrno-oai - openai#24937 Revert "Add app-server startup benchmark crate" @anp-oai - openai#24928 Wire task completion into thread-idle lifecycle @jif-oai - openai#24723 Add feature-gated standalone image generation extension @won-openai - openai#24952 Move Bazel Windows jobs onto codex-runners @anp-oai - openai#24940 Add `codex app-server --stdio` alias @anp-oai - openai#24954 fix(tui): prevent repository-configured code execution in /diff @fcoury-oai - openai#24949 [codex] Handle PowerShell UTF-8 setup failures @iceweasel-oai - openai#24960 [codex] Remove Bedrock OSS models from catalog @celia-oai - openai#23768 runtime: prepend zsh fork bin dir to PATH @bolinfest - openai#19880 fix: cancel Windows sandbox on network denial @viyatb-oai - openai#24947 fix(exec-server): reject websocket requests with Origin headers @viyatb-oai - openai#24653 [codex] Add user input client ids @alexi-openai - openai#23924 Surface filesystem permission profiles in prompt context @bolinfest - openai#24108 windows-sandbox: pass workspace roots to runner @bolinfest - openai#24974 windows-sandbox: fix capture cancellation test roots @bolinfest - openai#24962 Tighten hook output event schemas @abhinav-oai - openai#24141 feat(app-server): migrate remote control to server tokens @apanasenko-oai - openai#24970 fix(config): use deny for Unix socket permissions @viyatb-oai - openai#24946 [codex] Avoid PowerShell safety parsing off Windows @adrian-openai - openai#24977 Add runtime extra skill roots API @xl-openai - openai#24298 Seed prompt history from resumed messages @etraut-openai - openai#23943 fix: preserve deny-read sandboxing for safe commands @bolinfest - openai#24716 Fix fs/watch debounce batching @etraut-openai - openai#24918 Use internal model context fragments for goal steering @jif-oai - openai#24924 Use inject_if_running for active goal steering @jif-oai - openai#25063 Drop the stale debug-client manifest @jif-oai - openai#25064 Remove the generated debug-client README @jif-oai - openai#25065 Delete debug-client app-server process plumbing @jif-oai - openai#25066 Retire debug-client interactive command parsing @jif-oai - openai#25067 Remove the debug-client CLI entrypoint @jif-oai - openai#25068 Delete debug-client JSONL output helper @jif-oai - openai#25069 Remove debug-client server event reader @jif-oai - openai#25070 Drop debug-client prompt state tracking @jif-oai - openai#25075 fix: main @jif-oai - openai#24794 [codex] Improve built-in tool schema docs @jif-oai - openai#25095 Handle goal usage limits from turn errors @jif-oai - openai#25106 Remove stale rollout TODO tests @jif-oai - openai#24965 Render multiline hook output in TUI @abhinav-oai - openai#25031 [codex] Add model tool mode selector @aibrahim-oai - openai#24693 Show activity for standalone web search calls @sayan-oai - openai#25110 Move config document helpers into their own module @jif-oai - openai#25013 feat: Add focused diagnostics for MCP HTTP send failures @xl-openai - openai#24964 [codex] Wait for MCP readiness in core integration tests @anp-oai - openai#24972 Route extension image generation through the native image completion pipeline @won-openai - openai#24831 Add Windows sandbox provisioning setup command @iceweasel-oai - openai#25017 Align TUI permissions labels with app @etraut-openai - openai#25027 Add `/archive` slash command @etraut-openai - openai#25035 Use session wording in `/rename` confirmation @etraut-openai - openai#24161 Add subagent lineage metadata for responsesapi @owenlin0 - openai#25116 [exec-server] Kill dropped filesystem helpers @erichoracek - openai#24180 code-mode: introduce durable session interface @cconger - openai#23165 thread-store: store permission profiles @bolinfest - openai#25131 [codex] Require model for standalone web search @sayan-oai - openai#25134 ci: use issue triage environment for issue workflows @etraut-openai - openai#25118 exec-server: preserve fs helper CoreFoundation env @starr-openai - openai#25022 [codex] Fix Vim normal mode editing @jinghanx88 - openai#25161 Recommend Bazel VSCode extension. @anp-oai - openai#24996 Filter plugin install suggestions by installed apps @nm-openai - openai#23766 Constrain Windows sandbox requirements @abhinav-oai - openai#25172 [codex] Update remote connector suggestions @ericning-o - openai#25171 fix: Bedrock API key region fallback @celia-oai - openai#24541 feat(config) experimental_request_user_input toggle @dylan-hurd-oai - openai#25021 Add thread archive CLI commands @etraut-openai - openai#25267 Rename multi-agent v2 assignment tool @jif-oai - openai#25318 fix: Limit Bedrock GPT models to default service tier @owenlin0 - openai#25381 [codex] Avoid forced directory refresh during plugin install auth checks @xl-openai
Termux rust-v0.136.0
…nt/wallentx_termux-target_from_release_0.136.0_ef2492451848
#273) * [codex] Add optional IDs to response items (#28812) ## Why `ResponseItem` variants do not have a consistent internal ID shape: some variants carry required IDs, some carry optional IDs, and some cannot represent an ID at all. The existing fields also use inconsistent serde, TypeScript, and JSON-schema annotations. A single enum-level access path is needed before history recording can assign and retain IDs. This PR establishes that internal model only. It intentionally does not generate or serialize IDs; allocation and wire persistence are isolated in the stacked follow-up. ## What changed - Give every concrete `ResponseItem` variant an `Option<String>` ID field. - Apply the same internal-only annotations to every ID field: `#[serde(default, skip_serializing)]`, `#[ts(skip)]`, and `#[schemars(skip)]`. - Add `ResponseItem::id()` and `ResponseItem::set_id()` as the shared accessors. - Preserve IDs when history items are rewritten for truncation. - Adapt consumers that previously assumed reasoning and image-generation IDs were required. - Regenerate app-server schemas so the hidden fields are represented consistently. The serde catch-all `ResponseItem::Other` remains ID-less because it must remain a unit variant. ## Test plan - `cargo check --tests -p codex-core -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-protocol` - `just test -p codex-app-server-protocol` - `just test -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-core event_mapping` * fix(install): support older awk checksum parsing (#28784) ## Why The standalone installer validates package checksums with an awk interval expression. Older mawk releases do not support that expression, so they reject valid 64-character digests and report that the release manifest is missing an entry. This affects both x64 and ARM64 systems on common Debian-derived environments. Fixes #24219. ## What Changed Replace the awk interval expression with an explicit length check plus rejection of non-hexadecimal characters. This preserves the existing SHA-256 validation and lowercase normalization while working with older awk implementations. ## How to Test 1. Build and run the checksum predicate with mawk 1.3.4 20121129. 2. Confirm the old interval predicate rejects a valid 64-character digest. 3. Confirm the updated predicate accepts that digest. 4. Put the old mawk binary first on PATH as awk and run scripts/install/install.sh with an isolated HOME, CODEX_HOME, and CODEX_INSTALL_DIR. 5. Confirm Codex installs successfully and the installed binary reports version 0.140.0. 6. Verify the predicate rejects wrong-length digests, non-hexadecimal digests, and entries for another asset while accepting uppercase hexadecimal digests. * [codex] Use unique IDs for realtime-routed turns (#28826) ## Why A durable realtime voice orchestrator can reconnect and resume through multiple fresh `Session` instances. Realtime handoffs were using the Session-local `auto-compact-N` counter as their turn identity, but that counter restarts at zero for every resumed Session. The durable thread could therefore accumulate duplicate turn IDs, violating the uniqueness assumptions made by app-server and web clients. In Codex Apps, a new delegated response stream could be attached to an older turn with the same ID, placing live output higher in history and putting turn-scoped actions at risk. Persisted rollout and reconstructed model-context order were already correct because raw response items remain append-only and chronological. This change restores unique identity for reconstructed and live turn surfaces. ## What changed - Generate a UUIDv7 specifically for each realtime-routed delegation. - Leave the existing `auto-compact-N` identity path unchanged for actual internal auto-compaction turns. - Extend the inbound realtime handoff integration test to require a UUID turn ID from `turn/started`. ## Verification - `just test -p codex-core inbound_handoff_request_starts_turn` - `just fix -p codex-core` - `just fmt` * [codex] control automatic realtime handoff delivery (#27986) ## What Built on the realtime speech-control plumbing merged in #27917. - Add optional `codexResponseHandoffPrefix` to `thread/realtime/start`. - Apply that prefix only to automatic V1 commentary sent through `conversation.handoff.append`; final answers remain unprefixed. - Add opt-in `clientManagedHandoffs`. When true, core suppresses automatic response handoffs and completion output so delivery is controlled by explicit client append APIs. - Preserve existing automatic behavior by default. `codexResponsesAsItems: true` continues to select item routing when client-managed mode is disabled. ## Why Voice clients need two delivery policies: automatic background context with silent commentary instructions and fully client-owned handoffs. Phase-aware prefixing keeps routine commentary silent without suppressing the final answer, while client-managed mode lets an app decide exactly which updates to append. ## Validation - `just fmt` - `cargo test -p codex-app-server-protocol serialize_thread_realtime_start` - `RUST_MIN_STACK=16777216 cargo test -p codex-core --test all conversation_handoff_persists_across_item_done_until_turn_complete` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_client_managed_handoffs_disable_automatic_output` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_final_automatic_handoff_omits_silent_prefix` - `cargo build -p codex-cli --bin codex` - Local Codex Apps compatibility check: 43 focused webview tests passed, and a live voice session routed through the source-built app-server. The explicit `RUST_MIN_STACK` avoids a macOS Tokio test-worker stack overflow seen with the default test environment. * [codex] Support assistant realtime append text (#28836) ## Why Frontend realtime voice continuity needs to replay a tiny previous-session overlap as actual conversation items, including assistant text. The app-server `thread/realtime/appendText` API already carries a role through to the Rust realtime websocket layer, but the shared role enum only accepted `user` and `developer`. ## What Changed - Added `assistant` to `ConversationTextRole` and regenerated the app-server schema/type fixtures. - Added `output_text` as a realtime conversation content type. - Updated realtime websocket item creation so assistant appendText emits `content: [{ type: "output_text", text }]`, while user and developer continue to emit `input_text`. - Updated app-server docs and tests to cover assistant appendText alongside the existing developer role behavior. ## Validation - `just write-app-server-schema` - `just fmt` (first sandboxed attempt failed because `uv` could not access `~/.cache/uv`; reran with filesystem access and passed) - `just test -p codex-api` passed: 126/126 - `just test -p codex-app-server-protocol` passed: 239/239, including generated JSON/TypeScript fixture checks - `just test -p codex-app-server` was started locally but stopped per request after unrelated local sandbox/Seatbelt failures (`sandbox-exec: sandbox_apply: Operation not permitted`) and one missing local `codex` binary failure; CI should be faster and more authoritative for the full suite. * Refresh signed exec-server URLs on reconnect (#28374) ## Summary - add a provider API that supplies a fresh signed WebSocket URL for each remote exec-server connection - refresh the signed URL after disconnects and retry once when a handshake returns `401 Unauthorized` - allow `EnvironmentManager` consumers to register remote environments backed by the URL provider ## Tests - `just test -p codex-exec-server -E 'test(remote_websocket_client_refreshes_url_after_unauthorized_handshake) | test(remote_websocket_client_refreshes_url_after_disconnect)'` — 2 passed - `cargo check -p codex-core-api` — passed - `just fix -p codex-exec-server` — passed - `just fix -p codex-core-api` — no test targets; no-op - `just fmt` — passed - `just test -p codex-exec-server` — 187 passed; 32 unrelated macOS sandbox tests could not invoke nested `sandbox-exec` (`Operation not permitted`) * Expose selecte namespaces as direct model tools (#28825) ## Why Som tools, such as history and notes, must remain top-level when MCP deferral is enabled while staying unavailable through code-mode `exec`. ## What changed - Added `features.code_mode.direct_only_tool_namespaces`. - Classified matching MCP tools as `DirectModelOnly`. - Kept those tools top-level in `code_mode_only`. - Excluded them from `tool_search` deferral and the nested `exec` surface. - Updated the generated config schema. ## Validation - `code_mode_only_exposes_direct_model_only_mcp_namespaces` - `load_config_resolves_code_mode_config` * [codex] Support plugin manifest path lists (#28790) ## Summary Allow plugin manifests to declare `skills` as either a single path string or an array of path strings in the core plugin loader. ## Why Some plugin packages need to expose skills from more than one directory. Before this change, `plugin.json` only accepted a single string for `skills`, so manifests like this were ignored as an invalid `skills` shape: ```json { "skills": ["./skills/abc", "./skills/edk"] } ``` This keeps the existing single-string form working while adding support for the list form. The final scope is intentionally limited to the core plugin manifest/load path for `skills`; `apps`, file-backed `mcpServers`, and the bundled plugin-creator assets are unchanged in this PR. ## What changed - Parse `skills` as either a string or an array of strings in `plugin.json`. - Store resolved skill paths as a list in `PluginManifestPaths`. - Load manifest-declared skill roots in addition to the default `./skills` root. - Deduplicate exact duplicate skill roots before loading. - Rely on existing skill-loader dedupe by canonical `SKILL.md` path for overlapping roots such as `./skills` plus `./skills/abc`. - Update plugin manifest tests to cover: - single string `skills` - list of string `skills` - duplicate skill roots - `./skills` as a manifest path - explicit child roots like `./skills/abc` and `./skills/edk` - overlapping-root dedupe ## Validation - `just test -p codex-plugin` - `just test -p codex-core-plugins` - `just test -p codex-mcp-extension` - `git diff --check` * Record more path migration guidance for codex. (#28851) Some common themes pulled out of both human and automated reviews from the last couple of days' migrations to `PathUri` and `LegacyAppPathString`. * unified-exec: retain PathUri in command events (#28780) ## Why App-server must report command events containing foreign-platform paths without changing existing client or rollout path-string formats. ## What changed - retain `PathUri` through exec command begin/end events - convert cwd values to `LegacyAppPathString` at the app-server compatibility boundary - drop command actions with foreign paths and log them - serialize rollout-trace cwd values using their inferred native path representation - restore Wine coverage for retained Windows cwd values and successful completion * [codex] Split plugin and skill warmup tracing (#28605) ## What changed - promote plugin config loading to an info-level `plugins_for_config` span - promote skill config loading to an info-level `skills_for_config` span - attach stable OpenTelemetry names to both spans ## Why `session_init.plugin_skill_warmup` currently combines plugin loading and skill loading, which makes cold-start traces unable to identify which phase dominates. These child spans preserve the existing aggregate while making the two costs independently visible. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact This is observability-only. It does not change plugin or skill loading behavior. ## Validation - `just test -p codex-core-skills -p codex-core-plugins` (347 passed) - `just fmt` * [codex] Pass plugin namespace into skill loading (#28608) ## What changed - retain the parsed plugin manifest namespace on loaded plugins - carry that namespace through `PluginSkillRoot` and `SkillRoot` - use the provided namespace when qualifying plugin skill names - include the namespace in the skills cache key ## Why Plugin loading has already parsed `plugin.json`, but skill parsing currently walks every `SKILL.md` ancestor and probes/reads the manifest again to reconstruct the same namespace. Passing the parsed namespace removes those repeated filesystem calls, which are particularly costly on remote filesystems. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact Plugin skill names remain unchanged. A regression test uses a deliberately different on-disk manifest name to verify that plugin roots use the provided parsed namespace. ## Validation - `just test -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` (352 passed) - `just fix -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` - `just fmt` * [codex] add rollout token budget configuration (varlength 1/N) (#28746) ## What This PR defines the structured configuration contract for shared rollout token budgets (across ALL agent threads under 1 rollout). ```toml [features.rollout_budget] enabled = true limit_tokens = 100000 reminder_interval_tokens = 10000 sampling_token_weight = 1.0 prefill_token_weight = 0.1 ``` The reminder interval defaults to 10% of the rollout limit. Sampling and prefill weights default to `1.0`. ## Scope This PR only defines and validates configuration. It does not track usage, inject reminders, or stop a rollout. Accounting and reminders are implemented in the stacked follow-up #28494. The existing `token_budget` feature remains unchanged. `rollout_budget` has its own feature key and configuration type. ## Tests The config test verifies that the structured fields resolve into `RolloutBudgetConfig` and do not enable the existing `token_budget` feature. Local checks: - `just write-config-schema` - `just test -p codex-core load_config_resolves_rollout_budget` - `cargo check -p codex-thread-manager-sample` - `git diff --check` The full workspace test suite was not run locally. * Add network environment ID plumbing (#28766) ## Why Prepare network approval scoping to distinguish execution environments without changing behavior yet. ## What changed - Add optional environment IDs to network policy requests. - Add optional network environment IDs to exec and sandbox request structs. - Thread default None values through existing construction points. - Fix stale constructor call sites that caused the CI compile failures. ## Not included - Per-environment proxy listeners. - Network approval cache or prompt behavior changes. - Ambiguous request attribution handling. Those behavior changes moved to stacked follow-up #28899. ## Validation - just fmt - CI will run tests and clippy * Avoid sandbox helper in apply_patch approval tests (#28915) ## Summary This keeps the apply_patch approval tests focused on approval behavior instead of macOS sandboxed filesystem helper startup. The changed cases still force patch approval with `UnlessTrusted`, but use `DangerFullAccess` after approval so the patch write is direct and cheap. Workspace-write and sandbox-helper behavior remain covered by the filesystem and apply_patch sandbox tests. * Pause active goals before TUI interrupts (#28813) Fixes #28104. ## Summary Active `/goal` turns should leave the persisted goal paused whenever the TUI interrupts the running turn. The bug in #28104 showed this most visibly through `Esc`: some interrupt paths aborted the turn without updating the goal status, so the goal could remain active and continue automatically. This change makes `ChatWidget` pause an active goal before the TUI sends an interrupt from the status-row path, the pending-steer path, `Ctrl+C`, or a request-user-input overlay. The modal overlay now reports whether a key will interrupt the turn, which keeps modal `Esc` and `Ctrl+C` behavior aligned with the normal interrupt paths. ## Manual Testing Built the local CLI with `just codex --help`, then launched the local TUI with goals enabled. Started an active `/goal` turn and interrupted it with `Esc`, then resumed and repeated with `Ctrl+C`; both paths showed `Goal paused`, the interrupted-conversation message, and the `Goal paused (/goal resume)` footer. I also stopped the background terminal and exited the TUI cleanly after the run. I did not find a reliable standalone manual path to force the request-user-input overlay case, so that path is covered by the focused automated test. * Recover exec process stdin writes (#28895) ## Summary Remote stdio MCP servers send tool calls by writing JSON-RPC bytes through `process/write`. When the exec-server websocket drops at the wrong time, the remote process can survive session recovery, but the stdin write can still fail back to RMCP as a transport send error. RMCP then closes the stdio MCP transport, so tools like `node_repl` are lost even though the process/session recovery path is working. This changes `process/write` to be safe to retry across exec-server recovery: - adds a required `writeId` to `process/write` - retries remote `Session::write` with the same `writeId` after reconnect - remembers accepted write ids per process so duplicate retries return `Accepted` without writing the same bytes to child stdin again - covers both the client retry path and server-side write id dedupe with tests In simple terms: ```text before: write to MCP stdin -> websocket closes -> write errors -> RMCP closes node_repl after: write to MCP stdin -> websocket closes -> reconnect -> retry same writeId server either writes once or recognizes it already did ``` * Pin Windows argument lint to Windows 2022 (#28940) ## What Run the Windows argument-comment-lint job on the `windows-2022` hosted runner instead of the custom Windows runner pool. ## Why The custom pool recently moved from the Visual Studio 2022 Windows image to `windows-2025-vs2026`. Since that migration, the job fails while Bazel materializes LLVM external repository sources, before the argument lint itself runs. The same failure appears across unrelated PRs. This narrow change tests GitHub’s recommended mitigation for workloads that still require the Visual Studio 2022 image: https://github.com/actions/runner-images/issues/14017 ## How Use the standard `windows-2022` runner for only the Windows argument-comment-lint matrix entry. No product code or lint behavior changes. * Scope MCP sandbox metadata to server environment (#28914) Scope MCP sandbox metadata to the MCP server's owning environment. Previously, `codex/sandbox-state-meta` always used the turn's primary cwd and rebuilt a legacy sandbox policy from that cwd. That can be wrong for MCP servers owned by a different execution environment. This now sends the owning environment cwd as a `file:` URI in `sandboxCwd`, keeps `permissionProfile` as the permission source of truth, and omits sandbox-state metadata when a non-default server environment is not selected for the turn. Local/default MCP servers keep the existing fallback cwd behavior. Tests: - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `just test -p codex-mcp` - `just test -p codex-core mcp_sandbox_cwd` - `cargo build -p codex-rmcp-client --bin test_stdio_server` - `just test -p codex-core stdio_mcp_tool_call_includes_sandbox_state_meta` * Add turn-scoped context contributions (#28911) ## Summary - keep context injection on a single ContextContributor trait - split context injection into thread-scoped and turn-scoped contribution methods - wire turn-scoped fragments into initial context assembly so extensions can contribute context from turn-local state * Fix goal-first live threads missing from thread/list (#28808) Fixes #28263. ## Why When a thread starts with `/goal`, the goal extension can update SQLite goal state before the thread has any user-turn rollout items. `thread/list` and `thread/search` rely on persisted listing metadata, so a goal-first live thread could be absent from app-server listings after restart even though the goal itself existed. This regressed when goal handling moved out of core: the core path wrote the goal update through the live thread rollout path, while the extension-backed app-server path only updated goal state and emitted the live notification. ## What - Add `GoalSetOutcome::thread_goal_updated_item()` so the goal extension owns the canonical `ThreadGoalUpdated` rollout item shape. - Expose a narrow `CodexThread::append_rollout_items()` helper that appends through the live thread and keeps derived SQLite metadata in sync. - When app-server sets a goal on an active live thread, persist the goal update through that live-thread path. - Add an app-server regression test that starts a live thread with `thread/goal/set` and verifies it appears in state-DB-only `thread/list`. ## Verification - `env -u CODEX_SQLITE_HOME just test -p codex-app-server goal_first_live_thread_appears_in_state_db_thread_list` * [codex] Initialize exec-server OpenTelemetry at startup (#25019) ## Summary - Initialize stderr tracing and the configured OpenTelemetry provider for local and remote `codex exec-server` startup. - Instrument the local and remote server entrypoints with a root runtime span. - Keep raw Noise environment, registration, and stream identifiers out of exported spans while preserving them in local debug events. - Keep telemetry setup in a focused CLI module instead of growing the top-level command entrypoint. ## Stack - Previous: none (`#27058` has merged) - Next: #27466 ## Validation - `just test -p codex-exec-server --lib` (139 passed) - `just test -p codex-cli --test exec_server` (3 passed) - `just bazel-lock-check` - `just fix -p codex-exec-server -p codex-cli` - `just fmt` --------- Co-authored-by: Richard Lee <richardlee@openai.com> * [codex] Fix Windows sandbox runtime ACL refresh (#28943) ## Why Codex Desktop repairs sandbox-user read/execute access for binaries copied to `%LOCALAPPDATA%\OpenAI\Codex\bin`, but Computer Use launches its bundled Node runtime from `%LOCALAPPDATA%\OpenAI\Codex\runtimes`. On fresh Windows installations, `CodexSandboxUsers` may therefore be unable to execute the bundled Node binary. The command runner starts, but `CreateProcessAsUserW` fails with error 5 (`ACCESS_DENIED`), causing the Node REPL to exit before Computer Use can discover applications. This is a follow-up to #21564, which added the original runtime `bin` ACL repair. ## What changed - Expand the Codex Desktop runtime ACL roots from only `bin` to both `bin` and `runtimes`. - Apply the existing inherited read/execute ACL repair to each runtime directory when it exists. - Rename the setup helper to reflect that it now handles multiple runtime paths. ## Validation - `cargo fmt -- --check` - `just test -p codex-windows-sandbox` was run: 113 tests passed and five environment-dependent legacy execution tests failed because `CreateRestrictedToken` returned error 87. * Synchronize realtime notification test requests (#28946) ## What Deliver the scripted realtime notification batch after the assistant text append request instead of after the preceding developer text append request. ## Why The batch ends with an upstream error that closes the realtime conversation. When it is emitted after the developer append, it races the subsequent assistant append: the app-server RPC can acknowledge the append before its downstream WebSocket send completes, and the test intermittently observes three requests instead of four. Making the fake server wait for the assistant append before emitting the terminal batch establishes the ordering the test asserts without sleeps or production-code changes. ## Validation - `git diff --check` - CI (the failure is timing-dependent and most reproducible in the Windows Bazel shard) * Add Config for Time Reminders (varlatency 1/n) (#28822) ## Summary Example: > [features.current_time_reminder] enabled = true reminder_interval_model_requests = 1 clock_source = "system" ## Testing - `just test -p codex-core varlatency` - `just test -p codex-core lock_contains_prompts_and_materializes_features` - `just fix -p codex-core -p codex-config -p codex-features` * [codex] rollout budget implementation (varlength 2/N) (#28494) ## Stack Depends on #28746. This PR implements shared rollout-budget accounting and model-visible reminders using the configuration defined in #28746. # Description / Main changes to Core: `AgentControl` will now be the area where "rollout level" features & accounting will have to live. It is incorrectly named for this responsibility, but I think it can hold all the necessary shared state & features (rollout token budget, mutliple thread interruption responsibilitym etc) In this PR, we have one "token ledger" that each thread will subtract from when sampling. The "charge" will occur when response.completed() is done and the calculation will be done on the responses api usage carrier. The calculation will weigh sampling and pre-fill tokens as specified. Every time the budget crosses the configured reminder threshold, a developer message is appended before the thread's next request This remaining budget will _always_ be restated/reminded after a compaction event. Expiration and fan-out interruption will be in the stacked follow-up (and also live in Agent Control). ## Reminders "You have weighted {session_tokens_left} tokens left in the shared session token budget." The first request in each thread context receives the current remainder. Later reminders are emitted after aggregate weighted usage crosses a configured interval. If several intervals are crossed before a thread sends another request, Core inserts one reminder with the latest remainder. Compaction response usage is charged before the next context starts. The next reminder is appended after the compaction summary, leaving the initial context content stable. ## Tests Integration coverage verifies: - weighted output and non-cached input accounting - initial and periodic reminders - shared accounting between a root and sub-agent - post-compaction remainder and message placement Local checks: - `just fmt` - `just test -p codex-core rollout_budget` - `git diff --check` The full workspace test suite was not run locally. * Support `openai/form` extended form elicitations (#27500) # Summary Allow App Server clients to opt into `openai/form` MCP elicitations. * [codex] Make thread store turn filter optional (#28949) Make `ListItemsParams::turn_id` optional so callers can list persisted items across an entire thread or narrow the result to one turn. This aligns the thread-store API and documentation with thread-wide item listing while preserving the optional turn-filter behavior for implementations. * current time reminders impl for system clock (varlatency 2/n) (#28824) Stacked on #28822. ## Summary - add a host-injectable current-time provider with a built-in system implementation - record UTC developer reminders in history immediately before due model requests - keep cadence state per session and force a refresh after compaction This does NOT include the app server client <-> server clock logic. This PR is only for the reminder message & system clock that will be used in prod. ## Testing - `just test -p codex-core varlatency_` - `just clippy -p codex-core -p codex-app-server -p codex-mcp-server -p codex-thread-manager-sample` - `just fmt` * [codex] Cache plugin metadata for tool suggestions (#27812) ## Why `built_tools` runs for every sampling request, and local plugin discovery was repeatedly rereading plugin manifests, skills, MCP configuration, and app declarations to build the same tool-suggest metadata. That source-derived metadata is stable until the existing plugin manager reloads its cache. Runtime eligibility still needs to reflect the current install, disable, policy, app-overlap, and authentication state. ## What changed - Add a bounded, in-memory tool-suggest metadata cache owned by `PluginsManager`. - Key cached metadata by plugin identity and source, while applying authentication routing each time the metadata is projected. - Invalidate the metadata alongside the existing loaded-plugin cache, including its normal configuration, marketplace refresh, and remote-installed-plugin invalidation paths. - Guard against an in-flight load repopulating stale metadata after invalidation. - Keep marketplace membership and all runtime eligibility filtering live rather than introducing a separate catalog or revision model. ## Impact Repeated sampling requests reuse already-loaded plugin capability metadata while retaining the existing plugin-manager lifecycle as the single freshness boundary. ## Validation - `just test -p codex-core-plugins` — 252 passed - Added focused coverage for cache invalidation and authentication reprojection. * apply-patch: carry paths as PathUri (#28854) ## Why Allows the model to edit files that are hosted on a different OS than where app-server is running. ## What * Use `PathUri` for apply_patch-internal data structures * Limit `PathUri` -> `AbsolutePathBuf` conversion to cases where the inferred path convention matches the host OS, allows requiring valid paths to pass to perms check * Adds `PathConvention::path_segments()` for iterating over path segments regardless of OS * Handle cross-platform relative paths in path filename parsing for sniffing a shell * Ensure we can apply patches in the wine e2e test * Add app-server current-time impl (varlatency 3/n) (#28835) ## What Server should request: ``` { "id": 42, "method": "currentTime/read", "params": { "threadId": "11111111-1111-1111-1111-aaaaafdc2c11" } } ``` Client should respond with something like: ```rust { "id": 42, "result": { "currentTimeAt": 1781717655 } } ``` ## Why Sessions configured with `clock_source = "external"` need a thread-specific external time source before inference. The system clock remains the default production provider. ## Validation - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server --test all current_time_read_round_trip_adds_reminder_to_model_input` - `cargo test -p codex-app-server first_attestation_capable_connection_for_thread_only_uses_thread_subscribers` - `cargo test -p codex-analytics` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` Stacked on #28824. * Make auto-review on-request prompt more proactive (#26496) ## Why `on-request` approval policy text is currently tuned for user-reviewed approvals. For auto-reviewed productivity runs, likely sandbox blocks should be escalated earlier so commands that need remote services, authentication, or other out-of-sandbox access do not first fail or hang inside the sandbox. ## What changed - Adds a separate `on_request_auto_review.md` permissions prompt selected for `AskForApproval::OnRequest` with `ApprovalsReviewer::AutoReview`. - Keeps the normal user-reviewed `on-request` wording unchanged. - Makes the `When to request escalation` bullets more explicit about likely sandbox blocks, network access, remote auth/cluster/cloud/database access, out-of-sandbox environment access, git operations that may write lock files, and short-timeout reruns after likely sandbox-blocked attempts. - Omits approved command prefix and `prefix_rule` guidance for the auto-review on-request prompt. - Adds prompt tests covering the auto-review path, normal on-request wording, and inline permission request behavior. * [codex] Remove hardcoded app ID filters (#28947) ## Summary - remove the duplicated originator-specific connector ID denylists - stop filtering connector directory/accessibility results and live/cached Codex Apps MCP tools by hardcoded connector ID - remove the now-unused `codex-login` dependency from `codex-utils-plugins` - update regression coverage so formerly blocked connector IDs are preserved ## Why The client-side policy was duplicated across crates, used opaque IDs without ownership or expiry information, and could drift between app listing and MCP tool behavior. Server-provided visibility, authorization, plugin discoverability, accessibility, enabled-state handling, and consequential-tool approval templates remain unchanged. ## Validation - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `git diff --check` - confirmed the final diff contains no hardcoded denylist symbols A targeted `codex-mcp` test build spent an unusually long time in local compilation/linking. Its first attempt exposed a test-only `PartialEq` assertion issue, which was corrected. A follow-up non-linking `cargo check -p codex-mcp --tests` was still running when this draft was opened; CI should provide the complete Rust validation. * TUI: improve unified mention selection visibility (#28959) ## Summary [@milanglacier reported in #28653](https://github.com/openai/codex/issues/28653) that the active mention candidate is hard to distinguish. I suspect [@binbjz’s #28500 report](https://github.com/openai/codex/issues/28500) _(where arrow-key navigation appeared not to work)_ may describe the same presentation problem: the selection may have been changing, but the UI was not showing the active row clearly in their terminal. This PR makes two small changes to the selection indication behavior: - Reserve a two-character gutter and mark the active candidate with `> ` for color-agnostic indicator coverage. - Apply the shared theme-aware accent to the entire selected row for extra emphasis. - Update the existing popup snapshot. Reverse-video styling was considered, but avoided it because it is overly dependent on the user’s terminal palette. <img width="2046" height="482" alt="image" src="https://github.com/user-attachments/assets/b5eb62c3-fd24-4c09-906e-7bd66913b5c6" /> ## Testing - `just test -p codex-tui default_unified_mention_popup_snapshot` - `just clippy -p codex-tui` - `just fmt` - Compiled `codex-cli` and tested the unified mentions picker in the terminal. * Emit Trusted MCP App Identity on Tool-Call Items (#27132) ## Summary - Add optional `appContext` to app-server MCP tool-call items with trusted `connectorId`, `linkId`, and `mcpAppResourceUri` metadata. - Preserve that context across tool-call events, persisted history, reconnects, and thread resume. - Keep the deprecated top-level `mcpAppResourceUri` temporarily for client migration. The consumer contract is `{ appContext: { connectorId, linkId, mcpAppResourceUri }, tool }`. ## Validation - Full GitHub Actions suite passes, including CLA, Bazel tests, clippy, release builds, and argument-comment lint. --------- Co-authored-by: martinauyeung-oai <280153141+martinauyeung-oai@users.noreply.github.com> * feat: opt ChatGPT auth into agent identity (#19049) ## Stack This is PR 2 of the simplified HAI single-run-task stack: - [#19047](https://github.com/openai/codex/pull/19047) Agent Identity assertion and task-registration primitives, including the shared run-task helper used by existing Agent Identity JWT auth. - [#19049](https://github.com/openai/codex/pull/19049) Disabled-by-default ChatGPT auth opt-in that provisions/reuses persisted Agent Identity runtime auth and its single run task. - [#19051](https://github.com/openai/codex/pull/19051) Run-scoped provider auth that uses one backend-owned task id for first-party inference and compaction requests. [#19054](https://github.com/openai/codex/pull/19054) collapsed out of the active stack because the simplified design no longer needs a separate background/control-plane task helper. ## Summary This PR adds the disabled-by-default path for normal ChatGPT-login Codex sessions to obtain Agent Identity runtime auth through the Codex backend. Existing Agent Identity JWT startup mode remains a separate path and does not require the feature flag. What changed: - adds the experimental `use_agent_identity` feature flag and config schema entry - adds an explicit `AgentIdentityAuthPolicy` so call sites choose `JwtOnly` or `ChatGptAuth` instead of passing a bare boolean - stores standalone Agent Identity JWT credentials separately from backend-registered Agent Identity records - persists the registered Agent Identity record, private key, and single run task id in `auth.json` so process restarts reuse the same identity - derives the agent/task registration base URL from ChatGPT/Codex auth config while keeping JWT JWKS lookup separate - provisions and caches ChatGPT-derived Agent Identity runtime auth when `use_agent_identity` is enabled - reuses the shared run-task registration helper from PR1 rather than adding a second task-registration path This PR intentionally does not switch model inference over to `AgentAssertion` auth. The provider-auth integration lands in the next PR. ## Testing - `just test -p codex-login` * [connectors] Ignore synthetic links for app accessibility (#28770) Summary - Stop treating Codex Apps MCP tools with `_meta._codex_apps.synthetic_link: true` as evidence that a connector is accessible in `app/list`. - Preserve synthetic tools in the agent-facing MCP connector set so they remain available for install/auth flows. - Keep the app-list accessibility cache limited to connectors backed by at least one non-synthetic tool. - Add focused regression coverage for both sides of the boundary. Validation - `just fmt` - `just test -p codex-core synthetic_links_are_exposed_to_the_agent_but_not_accessible_in_app_list` - `git diff --check` - A crate-wide `just test -p codex-core` run completed with 2,699 passing and 51 unrelated local sandbox/state failures, primarily state DB migration races (`UNIQUE constraint failed: _sqlx_migrations.version`). * [codex] Preserve remote plugin download status errors (#28863) ## Summary - preserve the original HTTP status when a remote plugin bundle download returns a non-success response - retain at most 8 KiB of the error response body and annotate truncation or body-read failures - add regression coverage for an oversized error response ## Root cause The non-success response path reused the normal size-limited body reader. When an error response exceeded 8 KiB, that reader returned `DownloadTooLarge` before the code constructed `DownloadStatus`, masking the upstream HTTP status and response context. ## Impact Remote plugin installation failures now retain the actionable upstream HTTP status without allowing unbounded error bodies into logs. ## Validation - `just test -p codex-app-server plugin_install_preserves_status_when_remote_bundle_error_body_is_too_large` - `just fmt` - `git diff --check` * core: load AGENTS.md from foreign environments (#28958) ## Why Make it possible to load AGENTS.md from remote exec-servers whose OS is different than app-server. ## What - keep `AGENTS.md` discovery and provenance as `PathUri`, with root-aware parent and ancestor traversal - expose lifecycle instruction sources as legacy app-server path strings in events while retaining `PathUri` internally - preserve and test mixed POSIX and Windows paths in model context and TUI status output - cover remote Windows loading end to end by seeding the Wine prefix through host filesystem APIs - fix bug in `PathUri`'s parent() implementation that would erase Windows drive letters * [codex] Support marketplace plugin manifest fallback (#28789) ## Summary Support marketplace plugins whose source directory does not include a discoverable plugin manifest. Metadata-rich `marketplace.json` entries now act as fallback plugin manifests for listing, local detail reads, install, and non-curated cache refresh. The fallback preserves marketplace-entry plugin fields wholesale, then adds the small Codex-facing compatibility bridge for presentation metadata. A real source `plugin.json` always wins when present. ## Details - Capture flattened marketplace-entry fields into `MarketplacePluginManifestFallback`, preserving fields such as `version`, `description`, `skills`, `mcpServers`, `apps`, `hooks`, `agents`, `commands`, `strict`, `author`, and future manifest fields without a per-field translation list. - Bridge Claude-style top-level `displayName`, `author.name`, `homepage`, and marketplace `category` into Codex's nested `interface` fields only when the nested values are absent. - Treat fallback metadata as installable only when the marketplace entry contributes metadata beyond bare `name` and `source`; existing missing-manifest behavior remains for metadata-free entries. - Read local plugin details from the already parsed fallback manifest, including fallback-declared app and MCP paths, instead of rereading only an on-disk manifest. - Pass fallback contents into `PluginStore`, which validates them and injects `.codex-plugin/plugin.json` into Store's existing atomic copy. Local marketplace source directories are never mutated, and the fallback path no longer needs an additional staging directory. - Keep Git source materialization unchanged; Git clones still use the existing marketplace source staging area before Store installation. * [codex] Remove child AGENTS.md prompt experiment (#28993) ## Why `child_agents_md` is a disabled, under-development experiment that adds a second model-visible explanation of hierarchical `AGENTS.md` behavior. Keeping it leaves unused prompt, configuration, documentation, and test surface. ## What changed - remove the `ChildAgentsMd` feature and `child_agents_md` config schema entry - remove the hierarchical prompt asset, export, and instruction injection - remove feature-specific tests and documentation - keep the generic unstable-feature warning coverage using `apply_patch_streaming_events` Normal project `AGENTS.md` discovery and composition are unchanged. ## Testing - `just test -p codex-features` - `just test -p codex-prompts` - `just test -p codex-core agents_md` - `just test -p codex-core unstable_features_warning` * core: log AGENTS.md paths as URIs (#28989) ## Why No need to do path contortions when it's for our own logs. ## What Follow up on a previous PR's nit and update the path-types skill for future reference. * core: keep remote exec on reported shell (#28983) ## Why We need to avoid resolving shells on the app-server's host for remote environments. We might make it possible to do fancier shell resolution from remote envs but for now just require the model to produce a shell that matches the environment's default. This gets my e2e demo working for shell commands after #28854 moved shell resolution to PathUri and caused remote envs to hit the fallback shell when the shell wasn't available on the host. ## What Remote `exec_command` calls now accept only the environment's reported default shell name or exact path, and execute with that reported path. Other explicit shells return a concise error. A Wine-backed integration test covers explicit PowerShell execution in the Windows cwd. * [codex] Reuse parsed plugin skills during session startup (#28844) ## Summary - Preserve raw plugin skill-root snapshots in the matching loaded-plugin cache entry, keyed by the effective plugin root identity including namespace. - Pass those snapshots through `SkillsLoadInput` as an optional preload, so session startup reuses plugin parsing while ordinary skill loads pass `None`. - Keep plugin skill loading cohesive: the existing loaders accept the optional snapshots directly, and uncached or marketplace-detail paths do not create a cache. ## Why Plugin discovery already parses plugin skills to determine available capabilities. Cold session startup then scanned and parsed the same roots again while building the skills snapshot. This solves the same duplicate-work problem as #28623 while keeping ownership narrow: `PluginsManager` creates and owns `PluginSkillSnapshots` only for its loaded-plugin cache entry; `SkillsService` consumes an optional clone. Entry replacement or clearing naturally drops the snapshots, with no separate generation, capacity policy, or watcher coupling. ## Validation - `cargo clippy -p codex-core-skills --all-targets -- -D warnings` - `just test -p codex-core-plugins skills_service_reuses_skills_parsed_during_plugin_load` - `just test -p codex-core-skills namespaces_plugin_skills_using_provided_namespace` - `just fmt` * core: add UUIDv7 context window IDs (#28953) ## Why The token-budget context currently identifies a context window by its thread-local sequence number. A UUIDv7 gives the model a stable opaque identity that remains fixed for a window and rotates when compaction or `new_context` starts the next one. ## What changed - Preserve the existing monotonic value as `window_number` and add a UUIDv7 `window_id` to `CompactedItem`. - Generate and rotate the UUID with auto-compaction window state, persist it alongside the number, and reconstruct it on resume and rollback. - Accept legacy compacted rollout records where the numeric `window_id` represented the window number. - Use the UUID only in token-budget context; existing request headers and metadata continue using `thread_id:window_number`. ## Testing - `just test -p codex-protocol compacted_item::tests` - `just test -p codex-core token_budget` * [plugins] Refresh plugin and tool caches after remote install (#28951) Summary - Refresh the installed remote-plugin snapshot and Codex Apps tools after completing a remote JIT install. - Gate `completed: true` on every expected `app_connector_id` appearing after the uncached `tools/list` refresh, while continuing to skip local bundle verification for server-side installs. - Keep the cached recommendations response and filter refreshed installed remote IDs locally, so this does not add another recommendations fetch. - Add regression coverage for tools appearing after the hard refresh and remaining absent after the refresh. The resumed model request sees the refreshed tool router when installation completes. Root Cause - Remote suggestions from `openai-curated-remote` returned `true` before taking the existing connector refresh path, leaving the resumed turn with the pre-install Apps tool catalog. Validation - `just test -p codex-core request_plugin_install` - `just test -p codex-core-plugins recommended_plugin_candidates_filter_installed_and_disabled_plugins` - `just test -p codex-core-plugins` - `just fix -p codex-core-plugins` - `just fix -p codex-core` - `just fmt` - `just test -p codex-core` was not fully clean locally: 2,729 passed, 26 failed, and 16 skipped. The failures were dominated by local Seatbelt/network/timing issues, including plugin-install timeouts under full-suite contention; the focused plugin-install runs pass. * Always use AVAS for realtime WebRTC calls (#28856) ## Summary - Remove the realtime `architecture` selector from core protocol, app-server protocol, config parsing, generated schemas, and callers. - Always create WebRTC realtime calls with the AVAS query params: `intent=quicksilver&architecture=avas`. - Keep direct websocket realtime behavior on the existing config/default path, while WebRTC starts without an explicit version now default to realtime v1 because AVAS requires v1. ## Notes - WebRTC realtime now means AVAS. If a caller explicitly asks to start WebRTC with realtime v2, Codex rejects that request because the AVAS WebRTC path only supports realtime v1. Websocket realtime is separate and can still use realtime v2. - The old `[realtime] architecture = "realtimeapi" | "avas"` config knob is removed. Local configs that still set it will need to delete that line. - Some app-server tests that were only trying to exercise realtime v2 protocol behavior now use websocket transport, because WebRTC is intentionally locked to AVAS/v1. Separate WebRTC tests cover the AVAS query params, v1 startup, SDP flow, and sideband join. ## Validation - Merged fresh `origin/main` at `83e6a786a2`. - `just fmt` - `just write-config-schema` - `just write-app-server-schema` - `git diff --check` - `just test -p codex-api -p codex-core -p codex-app-server-protocol -p codex-app-server realtime` (176 passed) - `just test -p codex-protocol -p codex-config` (413 passed) * [codex] Assign response item IDs when recording history (#28814) ## Why Client-created response items enter history without IDs, so their identity is lost across rollout persistence and resume. IDs should be assigned once at the history-recording boundary, while IDs returned by the server must remain unchanged. The Responses API validates item IDs using type-specific prefixes. Locally generated IDs therefore use the matching prefix plus a hyphenated UUIDv7, keeping them valid while distinguishable from server-generated IDs. Because this changes persisted history and provider request shapes, the behavior is opt-in behind the under-development `item_ids` feature. Compaction triggers remain request controls whose API shape does not accept an ID. ## What changed - Register the disabled-by-default `item_ids` feature and expose it in `config.schema.json`. - Make supported optional `ResponseItem` IDs serializable and expose them in the generated app-server schemas. - When `item_ids` is enabled, assign an ID during conversation-history preparation if an item has no ID. - Generate type-prefixed, hyphenated UUIDv7 IDs using the Responses API item conventions. - Preserve existing server IDs without rewriting them. - Persist assigned IDs in rollouts and include them in subsequent Responses requests. - Remove the unsupported ID field from `CompactionTrigger` and document why it has no ID. - Add integration coverage for enabled ID persistence, preservation of server IDs, and omission of generated IDs while the feature is disabled. `prepare_conversation_items_for_history` is the single response-item ID allocation boundary. ## Test plan - `just test -p codex-features` - `just test -p codex-core response_item_ids_persist_across_resume_and_preserve_server_ids` - `just test -p codex-core non_openai_responses_requests_omit_item_turn_metadata` - `just test -p codex-core resize_all_images_prepares_failures_before_history_insertion` - `just test -p codex-protocol` - `just test -p codex-app-server-protocol` - `just test -p codex-api azure_default_store_attaches_ids_and_headers` * [codex] Skip curated repo sync for remote plugins (#29005) ## Summary - skip the legacy `openai-curated` startup repository sync when remote plugins are enabled and the current auth uses the Codex backend - keep the curated sync for API-key, Bedrock, and unauthenticated sessions that fall back to the local marketplace - preserve configured marketplace upgrades and all remote plugin startup warmups ## Why The remote catalog owns plugin discovery and materialization only when it is usable for the current auth mode. Starting the legacy curated repository sync in that case performs an unnecessary Git/HTTP/archive download and cache refresh. API-key and Bedrock sessions still require the local curated marketplace, so they must continue syncing it. ## User impact Codex startup no longer downloads or refreshes the local `openai-curated` snapshot when the remote catalog is active. Behavior is unchanged for auth modes that use the local curated marketplace. ## Validation - `just fmt` - `git diff --check` Rust tests were not run per the repository's local verification policy for this narrow conditional change. * [codex] add clock current-time tool (#29011) ## Summary - expose `clock.curr_time` when current-time reminders are enabled - query the session's configured time provider with the calling thread id - return the existing UTC reminder text for direct model calls - return `{ "current_time": "YYYY-MM-DD HH:MM:SS UTC" }` in Code Mode Clock lookup failures remain fatal, matching pre-inference reminder behavior. ## Testing - `just test -p codex-core current_time_tool_returns_the_latest_time` - `just test -p codex-core code_mode_current_time_returns_structured_result` - `just fix -p codex-core` * core: assign item IDs to compacted replacement history (#29012) ## Why Remote v2 compaction can return replacement-history items without IDs. Because replacement history is installed directly, those items bypass normal history preparation and remain ID-less in later Responses requests even when the `item_ids` feature is enabled. ## What changed - Pass the active `TurnContext` into `replace_compacted_history`. - When `item_ids` is enabled, assign missing IDs before installing and persisting replacement history. - Rebuild `CompactedItem` from the prepared history so live and persisted replacement histories match. - Add integration coverage requiring IDs on every ID-capable input item in the initial, remote v2 compaction, and post-compaction requests. ## Test plan - `just test -p codex-core response_item_ids` - `just test -p codex-core websocket_v2_test_codex_shell_chain` - `just test -p codex-core remote_compaction_parity_pre_turn_auto` - `just test -p codex-app-server thread_inject_items_adds_raw_response_items_to_thread_history` * [codex] Support protected resource OAuth discovery (#29022) ## Why Plugin-install preflight and the actual OAuth login flow used different discovery implementations. Preflight had a Codex-specific implementation that only queried authorization-server metadata on the MCP host, while login already used the upstream `rmcp` Rust MCP SDK. As a result, servers that advertise a separate authorization server through RFC 9728 Protected Resource Metadata were classified as OAuth-unsupported during plugin installation, so login was skipped. ## What changed - delegate plugin-install OAuth discovery to `rmcp::transport::AuthorizationManager`, the same implementation used by the login flow - let `rmcp` follow Protected Resource Metadata first and perform direct RFC 8414 authorization-server discovery when protected-resource discovery does not yield usable metadata - retain Codex's existing HTTP headers, timeout, `no_proxy` behavior, and scope normalization around that discovery - add unit coverage and a pure-MCP plugin-install integration test that proves the protected-resource path reaches OAuth client registration This only changes shared MCP OAuth discovery. App declarations and `appsNeedingAuth` behavior are unchanged. ## Verification - `just test -p codex-rmcp-client auth_status` - `just test -p codex-app-server plugin_install_starts_mcp_oauth` - real plugin-install smoke test with an isolated `CODEX_HOME`: both DigitalOcean MCP servers started OAuth callback listeners, while Linear continued to start its existing direct-discovery OAuth flow * [1/3] core: add remote environment connection lifecycle (#28674) ## Why Remote environments can be registered before their exec-server is first used. Starting the connection at registration time uses that startup window, while sharing one startup result prevents background work and capability calls from opening competing connections. Keep initial startup simple: each environment makes one connection attempt using its configured transport timeout. A failed initial attempt is final for that environment, while an environment that disconnects after connecting can still recover on a later operation. ## What changed - Start URL and Noise environments in the background when they are added to `EnvironmentManager`. Provider snapshots are fully validated before connection work begins. - Share one initial connection attempt and its saved result across metadata, process, filesystem, and HTTP callers. - Keep configured stdio environments lazy until first use so registration does not launch a process. - Tie background startup work to the environment lifetime so replacing or dropping an environment cancels unfinished work. - After an established client disconnects, share one fresh connection attempt across concurrent callers. A failed attempt fails the current operation without permanently preventing a later attempt. - Store the shared lazy client directly on `Environment` and expose small methods for starting, observing, and awaiting startup. ## Test plan - `just test -p codex-exec-server` - `just test -p codex-app-server turn_start_resolves_sticky_thread_local_environment_and_turn_overrides` * [2/3] core: track starting environments in snapshots (#28683) ## Why Remote environments may still be resolving when Codex creates a session or turn. Waiting for the existing all-or-nothing environment snapshot can hold startup until the selected environment is usable. Behind the default-off `deferred_executor` feature, let callers take a useful snapshot immediately: completed environments remain available normally, while unfinished environments are reported without blocking startup. With the feature disabled, snapshots preserve the existing blocking behavior. Depends on #28674. ## What changed - Store one ordered list of selected environments in `ThreadEnvironments`. Each selection owns one shared resolution that produces its complete `TurnEnvironment`. - Start new resolutions in the background with `remote_handle()`, allowing snapshots and the future wait tool to share the same result while cancellation follows the retained handles. - Make `snapshot()` a read-only operation: nonblocking snapshots collect completed resolutions and retain handles for unfinished ones, while blocking snapshots await every resolution. - Replace completed failed resolutions from the current manager entry and log when failed environments are omitted. - Return attached and starting environments as a point-in-time view, and count starting environments when deciding whether a snapshot is local-only. - Keep existing consumers attached-only. `to_selections()` derives from attached environments, so child threads do not inherit an environment that is still starting. ## Test plan - `just test -p codex-core environment_selection` - `just test -p codex-core deferred_executor_reaches_model_before_remote_environment_is_ready` ## Landing note Keep `deferred_executor` disabled for slow-starting executors until configurable `environment/add` connection timeouts and caller support land. When enabled, an environment that attaches after session startup may remain absent from environment-derived model context, tools, instructions, skills, and related state until follow-up refresh work lands. * [3/3] app-server: configure environment connection timeout (#29025) ## Why Remote environments registered through `environment/add` currently use the fixed 10-second WebSocket connection timeout. Slow-starting executors need a caller-selected connection window, but this should not add retry policy or couple exec-server behavior to Core’s `deferred_executor` feature. Make the timeout an optional part of the existing experimental request. Existing clients continue using the current default, while callers that know an executor may take longer can request a larger window explicitly. Depends on #28683. ## What changed - Add optional `connectTimeoutMs` to `EnvironmentAddParams` and document it in the app-server README. - Pass the optional timeout through `EnvironmentRequestProcessor` into one `EnvironmentManager::upsert_environment()` path; the manager applies the existing default when it is omitted. - Preserve the existing single-attempt lifecycle. The configured value controls WebSocket connection and handshake time for both initial connection and later reconnects; initialization retains its separate timeout. - Add an app-server integration test that sends the real JSON-RPC request and verifies a stalled handshake observes the requested timeout. ## Test plan - `just test -p codex-app-server-protocol` - `just test -p codex-exec-server` - `just test -p codex-app-server environment_add_applies_connect_timeout` ## Rollout This is additive and does not enable `deferred_executor`. Callers should send a non-default timeout only after a compatible app-server is deployed; omitted or `null` values retain the existing 10-second default. * Add per-turn multi-agent mode (#28685) ## Why Multi-agent v2 currently carries an explicit-request-only delegation rule in its static usage hint. That provides a safe default, but it prevents clients from selecting proactive delegation per turn without changing static guidance or rewriting prior model context. This change makes delegation mode a session selection that can be updated through `turn/start`, while deriving the effective model-visible mode separately for each turn. Eligible multi-agent v2 turns remain explicit-request-only unless proactive mode is both selected and enabled. ## What changed - Add the experimental `turn/start.multiAgentMode` parameter with `explicitRequestOnly` and `proactive` values. Omission retains the loaded session's current optional selection. - Add the default-off `features.multi_agent_mode` feature gate. Eligible multi-agent v2 turns use the selected mode when enabled; an unset selection or disabled gate resolves to `explicitRequestOnly`. - Treat mode prompting as inapplicable for multi-agent v1 and other unsupported session configurations, producing no multi-agent mode developer message rather than rejecting the turn. - Move the explicit-request-only rule out of the static v2 usage hint and into a bounded, tagged developer context fragment. - Emit the effective mode in initial context and only when that effective mode changes on later turns. - Persist the effective mode in `TurnContextItem` as the durable baseline for resume and context-update comparisons. Historical rollout items are not rewritten. Later mode developer messages establish the current rule incrementally. ## Not covered - Initial selection through `thread/start` and selected-mode reporting from thread lifecycle/settings APIs; those are isolated in the stacked #28792. - A TUI control or slash command for selecting the mode. - Persisting a preferred mode to `config.toml`; selection remains session/turn scoped. - Changes to multi-agent concurrency limits, tool availability, or model catalog capability declarations. - Rewriting historical rollout prompt items. Cold resume restores the latest persisted effective mode when available while leaving historical developer messages intact. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-core multi_agent_mode` - Focused app-server coverage verifies that `turn/start.multiAgentMode` produces proactive developer instructions for an eligible v2 turn. ## Stack Followed by #28792, which adds `thread/start` initialization and lifecycle/settings observability. * Expose thread-level multi-agent mode (#28792) ## Why Once multi-agent mode can be selected per turn, clients also need to choose the initial selection when creating a thread and observe that selection through lifecycle and settings APIs. The selected value is intentionally distinct from the effective model-visible value: no client selection is represented as `null`, even though an eligible multi-agent v2 turn derives `explicitRequestOnly` as its effective default. ## What changed - Add the optional experimental `thread/start.multiAgentMode` parameter and pass it through thread creation. - Preserve an omitted initial value as an unset selection rather than eagerly storing `explicitRequestOnly`. - Apply an explicit `thread/start` selection to the first turn through the session configuration established at thread creation. - Restore the latest persisted effective mode as the selected baseline on cold resume when rollout history contains one. - Inherit the optional selected mode from a loaded parent when creating related runtime threads. - Return the current selected `multiAgentMode` from `thread/start`, `thread/resume`, `thread/fork`, and thread settings, using `null` when no mode is selected. - Keep lifecycle reporting independent from model capability and feature eligibility; core turn construction remains responsible for calculating and persisting the effective mode. ## Not covered - Clearing an existing loaded-session selection back to unset through `turn/start`; omitted or `null` currently retains the session's selection. - A TUI control, slash command, or `config.toml` preference. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-app-server-protocol` - `CARGO_INCREMENTAL=0 just test -p codex-app-server multi_agent_mode` The focused app-server coverage verifies explicit `thread/start` initialization, first-turn prompting, nullable reporting for an omitted selection, and retention of selections that are not currently runtime-eligible. ## Stack Stacked on #28685. This PR contains only the thread initialization and lifecycle/settings API layer. * [codex] abort turns when rollout budgets expire (token budget 3/3) (#28707) ## Stack Depends on #28494. ## Description This PR propagates shared rollout-budget exhaustion through the existing `CodexErr::TurnAborted` task result. Each thread records its model usage against the same ledger. Once the ledger is exhausted, that…
- restore the v1 clarification that requests for depth, research, or investigation do not authorize subagent spawning - restore guidance for keeping critical-path, urgent, tightly coupled, or difficult work local - update the focused v1 tool-search and spawn-description coverage PR openai#27919 simplified the v1 `spawn_agent` prompt by removing its delegation decision guidance. That left the authorization rule intact, but removed the instructions that constrained what should be delegated after spawning was authorized. Restore those guardrails while preserving later support for explicit delegation authorization from applicable AGENTS.md and skill instructions. Multi-agent v2 prompts are unchanged. Models using the v1 multi-agent tool surface receive clearer guidance to delegate independent side work while keeping blocking work on the main rollout. - `just fmt` - `git diff --check` - tests not run locally per repository guidance; CI will validate the focused coverage
#275) * [codex] Add optional IDs to response items (#28812) ## Why `ResponseItem` variants do not have a consistent internal ID shape: some variants carry required IDs, some carry optional IDs, and some cannot represent an ID at all. The existing fields also use inconsistent serde, TypeScript, and JSON-schema annotations. A single enum-level access path is needed before history recording can assign and retain IDs. This PR establishes that internal model only. It intentionally does not generate or serialize IDs; allocation and wire persistence are isolated in the stacked follow-up. ## What changed - Give every concrete `ResponseItem` variant an `Option<String>` ID field. - Apply the same internal-only annotations to every ID field: `#[serde(default, skip_serializing)]`, `#[ts(skip)]`, and `#[schemars(skip)]`. - Add `ResponseItem::id()` and `ResponseItem::set_id()` as the shared accessors. - Preserve IDs when history items are rewritten for truncation. - Adapt consumers that previously assumed reasoning and image-generation IDs were required. - Regenerate app-server schemas so the hidden fields are represented consistently. The serde catch-all `ResponseItem::Other` remains ID-less because it must remain a unit variant. ## Test plan - `cargo check --tests -p codex-core -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-protocol` - `just test -p codex-app-server-protocol` - `just test -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-core event_mapping` * fix(install): support older awk checksum parsing (#28784) ## Why The standalone installer validates package checksums with an awk interval expression. Older mawk releases do not support that expression, so they reject valid 64-character digests and report that the release manifest is missing an entry. This affects both x64 and ARM64 systems on common Debian-derived environments. Fixes #24219. ## What Changed Replace the awk interval expression with an explicit length check plus rejection of non-hexadecimal characters. This preserves the existing SHA-256 validation and lowercase normalization while working with older awk implementations. ## How to Test 1. Build and run the checksum predicate with mawk 1.3.4 20121129. 2. Confirm the old interval predicate rejects a valid 64-character digest. 3. Confirm the updated predicate accepts that digest. 4. Put the old mawk binary first on PATH as awk and run scripts/install/install.sh with an isolated HOME, CODEX_HOME, and CODEX_INSTALL_DIR. 5. Confirm Codex installs successfully and the installed binary reports version 0.140.0. 6. Verify the predicate rejects wrong-length digests, non-hexadecimal digests, and entries for another asset while accepting uppercase hexadecimal digests. * [codex] Use unique IDs for realtime-routed turns (#28826) ## Why A durable realtime voice orchestrator can reconnect and resume through multiple fresh `Session` instances. Realtime handoffs were using the Session-local `auto-compact-N` counter as their turn identity, but that counter restarts at zero for every resumed Session. The durable thread could therefore accumulate duplicate turn IDs, violating the uniqueness assumptions made by app-server and web clients. In Codex Apps, a new delegated response stream could be attached to an older turn with the same ID, placing live output higher in history and putting turn-scoped actions at risk. Persisted rollout and reconstructed model-context order were already correct because raw response items remain append-only and chronological. This change restores unique identity for reconstructed and live turn surfaces. ## What changed - Generate a UUIDv7 specifically for each realtime-routed delegation. - Leave the existing `auto-compact-N` identity path unchanged for actual internal auto-compaction turns. - Extend the inbound realtime handoff integration test to require a UUID turn ID from `turn/started`. ## Verification - `just test -p codex-core inbound_handoff_request_starts_turn` - `just fix -p codex-core` - `just fmt` * [codex] control automatic realtime handoff delivery (#27986) ## What Built on the realtime speech-control plumbing merged in #27917. - Add optional `codexResponseHandoffPrefix` to `thread/realtime/start`. - Apply that prefix only to automatic V1 commentary sent through `conversation.handoff.append`; final answers remain unprefixed. - Add opt-in `clientManagedHandoffs`. When true, core suppresses automatic response handoffs and completion output so delivery is controlled by explicit client append APIs. - Preserve existing automatic behavior by default. `codexResponsesAsItems: true` continues to select item routing when client-managed mode is disabled. ## Why Voice clients need two delivery policies: automatic background context with silent commentary instructions and fully client-owned handoffs. Phase-aware prefixing keeps routine commentary silent without suppressing the final answer, while client-managed mode lets an app decide exactly which updates to append. ## Validation - `just fmt` - `cargo test -p codex-app-server-protocol serialize_thread_realtime_start` - `RUST_MIN_STACK=16777216 cargo test -p codex-core --test all conversation_handoff_persists_across_item_done_until_turn_complete` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_client_managed_handoffs_disable_automatic_output` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_final_automatic_handoff_omits_silent_prefix` - `cargo build -p codex-cli --bin codex` - Local Codex Apps compatibility check: 43 focused webview tests passed, and a live voice session routed through the source-built app-server. The explicit `RUST_MIN_STACK` avoids a macOS Tokio test-worker stack overflow seen with the default test environment. * [codex] Support assistant realtime append text (#28836) ## Why Frontend realtime voice continuity needs to replay a tiny previous-session overlap as actual conversation items, including assistant text. The app-server `thread/realtime/appendText` API already carries a role through to the Rust realtime websocket layer, but the shared role enum only accepted `user` and `developer`. ## What Changed - Added `assistant` to `ConversationTextRole` and regenerated the app-server schema/type fixtures. - Added `output_text` as a realtime conversation content type. - Updated realtime websocket item creation so assistant appendText emits `content: [{ type: "output_text", text }]`, while user and developer continue to emit `input_text`. - Updated app-server docs and tests to cover assistant appendText alongside the existing developer role behavior. ## Validation - `just write-app-server-schema` - `just fmt` (first sandboxed attempt failed because `uv` could not access `~/.cache/uv`; reran with filesystem access and passed) - `just test -p codex-api` passed: 126/126 - `just test -p codex-app-server-protocol` passed: 239/239, including generated JSON/TypeScript fixture checks - `just test -p codex-app-server` was started locally but stopped per request after unrelated local sandbox/Seatbelt failures (`sandbox-exec: sandbox_apply: Operation not permitted`) and one missing local `codex` binary failure; CI should be faster and more authoritative for the full suite. * Refresh signed exec-server URLs on reconnect (#28374) ## Summary - add a provider API that supplies a fresh signed WebSocket URL for each remote exec-server connection - refresh the signed URL after disconnects and retry once when a handshake returns `401 Unauthorized` - allow `EnvironmentManager` consumers to register remote environments backed by the URL provider ## Tests - `just test -p codex-exec-server -E 'test(remote_websocket_client_refreshes_url_after_unauthorized_handshake) | test(remote_websocket_client_refreshes_url_after_disconnect)'` — 2 passed - `cargo check -p codex-core-api` — passed - `just fix -p codex-exec-server` — passed - `just fix -p codex-core-api` — no test targets; no-op - `just fmt` — passed - `just test -p codex-exec-server` — 187 passed; 32 unrelated macOS sandbox tests could not invoke nested `sandbox-exec` (`Operation not permitted`) * Expose selecte namespaces as direct model tools (#28825) ## Why Som tools, such as history and notes, must remain top-level when MCP deferral is enabled while staying unavailable through code-mode `exec`. ## What changed - Added `features.code_mode.direct_only_tool_namespaces`. - Classified matching MCP tools as `DirectModelOnly`. - Kept those tools top-level in `code_mode_only`. - Excluded them from `tool_search` deferral and the nested `exec` surface. - Updated the generated config schema. ## Validation - `code_mode_only_exposes_direct_model_only_mcp_namespaces` - `load_config_resolves_code_mode_config` * [codex] Support plugin manifest path lists (#28790) ## Summary Allow plugin manifests to declare `skills` as either a single path string or an array of path strings in the core plugin loader. ## Why Some plugin packages need to expose skills from more than one directory. Before this change, `plugin.json` only accepted a single string for `skills`, so manifests like this were ignored as an invalid `skills` shape: ```json { "skills": ["./skills/abc", "./skills/edk"] } ``` This keeps the existing single-string form working while adding support for the list form. The final scope is intentionally limited to the core plugin manifest/load path for `skills`; `apps`, file-backed `mcpServers`, and the bundled plugin-creator assets are unchanged in this PR. ## What changed - Parse `skills` as either a string or an array of strings in `plugin.json`. - Store resolved skill paths as a list in `PluginManifestPaths`. - Load manifest-declared skill roots in addition to the default `./skills` root. - Deduplicate exact duplicate skill roots before loading. - Rely on existing skill-loader dedupe by canonical `SKILL.md` path for overlapping roots such as `./skills` plus `./skills/abc`. - Update plugin manifest tests to cover: - single string `skills` - list of string `skills` - duplicate skill roots - `./skills` as a manifest path - explicit child roots like `./skills/abc` and `./skills/edk` - overlapping-root dedupe ## Validation - `just test -p codex-plugin` - `just test -p codex-core-plugins` - `just test -p codex-mcp-extension` - `git diff --check` * Record more path migration guidance for codex. (#28851) Some common themes pulled out of both human and automated reviews from the last couple of days' migrations to `PathUri` and `LegacyAppPathString`. * unified-exec: retain PathUri in command events (#28780) ## Why App-server must report command events containing foreign-platform paths without changing existing client or rollout path-string formats. ## What changed - retain `PathUri` through exec command begin/end events - convert cwd values to `LegacyAppPathString` at the app-server compatibility boundary - drop command actions with foreign paths and log them - serialize rollout-trace cwd values using their inferred native path representation - restore Wine coverage for retained Windows cwd values and successful completion * [codex] Split plugin and skill warmup tracing (#28605) ## What changed - promote plugin config loading to an info-level `plugins_for_config` span - promote skill config loading to an info-level `skills_for_config` span - attach stable OpenTelemetry names to both spans ## Why `session_init.plugin_skill_warmup` currently combines plugin loading and skill loading, which makes cold-start traces unable to identify which phase dominates. These child spans preserve the existing aggregate while making the two costs independently visible. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact This is observability-only. It does not change plugin or skill loading behavior. ## Validation - `just test -p codex-core-skills -p codex-core-plugins` (347 passed) - `just fmt` * [codex] Pass plugin namespace into skill loading (#28608) ## What changed - retain the parsed plugin manifest namespace on loaded plugins - carry that namespace through `PluginSkillRoot` and `SkillRoot` - use the provided namespace when qualifying plugin skill names - include the namespace in the skills cache key ## Why Plugin loading has already parsed `plugin.json`, but skill parsing currently walks every `SKILL.md` ancestor and probes/reads the manifest again to reconstruct the same namespace. Passing the parsed namespace removes those repeated filesystem calls, which are particularly costly on remote filesystems. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact Plugin skill names remain unchanged. A regression test uses a deliberately different on-disk manifest name to verify that plugin roots use the provided parsed namespace. ## Validation - `just test -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` (352 passed) - `just fix -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` - `just fmt` * [codex] add rollout token budget configuration (varlength 1/N) (#28746) ## What This PR defines the structured configuration contract for shared rollout token budgets (across ALL agent threads under 1 rollout). ```toml [features.rollout_budget] enabled = true limit_tokens = 100000 reminder_interval_tokens = 10000 sampling_token_weight = 1.0 prefill_token_weight = 0.1 ``` The reminder interval defaults to 10% of the rollout limit. Sampling and prefill weights default to `1.0`. ## Scope This PR only defines and validates configuration. It does not track usage, inject reminders, or stop a rollout. Accounting and reminders are implemented in the stacked follow-up #28494. The existing `token_budget` feature remains unchanged. `rollout_budget` has its own feature key and configuration type. ## Tests The config test verifies that the structured fields resolve into `RolloutBudgetConfig` and do not enable the existing `token_budget` feature. Local checks: - `just write-config-schema` - `just test -p codex-core load_config_resolves_rollout_budget` - `cargo check -p codex-thread-manager-sample` - `git diff --check` The full workspace test suite was not run locally. * Add network environment ID plumbing (#28766) ## Why Prepare network approval scoping to distinguish execution environments without changing behavior yet. ## What changed - Add optional environment IDs to network policy requests. - Add optional network environment IDs to exec and sandbox request structs. - Thread default None values through existing construction points. - Fix stale constructor call sites that caused the CI compile failures. ## Not included - Per-environment proxy listeners. - Network approval cache or prompt behavior changes. - Ambiguous request attribution handling. Those behavior changes moved to stacked follow-up #28899. ## Validation - just fmt - CI will run tests and clippy * Avoid sandbox helper in apply_patch approval tests (#28915) ## Summary This keeps the apply_patch approval tests focused on approval behavior instead of macOS sandboxed filesystem helper startup. The changed cases still force patch approval with `UnlessTrusted`, but use `DangerFullAccess` after approval so the patch write is direct and cheap. Workspace-write and sandbox-helper behavior remain covered by the filesystem and apply_patch sandbox tests. * Pause active goals before TUI interrupts (#28813) Fixes #28104. ## Summary Active `/goal` turns should leave the persisted goal paused whenever the TUI interrupts the running turn. The bug in #28104 showed this most visibly through `Esc`: some interrupt paths aborted the turn without updating the goal status, so the goal could remain active and continue automatically. This change makes `ChatWidget` pause an active goal before the TUI sends an interrupt from the status-row path, the pending-steer path, `Ctrl+C`, or a request-user-input overlay. The modal overlay now reports whether a key will interrupt the turn, which keeps modal `Esc` and `Ctrl+C` behavior aligned with the normal interrupt paths. ## Manual Testing Built the local CLI with `just codex --help`, then launched the local TUI with goals enabled. Started an active `/goal` turn and interrupted it with `Esc`, then resumed and repeated with `Ctrl+C`; both paths showed `Goal paused`, the interrupted-conversation message, and the `Goal paused (/goal resume)` footer. I also stopped the background terminal and exited the TUI cleanly after the run. I did not find a reliable standalone manual path to force the request-user-input overlay case, so that path is covered by the focused automated test. * Recover exec process stdin writes (#28895) ## Summary Remote stdio MCP servers send tool calls by writing JSON-RPC bytes through `process/write`. When the exec-server websocket drops at the wrong time, the remote process can survive session recovery, but the stdin write can still fail back to RMCP as a transport send error. RMCP then closes the stdio MCP transport, so tools like `node_repl` are lost even though the process/session recovery path is working. This changes `process/write` to be safe to retry across exec-server recovery: - adds a required `writeId` to `process/write` - retries remote `Session::write` with the same `writeId` after reconnect - remembers accepted write ids per process so duplicate retries return `Accepted` without writing the same bytes to child stdin again - covers both the client retry path and server-side write id dedupe with tests In simple terms: ```text before: write to MCP stdin -> websocket closes -> write errors -> RMCP closes node_repl after: write to MCP stdin -> websocket closes -> reconnect -> retry same writeId server either writes once or recognizes it already did ``` * Pin Windows argument lint to Windows 2022 (#28940) ## What Run the Windows argument-comment-lint job on the `windows-2022` hosted runner instead of the custom Windows runner pool. ## Why The custom pool recently moved from the Visual Studio 2022 Windows image to `windows-2025-vs2026`. Since that migration, the job fails while Bazel materializes LLVM external repository sources, before the argument lint itself runs. The same failure appears across unrelated PRs. This narrow change tests GitHub’s recommended mitigation for workloads that still require the Visual Studio 2022 image: https://github.com/actions/runner-images/issues/14017 ## How Use the standard `windows-2022` runner for only the Windows argument-comment-lint matrix entry. No product code or lint behavior changes. * Scope MCP sandbox metadata to server environment (#28914) Scope MCP sandbox metadata to the MCP server's owning environment. Previously, `codex/sandbox-state-meta` always used the turn's primary cwd and rebuilt a legacy sandbox policy from that cwd. That can be wrong for MCP servers owned by a different execution environment. This now sends the owning environment cwd as a `file:` URI in `sandboxCwd`, keeps `permissionProfile` as the permission source of truth, and omits sandbox-state metadata when a non-default server environment is not selected for the turn. Local/default MCP servers keep the existing fallback cwd behavior. Tests: - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `just test -p codex-mcp` - `just test -p codex-core mcp_sandbox_cwd` - `cargo build -p codex-rmcp-client --bin test_stdio_server` - `just test -p codex-core stdio_mcp_tool_call_includes_sandbox_state_meta` * Add turn-scoped context contributions (#28911) ## Summary - keep context injection on a single ContextContributor trait - split context injection into thread-scoped and turn-scoped contribution methods - wire turn-scoped fragments into initial context assembly so extensions can contribute context from turn-local state * Fix goal-first live threads missing from thread/list (#28808) Fixes #28263. ## Why When a thread starts with `/goal`, the goal extension can update SQLite goal state before the thread has any user-turn rollout items. `thread/list` and `thread/search` rely on persisted listing metadata, so a goal-first live thread could be absent from app-server listings after restart even though the goal itself existed. This regressed when goal handling moved out of core: the core path wrote the goal update through the live thread rollout path, while the extension-backed app-server path only updated goal state and emitted the live notification. ## What - Add `GoalSetOutcome::thread_goal_updated_item()` so the goal extension owns the canonical `ThreadGoalUpdated` rollout item shape. - Expose a narrow `CodexThread::append_rollout_items()` helper that appends through the live thread and keeps derived SQLite metadata in sync. - When app-server sets a goal on an active live thread, persist the goal update through that live-thread path. - Add an app-server regression test that starts a live thread with `thread/goal/set` and verifies it appears in state-DB-only `thread/list`. ## Verification - `env -u CODEX_SQLITE_HOME just test -p codex-app-server goal_first_live_thread_appears_in_state_db_thread_list` * [codex] Initialize exec-server OpenTelemetry at startup (#25019) ## Summary - Initialize stderr tracing and the configured OpenTelemetry provider for local and remote `codex exec-server` startup. - Instrument the local and remote server entrypoints with a root runtime span. - Keep raw Noise environment, registration, and stream identifiers out of exported spans while preserving them in local debug events. - Keep telemetry setup in a focused CLI module instead of growing the top-level command entrypoint. ## Stack - Previous: none (`#27058` has merged) - Next: #27466 ## Validation - `just test -p codex-exec-server --lib` (139 passed) - `just test -p codex-cli --test exec_server` (3 passed) - `just bazel-lock-check` - `just fix -p codex-exec-server -p codex-cli` - `just fmt` --------- Co-authored-by: Richard Lee <richardlee@openai.com> * [codex] Fix Windows sandbox runtime ACL refresh (#28943) ## Why Codex Desktop repairs sandbox-user read/execute access for binaries copied to `%LOCALAPPDATA%\OpenAI\Codex\bin`, but Computer Use launches its bundled Node runtime from `%LOCALAPPDATA%\OpenAI\Codex\runtimes`. On fresh Windows installations, `CodexSandboxUsers` may therefore be unable to execute the bundled Node binary. The command runner starts, but `CreateProcessAsUserW` fails with error 5 (`ACCESS_DENIED`), causing the Node REPL to exit before Computer Use can discover applications. This is a follow-up to #21564, which added the original runtime `bin` ACL repair. ## What changed - Expand the Codex Desktop runtime ACL roots from only `bin` to both `bin` and `runtimes`. - Apply the existing inherited read/execute ACL repair to each runtime directory when it exists. - Rename the setup helper to reflect that it now handles multiple runtime paths. ## Validation - `cargo fmt -- --check` - `just test -p codex-windows-sandbox` was run: 113 tests passed and five environment-dependent legacy execution tests failed because `CreateRestrictedToken` returned error 87. * Synchronize realtime notification test requests (#28946) ## What Deliver the scripted realtime notification batch after the assistant text append request instead of after the preceding developer text append request. ## Why The batch ends with an upstream error that closes the realtime conversation. When it is emitted after the developer append, it races the subsequent assistant append: the app-server RPC can acknowledge the append before its downstream WebSocket send completes, and the test intermittently observes three requests instead of four. Making the fake server wait for the assistant append before emitting the terminal batch establishes the ordering the test asserts without sleeps or production-code changes. ## Validation - `git diff --check` - CI (the failure is timing-dependent and most reproducible in the Windows Bazel shard) * Add Config for Time Reminders (varlatency 1/n) (#28822) ## Summary Example: > [features.current_time_reminder] enabled = true reminder_interval_model_requests = 1 clock_source = "system" ## Testing - `just test -p codex-core varlatency` - `just test -p codex-core lock_contains_prompts_and_materializes_features` - `just fix -p codex-core -p codex-config -p codex-features` * [codex] rollout budget implementation (varlength 2/N) (#28494) ## Stack Depends on #28746. This PR implements shared rollout-budget accounting and model-visible reminders using the configuration defined in #28746. # Description / Main changes to Core: `AgentControl` will now be the area where "rollout level" features & accounting will have to live. It is incorrectly named for this responsibility, but I think it can hold all the necessary shared state & features (rollout token budget, mutliple thread interruption responsibilitym etc) In this PR, we have one "token ledger" that each thread will subtract from when sampling. The "charge" will occur when response.completed() is done and the calculation will be done on the responses api usage carrier. The calculation will weigh sampling and pre-fill tokens as specified. Every time the budget crosses the configured reminder threshold, a developer message is appended before the thread's next request This remaining budget will _always_ be restated/reminded after a compaction event. Expiration and fan-out interruption will be in the stacked follow-up (and also live in Agent Control). ## Reminders "You have weighted {session_tokens_left} tokens left in the shared session token budget." The first request in each thread context receives the current remainder. Later reminders are emitted after aggregate weighted usage crosses a configured interval. If several intervals are crossed before a thread sends another request, Core inserts one reminder with the latest remainder. Compaction response usage is charged before the next context starts. The next reminder is appended after the compaction summary, leaving the initial context content stable. ## Tests Integration coverage verifies: - weighted output and non-cached input accounting - initial and periodic reminders - shared accounting between a root and sub-agent - post-compaction remainder and message placement Local checks: - `just fmt` - `just test -p codex-core rollout_budget` - `git diff --check` The full workspace test suite was not run locally. * Support `openai/form` extended form elicitations (#27500) # Summary Allow App Server clients to opt into `openai/form` MCP elicitations. * [codex] Make thread store turn filter optional (#28949) Make `ListItemsParams::turn_id` optional so callers can list persisted items across an entire thread or narrow the result to one turn. This aligns the thread-store API and documentation with thread-wide item listing while preserving the optional turn-filter behavior for implementations. * current time reminders impl for system clock (varlatency 2/n) (#28824) Stacked on #28822. ## Summary - add a host-injectable current-time provider with a built-in system implementation - record UTC developer reminders in history immediately before due model requests - keep cadence state per session and force a refresh after compaction This does NOT include the app server client <-> server clock logic. This PR is only for the reminder message & system clock that will be used in prod. ## Testing - `just test -p codex-core varlatency_` - `just clippy -p codex-core -p codex-app-server -p codex-mcp-server -p codex-thread-manager-sample` - `just fmt` * [codex] Cache plugin metadata for tool suggestions (#27812) ## Why `built_tools` runs for every sampling request, and local plugin discovery was repeatedly rereading plugin manifests, skills, MCP configuration, and app declarations to build the same tool-suggest metadata. That source-derived metadata is stable until the existing plugin manager reloads its cache. Runtime eligibility still needs to reflect the current install, disable, policy, app-overlap, and authentication state. ## What changed - Add a bounded, in-memory tool-suggest metadata cache owned by `PluginsManager`. - Key cached metadata by plugin identity and source, while applying authentication routing each time the metadata is projected. - Invalidate the metadata alongside the existing loaded-plugin cache, including its normal configuration, marketplace refresh, and remote-installed-plugin invalidation paths. - Guard against an in-flight load repopulating stale metadata after invalidation. - Keep marketplace membership and all runtime eligibility filtering live rather than introducing a separate catalog or revision model. ## Impact Repeated sampling requests reuse already-loaded plugin capability metadata while retaining the existing plugin-manager lifecycle as the single freshness boundary. ## Validation - `just test -p codex-core-plugins` — 252 passed - Added focused coverage for cache invalidation and authentication reprojection. * apply-patch: carry paths as PathUri (#28854) ## Why Allows the model to edit files that are hosted on a different OS than where app-server is running. ## What * Use `PathUri` for apply_patch-internal data structures * Limit `PathUri` -> `AbsolutePathBuf` conversion to cases where the inferred path convention matches the host OS, allows requiring valid paths to pass to perms check * Adds `PathConvention::path_segments()` for iterating over path segments regardless of OS * Handle cross-platform relative paths in path filename parsing for sniffing a shell * Ensure we can apply patches in the wine e2e test * Add app-server current-time impl (varlatency 3/n) (#28835) ## What Server should request: ``` { "id": 42, "method": "currentTime/read", "params": { "threadId": "11111111-1111-1111-1111-aaaaafdc2c11" } } ``` Client should respond with something like: ```rust { "id": 42, "result": { "currentTimeAt": 1781717655 } } ``` ## Why Sessions configured with `clock_source = "external"` need a thread-specific external time source before inference. The system clock remains the default production provider. ## Validation - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server --test all current_time_read_round_trip_adds_reminder_to_model_input` - `cargo test -p codex-app-server first_attestation_capable_connection_for_thread_only_uses_thread_subscribers` - `cargo test -p codex-analytics` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` Stacked on #28824. * Make auto-review on-request prompt more proactive (#26496) ## Why `on-request` approval policy text is currently tuned for user-reviewed approvals. For auto-reviewed productivity runs, likely sandbox blocks should be escalated earlier so commands that need remote services, authentication, or other out-of-sandbox access do not first fail or hang inside the sandbox. ## What changed - Adds a separate `on_request_auto_review.md` permissions prompt selected for `AskForApproval::OnRequest` with `ApprovalsReviewer::AutoReview`. - Keeps the normal user-reviewed `on-request` wording unchanged. - Makes the `When to request escalation` bullets more explicit about likely sandbox blocks, network access, remote auth/cluster/cloud/database access, out-of-sandbox environment access, git operations that may write lock files, and short-timeout reruns after likely sandbox-blocked attempts. - Omits approved command prefix and `prefix_rule` guidance for the auto-review on-request prompt. - Adds prompt tests covering the auto-review path, normal on-request wording, and inline permission request behavior. * [codex] Remove hardcoded app ID filters (#28947) ## Summary - remove the duplicated originator-specific connector ID denylists - stop filtering connector directory/accessibility results and live/cached Codex Apps MCP tools by hardcoded connector ID - remove the now-unused `codex-login` dependency from `codex-utils-plugins` - update regression coverage so formerly blocked connector IDs are preserved ## Why The client-side policy was duplicated across crates, used opaque IDs without ownership or expiry information, and could drift between app listing and MCP tool behavior. Server-provided visibility, authorization, plugin discoverability, accessibility, enabled-state handling, and consequential-tool approval templates remain unchanged. ## Validation - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `git diff --check` - confirmed the final diff contains no hardcoded denylist symbols A targeted `codex-mcp` test build spent an unusually long time in local compilation/linking. Its first attempt exposed a test-only `PartialEq` assertion issue, which was corrected. A follow-up non-linking `cargo check -p codex-mcp --tests` was still running when this draft was opened; CI should provide the complete Rust validation. * TUI: improve unified mention selection visibility (#28959) ## Summary [@milanglacier reported in #28653](https://github.com/openai/codex/issues/28653) that the active mention candidate is hard to distinguish. I suspect [@binbjz’s #28500 report](https://github.com/openai/codex/issues/28500) _(where arrow-key navigation appeared not to work)_ may describe the same presentation problem: the selection may have been changing, but the UI was not showing the active row clearly in their terminal. This PR makes two small changes to the selection indication behavior: - Reserve a two-character gutter and mark the active candidate with `> ` for color-agnostic indicator coverage. - Apply the shared theme-aware accent to the entire selected row for extra emphasis. - Update the existing popup snapshot. Reverse-video styling was considered, but avoided it because it is overly dependent on the user’s terminal palette. <img width="2046" height="482" alt="image" src="https://github.com/user-attachments/assets/b5eb62c3-fd24-4c09-906e-7bd66913b5c6" /> ## Testing - `just test -p codex-tui default_unified_mention_popup_snapshot` - `just clippy -p codex-tui` - `just fmt` - Compiled `codex-cli` and tested the unified mentions picker in the terminal. * Emit Trusted MCP App Identity on Tool-Call Items (#27132) ## Summary - Add optional `appContext` to app-server MCP tool-call items with trusted `connectorId`, `linkId`, and `mcpAppResourceUri` metadata. - Preserve that context across tool-call events, persisted history, reconnects, and thread resume. - Keep the deprecated top-level `mcpAppResourceUri` temporarily for client migration. The consumer contract is `{ appContext: { connectorId, linkId, mcpAppResourceUri }, tool }`. ## Validation - Full GitHub Actions suite passes, including CLA, Bazel tests, clippy, release builds, and argument-comment lint. --------- Co-authored-by: martinauyeung-oai <280153141+martinauyeung-oai@users.noreply.github.com> * feat: opt ChatGPT auth into agent identity (#19049) ## Stack This is PR 2 of the simplified HAI single-run-task stack: - [#19047](https://github.com/openai/codex/pull/19047) Agent Identity assertion and task-registration primitives, including the shared run-task helper used by existing Agent Identity JWT auth. - [#19049](https://github.com/openai/codex/pull/19049) Disabled-by-default ChatGPT auth opt-in that provisions/reuses persisted Agent Identity runtime auth and its single run task. - [#19051](https://github.com/openai/codex/pull/19051) Run-scoped provider auth that uses one backend-owned task id for first-party inference and compaction requests. [#19054](https://github.com/openai/codex/pull/19054) collapsed out of the active stack because the simplified design no longer needs a separate background/control-plane task helper. ## Summary This PR adds the disabled-by-default path for normal ChatGPT-login Codex sessions to obtain Agent Identity runtime auth through the Codex backend. Existing Agent Identity JWT startup mode remains a separate path and does not require the feature flag. What changed: - adds the experimental `use_agent_identity` feature flag and config schema entry - adds an explicit `AgentIdentityAuthPolicy` so call sites choose `JwtOnly` or `ChatGptAuth` instead of passing a bare boolean - stores standalone Agent Identity JWT credentials separately from backend-registered Agent Identity records - persists the registered Agent Identity record, private key, and single run task id in `auth.json` so process restarts reuse the same identity - derives the agent/task registration base URL from ChatGPT/Codex auth config while keeping JWT JWKS lookup separate - provisions and caches ChatGPT-derived Agent Identity runtime auth when `use_agent_identity` is enabled - reuses the shared run-task registration helper from PR1 rather than adding a second task-registration path This PR intentionally does not switch model inference over to `AgentAssertion` auth. The provider-auth integration lands in the next PR. ## Testing - `just test -p codex-login` * [connectors] Ignore synthetic links for app accessibility (#28770) Summary - Stop treating Codex Apps MCP tools with `_meta._codex_apps.synthetic_link: true` as evidence that a connector is accessible in `app/list`. - Preserve synthetic tools in the agent-facing MCP connector set so they remain available for install/auth flows. - Keep the app-list accessibility cache limited to connectors backed by at least one non-synthetic tool. - Add focused regression coverage for both sides of the boundary. Validation - `just fmt` - `just test -p codex-core synthetic_links_are_exposed_to_the_agent_but_not_accessible_in_app_list` - `git diff --check` - A crate-wide `just test -p codex-core` run completed with 2,699 passing and 51 unrelated local sandbox/state failures, primarily state DB migration races (`UNIQUE constraint failed: _sqlx_migrations.version`). * [codex] Preserve remote plugin download status errors (#28863) ## Summary - preserve the original HTTP status when a remote plugin bundle download returns a non-success response - retain at most 8 KiB of the error response body and annotate truncation or body-read failures - add regression coverage for an oversized error response ## Root cause The non-success response path reused the normal size-limited body reader. When an error response exceeded 8 KiB, that reader returned `DownloadTooLarge` before the code constructed `DownloadStatus`, masking the upstream HTTP status and response context. ## Impact Remote plugin installation failures now retain the actionable upstream HTTP status without allowing unbounded error bodies into logs. ## Validation - `just test -p codex-app-server plugin_install_preserves_status_when_remote_bundle_error_body_is_too_large` - `just fmt` - `git diff --check` * core: load AGENTS.md from foreign environments (#28958) ## Why Make it possible to load AGENTS.md from remote exec-servers whose OS is different than app-server. ## What - keep `AGENTS.md` discovery and provenance as `PathUri`, with root-aware parent and ancestor traversal - expose lifecycle instruction sources as legacy app-server path strings in events while retaining `PathUri` internally - preserve and test mixed POSIX and Windows paths in model context and TUI status output - cover remote Windows loading end to end by seeding the Wine prefix through host filesystem APIs - fix bug in `PathUri`'s parent() implementation that would erase Windows drive letters * [codex] Support marketplace plugin manifest fallback (#28789) ## Summary Support marketplace plugins whose source directory does not include a discoverable plugin manifest. Metadata-rich `marketplace.json` entries now act as fallback plugin manifests for listing, local detail reads, install, and non-curated cache refresh. The fallback preserves marketplace-entry plugin fields wholesale, then adds the small Codex-facing compatibility bridge for presentation metadata. A real source `plugin.json` always wins when present. ## Details - Capture flattened marketplace-entry fields into `MarketplacePluginManifestFallback`, preserving fields such as `version`, `description`, `skills`, `mcpServers`, `apps`, `hooks`, `agents`, `commands`, `strict`, `author`, and future manifest fields without a per-field translation list. - Bridge Claude-style top-level `displayName`, `author.name`, `homepage`, and marketplace `category` into Codex's nested `interface` fields only when the nested values are absent. - Treat fallback metadata as installable only when the marketplace entry contributes metadata beyond bare `name` and `source`; existing missing-manifest behavior remains for metadata-free entries. - Read local plugin details from the already parsed fallback manifest, including fallback-declared app and MCP paths, instead of rereading only an on-disk manifest. - Pass fallback contents into `PluginStore`, which validates them and injects `.codex-plugin/plugin.json` into Store's existing atomic copy. Local marketplace source directories are never mutated, and the fallback path no longer needs an additional staging directory. - Keep Git source materialization unchanged; Git clones still use the existing marketplace source staging area before Store installation. * [codex] Remove child AGENTS.md prompt experiment (#28993) ## Why `child_agents_md` is a disabled, under-development experiment that adds a second model-visible explanation of hierarchical `AGENTS.md` behavior. Keeping it leaves unused prompt, configuration, documentation, and test surface. ## What changed - remove the `ChildAgentsMd` feature and `child_agents_md` config schema entry - remove the hierarchical prompt asset, export, and instruction injection - remove feature-specific tests and documentation - keep the generic unstable-feature warning coverage using `apply_patch_streaming_events` Normal project `AGENTS.md` discovery and composition are unchanged. ## Testing - `just test -p codex-features` - `just test -p codex-prompts` - `just test -p codex-core agents_md` - `just test -p codex-core unstable_features_warning` * core: log AGENTS.md paths as URIs (#28989) ## Why No need to do path contortions when it's for our own logs. ## What Follow up on a previous PR's nit and update the path-types skill for future reference. * core: keep remote exec on reported shell (#28983) ## Why We need to avoid resolving shells on the app-server's host for remote environments. We might make it possible to do fancier shell resolution from remote envs but for now just require the model to produce a shell that matches the environment's default. This gets my e2e demo working for shell commands after #28854 moved shell resolution to PathUri and caused remote envs to hit the fallback shell when the shell wasn't available on the host. ## What Remote `exec_command` calls now accept only the environment's reported default shell name or exact path, and execute with that reported path. Other explicit shells return a concise error. A Wine-backed integration test covers explicit PowerShell execution in the Windows cwd. * [codex] Reuse parsed plugin skills during session startup (#28844) ## Summary - Preserve raw plugin skill-root snapshots in the matching loaded-plugin cache entry, keyed by the effective plugin root identity including namespace. - Pass those snapshots through `SkillsLoadInput` as an optional preload, so session startup reuses plugin parsing while ordinary skill loads pass `None`. - Keep plugin skill loading cohesive: the existing loaders accept the optional snapshots directly, and uncached or marketplace-detail paths do not create a cache. ## Why Plugin discovery already parses plugin skills to determine available capabilities. Cold session startup then scanned and parsed the same roots again while building the skills snapshot. This solves the same duplicate-work problem as #28623 while keeping ownership narrow: `PluginsManager` creates and owns `PluginSkillSnapshots` only for its loaded-plugin cache entry; `SkillsService` consumes an optional clone. Entry replacement or clearing naturally drops the snapshots, with no separate generation, capacity policy, or watcher coupling. ## Validation - `cargo clippy -p codex-core-skills --all-targets -- -D warnings` - `just test -p codex-core-plugins skills_service_reuses_skills_parsed_during_plugin_load` - `just test -p codex-core-skills namespaces_plugin_skills_using_provided_namespace` - `just fmt` * core: add UUIDv7 context window IDs (#28953) ## Why The token-budget context currently identifies a context window by its thread-local sequence number. A UUIDv7 gives the model a stable opaque identity that remains fixed for a window and rotates when compaction or `new_context` starts the next one. ## What changed - Preserve the existing monotonic value as `window_number` and add a UUIDv7 `window_id` to `CompactedItem`. - Generate and rotate the UUID with auto-compaction window state, persist it alongside the number, and reconstruct it on resume and rollback. - Accept legacy compacted rollout records where the numeric `window_id` represented the window number. - Use the UUID only in token-budget context; existing request headers and metadata continue using `thread_id:window_number`. ## Testing - `just test -p codex-protocol compacted_item::tests` - `just test -p codex-core token_budget` * [plugins] Refresh plugin and tool caches after remote install (#28951) Summary - Refresh the installed remote-plugin snapshot and Codex Apps tools after completing a remote JIT install. - Gate `completed: true` on every expected `app_connector_id` appearing after the uncached `tools/list` refresh, while continuing to skip local bundle verification for server-side installs. - Keep the cached recommendations response and filter refreshed installed remote IDs locally, so this does not add another recommendations fetch. - Add regression coverage for tools appearing after the hard refresh and remaining absent after the refresh. The resumed model request sees the refreshed tool router when installation completes. Root Cause - Remote suggestions from `openai-curated-remote` returned `true` before taking the existing connector refresh path, leaving the resumed turn with the pre-install Apps tool catalog. Validation - `just test -p codex-core request_plugin_install` - `just test -p codex-core-plugins recommended_plugin_candidates_filter_installed_and_disabled_plugins` - `just test -p codex-core-plugins` - `just fix -p codex-core-plugins` - `just fix -p codex-core` - `just fmt` - `just test -p codex-core` was not fully clean locally: 2,729 passed, 26 failed, and 16 skipped. The failures were dominated by local Seatbelt/network/timing issues, including plugin-install timeouts under full-suite contention; the focused plugin-install runs pass. * Always use AVAS for realtime WebRTC calls (#28856) ## Summary - Remove the realtime `architecture` selector from core protocol, app-server protocol, config parsing, generated schemas, and callers. - Always create WebRTC realtime calls with the AVAS query params: `intent=quicksilver&architecture=avas`. - Keep direct websocket realtime behavior on the existing config/default path, while WebRTC starts without an explicit version now default to realtime v1 because AVAS requires v1. ## Notes - WebRTC realtime now means AVAS. If a caller explicitly asks to start WebRTC with realtime v2, Codex rejects that request because the AVAS WebRTC path only supports realtime v1. Websocket realtime is separate and can still use realtime v2. - The old `[realtime] architecture = "realtimeapi" | "avas"` config knob is removed. Local configs that still set it will need to delete that line. - Some app-server tests that were only trying to exercise realtime v2 protocol behavior now use websocket transport, because WebRTC is intentionally locked to AVAS/v1. Separate WebRTC tests cover the AVAS query params, v1 startup, SDP flow, and sideband join. ## Validation - Merged fresh `origin/main` at `83e6a786a2`. - `just fmt` - `just write-config-schema` - `just write-app-server-schema` - `git diff --check` - `just test -p codex-api -p codex-core -p codex-app-server-protocol -p codex-app-server realtime` (176 passed) - `just test -p codex-protocol -p codex-config` (413 passed) * [codex] Assign response item IDs when recording history (#28814) ## Why Client-created response items enter history without IDs, so their identity is lost across rollout persistence and resume. IDs should be assigned once at the history-recording boundary, while IDs returned by the server must remain unchanged. The Responses API validates item IDs using type-specific prefixes. Locally generated IDs therefore use the matching prefix plus a hyphenated UUIDv7, keeping them valid while distinguishable from server-generated IDs. Because this changes persisted history and provider request shapes, the behavior is opt-in behind the under-development `item_ids` feature. Compaction triggers remain request controls whose API shape does not accept an ID. ## What changed - Register the disabled-by-default `item_ids` feature and expose it in `config.schema.json`. - Make supported optional `ResponseItem` IDs serializable and expose them in the generated app-server schemas. - When `item_ids` is enabled, assign an ID during conversation-history preparation if an item has no ID. - Generate type-prefixed, hyphenated UUIDv7 IDs using the Responses API item conventions. - Preserve existing server IDs without rewriting them. - Persist assigned IDs in rollouts and include them in subsequent Responses requests. - Remove the unsupported ID field from `CompactionTrigger` and document why it has no ID. - Add integration coverage for enabled ID persistence, preservation of server IDs, and omission of generated IDs while the feature is disabled. `prepare_conversation_items_for_history` is the single response-item ID allocation boundary. ## Test plan - `just test -p codex-features` - `just test -p codex-core response_item_ids_persist_across_resume_and_preserve_server_ids` - `just test -p codex-core non_openai_responses_requests_omit_item_turn_metadata` - `just test -p codex-core resize_all_images_prepares_failures_before_history_insertion` - `just test -p codex-protocol` - `just test -p codex-app-server-protocol` - `just test -p codex-api azure_default_store_attaches_ids_and_headers` * [codex] Skip curated repo sync for remote plugins (#29005) ## Summary - skip the legacy `openai-curated` startup repository sync when remote plugins are enabled and the current auth uses the Codex backend - keep the curated sync for API-key, Bedrock, and unauthenticated sessions that fall back to the local marketplace - preserve configured marketplace upgrades and all remote plugin startup warmups ## Why The remote catalog owns plugin discovery and materialization only when it is usable for the current auth mode. Starting the legacy curated repository sync in that case performs an unnecessary Git/HTTP/archive download and cache refresh. API-key and Bedrock sessions still require the local curated marketplace, so they must continue syncing it. ## User impact Codex startup no longer downloads or refreshes the local `openai-curated` snapshot when the remote catalog is active. Behavior is unchanged for auth modes that use the local curated marketplace. ## Validation - `just fmt` - `git diff --check` Rust tests were not run per the repository's local verification policy for this narrow conditional change. * [codex] add clock current-time tool (#29011) ## Summary - expose `clock.curr_time` when current-time reminders are enabled - query the session's configured time provider with the calling thread id - return the existing UTC reminder text for direct model calls - return `{ "current_time": "YYYY-MM-DD HH:MM:SS UTC" }` in Code Mode Clock lookup failures remain fatal, matching pre-inference reminder behavior. ## Testing - `just test -p codex-core current_time_tool_returns_the_latest_time` - `just test -p codex-core code_mode_current_time_returns_structured_result` - `just fix -p codex-core` * core: assign item IDs to compacted replacement history (#29012) ## Why Remote v2 compaction can return replacement-history items without IDs. Because replacement history is installed directly, those items bypass normal history preparation and remain ID-less in later Responses requests even when the `item_ids` feature is enabled. ## What changed - Pass the active `TurnContext` into `replace_compacted_history`. - When `item_ids` is enabled, assign missing IDs before installing and persisting replacement history. - Rebuild `CompactedItem` from the prepared history so live and persisted replacement histories match. - Add integration coverage requiring IDs on every ID-capable input item in the initial, remote v2 compaction, and post-compaction requests. ## Test plan - `just test -p codex-core response_item_ids` - `just test -p codex-core websocket_v2_test_codex_shell_chain` - `just test -p codex-core remote_compaction_parity_pre_turn_auto` - `just test -p codex-app-server thread_inject_items_adds_raw_response_items_to_thread_history` * [codex] Support protected resource OAuth discovery (#29022) ## Why Plugin-install preflight and the actual OAuth login flow used different discovery implementations. Preflight had a Codex-specific implementation that only queried authorization-server metadata on the MCP host, while login already used the upstream `rmcp` Rust MCP SDK. As a result, servers that advertise a separate authorization server through RFC 9728 Protected Resource Metadata were classified as OAuth-unsupported during plugin installation, so login was skipped. ## What changed - delegate plugin-install OAuth discovery to `rmcp::transport::AuthorizationManager`, the same implementation used by the login flow - let `rmcp` follow Protected Resource Metadata first and perform direct RFC 8414 authorization-server discovery when protected-resource discovery does not yield usable metadata - retain Codex's existing HTTP headers, timeout, `no_proxy` behavior, and scope normalization around that discovery - add unit coverage and a pure-MCP plugin-install integration test that proves the protected-resource path reaches OAuth client registration This only changes shared MCP OAuth discovery. App declarations and `appsNeedingAuth` behavior are unchanged. ## Verification - `just test -p codex-rmcp-client auth_status` - `just test -p codex-app-server plugin_install_starts_mcp_oauth` - real plugin-install smoke test with an isolated `CODEX_HOME`: both DigitalOcean MCP servers started OAuth callback listeners, while Linear continued to start its existing direct-discovery OAuth flow * [1/3] core: add remote environment connection lifecycle (#28674) ## Why Remote environments can be registered before their exec-server is first used. Starting the connection at registration time uses that startup window, while sharing one startup result prevents background work and capability calls from opening competing connections. Keep initial startup simple: each environment makes one connection attempt using its configured transport timeout. A failed initial attempt is final for that environment, while an environment that disconnects after connecting can still recover on a later operation. ## What changed - Start URL and Noise environments in the background when they are added to `EnvironmentManager`. Provider snapshots are fully validated before connection work begins. - Share one initial connection attempt and its saved result across metadata, process, filesystem, and HTTP callers. - Keep configured stdio environments lazy until first use so registration does not launch a process. - Tie background startup work to the environment lifetime so replacing or dropping an environment cancels unfinished work. - After an established client disconnects, share one fresh connection attempt across concurrent callers. A failed attempt fails the current operation without permanently preventing a later attempt. - Store the shared lazy client directly on `Environment` and expose small methods for starting, observing, and awaiting startup. ## Test plan - `just test -p codex-exec-server` - `just test -p codex-app-server turn_start_resolves_sticky_thread_local_environment_and_turn_overrides` * [2/3] core: track starting environments in snapshots (#28683) ## Why Remote environments may still be resolving when Codex creates a session or turn. Waiting for the existing all-or-nothing environment snapshot can hold startup until the selected environment is usable. Behind the default-off `deferred_executor` feature, let callers take a useful snapshot immediately: completed environments remain available normally, while unfinished environments are reported without blocking startup. With the feature disabled, snapshots preserve the existing blocking behavior. Depends on #28674. ## What changed - Store one ordered list of selected environments in `ThreadEnvironments`. Each selection owns one shared resolution that produces its complete `TurnEnvironment`. - Start new resolutions in the background with `remote_handle()`, allowing snapshots and the future wait tool to share the same result while cancellation follows the retained handles. - Make `snapshot()` a read-only operation: nonblocking snapshots collect completed resolutions and retain handles for unfinished ones, while blocking snapshots await every resolution. - Replace completed failed resolutions from the current manager entry and log when failed environments are omitted. - Return attached and starting environments as a point-in-time view, and count starting environments when deciding whether a snapshot is local-only. - Keep existing consumers attached-only. `to_selections()` derives from attached environments, so child threads do not inherit an environment that is still starting. ## Test plan - `just test -p codex-core environment_selection` - `just test -p codex-core deferred_executor_reaches_model_before_remote_environment_is_ready` ## Landing note Keep `deferred_executor` disabled for slow-starting executors until configurable `environment/add` connection timeouts and caller support land. When enabled, an environment that attaches after session startup may remain absent from environment-derived model context, tools, instructions, skills, and related state until follow-up refresh work lands. * [3/3] app-server: configure environment connection timeout (#29025) ## Why Remote environments registered through `environment/add` currently use the fixed 10-second WebSocket connection timeout. Slow-starting executors need a caller-selected connection window, but this should not add retry policy or couple exec-server behavior to Core’s `deferred_executor` feature. Make the timeout an optional part of the existing experimental request. Existing clients continue using the current default, while callers that know an executor may take longer can request a larger window explicitly. Depends on #28683. ## What changed - Add optional `connectTimeoutMs` to `EnvironmentAddParams` and document it in the app-server README. - Pass the optional timeout through `EnvironmentRequestProcessor` into one `EnvironmentManager::upsert_environment()` path; the manager applies the existing default when it is omitted. - Preserve the existing single-attempt lifecycle. The configured value controls WebSocket connection and handshake time for both initial connection and later reconnects; initialization retains its separate timeout. - Add an app-server integration test that sends the real JSON-RPC request and verifies a stalled handshake observes the requested timeout. ## Test plan - `just test -p codex-app-server-protocol` - `just test -p codex-exec-server` - `just test -p codex-app-server environment_add_applies_connect_timeout` ## Rollout This is additive and does not enable `deferred_executor`. Callers should send a non-default timeout only after a compatible app-server is deployed; omitted or `null` values retain the existing 10-second default. * Add per-turn multi-agent mode (#28685) ## Why Multi-agent v2 currently carries an explicit-request-only delegation rule in its static usage hint. That provides a safe default, but it prevents clients from selecting proactive delegation per turn without changing static guidance or rewriting prior model context. This change makes delegation mode a session selection that can be updated through `turn/start`, while deriving the effective model-visible mode separately for each turn. Eligible multi-agent v2 turns remain explicit-request-only unless proactive mode is both selected and enabled. ## What changed - Add the experimental `turn/start.multiAgentMode` parameter with `explicitRequestOnly` and `proactive` values. Omission retains the loaded session's current optional selection. - Add the default-off `features.multi_agent_mode` feature gate. Eligible multi-agent v2 turns use the selected mode when enabled; an unset selection or disabled gate resolves to `explicitRequestOnly`. - Treat mode prompting as inapplicable for multi-agent v1 and other unsupported session configurations, producing no multi-agent mode developer message rather than rejecting the turn. - Move the explicit-request-only rule out of the static v2 usage hint and into a bounded, tagged developer context fragment. - Emit the effective mode in initial context and only when that effective mode changes on later turns. - Persist the effective mode in `TurnContextItem` as the durable baseline for resume and context-update comparisons. Historical rollout items are not rewritten. Later mode developer messages establish the current rule incrementally. ## Not covered - Initial selection through `thread/start` and selected-mode reporting from thread lifecycle/settings APIs; those are isolated in the stacked #28792. - A TUI control or slash command for selecting the mode. - Persisting a preferred mode to `config.toml`; selection remains session/turn scoped. - Changes to multi-agent concurrency limits, tool availability, or model catalog capability declarations. - Rewriting historical rollout prompt items. Cold resume restores the latest persisted effective mode when available while leaving historical developer messages intact. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-core multi_agent_mode` - Focused app-server coverage verifies that `turn/start.multiAgentMode` produces proactive developer instructions for an eligible v2 turn. ## Stack Followed by #28792, which adds `thread/start` initialization and lifecycle/settings observability. * Expose thread-level multi-agent mode (#28792) ## Why Once multi-agent mode can be selected per turn, clients also need to choose the initial selection when creating a thread and observe that selection through lifecycle and settings APIs. The selected value is intentionally distinct from the effective model-visible value: no client selection is represented as `null`, even though an eligible multi-agent v2 turn derives `explicitRequestOnly` as its effective default. ## What changed - Add the optional experimental `thread/start.multiAgentMode` parameter and pass it through thread creation. - Preserve an omitted initial value as an unset selection rather than eagerly storing `explicitRequestOnly`. - Apply an explicit `thread/start` selection to the first turn through the session configuration established at thread creation. - Restore the latest persisted effective mode as the selected baseline on cold resume when rollout history contains one. - Inherit the optional selected mode from a loaded parent when creating related runtime threads. - Return the current selected `multiAgentMode` from `thread/start`, `thread/resume`, `thread/fork`, and thread settings, using `null` when no mode is selected. - Keep lifecycle reporting independent from model capability and feature eligibility; core turn construction remains responsible for calculating and persisting the effective mode. ## Not covered - Clearing an existing loaded-session selection back to unset through `turn/start`; omitted or `null` currently retains the session's selection. - A TUI control, slash command, or `config.toml` preference. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-app-server-protocol` - `CARGO_INCREMENTAL=0 just test -p codex-app-server multi_agent_mode` The focused app-server coverage verifies explicit `thread/start` initialization, first-turn prompting, nullable reporting for an omitted selection, and retention of selections that are not currently runtime-eligible. ## Stack Stacked on #28685. This PR contains only the thread initialization and lifecycle/settings API layer. * [codex] abort turns when rollout budgets expire (token budget 3/3) (#28707) ## Stack Depends on #28494. ## Description This PR propagates shared rollout-budget exhaustion through the existing `CodexErr::TurnAborted` task result. Each thread records its model usage against the same ledger. Once the ledger is exhausted, that…
Termux rust-v0.143.0-alpha.31
…nt/wallentx_termux-target_from_release_0.143.0_e22a850a6a26
…et_from_release_0.143.0_e22a850a6a26 checkpoint: into wallentx/termux-target from release/0.143.0 @ e22a850
## Summary Backports openai#30757 to `release/0.142`. Removes the trace-level log that emitted the full Responses WebSocket request text. ## Why The full request payload was still being logged by this trace statement and was not covered by the existing request-log filtering. ## Impact Prevents full WebSocket request contents from being written to traces on the 0.142 release branch. This does not change request behavior or the app-server API. ## Testing - `just fmt` - `just test -p codex-api` (130 passed) Cherry-picked from `db887d03e1f907467e33271572dffb73bceecd6b` with `-x`.
- Prevented full Responses WebSocket request payloads from being written to trace logs. (openai#30771) ## Changelog Full Changelog: openai/codex@rust-v0.142.4...rust-v0.142.5 - openai#30771 [codex] Backport websocket trace fix to release/0.142 @dylan-hurd-oai
Termux rust-v0.142.5
…nt/wallentx_termux-target_from_release_0.142.5_1204c86f8ef6
…et_from_release_0.142.5_1204c86f8ef6 checkpoint: into wallentx/termux-target from release/0.142.5 @ 1204c86
…ust-v0.143.0 # Conflicts: # codex-rs/exec-server/src/remote.rs # codex-rs/tui/src/history_cell/notices.rs # codex-rs/tui/src/history_cell/snapshots/codex_tui__history_cell__tests__safety_access_block_event_snapshot.snap
|
Termux Android artifact ready for testing:
You must be signed in to GitHub with repository access to download Actions artifacts. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Termux release train
rust-v0.143.0-alpha.32rust-v0.143.0-alpha.32-termuxrelease/0.143.0wallentx/termux-targetThis PR is intentionally created from
wallentx/termux-targetwith the Termux release automation files copied fromdev, then targeted at the upstream release branch. If GitHub reports conflicts, resolve them manually by keeping the upstream release code while preserving the Termux compatibility fixes.Auto-merge is enabled when GitHub reports the PR as mergeable. Required CI, including the Termux artifact smoke test, is the approval gate. After merge, the deployment workflow attaches the tested artifact to
rust-v0.143.0-alpha.32-termuxand opens the checkpoint PR.Upstream notes
Release 0.143.0-alpha.32