mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
fdd72e9cd9a952e14bc123d2c8cd13d950c1928a
299 Commits
-
feat: add secret auth storage configuration (#27504)
## Why Windows Credential Manager limits generic credential blobs to 2,560 bytes. The encrypted local secrets backend avoids storing large serialized auth payloads directly in the OS keyring, but selecting that backend needs an independently reviewable feature/config layer before the auth and secrets implementation is wired in. ## What Changed - Added the stable `secret_auth_storage` feature, enabled by default on Windows and disabled by default elsewhere. - Added `AuthKeyringBackendKind` and config resolution for full and bootstrap config loading. - Applied managed feature requirements when resolving the bootstrap auth backend. - Updated the generated config schema and added focused tests. This is the base PR for #17931. The auth, secrets, MCP, CLI, TUI, and app-server implementation remains in that follow-up PR. ## Validation - `just test -p codex-features` - `just test -p codex-config` - `just test -p codex-core resolve_bootstrap_auth_keyring_backend_kind_uses_secret_auth_storage_feature` - `just write-config-schema` - `just fix -p codex-core` The full `just test -p codex-core` run compiled successfully and ran 2,690 tests; 2,589 passed, one was flaky, and 101 environment-sensitive tests failed because this shell injects a `pyenv` rehash warning into command output or because sandboxed subprocesses timed out.
Celia Chen ·
2026-06-12 19:15:21 +00:00 -
realtime: add AVAS architecture override (#27720)
## Summary Adds a `RealtimeConversationArchitecture` option for realtime conversation startup, with `realtimeapi` as the default and `avas` as an opt-in architecture. The AVAS path is limited to realtime v1 conversational WebRTC starts, and WebRTC call creation appends `intent=quicksilver&architecture=avas` to `/v1/realtime/calls`. The existing sideband websocket still joins by `call_id`. This also exposes the per-session architecture override through app-server v2 `thread/realtime/start` params and updates the config schema for `[realtime].architecture`. ## Validation - `just fmt` - `just write-config-schema` - `just test -p codex-api sends_avas_session_call_query_params` - `just test -p codex-core -E 'test(~conversation_webrtc_start_uses_avas_architecture_query)'` - `just test -p codex-core -E 'test(realtime_loads_from_config_toml)'` - `just test -p codex-app-server-protocol -E 'test(~serialize_thread_realtime_start) | test(generated_ts_optional_nullable_fields_only_in_params)'` - `just test -p codex-app-server -E 'test(realtime_webrtc_start_emits_sdp_notification)'`
Peter Bakkum ·
2026-06-12 18:11:13 +00:00 -
[ez][codex-rs] Support approvals reviewer in app defaults (#27075)
[from codex] ## Summary - add `approvals_reviewer` support to `[apps._default]` - resolve connected-app reviewers in per-app, app-default, then global order - expose the setting through the v2 config API and regenerate schema fixtures ## Context PR #25167 added `apps.<connector_id>.approvals_reviewer`, but the shared app defaults table could not specify the reviewer. This extends the same behavior to `[apps._default]` while preserving per-app overrides. Managed `allowed_approvals_reviewers` requirements still constrain both default and per-app values. A disallowed app value falls back to the global reviewer, and non-app MCP servers continue using the global reviewer. ## Testing - `just write-config-schema` - `just write-app-server-schema` - `just fmt` - `just test -p codex-config` - `just test -p codex-core app_approvals_reviewer` - `just test -p codex-app-server-protocol` - `just test -p codex-app-server config_read_includes_apps`
Alex Zamoshchin ·
2026-06-12 09:06:58 -07:00 -
[codex] Add token budget context feature (#27438)
## Why The model should be able to see bounded context-window budget metadata when the `token_budget` feature is enabled. The full-window message is only injected with full context, while normal turns get a smaller follow-up only when reported usage first crosses a budget threshold. ## What changed - Added the `TokenBudget` feature flag. - Added `<token_budget>` developer fragments for full context-window metadata and current-window remaining tokens. - Inserted the threshold message during normal turn handling by comparing token usage before and after sampling, avoiding persistent threshold bookkeeping. - Added core integration coverage for full-context-only metadata and 25/50/75 percent threshold messages. ## Verification - `just test -p codex-core token_budget` - `git diff --check`
pakrym-oai ·
2026-06-10 20:07:06 -07:00 -
core: resize all history images behind a feature flag (#27247)
## Summary Adds complete client-side image preparation behind the default-off `resize_all_images` feature flag. When enabled, local image producers defer decoding and resizing. Images are prepared centrally before insertion into conversation history, covering user input, `view_image`, and structured tool-output images. ## Behavior - Processes base64 `data:` images in messages and function/custom tool outputs. - Leaves non-data URLs, including HTTP(S) URLs, unchanged. - Applies image-detail budgets: - `high` and omitted: 2048px maximum dimension and 2.5K 32px patches. - `original`: 6000px maximum dimension and 10K 32px patches. - `auto`: uses the same 2048px / 2.5K-patch budget as high. - `low`: unsupported and replaced with an actionable placeholder. - Preserves original image bytes when no resize or format conversion is needed. - Enforces the shared 1 GiB encoded and decoded data-URL sanity limits. - Replaces only an image that fails preparation, preserving sibling content and tool-output metadata. - Uses bounded placeholders distinguishing generic processing failures, oversized images, and unsupported `low` detail. - Prepares resumed and forked history before installing it as live history without modifying persisted rollouts. ## Flag-Off Behavior When `resize_all_images` is disabled: - Existing local user-input and `view_image` processing remains unchanged. - Existing decoding and error behavior remains unchanged. - Arbitrary tool-output images are not processed. - HTTP(S) image URLs continue to be forwarded unchanged. #### [git stack](https://github.com/magus/git-stack-cli) - ✅ `1` https://github.com/openai/codex/pull/27245 - 👉 `2` https://github.com/openai/codex/pull/27247 - ⏳ `3` https://github.com/openai/codex/pull/27246 - ⏳ `4` https://github.com/openai/codex/pull/27266
Curtis 'Fjord' Hawthorne ·
2026-06-10 19:21:24 -07:00 -
Use plugin-service MCP as the hosted plugin runtime (#27198)
## Stack - Base: #27191 - This PR is the third vertical and should be reviewed against `jif/external-plugins-2`, not `main`. ## Why #27191 moves the host-owned Apps MCP registration behind an extension contributor, but deliberately preserves the existing endpoint-selection feature while that contribution contract lands. App-server can therefore resolve the server through extensions, yet the hosted plugin endpoint is still selected through temporary `apps_mcp_path_override` plumbing. That is not the long-term plugin model. A plugin can bundle skills, connectors, MCP servers, and hooks, and those components do not all need the same source or execution environment. In particular, an authenticated HTTP MCP server can expose plugin capabilities directly from a backend without an executor or an orchestrator filesystem. This PR completes that hosted vertical. App-server's MCP extension now owns the aggregate hosted plugin runtime at `/ps/mcp`. Connector actions continue to arrive as MCP tools, while backend-provided skills arrive as MCP resources and use Codex's existing resource list/read paths. No second backend client, skill filesystem, or generic plugin activation framework is introduced. The backend route remains the hosted implementation. This change replaces Codex's temporary endpoint-selection mechanism, not the service behind the endpoint. ## What changed ### Hosted plugin runtime The MCP extension now contributes `codex_apps` as the hosted plugin runtime rather than as a configurable Apps endpoint: - `https://chatgpt.com` resolves to `https://chatgpt.com/backend-api/ps/mcp`; - a bare custom ChatGPT base resolves to `/api/codex/ps/mcp`; - the existing product-SKU header and ChatGPT authentication behavior are preserved; - executor availability is never consulted for this streamable HTTP transport. The same MCP connection carries both component shapes supported by the hosted endpoint: - connector actions are discovered and invoked as MCP tools; - hosted skills are enumerated and read as MCP resources through the existing `list_mcp_resources` and `read_mcp_resource` paths. This keeps component access in the subsystem that already owns the protocol instead of downloading backend skills into an orchestrator filesystem or inventing a parallel hosted-skill client. ### Explicit runtime ordering `McpManager` now resolves the reserved `codex_apps` entry in three ordered phases: 1. install the legacy Apps fallback for compatibility; 2. apply ordered extension `Set` or `Remove` overlays; 3. apply the final ChatGPT-auth gate without synthesizing the server again. This ordering is important: - an ordinary configured or plugin MCP server cannot claim the auth-bearing `codex_apps` name; - an extension-contributed hosted runtime wins over the fallback; - an extension `Remove` remains authoritative; - a host without the MCP extension retains the legacy Apps endpoint and current local-only behavior. The temporary `legacy_apps_mcp_loader_enabled` coordination flag is no longer needed. ### Remove the path override The `apps_mcp_path_override` feature and its runtime plumbing are removed, including: - the feature registry entry and structured feature config; - `Config` and `McpConfig` fields; - config schema output; - config-lock materialization; - URL override handling in `codex-mcp`. Existing boolean and structured forms still deserialize as ignored compatibility input. They are omitted from new serialized config, and config-lock comparison normalizes the removed input so older locks remain replayable. ### App-server coverage App-server MCP fixtures now serve the hosted route at `/api/codex/ps/mcp`. Existing resource-read and tool/elicitation flows therefore exercise the extension-owned endpoint rather than succeeding through the legacy fallback. The stack also adds the missing `codex_chatgpt::connectors` re-export for the manager-backed connector helper introduced in #27191. ## Compatibility - App-server installs the extension and uses `/ps/mcp` for the hosted runtime. - CLI and other hosts that do not install the extension retain the legacy Apps endpoint. - Apps disabled or non-ChatGPT authentication removes `codex_apps` from the effective runtime view. - Existing local plugins, local skills, executor-selected skills, configured MCP servers, and MCP OAuth behavior are otherwise unchanged. - Backend plugin enablement remains account/workspace state owned by the hosted endpoint; this PR does not add thread-local backend plugin selection. ## Architectural fit The stack now proves two independent runtime shapes: 1. #27184 resolves filesystem-backed skills through the executor that owns a selected root. 2. #27191 and this PR resolve a backend-hosted HTTP MCP through an extension with no executor. Together they preserve the intended separation: - selection identifies a plugin/root when explicit selection is needed; - each component's owning extension resolves its concrete access mechanism; - execution stays with the runtime required by that component; - existing skills, MCP, connector, and hook subsystems remain the downstream consumers. ## Planned follow-ups 1. **Executor stdio MCP:** selecting an executor plugin registers a manifest-declared stdio MCP server and executes it in the environment that owns the plugin. 2. **Optional backend selection:** only if CCA needs thread-local selection distinct from backend account/workspace enablement, add a concrete backend-owned capability location and surface those selected skills through the skills catalog. 3. **Connector metadata and hooks:** activate those plugin components through their existing owning subsystems, with executor hooks remaining environment-bound. 4. **Propagation and persistence:** define explicit resume, fork, subagent, refresh, and environment-removal semantics once selected roots have multiple real consumers. 5. **Local convergence:** migrate legacy local skill, MCP, connector, and hook paths behind their owning extensions one vertical at a time, then remove duplicate core managers and compatibility plumbing after parity. ## Verification Coverage in this change exercises: - extension-owned `/backend-api/ps/mcp` registration without an executor; - preservation of the legacy endpoint in hosts without the extension; - extension `Set` and `Remove` precedence over the legacy fallback; - ChatGPT-auth gating for the reserved server; - hosted MCP resource reads with and without an active thread; - connector tool invocation and MCP elicitation through the hosted route; - ignored boolean and structured forms of the removed path override; - config-lock replay compatibility for the removed feature. `cargo check -p codex-features -p codex-mcp-extension -p codex-app-server` passes. Tests and Clippy were not run locally under the current development instruction; CI provides the full validation pass.
jif ·
2026-06-10 12:54:21 +02:00 -
[codex] Gate terminal visualization instructions in TUI (#26013)
## Summary - add `Feature::TerminalVisualizationInstructions` as `UnderDevelopment`, disabled by default - keep terminal visualization instructions inside the TUI package - append them to existing developer instructions for TUI start, resume, and fork flows only when enabled - intentionally do not apply them to `codex exec` ## Rollout Control behavior is unchanged. TUI dogfooders can enable `terminal_visualization_instructions`; no default user receives the new terminal-specific instructions. The shared visualization-selection rule is supplied separately through the `codex_proxy_model_3` Statsig layer for every target Codex model slug in the gated cohort. This TUI feature determines how to render an appropriate visualization on the terminal surface; the model-layer treatment determines when to use one. ## Validation - `cargo test -p codex-tui terminal_visualization_instructions_are_gated_for_all_tui_thread_flows --lib` - `cargo test -p codex-features --lib` - `cargo fmt --all -- --check` - `git diff --check` - GPT-5.4 and GPT-5.5 real prompt-pipeline smoke tests: both visualized the positive mapping case, abstained on the negative route case, and passed exact prompt-stack verification on CLI and App - refreshed onto current `main` with a clean merge and reran the focused validation The full 53-probe all-model treatment comparison and requested production coding evals remain rollout gates before broadening beyond the initial employee cohort. This PR remains open for normal human review.
vie-oai ·
2026-06-05 17:23:45 -07:00 -
[codex] Support model-defined reasoning efforts (#26444)
## Summary - accept non-empty model-defined reasoning effort values while preserving built-in effort behavior - propagate the non-Copy effort type through core, app-server, TUI, telemetry, and persistence call sites - preserve string wire encoding and expose an open-string schema for clients - update model selection and shortcut behavior for model-advertised effort values ## Root cause `ReasoningEffort` gained a string-backed custom variant, so it could no longer implement `Copy` or rely on derived closed-enum serialization. Existing consumers still moved effort values from shared references and assumed a fixed built-in value set. ## Validation - `just fmt` - Local tests and compilation were not run per request; relying on CI.
Ahmed Ibrahim ·
2026-06-04 13:36:24 -07:00 -
Remove response.processed websocket request (#26447)
## Why The Responses websocket client no longer needs to send a follow-up `response.processed` request after a turn response has already been recorded. Keeping that extra acknowledgement path adds feature-gated control flow and a second websocket request shape that no longer carries useful behavior. ## What Changed - Removed the `response.processed` websocket request type and sender. - Removed the `responses_websocket_response_processed` feature flag and schema entry. - Removed turn and remote-compaction plumbing that only tracked response IDs to send the acknowledgement. - Removed tests that existed solely to cover the deleted feature path. ## Validation - `just fix -p codex-core -p codex-api -p codex-features`
pakrym-oai ·
2026-06-04 13:15:50 -07:00 -
core: allow excluding tool namespaces from code mode (#26320)
## Why Research and training setups need to control which tool namespaces appear inside code mode's nested `tools` surface without disabling those tools entirely. This makes it possible to train against a deliberately reduced nested-tool setup while preserving the normal direct and deferred tool paths. ## What - Extend `features.code_mode` to accept structured configuration while preserving the existing boolean syntax. - Add an exact `excluded_tool_namespaces` list under `[features.code_mode]`: ```toml [features.code_mode] enabled = true excluded_tool_namespaces = ["mcp__codex_apps", "multi_agent_v1"] ``` - Filter matching canonical `ToolName` namespaces when constructing code mode's nested router and code-mode-specific direct tool descriptions. - Keep excluded tools registered, directly exposed in mixed code mode, and discoverable through top-level `tool_search` when otherwise eligible. - Derive deferred nested-tool guidance after namespace filtering so the `exec` description does not advertise excluded-only deferred tools. - Preserve the boolean/table representation when materializing config locks and update the generated config schema. ## Testing - `just test -p codex-features` - `just test -p codex-config` - `just test -p codex-core load_config_resolves_code_mode_config` - `just test -p codex-core lock_contains_prompts_and_materializes_features` - `just test -p codex-core excluded_deferred_namespaces_do_not_enable_nested_tool_guidance` - `just test -p codex-core code_mode_excludes_configured_nested_tool_namespaces` - `cargo check -p codex-thread-manager-sample`
sayan-oai ·
2026-06-04 18:40:18 +00:00 -
[app-server][core] Add connector-level Guardian reviewer overrides (#25167)
Context: https://openai.slack.com/archives/C0B4JAF0Q2C/p1779912328647229 ``` approvals_reviewer = "auto_review" [apps.connector_5f3c8c41a1e54ad7a76272c89e2554fa] enabled = true approvals_reviewer = "user" default_tools_approval_mode = "prompt" ``` <img width="230" height="84" alt="Screenshot 2026-05-31 at 11 56 34 AM" src="https://github.com/user-attachments/assets/e319f8f7-0983-42a7-98cd-3302732fa406" /> <img width="841" height="233" alt="Screenshot 2026-05-31 at 11 52 42 AM" src="https://github.com/user-attachments/assets/7ac76645-4e90-4d00-8242-f031146a22a5" /> ------- ``` approvals_reviewer = "user" [apps.connector_5f3c8c41a1e54ad7a76272c89e2554fa] enabled = true approvals_reviewer = "auto_review" default_tools_approval_mode = "prompt" ``` <img width="195" height="83" alt="Screenshot 2026-05-31 at 12 02 27 PM" src="https://github.com/user-attachments/assets/3d374dc8-8aa2-466f-a13f-e4ed8567aa2e" /> <img width="771" height="207" alt="Screenshot 2026-05-31 at 12 05 42 PM" src="https://github.com/user-attachments/assets/105c2575-68d6-4ca6-8e69-dc8c82da36a2" /> ## Summary - add `apps.<connector_id>.approvals_reviewer` to override Guardian or user review routing per connected app - apply overrides across direct app MCP calls, delegated MCP prompts, and app-server MCP elicitation review while preserving global behavior for non-app MCP servers - expose and document the config through app-server v2 and generated schemas, while honoring global managed reviewer requirements --------- Co-authored-by: jif-oai <jif@openai.com>
Alex Zamoshchin ·
2026-06-02 17:04:11 +02:00 -
feat: gate unified exec zsh fork composition (#24979)
## Why `shell_zsh_fork` and unified exec need to remain independently controllable for enterprise rollouts, but we also need a third mode that composes them. That composed mode is intended to preserve unified exec command lifecycle support while letting the zsh fork provide more accurate `execv(2)` interception. Enabling `unified_exec_zsh_fork` by itself is intentionally not sufficient. It is a composition gate, not a dependency-enabling shortcut: - `unified_exec` selects the PTY-backed unified exec tool. - `shell_zsh_fork` opts into the zsh fork backend. - `unified_exec_zsh_fork` only allows those two already-enabled modes to be composed so local zsh unified exec commands can launch through the zsh fork. This separation is deliberate. Enterprises and staged rollouts must be able to enable or disable unified exec and zsh-fork independently. If `unified_exec_zsh_fork` implied either dependency, then enabling one under-development composition flag would silently activate a shell backend that the configured feature set left disabled. This PR introduces only the configuration and planning gate for that composition. Existing `shell_zsh_fork` behavior continues to use the standalone shell tool unless the new composition feature is explicitly enabled alongside both dependencies. ## What Changed - Added the under-development feature flag `unified_exec_zsh_fork`. - Added `UnifiedExecFeatureMode` so the three input feature flags collapse into `Disabled`, `Direct`, or `ZshFork` mode before tool planning. - Updated tool selection so zsh-fork composition requires `unified_exec`, `shell_zsh_fork`, and `unified_exec_zsh_fork`. - Kept the existing standalone zsh-fork shell tool behavior when only `shell_zsh_fork` is enabled. - Updated config schema output for the new feature flag. ## Verification - Added feature and tool-config coverage for the new gate. - Added planner coverage proving `shell_zsh_fork` remains standalone until composition is explicitly enabled. - Ran focused tests for `codex-features`, `codex-tools`, and the affected `codex-core` planner case. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/24979). * #24982 * #24981 * #24980 * __->__ #24979
Michael Bolin ·
2026-06-01 13:01:36 -07:00 -
Compress cold local rollouts (#25089)
## Rollout compression stack This stack splits #24941 into reviewable steps for local rollout compression. The design is intentionally staged: 1. Teach readers, listing, search, and lookup to understand compressed rollouts. 2. Make append and resume paths materialize compressed rollouts back to plain JSONL before writing. 3. Add a disabled-by-default worker that can compress cold archived rollouts behind `local_thread_store_compression`. The key invariant is that writers append to plain `.jsonl`. A `.jsonl.zst` file is a cold/read representation; if a write is needed, the compressed file is materialized back to plain JSONL first. Readers prefer plain `.jsonl` when both forms exist and can fall back to the compressed sibling during transitions. The worker is deliberately the last PR and remains behind an under-development feature flag. It currently scans only `archived_sessions`, not active `sessions`, because active sessions have the highest resume/append race risk. That means this stack does not yet compress most unarchived local history. ## Known race / follow-up The remaining unresolved design question is writer/compressor coordination. Even for archived rollouts, a resume or metadata update can append while the worker is replacing the plain file with `.jsonl.zst`; the current double-stat checks narrow but do not fully eliminate the window where a writer has opened the plain file before unlink. Do not treat the worker PR as production-ready until we either: - prevent append/resume paths from racing archived compression, or - introduce a shared representation/append lock or equivalent coordination. The first two PRs are useful independently: they make compressed rollouts readable and make append paths safely recover back to plain JSONL. The third PR isolates the worker behavior so that coordination issue is reviewable separately. ## Validation Focused local validation for the stack includes: - `just test -p codex-rollout` - `just test -p codex-thread-store` where thread-store paths were touched - `just test -p codex-features` for the feature flag slice - `just bazel-lock-check` after dependency graph changes - scoped `just fix -p ...` passes for changed crates CI is still the source of truth for the full platform matrix. ## This PR in the stack This is PR 3/3, based on #25088. It adds the under-development feature flag and starts the best-effort background worker when enabled. The worker currently compresses only cold archived rollouts, skips active sessions, verifies compressed output, preserves mtime and permissions, keeps a store-level lock heartbeat, and cleans stale temp files. Stack order: 1. #25087: read compressed local rollouts. 2. #25088: materialize compressed rollouts before append. 3. This PR: add the disabled local compression worker.
jif-oai ·
2026-06-01 18:35:58 +02:00 -
feat(config) experimental_request_user_input toggle (#24541)
## Summary Experimental flag to allow toggling `request_user_input`: ``` tools.experimental_request_user_input = false ``` ## Testing - [x] Added unit tests
Dylan Hurd ·
2026-05-29 21:35:53 -07:00 -
[codex] Fix Vim normal mode editing (#25022)
## Summary - add Vim normal-mode `s` support to substitute the character under the cursor and enter insert mode - fix Vim normal-mode `o` so opening below the final line moves the cursor onto the new blank line - update keymap config/schema and keymap picker snapshots for the new action ## Validation - `just fmt` - `just write-config-schema` - `just test -p codex-config` - focused `just test -p codex-tui` coverage for the Vim `s` and `o` behavior, keymap conflict handling, and keymap picker snapshots - `cargo insta pending-snapshots --manifest-path tui/Cargo.toml` - `git diff --check` ## Notes A full `just test -p codex-tui` run still has two unrelated Guardian feature-flag failures in this checkout: - `app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default` - `app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history`
Jinghan Xu ·
2026-05-29 14:01:27 -07:00 -
fix(config): use deny for Unix socket permissions (#24970)
## Why Unix socket permissions still accepted and displayed `"none"` while file permissions use the clearer `"deny"` spelling. This keeps network Unix socket policy vocabulary consistent with filesystem policy vocabulary. ## What changed - Replace the Unix socket permission variant and serialized spelling from `none` to `deny` across config, feature configuration, and network proxy types. - Update app-server v2 serialization, TUI debug output, focused tests, and generated schemas to expose `"deny"`. - Add coverage for denied Unix socket entries in managed requirements and profile overlay behavior. ## Security This is a vocabulary change for explicit Unix socket rejection, not a network access expansion. Denied entries continue to be omitted from the effective allowlist. ## Validation - `just fmt` - `just write-config-schema` - `just write-app-server-schema` - `just test -p codex-config -p codex-core -p codex-app-server-protocol -p codex-tui -E 'test(network_requirements_are_preserved_as_constraints_with_source) | test(network_permission_containers_project_allowed_and_denied_entries) | test(network_toml_overlays_unix_socket_permissions_by_path) | test(permissions_profiles_resolve_extends_parent_first_with_child_overrides) | test(network_requirements_serializes_canonical_and_legacy_fields) | test(debug_config_output_formats_unix_socket_permissions)'`\n- Automatic `bench-smoke` follow-up from `just test`\n- `cargo clippy -p codex-config -p codex-core -p codex-features -p codex-network-proxy -p codex-app-server-protocol -p codex-app-server -p codex-tui --all-targets -- -D warnings`
viyatb-oai ·
2026-05-28 23:53:26 +00:00 -
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>
Won Park ·
2026-05-28 11:44:55 -07:00 -
feat(tui): make turn interruption keybind configurable (#24766)
## Why Interrupting an active turn is currently fixed to `Esc`, which is easy to hit accidentally and cannot be customized through `/keymap`. This gives users a less accidental binding while preserving the existing default. ## What Changed - Adds `tui.keymap.chat.interrupt_turn` to `/keymap`, defaulting to `esc` and supporting remapping or unbinding. - Uses the configured interrupt binding for running-turn status, queued steer interruption, and `request_user_input`, including the visible hints. - Preserves local `Esc` behavior for popups, Vim insert mode, and `/agent` editing while validating conflicts with fixed/backtrack and request-input navigation bindings. - Adds behavior and snapshot coverage for remapped interruption paths. ## How to Test 1. Run Codex and open `/keymap`, then set **Interrupt Turn** to `f12`. 2. Start a turn and confirm `Esc` no longer interrupts it while `f12` does; the running hint should display `f12 to interrupt`. 3. Queue a steer while a turn is running and confirm the preview displays `f12`; pressing it should interrupt and submit the steer immediately. 4. Trigger a `request_user_input` prompt and confirm its footer uses `f12`; with notes open, `Esc` should still clear notes while `f12` interrupts the turn. 5. Clear the Interrupt Turn binding and confirm the key-specific interrupt hint is removed while `Ctrl+C` remains available. Targeted validation: - `just write-config-schema` - `just fix -p codex-config` - `just fix -p codex-tui` - `just fmt` - `just argument-comment-lint-from-source -p codex-config -p codex-tui` - `just test -p codex-config` - `cargo insta pending-snapshots --manifest-path tui/Cargo.toml` - `just test -p codex-tui keymap_setup::tests` - `just test -p codex-tui` (fails in two pre-existing guardian feature-flag tests unrelated to this diff; the intentional picker snapshot updates were reviewed and accepted)
Felipe Coury ·
2026-05-27 18:59:17 +00:00 -
feat(tui): add vim text object bindings (#24382)
## Why Vim mode currently supports some normal-mode operators and motions, but common text-object combinations like `ciw`, `daw`, `di(`, and quote/bracket variants are still missing. That makes the composer feel incomplete for users who expect operator + text object editing to work inside prompts. Closes #21383. ## What Changed - Add Vim pending-state support for operator/text-object sequences. - Add `c` as a normal-mode operator for text objects, so combinations like `ciw` delete the object and enter insert mode. - Support word, WORD, delimiter, and quote text objects: - `iw`, `aw`, `iW`, `aW` - `i(`, `a(`, `i)`, `a)`, `ib`, `ab` - `i[`, `a[`, `i]`, `a]` - `i{`, `a{`, `i}`, `a}`, `iB`, `aB` - `i"`, `a"`, `i'`, `a'`, `i\``, `a\`` - Add configurable keymap entries and keymap picker coverage for the new Vim text-object context. - Regenerate the config schema and update keymap picker snapshots. ## How to Test Manual smoke test: 1. Start Codex with Vim composer mode enabled. 2. Type a draft such as: ```text alpha beta gamma call(foo[bar], {"x": "hello world"}) say "one \"two\" three" now ``` 3. Put the cursor on `beta`, press `ciw`, and confirm `beta` is removed and the composer enters insert mode. 4. Escape back to normal mode, put the cursor on `gamma`, press `daw`, and confirm `gamma` plus surrounding whitespace is removed. 5. Put the cursor inside `foo[bar]`, press `di[`, and confirm only `bar` is removed. 6. Put the cursor inside `call(...)`, press `da(`, and confirm the whole parenthesized section is removed. 7. Put the cursor inside the quoted text, press `ci"`, and confirm the quote contents are removed and insert mode starts. 8. Verify cancellation does not edit text: press `d` then `Esc`, and press `d` then `i` then `Esc`. Targeted tests: - `cargo test -p codex-tui --lib vim_` - `cargo nextest run -p codex-tui keymap_setup::tests` Additional local checks: - `just write-config-schema` - `just fmt` - `just fix -p codex-tui` - `git diff --check` - `cargo insta pending-snapshots --manifest-path tui/Cargo.toml` Local full-suite note: `just test -p codex-tui` ran to completion. The keymap snapshot failures were expected and accepted. Two unrelated guardian feature-flag tests still fail locally: - `app::tests::update_feature_flags_disabling_guardian_clears_review_policy_and_restores_default` - `app::tests::update_feature_flags_disabling_guardian_clears_manual_review_policy_without_history` `just argument-comment-lint` is currently blocked locally by Bazel analysis before the lint runs because `compiler-rt` has an empty `include/sanitizer/*.h` glob in the local Bazel cache. The touched Rust diff was manually inspected for opaque positional literals.
Felipe Coury ·
2026-05-27 15:15:03 -03:00 -
fix(tui): complete vim word-end and line-end behavior (#24380)
## Why The TUI Vim composer currently diverges from normal Vim editing in two common workflows: pressing `e` repeatedly can remain stuck at an existing word end, and normal mode does not support `C` for changing through the end of the line. The existing `D` behavior also removes the newline when the cursor is already at the line boundary, which makes the new `C` action and existing deletion action surprising in multiline prompts. Closes #23926. Closes #24238. ## What Changed - Make normal-mode `e` advance from the current word end to the next word end, including for operator motions such as `de`. - Add configurable Vim normal-mode `change_to_line_end` behavior, bound to `C` by default, which deletes to the end of the current line and enters Insert mode. - Keep the newline intact when `D` or `C` is pressed at the end-of-line boundary. - Add regression coverage for repeated `e`, `de`, `C`, and the multiline `C`/`D` boundary behavior. - Regenerate the config schema and update the keymap picker snapshots for the new Vim action. ## How to Test 1. Run Codex with Vim composer mode enabled: ```bash cd codex-rs cargo run --bin codex -- -c tui.vim_mode_default=true ``` 2. Enter `alpha beta gamma`, press `Esc`, `0`, then press `e` repeatedly. Confirm the cursor advances through the ends of `alpha`, `beta`, and `gamma`. 3. Enter `hello world`, press `Esc`, `0`, `w`, then `C`. Confirm `world` is deleted and the composer enters Insert mode. 4. Enter a multiline prompt with `hello` above `world`, press `Esc`, `k`, `$`, and then `D`. Confirm the newline is preserved and the two lines do not join. 5. At the same boundary, press `C` and type `!`. Confirm the composer enters Insert mode and yields `hello!` above `world`, preserving the newline. Targeted automated verification: - `just fix -p codex-tui` - `just argument-comment-lint-from-source -p codex-tui -p codex-config` - `cargo insta pending-snapshots` reports no pending snapshots. - `just test -p codex-tui` validates the new Vim and keymap snapshot coverage, but the command remains red due to two reproducible unrelated failures in `app::tests::update_feature_flags_disabling_guardian_*`. ## Validation Note The workspace-wide `just argument-comment-lint` form is currently blocked during Bazel analysis by the existing LLVM `compiler-rt` missing `include/sanitizer/*.h` failure; package-scoped source linting for the changed Rust crates passed.
Felipe Coury ·
2026-05-27 07:36:52 -07:00 -
standalone websearch extension (#23823)
## Summary Add the extension-backed standalone `web.run` tool so Codex can call the standalone search endpoint through the `codex-api` search client and return its encrypted output to Responses. - gate the new tool behind `standalone_web_search` - install the extension in the app-server thread registry and hide hosted `web_search` when standalone search is enabled for OpenAI providers so the two paths stay mutually exclusive - build search context from persisted history using a small tail heuristic: previous user message, assistant text between the last two user turns capped at about 1k tokens, and current user message ## Test Plan - `cargo test -p codex-web-search-extension` - `cargo test -p codex-api` - `cargo test -p codex-core hosted_tools_follow_provider_auth_model_and_config_gates`
sayan-oai ·
2026-05-26 11:12:24 -07:00 -
feat: gate dedicated memories tools in config (#24600)
## Why The memories extension already has dedicated `list`, `read`, `search`, and `add_ad_hoc_note` tools, but app-server registration was still disabled. The memories app collaborator needs an explicit config switch so those native extension tools can be exposed intentionally, without making ordinary memory prompt usage automatically register the dedicated tool surface. ## What changed - Added `[memories].dedicated_tools`, defaulting to `false`, to `MemoriesToml` / `MemoriesConfig`. - Regenerated `core/config.schema.json` for the new setting. - Registered the memories extension as a `ToolContributor`, while keeping tool contribution gated on both memories being enabled and `dedicated_tools = true`. - Added tests for the disabled default, the enabled dedicated-tools path, and installer registration. ## Verification - `just test -p codex-config -p codex-memories-extension`
jif-oai ·
2026-05-26 18:18:58 +02:00 -
Move MCP tool naming mode into manager (#21576)
## Why The `non_prefixed_mcp_tool_names` feature should be applied where MCP tools become model-visible, not by remapping names later in core. Keeping the decision in `McpConnectionManager` construction makes `ToolInfo` the single shaped view that spec building, deferred tool search, routing, and unavailable-tool placeholders can consume directly. This also preserves the existing external behavior while the feature is off, and keeps the feature-on behavior for code mode and hooks explicit at the manager boundary. ## What Changed - Add `McpToolNameMode` to `codex-mcp` and flow it through `McpConfig` into `McpConnectionManager::new`. - Normalize MCP `ToolInfo` names in the manager using either legacy-prefixed namespaces or non-prefixed namespaces; the legacy path adds `mcp__` without restoring the old trailing namespace suffix. - Remove the core-side MCP name remapping path so specs, tool search, session resolution, and unavailable-tool placeholder construction use the manager-provided `ToolName` values directly. - Keep code mode flattening on the `__` namespace separator. - Preserve hook compatibility by giving non-prefixed MCP hook names legacy `mcp__...` matcher aliases. - Add/adjust integration and unit coverage for non-prefixed code-mode behavior, hook matching with the feature on and off, and manager-level legacy prefixing. ## Testing - `cargo test -p codex-mcp --lib` - `cargo test -p codex-core --lib tools::spec::tests -- --nocapture` - `cargo test -p codex-core --lib mcp_tools -- --nocapture` - `cargo test -p codex-core --lib mcp_tool_exposure -- --nocapture` - `cargo test -p codex-core --test all mcp_tool -- --nocapture` - `cargo test -p codex-core --test all search_tool -- --nocapture` - `cargo test -p codex-core --test all hooks_mcp -- --nocapture` - `cargo test -p codex-core --test all code_mode_uses_non_prefixed_mcp_tool_names_when_feature_enabled -- --nocapture` - `cargo test -p codex-tools` - `cargo test -p codex-features`
pakrym-oai ·
2026-05-26 08:21:15 -07:00 -
package: include zsh fork in Codex package (#23756)
## Why The package layout gives Codex a stable place for runtime helpers that should travel with the entrypoint. `shell_zsh_fork` still required users to configure `zsh_path` manually, even though we already publish prebuilt zsh fork artifacts. This PR builds on #24129 and uses the shared DotSlash artifact fetcher to include the zsh fork in Codex packages when a matching target artifact exists. Packaged Codex builds can then discover the bundled fork automatically; the user/profile `zsh_path` override is removed so the feature uses the package-managed artifact instead of a legacy path knob. ## What Changed - Added `scripts/codex_package/codex-zsh`, a checked-in DotSlash manifest for the current macOS arm64 and Linux zsh fork artifacts. - Taught `scripts/build_codex_package.py` to fetch the matching zsh fork artifact and install it at `codex-resources/zsh/bin/zsh` when available for the selected target. - Added package layout validation for the optional bundled zsh resource. - Added `InstallContext::bundled_zsh_path()` and `InstallContext::bundled_zsh_bin_dir()` for package-layout resource discovery. - Threaded the packaged zsh path through config loading as the runtime `zsh_path` for packaged installs, and removed the config/profile/CLI override path. - Kept the packaged default zsh override typed as `AbsolutePathBuf` until the existing runtime `Config::zsh_path` boundary. - Updated app-server zsh-fork integration tests to spawn `codex-app-server` from a temporary package layout with `codex-resources/zsh/bin/zsh`, matching the new packaged discovery path instead of setting `zsh_path` in config. - Switched package executable copying from metadata-preserving `copy2()` to `copyfile()` plus explicit executable bits, which avoids macOS file-flag failures when local smoke tests use system binaries as inputs. ## Testing To verify that the `zsh` executable from the Codex package is picked up correctly, first I ran: ```shell ./scripts/build_codex_package.py ``` which created: ``` /private/var/folders/vw/x2knqmks50sfhfpy27nftl900000gp/T/codex-package-pms94kdp/ ``` so then I ran: ``` /private/var/folders/vw/x2knqmks50sfhfpy27nftl900000gp/T/codex-package-pms94kdp/bin/codex exec --enable shell_zsh_fork 'run `echo $0`' ``` which reported the following, as expected: ``` /private/var/folders/vw/x2knqmks50sfhfpy27nftl900000gp/T/codex-package-pms94kdp/codex-resources/zsh/bin/zsh ``` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/23756). * #23768 * __->__ #23756
Michael Bolin ·
2026-05-22 17:54:07 -07:00 -
tui: make
codex-tui.logopt-in (#24081)## Why The TUI currently creates a shared plaintext `codex-tui.log` under the default log directory. That append-only file can keep growing across runs even though the TUI already records diagnostics in bounded local stores. Make the plaintext file log an explicit troubleshooting choice instead of a default side effect. This is possible because logs are also stored in the DB with proper rotation ## What changed - Only install the TUI file logging layer when `log_dir` is explicitly set. - Remove the prior `codex-tui.log` at startup before an opt-in file layer is created. - Clarify the `log_dir` config/schema text and `docs/install.md` example so users opt in with `codex -c log_dir=...` when they need a plaintext log.
jif-oai ·
2026-05-22 17:19:51 +00:00 -
Route MCP servers through explicit environments (#23583)
## Summary - route each configured MCP server through an explicit per-server `environment_id` instead of a manager-wide remote toggle - default omitted `environment_id` to `local`, resolve named ids through `EnvironmentManager`, and fail only the affected MCP server when an explicit id is unknown - keep local stdio on the existing local launcher path for now, while named-environment stdio uses the selected environment backend and requires an absolute `cwd` - allow local HTTP MCP servers to keep using the ambient HTTP client when no local `Environment` is configured; named-environment HTTP MCPs use that environment's HTTP client ## Validation - devbox Bazel build: `bazel build --bes_backend= --bes_results_url= //codex-rs/cli:codex //codex-rs/rmcp-client:test_stdio_server //codex-rs/rmcp-client:test_streamable_http_server` - devbox app-server config matrix with real `config.toml` / `environments.toml` files covering omitted local, explicit local, omitted local under remote default, explicit remote stdio, local HTTP without local env, explicit remote HTTP, local stdio without local env, unknown explicit env, and remote stdio without `cwd`
starr-openai ·
2026-05-21 17:19:54 +02:00 -
Use named MITM permissions config (#18240)
## Stack 1. Parent PR: #18868 adds MITM hook config and model only. 2. Parent PR: #20659 wires hook enforcement into the proxy request path. 3. This PR changes the user facing PermissionProfile TOML shape. ## Why 1. The broader goal is to make MITM clamping usable from the same permission profile that already controls network behavior. 2. This PR is the config UX layer for the stack. It moves MITM policy into `[permissions.<profile>.network.mitm]` instead of exposing the flat runtime shape to users. 3. The named hook and action tables belong here because users need reusable policy blocks that are easy to review, while the proxy runtime only needs a flat hook list. 4. This PR validates action refs during config parsing so mistakes in the user facing policy fail before a proxy session starts. 5. Keeping the lowering here lets the proxy keep its simpler runtime model and lets PermissionProfile remain the single source of network permission policy. ## Summary 1. Keep MITM policy inside `[permissions.<profile>.network.mitm]` so the selected PermissionProfile owns network proxy policy. 2. Use named MITM hooks under `[permissions.<profile>.network.mitm.hooks.<name>]`. 3. Put host, methods, path prefixes, query, headers, body, and action refs on the hook table. 4. Define reusable action blocks under `[permissions.<profile>.network.mitm.actions.<name>]`. 5. Represent action blocks with `NetworkMitmActionToml`, then lower them into the proxy runtime action config. 6. Reject unknown refs, empty refs, and empty action blocks during config parsing. 7. Keep the runtime hook model unchanged by lowering config into the existing proxy hook list. 8. Preserve the #20659 activation fix for nested MITM policy. ## Example ```toml [permissions.workspace.network.mitm] enabled = true [permissions.workspace.network.mitm.hooks.github_write] host = "api.github.com" methods = ["POST", "PUT"] path_prefixes = ["/repos/openai/"] action = ["strip_auth"] [permissions.workspace.network.mitm.actions.strip_auth] strip_request_headers = ["authorization"] ``` ## Validation 1. Regenerated the config schema. 2. Ran the core MITM config parsing and validation tests. 3. Ran the core PermissionProfile MITM proxy activation tests. 4. Ran the core config schema fixture test. 5. Ran the network proxy MITM policy tests. 6. Ran the scoped Clippy fixer for the network proxy crate. 7. Ran the scoped Clippy fixer for the core crate. --------- Co-authored-by: Winston Howes <winston@openai.com>
evawong-oai ·
2026-05-20 17:10:37 -07:00 -
Honor client-resolved service tier defaults (#23537)
## Why Model catalog responses can now advertise a nullable `default_service_tier` for each model. Codex needs to preserve three distinct states all the way from config/app-server inputs to inference: - no explicit service tier, so the client may apply the current model catalog default when FastMode is enabled - explicit `default`, meaning the user intentionally wants standard routing - explicit catalog tier ids such as `priority`, `flex`, or future tiers Keeping those states distinct prevents the UI from showing one tier while core sends another, especially after model switches or app-server `thread/start` / `turn/start` updates. ## What Changed - Plumbed `default_service_tier` through model catalog protocol types, app-server model responses, generated schemas, model cache fixtures, and provider/model-manager conversions. - Added the request-only `default` service tier sentinel and normalized legacy config spelling so `fast` in `config.toml` still materializes as the runtime/request id `priority`. - Moved catalog default resolution to the TUI/client side, including recomputing the effective service tier when model/FastMode-dependent surfaces change. - Updated app-server thread lifecycle config construction so `serviceTier: null` preserves explicit standard-routing intent by mapping to `default` instead of internal `None`. - Kept core responsible for validating explicit tiers against the current model and stripping `default` before `/v1/responses`, without applying catalog defaults itself. ## Validation - `CARGO_INCREMENTAL=0 cargo build -p codex-cli` - `CARGO_INCREMENTAL=0 cargo test -p codex-app-server model_list` - `cargo test -p codex-tui service_tier` - `cargo test -p codex-protocol service_tier_for_request` - `cargo test -p codex-core get_service_tier` - `RUST_MIN_STACK=8388608 CARGO_INCREMENTAL=0 cargo test -p codex-core service_tier`
Shijie Rao ·
2026-05-20 15:57:50 -07:00 -
Add SubagentStop hook (#22873)
# What <img width="1792" height="1024" alt="image" src="https://github.com/user-attachments/assets/8f81d232-5813-4994-a61d-e42a05a93a3e" /> `SubagentStop` runs when a thread-spawned subagent turn is about to finish. Thread-spawned subagents use `SubagentStop` instead of the normal root-agent `Stop` hook. Configured handlers match on `agent_type`. Hook input includes the normal stop fields plus: - `agent_id`: the child thread id. - `agent_type`: the resolved subagent type. - `agent_transcript_path`: the child subagent transcript path. - `transcript_path`: the parent thread transcript path. - `last_assistant_message`: the final assistant message from the child turn, when available. - `stop_hook_active`: `true` when the child is already continuing because an earlier stop-like hook blocked completion. `SubagentStop` shares the same completion-control semantics as `Stop`, scoped to the child turn: - No decision allows the child turn to finish. - `decision: "block"` with a non-empty `reason` records that reason as hook feedback and continues the child with that prompt. - `continue: false` stops the child turn. If `stopReason` is present, Codex surfaces it as the stop reason. # Lifecycle Scope Only thread-spawned subagents run `SubagentStop`. Internal/system subagents such as Review, Compact, MemoryConsolidation, and Other do not run normal `Stop` hooks and do not run `SubagentStop`. This avoids exposing synthetic matcher labels for internal implementation paths. # Stack 1. #22782: add `SubagentStart`. 2. This PR: add `SubagentStop`. 3. #22882: add subagent identity to normal hook inputs.
Abhinav ·
2026-05-20 14:59:41 -07:00 -
feat(permissions): resolve permission profile inheritance (#22270)
## Stack This is the foundation PR for the permission-profile inheritance stack. - This PR adds config-level `extends` resolution and merge semantics. - Follow-up: #23705 applies resolved profiles at runtime and updates the active-profile protocol surfaces. ## Why Permission profiles are starting to carry enough policy that copy-pasting near-identical definitions becomes hard to review and easy to drift. Before the runtime can consume inherited profiles, the config layer needs one explicit resolver that can merge parent chains and reject unsafe or invalid inheritance shapes. ## What changed - Add `extends` to permission-profile TOML and resolve parent chains in inheritance order. - Merge inherited profile TOML with the existing config merge behavior while preserving the permission-specific normalization needed for network domain keys. - Keep parent descriptions out of resolved child profiles and record inherited profile names separately for downstream consumers. - Reject undefined parents, unsupported built-in parents, and inheritance cycles with targeted errors. - Cover resolver behavior with TOML fixture tests and refresh the generated config schema. ## Validation - `cargo test -p codex-config` - `cargo test -p codex-core permissions_profiles_`
viyatb-oai ·
2026-05-20 20:12:07 +00:00 -
feat: add permission profile list api (#23412)
## Why Clients need a typed permission-profile catalog instead of reconstructing that state from config internals. ## What changed - Added `permissionProfile/list` to the app-server v2 protocol with cursor pagination and optional `cwd`. - The list response includes built-in permission profiles plus config-defined `[permissions.<id>]` profiles from the effective config for the request context. - Permission profiles keep optional `description` metadata for display purposes. - App-server docs and schema fixtures are updated for the new RPC.
viyatb-oai ·
2026-05-20 02:42:56 +00:00 -
Add SubagentStart hook (#22782)
# What `SubagentStart` runs once when Codex creates a thread-spawned subagent, before that child sends its first model request. Thread-spawned subagents use `SubagentStart` instead of the normal root-agent `SessionStart` hook. Configured handlers match on the subagent `agent_type`, using the same value passed to `spawn_agent`. When no agent type is specified, Codex uses the default agent type. Hook input includes the normal session-start fields plus: - `agent_id`: the child thread id. - `agent_type`: the resolved subagent type. `SubagentStart` may return `hookSpecificOutput.additionalContext`. That context is added to the child conversation before the first model request. # Lifecycle Scope Only thread-spawned subagents run `SubagentStart`. Internal/system subagents such as Review, Compact, MemoryConsolidation, and Other do not run normal `SessionStart` hooks and do not run `SubagentStart`. This avoids exposing synthetic matcher labels for internal implementation paths. Also the `SessionStart` hook no longer fires for subagents, this matches behavior with other coding agents' implementation # Stack 1. This PR: add `SubagentStart`. 2. #22873: add `SubagentStop`. 3. #22882: add subagent identity to normal hook inputs.
Abhinav ·
2026-05-19 12:45:08 -07:00 -
Make
denycanonical for filesystem permission entries (#23493)## Why Filesystem permission profiles used `none` for deny-read entries, which is less direct than the action the entry actually represents. This change makes `deny` the canonical filesystem permission spelling while preserving compatibility for older configs that still send `none`. ## What changed - rename `FileSystemAccessMode::None` to `Deny` - serialize and generate schemas with `deny` as the canonical value - retain `none` only as a legacy input alias for temporary config compatibility - update filesystem glob diagnostics and regression coverage to use the canonical spelling - refresh config and app-server schema fixtures to match the new wire shape ## Validation - `cargo test -p codex-protocol` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-core config_toml_deserializes_permission_profiles --lib` - `cargo test -p codex-core read_write_glob_patterns_still_reject_non_subpath_globs --lib` Earlier in the session, a broad `cargo test -p codex-core` run reached unrelated pre-existing failures in timing/snapshot/git-info tests under this environment; the targeted surfaces touched by this PR passed cleanly.
viyatb-oai ·
2026-05-19 11:03:47 -07:00 -
Add
body_after_prefixauto-compact token limit scope (#22870)## Why `model_auto_compact_token_limit` has only been able to budget the full active context. That makes it hard to set a small "growth since compaction" budget for sessions that preserve a large carried window prefix: the preserved prefix can consume the whole budget and force immediate repeated compaction. This PR adds an opt-in `body_after_prefix` scope so callers can apply `model_auto_compact_token_limit` to sampled output and later growth after the current carried prefix, while still forcing compaction before the full model context window is exhausted. ## What changed - Adds `AutoCompactTokenLimitScope` with the existing `total` behavior as the default and a new `body_after_prefix` mode: [`config_types.rs`](https://github.com/openai/codex/blob/973806b1cb35792555bead994cb3ed94656eb171/codex-rs/protocol/src/config_types.rs#L24-L37). - Threads `model_auto_compact_token_limit_scope` through config loading, `Config`, `core-api`, and app-server v2 schema/TypeScript generation. - Records the first observed input-token count for a `body_after_prefix` compaction window and uses it as the baseline when deciding whether the scoped auto-compaction budget is exhausted: [`turn.rs`](https://github.com/openai/codex/blob/973806b1cb35792555bead994cb3ed94656eb171/codex-rs/core/src/session/turn.rs#L743-L781). - Keeps a hard context-window cap in `body_after_prefix`, so scoped budgeting cannot let the active context overrun the usable window. ## Verification Added compact-suite coverage for the two key behaviors: `body_after_prefix` does not re-compact just because the carried prefix is larger than the scoped budget, and it still compacts when the total active context reaches the configured context window: [`compact.rs`](https://github.com/openai/codex/blob/973806b1cb35792555bead994cb3ed94656eb171/codex-rs/core/tests/suite/compact.rs#L3003-L3128).
jif-oai ·
2026-05-19 10:19:46 +00:00 -
Make multi-agent v2 tool namespace configurable (#23147)
## Summary - Add `features.multi_agent_v2.tool_namespace` with config/schema validation for Responses-compatible namespace values. - Thread the resolved namespace into `ToolsConfig` for normal turns and review turns. - Wrap MultiAgentV2 tool specs and registry names in the configured namespace when namespace tools are supported, while falling back to the plain tool names when they are not. ## Validation - `just fmt` - `just write-config-schema` - `cargo test -p codex-features multi_agent_v2_feature_config -- --nocapture` - `cargo test -p codex-core test_build_specs_multi_agent_v2 -- --nocapture` - `cargo test -p codex-core multi_agent_v2_config -- --nocapture` - `cargo test -p codex-core multi_agent_v2_rejects_invalid_tool_namespace -- --nocapture` - `cargo test -p codex-tools` - `git diff --check`
jif-oai ·
2026-05-17 15:27:43 +02:00 -
Forward apps MCP product SKU from Codex config (#22872)
This adds `apps_mcp_product_sku` as a toplevel config.toml key. We pass the given value as a header when listing MCPs for the client, allowing connectors to be filtered per product entry point. --------- Co-authored-by: Codex <noreply@openai.com>
Boyang Niu ·
2026-05-15 11:52:14 -07:00 -
[codex] Add opaque desktop config namespace (#22584)
## Summary - reserve an explicit opaque `desktop` namespace in `ConfigToml` - expose `desktop` directly in the app-server v2 `config/read` response - keep `config/value/write` and `config/batchWrite` as the only mutation seam for paths like `desktop.someKey` - regenerate the config/app-server schema outputs and document the new contract ## Why The desktop settings work wants one durable, user-editable home for app-owned preferences in `~/.codex/config.toml`, without forcing Rust to model every individual desktop setting key. This PR is only the enabling Rust/app-server layer. It gives the Electron app a first-class config namespace it can read and write through the existing config APIs, while leaving the actual desktop migration to the app PR. ## Behavior and design notes - **Opaque but explicit:** `desktop` is first-class at the typed config root, while its children remain app-owned and open-ended. - **Strict validation still works:** arbitrary nested `desktop.*` keys are accepted instead of being rejected as unknown config. - **Existing config APIs stay the seam:** `config/read` returns the bag, and dotted writes such as `desktop.someKey` continue to flow through `config/value/write` / `config/batchWrite` rather than a bespoke RPC. - **No new consumer behavior:** Core/TUI do not start depending on desktop preferences. This only preserves and exposes the namespace for callers that intentionally use it. - **Same persistence machinery:** hand-edited `config.toml` keeps using the existing TOML edit/write path; this PR does not introduce a second serializer or side channel. - **TOML-friendly values:** the namespace is intended for ordinary JSON-shaped setting values that map cleanly into TOML: strings, numbers, booleans, arrays, and nested object/table values. This PR does not add special handling for TOML-only edge cases such as datetimes. ## Layering semantics Reads keep using the ordinary effective config pipeline, so `desktop` participates in the same layered `config/read` behavior as the rest of `ConfigToml`. Writes still target user config through the existing config service. ## Why this is the shape The alternative would be teaching Rust about each desktop setting as it is added. That would make ordinary app preferences into a cross-repo change, which is exactly the coupling we want to avoid. This keeps the contract small: 1. Rust owns one opaque `desktop` namespace in `config.toml`. 2. The desktop app owns the schema and meaning of individual keys inside it. 3. The existing config APIs remain the transport and mutation surface. That is the piece the desktop settings PR needs in order to move forward cleanly. ## Verification - `cargo test -p codex-config strict_config_accepts_opaque_desktop_keys` - `cargo test -p codex-core desktop_toml_round_trips_opaque_nested_values` - `cargo test -p codex-core config_schema_matches_fixture` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server --test all desktop_settings`
guinness-oai ·
2026-05-15 02:34:21 +00:00 -
permissions: support workspace roots in profiles (#22610)
## Why This is the configuration/model half of the alternative permissions migration we discussed as a comparison point for [#22401](https://github.com/openai/codex/pull/22401) and [#22402](https://github.com/openai/codex/pull/22402). The old `workspace-write` model mixes three concerns that we want to keep separate: - reusable profile rules that should stay immutable once selected - user/runtime workspace roots from `cwd`, `--add-dir`, and legacy workspace-write config - internal Codex writable roots such as memories, which should not be shown as user workspace roots This PR gives permission profiles first-class `workspace_roots` so users can opt multiple repositories into the same `:workspace_roots` rules without using broad absolute-path write grants. It also starts separating the raw selected profile from the effective runtime profile by making `Permissions` expose explicit accessors instead of public mutable fields. A representative `config.toml` looks like this: ```toml default_permissions = "dev" [permissions.dev.workspace_roots] "~/code/openai" = true "~/code/developers-website" = true [permissions.dev.filesystem.":workspace_roots"] "." = "write" ".codex" = "read" ".git" = "read" ".vscode" = "read" ``` If Codex starts in `~/code/codex` with that profile selected, the effective workspace-root set becomes: - `~/code/codex` from the runtime `cwd` - `~/code/openai` from the profile - `~/code/developers-website` from the profile The `:workspace_roots` rules are materialized across each root, so `.git`, `.codex`, and `.vscode` stay scoped the same way everywhere. Runtime additions such as `--add-dir` can still layer on later stack entries without mutating the selected profile. ## Stack Shape This PR intentionally stops before the profile-identity cleanup in [#22683](https://github.com/openai/codex/pull/22683) so the base review stays focused on config loading, workspace-root materialization, and compatibility with legacy `workspace-write`. The representation in this PR is therefore transitional: `Permissions` carries enough state to distinguish the raw constrained profile from the effective runtime profile, and there are still call sites that must keep the active profile identity and constrained profile value in sync. The follow-up PR replaces that with a single resolved profile state (`ResolvedPermissionProfile` / `PermissionProfileState`) that keeps the profile id, immutable `PermissionProfile`, and profile-declared workspace roots together. That follow-up removes APIs such as `set_constrained_permission_profile_with_active_profile()` where separate arguments could drift out of sync. Downstream PRs then build on this base to switch app-server turn updates to profile ids plus runtime workspace roots and to finish the user-visible summary behavior. Reviewers should judge this PR as the workspace-roots foundation, not as the final in-memory shape of selected permission profiles. ## Review Guide Suggested review order: 1. Start with `codex-rs/core/src/config/mod.rs`. This is the main shape change in the base slice. `Permissions` now stores a private raw `Constrained<PermissionProfile>` plus runtime `workspace_roots`. Callers use `permission_profile()` when they need the raw constrained value and `effective_permission_profile()` when they need a materialized runtime profile. As noted above, [#22683](https://github.com/openai/codex/pull/22683) replaces this transitional shape with a resolved profile state that keeps identity and profile data together. 2. Review `codex-rs/config/src/permissions_toml.rs` and `codex-rs/core/src/config/permissions.rs`. These add `[permissions.<id>.workspace_roots]`, resolve enabled entries relative to the policy cwd, and keep `:workspace_roots` deny-read glob patterns symbolic until the actual roots are known. 3. Review `codex-rs/protocol/src/permissions.rs` and `codex-rs/protocol/src/models.rs`. These add the policy/profile materialization helpers that expand exact `:workspace_roots` entries and scoped deny-read globs over every workspace root. This is also where `ActivePermissionProfileModification` is removed from the core model. 4. Review the legacy bridge in `Config::load_from_base_config_with_overrides` and `Config::set_legacy_sandbox_policy`. This is where legacy `workspace-write` roots become runtime workspace roots, while Codex internal writable roots stay internal and do not appear as user-facing workspace roots. 5. Then skim downstream call sites. The interesting pattern is raw-vs-effective access: state/proxy/bwrap paths keep the raw constrained profile, while execution, summaries, and user-visible status use the effective profile and workspace-root list. ## What Changed - added `[permissions.<id>.workspace_roots]` to the config model and schema - added runtime `workspace_roots` state to `Config`/`Permissions` and `ConfigOverrides` - made `Permissions` profile fields private and replaced direct mutation with accessors/setters - added `PermissionProfile` and `FileSystemSandboxPolicy` helpers for materializing `:workspace_roots` exact paths and deny-read globs across all roots - moved legacy additional writable roots into runtime workspace-root state instead of active profile modifications - removed `ActivePermissionProfileModification` and its app-server protocol/schema export - updated sandbox/status summary paths so internal writable roots are not reported as user workspace roots ## Verification Strategy The targeted tests cover the behavior at the layers where regressions are most likely: - `codex-rs/core/src/config/config_tests.rs` verifies config loading, legacy workspace-root seeding, effective profile materialization, and memory-root handling. - `codex-rs/core/src/config/permissions_tests.rs` verifies profile `workspace_roots` parsing and `:workspace_roots` scoped/glob compilation. - `codex-rs/protocol/src/permissions.rs` unit tests verify exact and glob materialization over multiple workspace roots. - `codex-rs/tui/src/status/tests.rs` and `codex-rs/utils/sandbox-summary/src/sandbox_summary.rs` verify the user-facing summaries show effective workspace roots and hide internal writes. I also ran `cargo check --tests` locally after the latest stack refresh to catch cross-crate API breakage from the private-field/accessor changes. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/22610). * #22612 * #22611 * #22683 * __->__ #22610
Michael Bolin ·
2026-05-14 18:25:23 -07:00 -
chore(config) rm windows_wsl_setup_acknowledged (#22717)
## Summary Remove dead code from a notice that no longer exists. ## Testing - [x] Unit tests pass.
Dylan Hurd ·
2026-05-14 23:25:15 +00:00 -
chore(features) rm Feature::ApplyPatchFreeform (#22711)
## Summary Removes the feature since this is effectively on by default in all cases where we should use it, or can be configured via models.json. ## Testing - [x] unit tests pass
Dylan Hurd ·
2026-05-14 16:15:56 -07:00 -
[codex] Support multiple forced ChatGPT workspaces (#18161)
## Summary This change lets `forced_chatgpt_workspace_id` accept multiple workspace IDs instead of a single value. It keeps the existing config key name, adds backward-compatible parsing for a single string in `config.toml`, and normalizes the setting into an allowed workspace list across login enforcement, app-server config surfaces, and local ChatGPT auth helpers. ## Why Workspace-restricted deployments may need to allow more than one ChatGPT workspace without dropping the guardrail entirely. ## Server-side impact Codex's local server and app-server protocol needed changes because they previously assumed a single workspace ID. The local login flow now matches the auth backend interface by sending the allowed workspace list as a single comma-separated `allowed_workspace_id` query parameter. ## Validation This was tested with: - A single workspace config - With multi-workspace configs - With multiple workspaces in the config - The user only being a part of a subset of them All were successful. Automated coverage: - `cargo test -p codex-login` - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-tui local_chatgpt_auth` - `cargo test --locked -p codex-app-server login_account_chatgpt_includes_forced_workspace_allowlist_query_param`
rreichel3-oai ·
2026-05-14 17:11:36 -04:00 -
Support explicit MCP OAuth client IDs (#22575)
## Why Some MCP OAuth providers require a pre-registered public client ID and cannot rely on dynamic client registration. Codex already supports MCP OAuth, but it had no way to supply that client ID from config into the PKCE flow. ## What changed - add `oauth.client_id` under `[mcp_servers.<server>]` config, including config editing and schema generation - thread the configured client ID through CLI, app-server, plugin login, and MCP skill dependency OAuth entrypoints - configure RMCP authorization with the explicit client when present, while preserving the existing dynamic-registration path when it is absent - add focused coverage for config parsing/serialization and OAuth URL generation ## Verification - `cargo test -p codex-config -p codex-rmcp-client -p codex-mcp -p codex-core-plugins` - `cargo test -p codex-core blocking_replace_mcp_servers_round_trips --lib` - `cargo test -p codex-core replace_mcp_servers_streamable_http_serializes_oauth_resource --lib` - `cargo test -p codex-core config_schema_matches_fixture --lib` ## Notes Broader local package runs still hit unrelated pre-existing stack overflows in: - `codex-app-server::in_process_start_clamps_zero_channel_capacity` - `codex-core::resume_agent_from_rollout_uses_edge_data_when_descendant_metadata_source_is_stale`
Matthew Zeng ·
2026-05-14 11:52:43 -07:00 -
chore(config) rm experimental_use_freeform_apply_patch (#22565)
## Summary Get rid of the `experimental_use_freeform_apply_patch` config option, since it is now encoded in model config. No deprecation message since it has been experimental this entire time. ## Testing - [x] Updated unit tests --------- Co-authored-by: Codex <noreply@openai.com>
Dylan Hurd ·
2026-05-13 17:52:15 -07:00 -
Make multi_agent_v2 wait_agent timeouts configurable (#22528)
## Why `multi_agent_v2` already allowed configuring the minimum `wait_agent` timeout, but the default timeout and upper bound were still hard-coded. That made it hard to tune waits for subagent mailbox activity in sessions that need either faster wakeups or longer waits, and it meant the model-visible `wait_agent` schema could not fully reflect the resolved runtime limits. ## What Changed - Added `features.multi_agent_v2.max_wait_timeout_ms` and `features.multi_agent_v2.default_wait_timeout_ms` alongside the existing `min_wait_timeout_ms` setting. - Validated all three timeouts in config as `0..=3_600_000`, with `min_wait_timeout_ms <= default_wait_timeout_ms <= max_wait_timeout_ms`. - Thread and review session tool config now passes the resolved min/default/max values into the `wait_agent` tool schema. - `wait_agent` now uses the configured default when `timeout_ms` is omitted and rejects explicit values outside the configured min/max range instead of silently clamping them. - Updated the generated config schema and config-lock test coverage for the new fields.
Andrey Mishchenko ·
2026-05-13 14:43:06 -07:00 -
chore(config) rm tools.view_image (#22501)
## Summary It appears this config flag has been broken/a noop for quite some time: since https://github.com/openai/codex/pull/8850. Let's simplify and get rid of this. ## Testing - [x] Updated unit tests
Dylan Hurd ·
2026-05-13 12:35:37 -07:00 -
chore(config) rm Feature::CodexGitCommit (#22412)
## Summary Removes the unused Feature::CodexGitCommit ## Testing - [x] tests pass
Dylan Hurd ·
2026-05-13 12:33:36 -07:00 -
feat: expose multi-agent v2 as model-only tools (#22514)
## Why `code_mode_only` filters code-mode nested tools out of the top-level tool list. For multi-agent v2, we need a rollout shape where the collaboration tools remain callable as normal model tools without also being embedded into the code-mode `exec` tool declaration. Related to this: https://openai-corpws.slack.com/archives/C0AQLHB4U75/p1778660267922549 ## What Changed - Adds `features.multi_agent_v2.non_code_mode_only`, including config resolution, profile override handling, and generated schema coverage. - Introduces `ToolExposure::DirectModelOnly` so a tool can be included in the initial model-visible list while staying out of the nested code-mode tool surface. - Applies that exposure to the multi-agent v2 tools when the new flag is set: `spawn_agent`, `send_message`, `followup_task`, `wait_agent`, `close_agent`, and `list_agents`. - Updates code-mode-only filtering so direct-model-only tools remain visible while ordinary nested code-mode tools are still hidden. ## Verification - Added config parsing/profile tests for `non_code_mode_only`. - Added tool spec coverage for the code-mode-only multi-agent v2 exposure behavior.
jif-oai ·
2026-05-13 19:49:47 +02:00 -
[codex] Remove unused legacy shell tools (#22246)
## Why Recent session history showed no active use of the raw `shell`, `local_shell`, or `container.exec` execution surfaces. Keeping those handlers/specs wired into core leaves duplicate shell execution paths alongside the supported `shell_command` and unified exec tools. ## What changed - Removed the raw `shell` handler/spec and its `ShellToolCallParams` protocol helper. - Removed the legacy `local_shell` and `container.exec` handler/spec plumbing while preserving persisted-history compatibility for old response items. - Normalized model/config `default` and `local` shell selections to `shell_command`. - Pruned tests that exercised removed raw-shell/local-shell/apply-patch variants and kept coverage on `shell_command`, unified exec, and freeform `apply_patch`. ## Verification - `git diff --check` - `cargo test -p codex-protocol` - `cargo test -p codex-tools` - `cargo test -p codex-core tools::handlers::shell` - `cargo test -p codex-core tools::spec` - `cargo test -p codex-core tools::router` - `cargo test -p codex-core active_call_preserves_triggering_command_context` - `cargo test -p codex-core guardian_tests` - `cargo test -p codex-core --test all shell_serialization` - `cargo test -p codex-core --test all apply_patch_cli` - `cargo test -p codex-core --test all shell_command_` - `cargo test -p codex-core --test all local_shell` - `cargo test -p codex-core --test all otel::` - `cargo test -p codex-core --test all hooks::` - `just fix -p codex-core` - `just fix -p codex-tools`
pakrym-oai ·
2026-05-13 16:43:25 +00:00 -
feat(tui): standardize picker navigation keys (#22347)
## Why Picker-style UI in the TUI has accumulated a mix of hardcoded navigation keys. Some lists supported page movement, some did not; some accepted Vim-like keys, while others only accepted arrows; and tabbed or horizontally adjustable pickers had no shared keymap action for left/right movement. This PR makes picker/list navigation consistent and configurable so users can rely on the same defaults across the TUI. ## What Changed - Adds shared list keymap actions for: - vertical movement: `move_up`, `move_down` - horizontal movement: `move_left`, `move_right` - paging and jumps: `page_up`, `page_down`, `jump_top`, `jump_bottom` - Adds defaults: - Up/down: arrows, `Ctrl+P/N`, `Ctrl+K/J`, and plain `k/j` where text input is not active - Page up/down: `PageUp/PageDown` and `Ctrl+B/F` - First/last: `Home/End` - Left/right: `Left/Right` and `Ctrl+H/L` - Wires the shared list keymap through picker and list surfaces including session resume, multi-select, tabbed selection lists, settings-style lists, app-link selection, MCP elicitation, request-user-input, and the OSS selection wizard. - Keeps search behavior intact by reserving printable characters for query text in searchable pickers. - Updates keymap setup actions, config schema, snapshots, and focused coverage for the new list actions. ## How to Test 1. Start Codex from this branch and open the session picker, for example with an existing session history. 2. In the session list, verify that `Ctrl+J/K` moves the selection down/up. 3. Verify that `Ctrl+F/B` pages down/up and `Home/End` jumps to the first/last visible session. 4. Type printable search text such as `j` or `k` and confirm it updates the query instead of navigating. 5. Focus a picker control that changes values horizontally, such as a session picker toolbar control, and verify `Ctrl+H/L` changes the focused value like left/right arrows. Targeted tests run: - `cargo test -p codex-tui keymap::tests::` - `cargo test -p codex-tui keymap_setup::tests::` - `cargo test -p codex-tui horizontal_list_keys` - `cargo test -p codex-tui page_and_jump_navigation_use_list_keymap` - `cargo test -p codex-tui ctrl_h_l_move_provider_selection` - `cargo test -p codex-tui scroll_state::tests` - `cargo test -p codex-tui switching_tabs_changes_visible_items_and_clears_search` - `cargo test -p codex-tui toggle_sort_key_reloads_with_new_sort` Also ran `just write-config-schema`, `just fmt`, `just fix -p codex-tui`, `just argument-comment-lint`, and `git diff --check`. Note: `cargo test -p codex-tui` was attempted and still aborts in the pre-existing `tests::fork_last_filters_latest_session_by_cwd_unless_show_all` stack overflow, which is unrelated to this branch.
Felipe Coury ·
2026-05-13 15:33:27 +00:00 -
feat(tui): remove Zellij TUI workarounds (#22214)
## Why We added Zellij-specific TUI workarounds because older Zellij behavior did not work with Codex's normal terminal model: - #8555 made `tui.alternate_screen = "auto"` disable alternate screen in Zellij so transcript history stayed available. - #16578 avoided scroll-region operations in Zellij by emitting raw newlines and using a separate composer styling path. This PR removes both workarounds because the latest Zellij release tested locally (`zellij 0.44.1`) works correctly with Codex's standard TUI behavior: normal alternate-screen handling, redraw, and history insertion. ## What Changed - Removed the `InsertHistoryMode::Zellij` path and the Zellij-only newline scrollback insertion behavior. - Removed cached `is_zellij` state from the TUI and composer. - Removed Zellij-specific composer styling, the helper snapshot, and the `TerminalInfo::is_zellij()` convenience method that only served this workaround. - Changed `tui.alternate_screen = "auto"` to use alternate screen for Zellij too; `--no-alt-screen` and `tui.alternate_screen = "never"` still preserve the inline mode escape hatch. - Updated the generated config schema description for `tui.alternate_screen`. ## How to Test Manual smoke path used with `zellij 0.44.1`: 1. Build and run this branch inside a Zellij `0.44.1` session with default config. 2. Start Codex normally and produce enough assistant/tool output to create scrollback. 3. Confirm the transcript remains readable, the composer renders normally, and scrolling through terminal history works. 4. Resize the Zellij pane while output exists and confirm the TUI redraws without duplicated, missing, or stale rows. 5. Compare with `--no-alt-screen` or `-c tui.alternate_screen=never` if you want to verify the inline fallback still works. Targeted tests: - `just write-config-schema` - `just fmt` - `just fix -p codex-tui` - `cargo test -p codex-terminal-detection` - `cargo test -p codex-tui alternate_screen_auto_uses_alt_screen` Attempted but did not complete locally: - `cargo test -p codex-tui` built and ran the new test successfully, then failed later on unrelated local failures in `status_permissions_full_disk_managed_*` and a stack overflow in `tests::fork_last_filters_latest_session_by_cwd_unless_show_all`. ## Documentation No developers.openai.com Codex documentation update is needed for this revert.
Felipe Coury ·
2026-05-13 12:11:15 -03:00