mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
f35285dc7839bbd2c258e8dfae2aa5b2cbf54ae9
6162 Commits
-
Add Windows sandbox readiness RPC (#20708)
## Why The desktop app on Windows needs a read-only way to tell, before the next tool call, whether the local Windows sandbox setup is in a state that should block the user and ask for setup again. The main case we want to cover is the elevated sandbox setup version bump. Today, if the app is configured for elevated Windows sandboxing and the installed setup is stale, the next sandboxed shell/exec path can end up triggering the elevated setup flow directly. That means the user can see an unexpected UAC prompt with no UI explanation. This change adds a small app-server preflight so the desktop app can ask “is Windows sandbox ready, not configured, or update-required?” during startup and show the appropriate blocking UI before the user hits a tool call. ## What changed - Added a new read-only app-server RPC: `windowsSandbox/readiness` - Added a new protocol enum and response type: - `WindowsSandboxReadiness` - `WindowsSandboxReadinessResponse` - Added core readiness logic in `core/src/windows_sandbox.rs`: - `ready` - `notConfigured` - `updateRequired` - Wired the new request through `codex_message_processor` - Regenerated the vendored app-server schema fixtures ## Readiness semantics This is intentionally a coarse startup/version-bump readiness check, not a full predictor of every runtime repair case. For now, readiness is determined from: - the configured Windows sandbox level - `sandbox_setup_is_complete()` for elevated mode That means: - `disabled` maps to `notConfigured` - `restricted token` maps to `ready` - `elevated` maps to `ready` or `updateRequired` depending on `sandbox_setup_is_complete()` This is deliberate for the first UI integration because the common case we want to catch is “the app updated, the elevated setup version bumped, and the user should see an update-required blocker instead of a surprise UAC prompt”. It does not attempt to model every case where the deeper runtime path might decide to repair or re-run setup. ## Testing - Ran `cargo fmt --all -- app-server-protocol/src/protocol/common.rs app-server-protocol/src/protocol/v2.rs app-server/src/codex_message_processor.rs core/src/windows_sandbox.rs core/src/windows_sandbox_tests.rs` - Added unit tests for the pure readiness mapping in `core/src/windows_sandbox_tests.rs` - Regenerated vendored schema fixtures with `cargo run -p codex-app-server-protocol --bin write_schema_fixtures -- --schema-root app-server-protocol/schema` - Did not run the full cargo test suite
iceweasel-oai ·
2026-05-05 09:58:23 -07:00 -
Validate /goal objective length in TUI (#20746)
## Why Long `/goal` definitions currently reach lower-level goal validation and can produce an opaque failure. This bug was reported by a user. Pasted instruction blocks are especially confusing because the composer can still contain a paste placeholder before expansion, which may otherwise fall into the generic prompt-size error path. There was also a related paste edge case where `/goal ` followed by a multiline block whose first pasted line was blank looked like a bare `/goal` command. That showed the goal usage/summary instead of setting the pasted objective. ## What Changed This adds TUI-side preflight validation for `/goal <objective>` using the shared `MAX_THREAD_GOAL_OBJECTIVE_CHARS` limit. Oversized typed, queued, and pasted goal objectives now fail locally with a goal-specific message that recommends putting longer instructions in a file and referencing that file from the goal. The TUI now also lets inline-argument slash commands consume later-line arguments before treating the first line as a bare command, so `/goal ` followed by blank lines and then objective text sets the goal instead of opening the bare `/goal` flow. ## Manual Testing 1. Start the TUI with goals enabled and an active session. 2. Submit `/goal ` followed by exactly 4,000 objective characters. It should continue through the normal goal-setting path. 3. Submit `/goal ` followed by 4,001 objective characters. It should not set a goal, and should show `Goal objective is too long: 4,001 characters. Limit: 4,000 characters.` followed by the guidance to put longer instructions in a file and reference that file from the goal. 4. Type `/goal `, paste a large block that becomes a `[Pasted Content ... chars]` placeholder, then submit. It should validate the expanded pasted text and show the goal-specific file guidance rather than the generic prompt-size error. 5. Type `/goal `, paste a multiline block whose first line is blank, then submit. It should set the objective from the non-blank pasted content instead of showing `Usage: /goal <objective>` or the bare goal summary. 6. While a turn is running, queue an oversized `/goal` command. When the queue drains, it should show the same goal-specific error and should not emit a goal-setting request.
Eric Traut ·
2026-05-05 09:55:07 -07:00 -
Add goal lifecycle metrics (#20799)
## Why Adding goal metrics makes it possible to track how often goals are created, completed, and stopped by budget limits, plus the final token and wall-clock usage for terminal outcomes. ## What Changed - Added OpenTelemetry metric constants for goal lifecycle tracking: - `codex.goal.created`: increments each time a new persisted goal is created or an existing goal is replaced with a new objective. - `codex.goal.completed`: increments when a goal transitions to `complete`. - `codex.goal.budget_limited`: increments when a goal transitions to `budget_limited` because its token budget has been reached. - `codex.goal.token_count`: records the final persisted token count when a goal transitions to `complete` or `budget_limited`. - `codex.goal.duration_s`: records the final persisted elapsed wall-clock time, in seconds, when a goal transitions to `complete` or `budget_limited`. - Emitted creation metrics when a goal is created or replaced. - Emitted terminal outcome counters and final usage histograms when a goal transitions to `complete` or `budget_limited`, avoiding double-counting later in-flight accounting for already budget-limited goals. - Added focused `codex-core` tests for create/complete metrics and one-time budget-limit metrics.
Eric Traut ·
2026-05-05 09:21:54 -07:00 -
fix(tui): make /copy work inside tmux without passthrough (#20207)
## Summary - prefer tmux's native clipboard integration for `/copy` when running inside tmux - fall back to OSC 52 when tmux clipboard copy is unavailable - add coverage for tmux-preferred, fallback, and combined-failure paths ## Why Inside tmux, `/copy` previously relied on DCS-wrapped OSC 52 when `TMUX` was set. That only reaches the outer terminal when tmux passthrough is enabled, so Codex could report success even though the system clipboard never changed. ## User impact `/copy` now works inside tmux even when `allow-passthrough` is off, as long as tmux clipboard integration is available. If tmux cannot handle the copy, Codex still keeps the existing OSC 52 fallback path. ## Validation - `cargo test -p codex-tui` - `just fmt` - `just fix -p codex-tui` - `just argument-comment-lint` - manually verified `/copy` inside tmux with `allow-passthrough off` Fixes #19926
Felipe Coury ·
2026-05-05 16:18:02 +00:00 -
feat: add normalized matching to memory search (#21205)
## Why Memory search currently treats separators literally, so callers need to know whether a stored term uses spaces, hyphens, or no separators at all. That makes recall brittle for terms such as `MultiAgentV2` vs. `multi agent v2` and `cold-resume` vs. `cold resume`. ## What changed - Add an opt-in `normalized` mode to memory search that removes non-alphanumeric separators after any requested case folding. - Thread the new flag through the MCP `search` tool into the local backend while keeping existing literal matching as the default. - Reject queries that normalize to an empty string, and add regression coverage for both normalized matching and that validation path. ## Testing - `cargo test -p codex-memories-mcp`
jif-oai ·
2026-05-05 17:33:07 +02:00 -
feat: support windowed multi-query memory search (#21204)
## Why Memory search currently supports either independent substring matches or requiring every query to appear on the same line. That is too restrictive for memory files where related terms often land on nearby lines in the same note or bullet block. ## What changed - Replace the old `all` match mode with explicit tagged modes: `all_on_same_line` and `all_within_lines { line_count }`. - Add windowed matching in `codex-rs/memories/mcp/src/local.rs` so callers can require every query to appear within a bounded line range while returning only the minimal qualifying windows. - Reject invalid zero-width windows and update the MCP tool description plus argument parsing to expose the new mode. - Add coverage for same-line matching, windowed matching, and invalid `line_count` input. ## Verification - Added targeted coverage in `codex-rs/memories/mcp/src/local_tests.rs` for `search_supports_all_within_lines_match_mode` and `search_rejects_zero_line_window`. - Added server-side parsing coverage in `codex-rs/memories/mcp/src/server.rs` for `search_args_accept_windowed_all_match_mode`.jif-oai ·
2026-05-05 17:15:21 +02:00 -
memories-mcp: hide dot paths from list, read, and search (#21201)
## Why The local memories root can contain implementation details such as `.git` plus incidental OS metadata like `.DS_Store`. Those entries are not authored memory content, so the memories MCP should keep them invisible instead of exposing them through normal discovery or direct lookup. Only for local implementation ofc ## What changed - Return `NotFound` for scoped `list`, `read`, and `search` requests that include a hidden path component. - Skip hidden files and directories while listing a directory or recursively searching the memories tree. - Add regression coverage for hidden files, hidden directories, and hidden scoped requests across `list`, `read`, and `search`. ## Testing - Added focused regression tests in `memories/mcp/src/local_tests.rs` covering hidden-path behavior across the affected APIs.
jif-oai ·
2026-05-05 16:59:05 +02:00 -
tools: remove unused experimental
list_dirtool (#21170)## Why `list_dir` still carries a full spec/handler/test path, but nothing in the current model catalog advertises it via `experimental_supported_tools`. That leaves us maintaining an environment-backed tool surface that is effectively unused. ## What changed - delete the `list_dir` handler and its tests from `codex-core` - remove the `list_dir` spec builder, handler kind, and registry wiring from `codex-tools` - clean up the remaining internal README and registry tests so they no longer mention the removed tool
jif-oai ·
2026-05-05 13:11:07 +02:00 -
1- Add model service tiers metadata (#20969)
## Why The model list needs to carry display-ready service tier metadata so clients can render tier choices with stable IDs, names, and descriptions. A raw speed-tier string list is not enough for richer UI copy or future tier labels. ## What changed - Added `ModelServiceTier` to shared model metadata with string `id`, `name`, and `description` fields. - Added `service_tiers` to `ModelInfo` and `ModelPreset`, preserving empty defaults for older cached model payloads. - Exposed `serviceTiers` on app-server v2 `Model` responses and threaded it through TUI app-server model conversion. - Marked legacy `additional_speed_tiers` / `additionalSpeedTiers` metadata as deprecated in source and generated schema output. - Regenerated app-server protocol JSON schema and TypeScript fixtures, including `ModelServiceTier.ts`. ## Verification - Ran `just write-app-server-schema`. - Did not run local tests per repo instruction; relying on PR CI. --------- Co-authored-by: Codex <noreply@openai.com>
Ahmed Ibrahim ·
2026-05-05 09:51:18 +03:00 -
Spill large hook outputs from context (#21069)
## Why Large hook outputs can enter model-visible context through hook-specific paths such as `additionalContext` and `Stop` continuation prompts. Without a dedicated cap, one hook can inject a large blob directly into conversation history instead of leaving a bounded preview for the model and preserving the full text elsewhere. ## What - spill hook text once it exceeds a fixed `2_500`-token budget, preserving the full output on disk and leaving a head/tail preview plus saved path in context - add shared hook-output spilling under `CODEX_HOME/hook_outputs/<thread_id>/<uuid>.txt` - apply the cap to both `additionalContext`, `feedback_message`, and `Stop` continuation fragments
Abhinav ·
2026-05-05 05:03:18 +00:00 -
codex: migrate (more) app-server thread history reads to ThreadStore (#20575)
Migrate token usage replay, rollback responses, and detached review setup (a special case of forking) to be served from ThreadStore reads rather direct rollout files. - replay restored token usage from already-loaded `RolloutItem` history instead of reopening `Thread.path` - rebuild rollback responses from loaded `ThreadStore` snapshots and history - start detached reviews from store-backed parent history and stored review-thread metadata - remove obsolete app-server rollout-summary helper code that became dead after the store-backed migration - preserve response/notification ordering for resume, fork, rollback, and detached review flows - add integration test coverage for the affected paths
Tom ·
2026-05-04 21:16:50 -07:00 -
edwardysun3 ·
2026-05-05 00:11:06 -04:00 -
Add plugin ID to skill analytics (#20923)
## Summary - thread plugin skill roots through the skills loader with their plugin ID - store plugin ID on loaded skill metadata for plugin-provided skills - include plugin ID on skill invocation analytics events ## Test plan - cargo check -p codex-core-skills - cargo check -p codex-core -p codex-core-plugins -p codex-analytics - cargo check -p codex-tui - cargo check -p codex-plugin -p codex-core -p codex-core-plugins -p codex-analytics - cargo check -p codex-app-server - cargo test -p codex-analytics - HOME=/private/tmp/codex-empty-home cargo test -p codex-core-skills - just fix -p codex-core-skills - just fix -p codex-analytics - just fix -p codex-core-plugins - just fix -p codex-core - just fmt - git diff --check
alexsong-oai ·
2026-05-04 20:36:29 -07:00 -
codex: route metadata updates through ThreadStore (#20576)
- Route `thread/metadata/update` through `ThreadStore::update_thread_metadata`. - Add `LocalThreadStore` git metadata patch support for set, partial update, and clear semantics. - Add some unit tests for the new thread store code - Remove a lot of dead code/tests!
Tom ·
2026-05-04 20:09:41 -07:00 -
Rename agent identity login surface to access token (#21059)
## Why The external startup/login surface for this auth path should talk about an access token instead of exposing the internal Agent Identity terminology. Users should pass `CODEX_ACCESS_TOKEN` or pipe a token into `codex login --with-access-token`; the old external env/flag spellings are removed so there is only one supported user-facing path. ## What Changed - Added `CODEX_ACCESS_TOKEN` as the supported environment variable for this auth path. - Added `codex login --with-access-token` as the supported stdin-based login command. - Removed the legacy `CODEX_AGENT_IDENTITY` env-var fallback and hidden `--with-agent-identity` CLI alias. - Updated CLI error, status, and stdin prompts to use access-token language. - Added coverage for access-token env loading, CLI login failure behavior, and renamed login status text. ## Validation - `cargo test -p codex-login` - `cargo test -p codex-cli` - `just fix -p codex-login` - `just fix -p codex-cli`
Shijie Rao ·
2026-05-04 19:43:48 -07:00 -
[network-proxy] Cover DNS timeout blocking (#21105)
## Summary - Add a testable DNS lookup helper for the local or private host precheck while preserving production `lookup_host` behavior. - Add deterministic coverage for DNS timeout, lookup error, private resolution, and public resolution decisions. - Keep BUGB 15982 guarded without relying on ambient DNS timing or resolver behavior. ## Why BUGB 15982 was fixed by failing closed on DNS lookup errors and timeouts. The existing regression covered lookup failure through real DNS, but did not deterministically exercise the timeout branch. This PR adds a small injection point so CI can cover that branch without standing up slow authoritative DNS. ## Validation - `cargo test -p codex-network-proxy host_resolves_to_non_public_ip -- --nocapture` - `cargo test -p codex-network-proxy host_blocked_rejects_allowlisted_hostname_when_dns_lookup_fails -- --nocapture` - `cargo test -p codex-network-proxy` - `just fmt` - `just fix -p codex-network-proxy` - `git diff --check` ## Tickets - BUGB 15982 - https://linear.app/openai/issue/BUGB-15982/codex-dns-timeout-fail-open-in-codex-network-proxy-bypasses - Bugcrowd: https://tracker.bugcrowd.com/openai/submissions/b2bf131d-db04-478f-85aa-cdd17ca8f604
evawong-oai ·
2026-05-04 19:03:56 -07:00 -
[codex] Add unsandboxed process exec API (#19040)
## Why App-server clients sometimes need argv-based local process execution while sandbox policy is controlled outside Codex. Those environments can reject sandbox-disabling paths before a command ever starts, even when the caller intentionally wants unsandboxed execution. This PR adds a distinct `process/*` API for that use case instead of extending `command/exec` with another sandbox-disabling shape. Keeping the new surface separate also makes the future removal of `command/exec` simpler: clients that need explicit process lifecycle control can move to the newer handle-based API without depending on `command/exec` business logic. ## What changed - Added v2 process lifecycle methods: `process/spawn`, `process/writeStdin`, `process/resizePty`, and `process/kill`. - Added process notifications: `process/outputDelta` for streamed stdout/stderr chunks and `process/exited` for final exit status and buffered output. - Made `process/spawn` intentionally unsandboxed and omitted sandbox-selection fields such as `sandboxPolicy` and `permissionProfile`. - Added client-supplied, connection-scoped `processHandle` values for follow-up control requests and notification routing. - Supported cwd, environment overrides, PTY mode and size, stdin streaming, stdout/stderr streaming, per-stream output caps, and timeout controls. - Killed active process sessions when the originating app-server connection closes. - Wired the implementation through the modular `request_processors/` app-server layout, with process-handle request serialization for follow-up control calls. - Updated generated JSON/TypeScript schema fixtures and documented the new API in `codex-rs/app-server/README.md`. - Added v2 app-server integration coverage in `codex-rs/app-server/tests/suite/v2/process_exec.rs` for spawn acknowledgement before exit, buffered output caps, and process termination. ## Verification - `cargo test -p codex-app-server-protocol` - `cargo test -p codex-app-server` --------- Co-authored-by: Owen Lin <owen@openai.com>
Ruslan Nigmatullin ·
2026-05-04 16:43:58 -07:00 -
Remove remote plugin uninstall prefix gate (#20722)
## Summary Remove the hardcoded remote plugin ID prefix allow-list from app-server uninstall routing. IDs that do not parse as local `plugin@marketplace` IDs now flow through the remote uninstall path, where the existing remote ID safety validation still rejects empty IDs, spaces, slashes, and other unsafe characters before URL/cache use. ## Why Plugin-service owns the backend remote plugin ID contract. Codex should not require remote IDs to start with the local hardcoded prefixes `plugins~`, `plugins_`, `app_`, `asdk_app_`, or `connector_`, because newer backend ID families could otherwise be rejected before plugin-service sees the request. ## Validation - `just fmt` - `cargo test -p codex-app-server plugin_uninstall` - `just fix -p codex-app-server` - `git diff --check`
xli-oai ·
2026-05-04 16:28:13 -07:00 -
[codex-analytics] add item lifecycle timing (#20514)
## Why Tool families already disagree on what their existing `duration` fields mean, so lifecycle latency should live on the shared item envelope instead of being inferred from per-tool execution fields. Carrying that envelope through app-server notifications gives downstream consumers one reusable timing signal without pretending every tool has the same execution semantics. ## What changed - Adds `started_at_ms` to core `ItemStartedEvent` values and `completed_at_ms` to core `ItemCompletedEvent` values. - Populates those timestamps in the shared session lifecycle emitters, so protocol-native items get timing without each producer tracking its own clock state. - Exposes `startedAtMs` on app-server `item/started` notifications and `completedAtMs` on `item/completed` notifications. - Maps the lifecycle timestamps through the app-server boundary while leaving legacy-converted notifications nullable when no lifecycle timestamp exists. - Regenerates the app-server JSON schema and TypeScript fixtures for the notification-envelope change and updates downstream fixtures that construct those notifications directly. - Extends the existing web-search and image-generation integration flows to assert the new lifecycle timestamps on the native item events. ## Verification - `cargo check -p codex-protocol -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-tui -p codex-exec -p codex-app-server-client` - `cargo test -p codex-core --test all web_search_item_is_emitted` - `cargo test -p codex-core --test all image_generation_call_event_is_emitted` - `cargo test -p codex-app-server-protocol` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/20514). * #18748 * #18747 * #17090 * #17089 * __->__ #20514
rhan-oai ·
2026-05-04 22:33:20 +00:00 -
Make realtime sideband startup async (#20715)
## Summary Moves the WebRTC realtime sideband websocket join out of the voice start critical path. Call creation still posts the SDP offer and session config synchronously so the client gets the SDP answer, but the sideband websocket now connects in the input task async and doesn't block conversation state installation. This lets the normal realtime input channels buffer text, handoff output, and audio while the WebRTC sideband websocket is connecting. If the sideband join fails while the conversation is still active, the task sends a RealtimeEvent::Error through the existing events_tx / fanout path. To rephrase this: * No longer blocked on sideband: the client can receive the SDP answer earlier, set up the WebRTC peer connection, and let the media leg progress while the sideband websocket joins. * Still blocked on sideband: queued text, handoff output, and sideband server events cannot flow until connect_webrtc_sideband(...).await finishes and then run_realtime_input_task(...) starts ## Validation - `env CODEX_SKIP_VENDORED_BWRAP=1 cargo test --manifest-path codex-rs/Cargo.toml -p codex-core --test all conversation_webrtc_start_posts_generated_session` `CODEX_SKIP_VENDORED_BWRAP=1` is needed in this local environment because `libcap.pc` is not installed for the vendored bubblewrap build. ## Testing I tested this locally by running `cargo run -p codex-cli --bin codex -- --enable realtime_conversation` and invoking `/realtime`. Then, we get logs emitted in `~/.codex/log/codex-tui.log`. ### Before the Change Logging commit (https://github.com/openai/codex/commit/c0299e6edf1222fa0c43c1796e4811976c26fecd) ``` 2026-05-04T16:06:09.251956Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: starting realtime conversation 2026-05-04T16:06:09.251980Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: creating realtime call transport="webrtc" 2026-05-04T16:06:10.365722Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: realtime call created; sdp answer ready transport="webrtc" call_id=rtc_u0_Dbq65nhak5eLjQZ73yhAy elapsed_ms=1113 total_elapsed_ms=1113 2026-05-04T16:06:10.365843Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: connecting realtime sideband websocket call_id=rtc_u0_Dbq65nhak5eLjQZ73yhAy 2026-05-04T16:06:10.784528Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: connected realtime sideband websocket call_id=rtc_u0_Dbq65nhak5eLjQZ73yhAy elapsed_ms=418 total_elapsed_ms=1532 2026-05-04T16:06:10.784665Z INFO session_loop{thread_id=019df3b9-e3d8-7271-b13a-b880119aa4c2}:submission_dispatch{otel.name="op.dispatch.realtime_conversation_start" submission.id="019df3bd-65df-7ee2-8125-1d6701fe39d2" codex.op="realtime_conversation_start"}: codex_core::realtime_conversation: realtime conversation started ``` ### After the Change Logging commit (https://github.com/openai/codex/commit/c8b00ac21adf4f8dd1fe3a81403a2bb6183fe13b) ``` 2026-05-04T15:41:24.080363Z INFO ... codex_core::realtime_conversation: starting realtime conversation 2026-05-04T15:41:24.080434Z INFO ... codex_core::realtime_conversation: creating realtime call transport="webrtc" 2026-05-04T15:41:25.106906Z INFO ... codex_core::realtime_conversation: realtime call created; sdp answer ready transport="webrtc" call_id=rtc_u0_Dbpi8nhak5eLjQZ73yhAy elapsed_ms=1026 total_elapsed_ms=1026 2026-05-04T15:41:25.107067Z INFO ... codex_core::realtime_conversation: spawned realtime sideband connection task transport="webrtc" total_elapsed_ms=1026 2026-05-04T15:41:25.107160Z INFO ... codex_core::realtime_conversation: realtime conversation started 2026-05-04T15:41:25.107185Z INFO codex_core::realtime_conversation: connecting realtime sideband websocket call_id=rtc_u0_Dbpi8nhak5eLjQZ73yhAy 2026-05-04T15:41:25.107352Z INFO ... codex_core::realtime_conversation: sent realtime sdp answer to client 2026-05-04T15:41:26.076685Z INFO codex_core::realtime_conversation: connected realtime sideband websocket call_id=rtc_u0_Dbpi8nhak5eLjQZ73yhAy elapsed_ms=969 total_elapsed_ms=1996 2026-05-04T15:41:26.573893Z INFO codex_core::realtime_conversation: realtime session updated realtime_session_id=sess_u0_Dbpi8nhak5eLjQZ73yhAy 2026-05-04T15:41:26.573970Z INFO codex_core::realtime_conversation: received realtime conversation event event=SessionUpdated { ... } ``` ### Conclusion Here we see that we saved about a half a second in conversation startup (1532ms -> 969ms). This also checks out with my sanity tests; I was seeing at most a second of saving. --------- Co-authored-by: Codex <noreply@openai.com>
kmeelu-oai ·
2026-05-04 22:28:14 +00:00 -
fix(tui): use shared paste burst interval on Windows (#18914)
## Summary Fixes #11678 by removing the Windows-specific `PASTE_BURST_CHAR_INTERVAL` override. Windows now uses the same `8ms` paste-burst character interval as macOS and Linux, which removes the extra per-character hold that made fast typing and key repeat feel delayed on Windows. The paste-burst heuristic itself is unchanged, and the Windows-specific active idle timeout remains in place. This PR only restores the shared character-to-character burst threshold that decides whether adjacent plain character events are part of a paste. ## Motivation PR #9348 raised the Windows character interval from `8ms` to `30ms` to protect the multiline paste behavior tracked in #2137, where pasted newlines could be interpreted as submits in Windows terminals. That fixed the paste failure, but it also made ordinary typing visibly laggy because the TUI waits briefly before flushing a single typed character while it checks whether a paste burst is forming. The deployed behavior here is to remove that Windows-only delay and return to the cross-platform threshold. Manual Windows validation of the critical VS Code integrated terminal path shows multiline paste still works with the final `8ms` value, including testing on VS Code `1.107.0`. ## Testing - `cargo test -p codex-tui` - Manual Windows validation in VS Code integrated PowerShell with the final `8ms` interval
Felipe Coury ·
2026-05-04 20:39:11 +00:00 -
bazel: run sharded rust integration tests (#21057)
## Why Bazel CI was not actually exercising some sharded Rust integration-test targets on macOS. The `rules_rust` sharding wrapper expects a symlink runfiles tree, but this repo runs Bazel with `--noenable_runfiles`. In that configuration the wrapper could fail to find the generated test binary, produce an empty test list, and exit successfully. That made targets such as `//codex-rs/core:core-all-test` look green even when Cargo CI could still catch failures in the same Rust tests. The coverage gap appears to have been introduced by [#18082](https://github.com/openai/codex/pull/18082), which enabled rules_rust native sharding on `//codex-rs/core:core-all-test` and the other large Rust test labels. The manifest-runfiles setup itself predates that change in [#10098](https://github.com/openai/codex/pull/10098), but #18082 is where the affected integration tests started running through the incompatible rules_rust sharding wrapper. [#18913](https://github.com/openai/codex/pull/18913) fixed the same class of issue for wrapped unit-test shards, but integration-test shards were still going through the rules_rust wrapper until this PR. We still do not have the V8/code-mode pieces stable under the Bazel CI cross-compile setup, so this keeps those tests out of Bazel while restoring coverage for the rest of the sharded Rust integration suites. Cargo CI remains responsible for V8/code-mode coverage for now. This change did uncover a real failing core test on `main`: `approved_folder_write_request_permissions_unblocks_later_apply_patch`. That fix is split into [#21060](https://github.com/openai/codex/pull/21060), which enables the `apply_patch` tool in the test, teaches the aggregate core test binary to dispatch the sandboxed filesystem helper, canonicalizes the macOS temp patch target, and isolates the core test harness from managed local/enterprise config. Keeping that fix separate lets this PR stay focused on restoring Bazel coverage while documenting the first failure it exposed. ## What changed - Build sharded Rust integration tests as manual `*-bin` binaries and run them through the existing manifest-aware `workspace_root_test` launcher. - Keep Bazel sharding on the launcher target so Rust test cases are still distributed by stable test-name hashing. - Configure Bazel CI to skip Rust tests whose names contain `suite::code_mode::`. - Exclude the standalone `codex-rs/code-mode` and `codex-rs/v8-poc` unit-test targets from `bazel.yml`. ## Verification - `bazel query --output=build //codex-rs/core:core-all-test` now shows `workspace_root_test` wrapping `//codex-rs/core:core-all-test-bin`. - `bazel test --test_output=all --nocache_test_results --test_sharding_strategy=disabled //codex-rs/core:core-all-test --test_filter=suite::request_permissions_tool::approved_folder_write_request_permissions_unblocks_later_apply_patch` runs the actual Rust test body and passes. - `bazel test --test_output=errors --nocache_test_results --test_env=CODEX_BAZEL_TEST_SKIP_FILTERS=suite::code_mode:: //codex-rs/core:core-all-test` runs the sharded target with code-mode skipped and passes overall locally, with one flaky attempt retried by the existing `flaky = True` setting.
Michael Bolin ·
2026-05-04 13:33:14 -07:00 -
fix(tui): support modified backspace/delete keys (#21058)
## Why Fixes #21046. Codex TUI 0.128.0 can show Backspace/Delete-related editor shortcuts in `/keymap`, but Windows-style modified Backspace/Delete events were still dropped by the composer because the default editor keymap did not include those modified special-key variants. On Windows/CMD this meant `Shift+Backspace` and `Shift+Delete` did not fall through to normal character deletion, and `Ctrl+Backspace` / `Ctrl+Delete` did not perform the word deletion users expect from Windows text inputs. ## What Changed - Added default editor bindings for `shift-backspace` and `shift-delete` so shifted delete keys keep normal grapheme deletion behavior. - Added default editor bindings for `ctrl-backspace`, `ctrl-shift-backspace`, `ctrl-delete`, and `ctrl-shift-delete` so Windows-style word deletion works when terminals preserve those modifiers. - Added regression coverage for the resolved default keymap and textarea behavior. ## How to Test 1. Start Codex in the TUI on Windows CMD or another terminal that reports modified Backspace/Delete keys distinctly. 2. Type `hello world` in the composer. 3. Press `Ctrl+Backspace`; confirm `world` is removed and `hello ` remains. 4. Type `world` again, move the cursor before it, then press `Ctrl+Delete`; confirm the next word is removed. 5. Type a few characters and press `Shift+Backspace` and `Shift+Delete`; confirm they delete one character in the expected direction instead of doing nothing. 6. Open `/keymap`, inspect the Editor deletion actions, and confirm the modified Backspace/Delete aliases are visible as configurable defaults. Targeted tests: - `cargo test -p codex-tui keymap::tests` - `cargo test -p codex-tui bottom_pane::textarea::tests` - `cargo test -p codex-tui keymap_setup::tests`
Felipe Coury ·
2026-05-04 17:16:41 -03:00 -
Add reasoning effort to turn tracing spans (#20060)
Why #19432 added token usage to the turn and response spans. This follow-up adds the configured reasoning effort so performance traces can be filtered by model effort. [example trace](https://openai.datadoghq.com/apm/trace/1ff708a87159ff4898bdc8bd6091ec18?graphType=waterfall&shouldShowLegend=true&spanID=6596351544047485652&traceQuery=) <img width="533" height="434" alt="Screenshot 2026-04-28 at 3 52 12 PM" src="https://github.com/user-attachments/assets/77ef32fc-d7cd-4eec-87b4-26c6798f1af8" /> What Changed - Adds `codex.turn.reasoning_effort` to the turn span. - Adds `codex.request.reasoning_effort` to `handle_responses`. - Extends the span test to cover explicit `high` effort with token usage. Testing - `cargo test -p codex-core turn_and_completed_response_spans_record_token_usage` - `cargo test -p codex-otel` - `just fmt` - `just fix -p codex-core` - `just fix -p codex-otel`
charley-openai ·
2026-05-04 12:57:05 -07:00 -
core: fix apply_patch request permissions test (#21060)
## Why The Bazel test coverage change exposed `approved_folder_write_request_permissions_unblocks_later_apply_patch`, and `rust-ci-full.yml` showed the same test failing on `main` on macOS. There were two separate classes of problems here. ### Clean CI failure The test emits an `apply_patch` tool call, but its config did not enable the `apply_patch` tool, so the mocked response completed without an `apply-patch-call` output. After enabling the tool, the same path also needs the aggregate `codex-core` test binary to dispatch `--codex-run-as-fs-helper`; sandboxed `apply_patch` uses that helper under macOS Seatbelt. The test now also canonicalizes the temporary patch target before building the patch payload so the path matches normalized grants on macOS, where `/var` paths often normalize to `/private/var`. ### Local/enterprise config isolation The core test harness now builds its default test config with managed config disabled, so host-managed enterprise config cannot alter these tests. The request-permissions turns in this test also explicitly use the user reviewer path, keeping the assertions focused on `request_permissions` behavior rather than reviewer defaults from the host. ## What Changed - Enable `apply_patch` in `approved_folder_write_request_permissions_unblocks_later_apply_patch`. - Teach the core integration test binary to dispatch `CODEX_FS_HELPER_ARG1`, matching the existing apply-patch and linux-sandbox dispatch paths. - Canonicalize the tempdir-backed patch target before creating the patch. - Ignore managed config in default core test configs and explicitly pin this test to `ApprovalsReviewer::User`. ## Verification Run outside the Codex app sandbox because these macOS tests intentionally spawn Seatbelt: - `cargo test -p codex-core approved_folder_write_request_permissions_unblocks_later_apply_patch` - `cargo test -p codex-core approved_folder_write_request_permissions_unblocks_later_exec_without_sandbox_args`
Michael Bolin ·
2026-05-04 12:48:59 -07:00 -
core: preserve last model ids in feedback tags (#21026)
## Why Feedback reports do not currently surface a direct pointer to the last model call, so investigations may require searching through many requests in a session to find the bad response. Preserve the last model-side IDs at response-stream time so immediate feedback reports carry that breadcrumb. ## What changed - Record `last_model_request_id` when a Responses stream exposes an upstream request ID. - Record `last_model_response_id` when the model response completes. - Add unit coverage for the emitted feedback tags. ## Verification - `cargo test -p codex-core client::tests::response_stream_records_last_model_feedback_ids`
sayan-oai ·
2026-05-04 12:46:08 -07:00 -
Use MCP server instructions in deferred namespace descriptions (#21053)
## Why MCP servers can provide `instructions` that explain what their tools are for. Directly exposed MCP namespaces already use those instructions when a connector description is not available, but deferred `tool_search` results did not preserve that fallback. The direct path falls back from connector metadata to server instructions, while the deferred path only carried `connector_description` and otherwise fell back to generic namespace text. That meant a plain MCP server could provide useful model-facing guidance and still appear as `Tools in the X namespace.` whenever it was discovered lazily through `tool_search`. ## What changed - Store one model-facing `namespace_description` on `ToolInfo`, using connector descriptions for connector-backed tools and server instructions for plain MCP servers. - Thread that namespace description through the `tool_search` source list, search indexing, and returned namespace metadata. - Add an end-to-end regression test for deferred non-app MCP search results exposing server instructions as the namespace description. ## Verification - `cargo test -p codex-tools search_tool_description_lists_each_mcp_source_once --lib` - `cargo test -p codex-core --test all tool_search_uses_non_app_mcp_server_instructions_as_namespace_description`
sayan-oai ·
2026-05-04 19:36:07 +00:00 -
feat(tui): improve TUI keymap coverage (#20798)
## Summary - normalize terminal-emitted C0 control characters through configurable editor keymaps, covering raw control-key fallbacks like Shift+Enter-as-LF in terminals from #20555 and #20898, plus part of the modified-Enter behavior in #20580 - add default-unbound keymap actions for toggling Fast mode and killing the current composer line, giving #20698 users a configurable zsh-style Ctrl+U option without changing the existing default Ctrl+U behavior - wire the new actions through gated /keymap picker entries, schema generation, and snapshot coverage Fixes #20555. Fixes #20898. ## Testing - just write-config-schema - just fmt - cargo test -p codex-config - cargo test -p codex-tui keymap::tests - cargo test -p codex-tui bottom_pane::textarea::tests - cargo test -p codex-tui keymap_setup::tests - cargo insta pending-snapshots - just fix -p codex-tui - git diff --check - just argument-comment-lint
Felipe Coury ·
2026-05-04 19:18:56 +00:00 -
feat(tui): add PR summary statusline items (#20892)
## Why? The Codex App already exposes branch and PR context in its branch-details UI. This brings the same context into the CLI footer as opt-in statusline items, so users can choose the extra signal without making the default footer busier. ## What? Add optional `pull-request-number` and `branch-changes` items to the configurable TUI status line. - `pull-request-number` shows the open PR for the current checkout and renders as a clickable terminal hyperlink when OSC 8 links are supported. - `branch-changes` shows committed additions/deletions against the repository default branch, or `No changes` when the branch has no committed diff. <img width="1257" height="261" alt="CleanShot 2026-05-03 at 20 44 15" src="https://github.com/user-attachments/assets/10b4380b-c3e9-4729-9ee1-3f742068fa47" /> ## Architecture This follows the same client/app-server split as the Codex App: the TUI owns presentation, caching, and optional rendering, while workspace-sensitive `git` and `gh` discovery runs through app-server. The new TUI-local `workspace_command` layer sends bounded, non-interactive `command/exec` requests to the active app-server. That makes the implementation remote-friendly: the TUI does not decide whether commands run in an embedded local workspace or a remote workspace, and it does not bypass app-server sandbox or permission policy. The branch summary logic stays internal to `codex-tui` because this PR only needs TUI statusline behavior. The command boundary is still isolated behind `WorkspaceCommandExecutor`, so the lookup code can be lifted or reused later without changing statusline rendering. ## How? - Add a TUI `WorkspaceCommandExecutor` abstraction backed by app-server `command/exec`. - Add branch summary probes for: - current branch name, - open PR metadata, - committed branch diff stats against the default branch. - Prefer remote-tracking default branch refs for diff stats, avoiding stale or absent local `main` branches. - Resolve PRs with `gh pr view` first, then fall back to commit-associated PR lookup across parent/fork repos. - Add `/statusline` picker entries, preview values, rendering, and OSC 8 clickable PR links. - Keep all probes best-effort so missing `git`, missing `gh`, auth failures, or non-git directories hide optional items instead of surfacing footer errors. ## Validation - `cargo test -p codex-tui branch_summary -- --nocapture` - Snapshot coverage for the `/statusline` preview/setup rendering paths - Hyperlink rendering coverage for clickable PR statusline cells
Felipe Coury ·
2026-05-04 16:11:15 -03:00 -
rollout: store web search and mcp tool calls (#21054)
Codex App would like these.
Owen Lin ·
2026-05-04 18:54:20 +00:00 -
state: pass state db handles through consumers (#20561)
## Why SQLite state was still being opened from consumer paths, including lazy `OnceCell`-backed thread-store call sites. That let one process construct multiple state DB connections for the same Codex home, which makes SQLite lock contention and `database is locked` failures much easier to hit. State DB lifetime should be chosen by main-like entrypoints and tests, then passed through explicitly. Consumers should use the supplied `Option<StateDbHandle>` or `StateDbHandle` and keep their existing filesystem fallback or error behavior when no handle is available. The startup path also needs to keep the rollout crate in charge of SQLite state initialization. Opening `codex_state::StateRuntime` directly bypasses rollout metadata backfill, so entrypoints should initialize through `codex_rollout::state_db` and receive a handle only after required rollout backfills have completed. ## What Changed - Initialize the state DB in main-like entrypoints for CLI, TUI, app-server, exec, MCP server, and the thread-manager sample. - Pass `Option<StateDbHandle>` through `ThreadManager`, `LocalThreadStore`, app-server processors, TUI app wiring, rollout listing/recording, personality migration, shell snapshot cleanup, session-name lookup, and memory/device-key consumers. - Remove the lazy local state DB wrapper from the thread store so non-test consumers use only the supplied handle or their existing fallback path. - Make `codex_rollout::state_db::init` the local state startup path: it opens/migrates SQLite, runs rollout metadata backfill when needed, waits for concurrent backfill workers up to a bounded timeout, verifies completion, and then returns the initialized handle. - Keep optional/non-owning SQLite helpers, such as remote TUI local reads, as open-only paths that do not run startup backfill. - Switch app-server startup from direct `codex_state::StateRuntime::init` to the rollout state initializer so app-server cannot skip rollout backfill. - Collapse split rollout lookup/list APIs so callers use the normal methods with an optional state handle instead of `_with_state_db` variants. - Restore `getConversationSummary(ThreadId)` to delegate through `ThreadStore::read_thread` instead of a LocalThreadStore-specific rollout path special case. - Keep DB-backed rollout path lookup keyed on the DB row and file existence, without imposing the filesystem filename convention on existing DB rows. - Verify readable DB-backed rollout paths against `session_meta.id` before returning them, so a stale SQLite row that points at another thread's JSONL falls back to filesystem search and read-repairs the DB row. - Keep `debug prompt-input` filesystem-only so a one-off debug command does not initialize or backfill SQLite state just to print prompt input. - Keep goal-session test Codex homes alive only in the goal-specific helper, rather than leaking tempdirs from the shared session test helper. - Update tests and call sites to pass explicit state handles where DB behavior is expected and explicit `None` where filesystem-only behavior is intended. ## Validation - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-thread-store -p codex-app-server -p codex-core -p codex-tui -p codex-exec -p codex-cli --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout state_db_` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout find_thread_path -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout try_init_ -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-rollout` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo clippy -p codex-rollout --lib -- -D warnings` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store read_thread_falls_back_when_sqlite_path_points_to_another_thread -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-thread-store` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core shell_snapshot` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all personality_migration` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find::find_prefers_sqlite_path_by_id -- --nocapture` - `RUST_MIN_STACK=8388608 CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core --test all rollout_list_find -- --nocapture` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-core interrupt_accounts_active_goal_before_pausing` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server get_auth_status -- --test-threads=1` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo test -p codex-app-server --lib` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db cargo check -p codex-rollout -p codex-app-server --tests` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-thread-store -p codex-core -p codex-app-server -p codex-tui -p codex-exec -p codex-cli` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout -p codex-app-server` - `CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-rollout` - `CODEX_SKIP_VENDORED_BWRAP=1 CARGO_TARGET_DIR=/tmp/codex-target-state-db just fix -p codex-core` - `just argument-comment-lint -p codex-core` - `just argument-comment-lint -p codex-rollout` Focused coverage added in `codex-rollout`: - `recorder::tests::state_db_init_backfills_before_returning` verifies the rollout metadata row exists before startup init returns. - `state_db::tests::try_init_waits_for_concurrent_startup_backfill` verifies startup waits for another worker to finish backfill instead of disabling the handle for the process. - `state_db::tests::try_init_times_out_waiting_for_stuck_startup_backfill` verifies startup does not hang indefinitely on a stuck backfill lease. - `tests::find_thread_path_accepts_existing_state_db_path_without_canonical_filename` verifies DB-backed lookup accepts valid existing rollout paths even when the filename does not include the thread UUID. - `tests::find_thread_path_falls_back_when_db_path_points_to_another_thread` verifies DB-backed lookup ignores a stale row whose existing path belongs to another thread and read-repairs the row after filesystem fallback. Focused coverage updated in `codex-core`: - `rollout_list_find::find_prefers_sqlite_path_by_id` now uses a DB-preferred rollout file with matching `session_meta.id`, so it still verifies that valid SQLite paths win without depending on stale/empty rollout contents. `cargo test -p codex-app-server thread_list_respects_search_term_filter -- --test-threads=1 --nocapture` was attempted locally but timed out waiting for the app-server test harness `initialize` response before reaching the changed thread-list code path. `bazel test //codex-rs/thread-store:thread-store-unit-tests --test_output=errors` was attempted locally after the thread-store fix, but this container failed before target analysis while fetching `v8+` through BuildBuddy/direct GitHub. The equivalent local crate coverage, including `cargo test -p codex-thread-store`, passes. A plain local `cargo check -p codex-rollout -p codex-app-server --tests` also requires system `libcap.pc` for `codex-linux-sandbox`; the follow-up app-server check above used `CODEX_SKIP_VENDORED_BWRAP=1` in this container.
Ruslan Nigmatullin ·
2026-05-04 11:46:03 -07:00 -
Add stdio exec-server listener (#20663)
## Why This stack adds configured exec-server environments, including environments reached over stdio. Before client-side stdio transports or config can use that path, the exec-server binary itself needs a first-class stdio listen mode so it can speak the same JSON-RPC protocol over stdin/stdout that it already speaks over websockets. **Stack position:** this is PR 1 of 5. It is the server-side transport foundation for the stack. ## What Changed - Accept `stdio` and `stdio://` for `codex exec-server --listen`. - Promote the existing stdio `JsonRpcConnection` helper from test-only code into normal exec-server transport code. - Add parse coverage for stdio listen URLs while preserving the existing websocket default. ## Stack - **1. This PR:** https://github.com/openai/codex/pull/20663 - Add stdio exec-server listener - 2. https://github.com/openai/codex/pull/20664 - Add stdio exec-server client transport - 3. https://github.com/openai/codex/pull/20665 - Make environment providers own default selection - 4. https://github.com/openai/codex/pull/20666 - Add CODEX_HOME environments TOML provider - 5. https://github.com/openai/codex/pull/20667 - Load configured environments from CODEX_HOME Split from original draft: https://github.com/openai/codex/pull/20508 ## Validation Not run locally; this was split out of the original draft stack. --------- Co-authored-by: Codex <noreply@openai.com>
starr-openai ·
2026-05-04 11:40:03 -07:00 -
Fix Windows PTY teardown by preserving ConPTY ownership (#20685)
## Why On Windows, background terminals could stay visible after their shell process had already exited. The elevated runner waits for the PTY output reader to reach EOF before it sends the final exit message, but the ConPTY helper was reducing ownership down to raw handles too early. That left the pseudoconsole's borrowed pipe handles alive past teardown, so EOF never propagated and the session stayed `running`. ## What changed - change `utils/pty/src/win/conpty.rs` to hand off owned ConPTY resources instead of leaking only raw handles - make `windows-sandbox-rs/src/conpty/mod.rs` keep the pseudoconsole owner and the backing pipe handles together until teardown - update the elevated runner and the legacy unified-exec backend to keep that `ConptyInstance` alive, take only the specific pipe handles they need, and drop the owner at teardown instead of trying to close a detached pseudoconsole handle later ## Testing - desktop app in `Auto-review`: 11 x `cmd /c "ping -n 3 google.com"` all exited cleanly and did not accumulate in the UI - desktop app in `Auto-review`: 5 x `cmd /c "ping -n 30 google.com"` appeared in the UI and drained back out on their own
iceweasel-oai ·
2026-05-04 18:40:00 +00:00 -
Prepare selected environment plumbing (#20669)
## Why This is a prep PR in the multi-environment process-tool stack. It separates ownership/config cleanup from the behavior change that teaches process tools to route by selected environment, so the follow-up PR can focus on model-facing `environment_id` behavior. ## Stack 1. https://github.com/openai/codex/pull/20646 - `EnvironmentContext` rendering for selected environments 2. https://github.com/openai/codex/pull/20669 - selected-environment ownership and tool config prep (this PR) 3. https://github.com/openai/codex/pull/20647 - process-tool `environment_id` routing ## What Changed - keep the resolved turn environment list wrapped in `ResolvedTurnEnvironments` through `TurnContext` instead of unwrapping it back to a raw `Vec` - add `TurnContext::resolve_path_against` so cwd-relative path resolution has one shared helper - replace the old tool config boolean with `ToolEnvironmentMode::{None, Single, Multiple}` ## Testing - Tests not run locally; this prep refactor is covered by GitHub CI for the stack. Co-authored-by: Codex <noreply@openai.com>
starr-openai ·
2026-05-04 17:55:49 +00:00 -
tui: retire /approvals and rename /autoreview to /approve (#21034)
## Why The TUI currently exposes overlapping command names for the same permissions flow: `/permissions` and the older `/approvals` alias. It also uses `/autoreview` for the manual retry flow, even though the action users take there is approving one denied auto-review request. This change makes the command surface consistent with the hard rebrand: - `/permissions` is the only command for permission settings. - `/approve` is the command for approving a recent auto-review denial. ## What changed - Removed the legacy `/approvals` slash command and its dispatch path. - Kept `/permissions` as the single permissions command shown and accepted by the TUI. - Renamed the auto-review denial command from `/autoreview` to `/approve`. - Updated nearby comments so they refer to `/permissions` rather than the retired `/approvals` name. ## Verification - Updated the slash-command unit test to assert that `AutoReview` now renders and parses as `approve`.
Won Park ·
2026-05-04 17:50:34 +00:00 -
feat(tui): add keymap debug inspector (#20794)
## Why We constantly get bug reports about keys not being recognized by Codex when the terminal is not handling the key press. Running `/keymap debug` or `/keymap` and going to the Debug tab, we can allow the user to either understand that the key being pressed is not being recognized or to check what it's being recognized as and report or reassign that key. | Menu | Inspector | Hint | |---|---|---| | <img width="1369" height="796" alt="CleanShot 2026-05-02 at 12 57 12" src="https://github.com/user-attachments/assets/512b6faa-344e-4aee-9c00-b4bdc633a662" /> | <img width="1261" height="754" alt="CleanShot 2026-05-02 at 12 56 36" src="https://github.com/user-attachments/assets/a6ddae7d-e174-4ee4-893f-e6bec4fff4ab" /> | <img width="1369" height="796" alt="CleanShot 2026-05-02 at 12 57 30" src="https://github.com/user-attachments/assets/db507784-f40a-4cff-ac23-a61d9703769b" /> | ## Summary - add a Debug tab to `/keymap` and support `/keymap debug` for direct access - show what key Codex receives, the config key representation, raw event details, and matching actions - add a progressive missing-key hint that escalates after a few seconds with no detected keypress ## Validation - `just fmt` - `cargo test -p codex-tui keymap_setup::tests::debug_view` - `cargo test -p codex-tui keymap_setup::tests` - `cargo test -p codex-tui slash_keymap` - `cargo test -p codex-tui` (unit tests passed; integration test `suite::model_availability_nux::resume_startup_does_not_consume_model_availability_nux_count` failed locally by itself with `codex resume` exiting 1 and terminal probe escape output) - `just fix -p codex-tui` - `just argument-comment-lint` - `cargo insta pending-snapshots` - `git diff --check`
Felipe Coury ·
2026-05-04 14:40:50 -03:00 -
fix(linux-sandbox): fall back when system bwrap lacks perms (#20628)
## Why Codex `0.128` started using `--perms` in more routine Linux sandbox construction when protected workspace metadata mounts landed in #19852. Upstream bubblewrap added `--perms` in `v0.5.0`, so system `bwrap` versions older than that, including the `v0.4.0` and `v0.4.1` family, do not support the flag. The launcher still selected those binaries as long as they existed on `PATH`. That means affected hosts can fail every sandboxed command up front with: ```text bwrap: Unknown option --perms ``` The reports in #20590 and duplicate #20623 match that compatibility gap; #20623 explicitly shows system bubblewrap `0.4.0`. ## What changed - Replace the single `--argv0` probe with a small system-bwrap capability probe in `codex-rs/linux-sandbox/src/launcher.rs`. - Continue using the old-system `--argv0` compatibility path when needed, but only select a system `bwrap` if it also advertises `--perms`. - Fall back to the vendored `bwrap` when the system binary is too old for the flags Codex now requires. - Add regression coverage for the old-system-bwrap case so binaries without `--perms` stay on the vendored path. ## Verification - Added `falls_back_to_vendored_when_system_bwrap_lacks_perms` to cover the reported compatibility gap. - Ran `cargo test -p codex-linux-sandbox` and `cargo clippy -p codex-linux-sandbox --tests` locally. On macOS, the crate builds but its Linux-only tests are cfg-gated out, so the new regression test still needs Linux CI or a Linux devbox run for real execution coverage. ## Related issues - Fixes #20590 - Duplicate report: #20623
viyatb-oai ·
2026-05-04 10:38:31 -07:00 -
feat(app-server): always return limited thread history (#20682)
## Why Whenever we return a thread's history (turns and items) over app-server, always return the limited form as specified by the rollout policy `EventPersistenceMode::Limited`, even if the thread was previously started with `EventPersistenceMode::Extended`. We're finding it is quite unscalable to be returning the extended history, so let's apply the same filtering logic of the rollout policy when we load and return the thread's history. ## What Changed - Reuse the rollout persistence policy when reconstructing app-server `ThreadItem` history so only `EventPersistenceMode::Limited` rollout items are replayed into API turns. - Route `thread/read`, `thread/resume`, `thread/fork`, `thread/turns/list`, and rollback responses through the same filtered app-server history projection. - Keep live active turns intact when composing a response for a currently running thread. - Update command execution coverage so persisted extended command events are excluded from returned history for `thread/read`, `thread/fork`, and `thread/turns/list`. ## Test Plan - `cargo test -p codex-app-server limited` - `cargo test -p codex-app-server thread_shell_command` - `cargo test -p codex-app-server thread_read` - `cargo test -p codex-app-server thread_rollback` - `cargo test -p codex-app-server thread_fork` - `cargo test -p codex-app-server-protocol`
Owen Lin ·
2026-05-04 10:37:35 -07:00 -
Unify skip-review handling for approval_mode = "approve" (#20750)
## Summary - Treat `approval_mode = "approve"` as skip-review across all permission modes. - Remove the mode-specific split in the MCP auto-approval gate so approved tools bypass review consistently. - Expand regression coverage in the shared MCP helper and the core tool-call flow. ## Testing - `just fmt` - `cargo test -p codex-mcp` - `cargo test -p codex-core approve_mode_skips_arc_and_guardian_in_every_permission_mode` - `git diff --check` - Full `cargo test -p codex-core` was also attempted, but the suite hit an unrelated pre-existing stack overflow in an existing multi-agent test
Matthew Zeng ·
2026-05-04 10:30:47 -07:00 -
[mcp-apps] Persist MCP Apps specific tool call end event. (#20853)
- [x] Persist a special type of MCP tool calls for triggering MCP App, this type of mcp tool calls has 'mcpAppResourceUri` set. These events are needed so that the Codex App can correctly render the MCP App after resume.
Matthew Zeng ·
2026-05-04 10:20:58 -07:00 -
core: share responses request builder with compact requests (#20989)
## Why `ModelClientSession` and `compact_conversation_history()` were still rebuilding the same `ResponsesApiRequest` fields separately. That duplication makes it easy for normal `/responses` turns and compact requests to drift when request-shape changes land later, which is exactly the kind of cache-affecting divergence we want to avoid. This follow-up keeps the scope small by extracting the shared request-construction logic into one helper and using it from both paths. ## What changed - move `ResponsesApiRequest` construction into a shared `ModelClient::build_responses_request(...)` helper in `core/src/client.rs` - update the normal `/responses` streaming path to call that helper instead of the old `ModelClientSession`-local implementation - update `compact_conversation_history()` to derive its compact payload from the same helper so `model`, `instructions`, `input`, `tools`, `parallel_tool_calls`, `reasoning`, and `text` stay aligned with normal request building - add a unit test covering the shared helper's prompt cache key, installation metadata, and `service_tier` behavior ## Verification - `cargo test -p codex-core build_responses_request_sets_shared_cache_and_metadata_fields` - `cargo test -p codex-core --test all remote_compact_v2_reuses_context_compaction_for_followups` ## Docs No docs update needed.
jif-oai ·
2026-05-04 17:18:38 +00:00 -
memories-mcp: reject symlink traversal in local backend (#21010)
## Why The local memories MCP backend only rejected symlinks after resolving the final path. That left room for scoped requests like `skills/secret.md` to walk through a symlinked ancestor directory and escape the configured memories root. This change also makes missing scoped paths fail explicitly instead of looking like an empty `list` / `search` result or a `NotFile` read error. ## What Changed - walk each scoped path component in `LocalMemoriesBackend::resolve_scoped_path` and reject symlinked ancestors before accessing the target - reject scoped paths that traverse through a non-directory intermediate component - add a `NotFound` backend error for missing `read`, `list`, and `search` paths and map it through the MCP server error conversion - add coverage for missing paths and symlinked ancestor directories in `codex-rs/memories/mcp/src/local_tests.rs` ## Testing - added unit coverage in `codex-rs/memories/mcp/src/local_tests.rs` for missing paths and symlinked ancestor directories across `read`, `list`, and `search`
jif-oai ·
2026-05-04 18:40:28 +02:00 -
memories/mcp: generate tool schemas with schemars (#21012)
## Why The memories MCP server currently keeps handwritten JSON Schema beside the Rust types that actually serialize and deserialize the tool payloads: [`schema.rs`](https://github.com/openai/codex/blob/2f5c06a29cdd68f11d07126dc56871bff1218ba1/codex-rs/memories/mcp/src/schema.rs#L4-L133), [`server.rs`](https://github.com/openai/codex/blob/2f5c06a29cdd68f11d07126dc56871bff1218ba1/codex-rs/memories/mcp/src/server.rs#L44-L75), and [`backend.rs`](https://github.com/openai/codex/blob/2f5c06a29cdd68f11d07126dc56871bff1218ba1/codex-rs/memories/mcp/src/backend.rs#L41-L117). That duplicates the tool contract and makes schema drift easier as the API evolves. ## What changed - derive `JsonSchema` for the memories tool arguments, responses, and nested response types - replace the handwritten schema builders with shared `schemars` generation - preserve the existing wire shape while generating schemas, including nullable output `Option` fields and non-nullable optional input fields - wire the `list`, `read`, and `search` tools to the generated schemas ## Verification - CI pending
jif-oai ·
2026-05-04 18:40:17 +02:00 -
jif-oai ·
2026-05-04 18:39:46 +02:00 -
[codex] Split app-server request processors (#20940)
## Why The app-server request path had grown around a large `CodexMessageProcessor` plus separate API wrapper/helper modules. That made the dependency graph hard to see and forced unrelated request families to share broad processor state. This PR makes the split mechanical and command-prefix oriented so request families own only the dependencies they use. ## What changed - Replaced `CodexMessageProcessor` with command-prefix request processors under `app-server/src/request_processors/`. - Removed the old config, device-key, external-agent-config, and fs API wrapper files by moving their API handling into processors. - Split apps, plugins, marketplace, catalog, account, MCP, command exec, fs, git, feedback, thread, turn, thread goals, and Windows sandbox handling into dedicated processors. - Kept shared lifecycle, summary conversion, token usage replay, and shared error mapping only where multiple processors use them; single-use helpers were inlined into their owning processor. - Removed the fallback processor path and moved processor tests to `_tests` files. ## Validation - `cargo test -p codex-app-server` - `cargo check -p codex-app-server` - `just fix -p codex-app-server`
pakrym-oai ·
2026-05-04 09:34:11 -07:00 -
Keep paused goals paused on thread resume (#20790)
## Summary Early adopters of the `/goal` feature have provided feedback that they expect a goal they explicitly paused to remain paused when they resume a thread. Previously, resuming a thread would reactivate a paused goal. This PR keeps persisted goal status unchanged during thread resume. This honors the user feedback while also simplifying the core goal logic. Rather than have the core logic automatically resume a paused goal, that responsibility is transferred to the client. The TUI now detects a resumed thread with a paused goal and asks the user whether to `Resume goal` or `Leave paused`. The prompt appears only for quiet resume flows, so users who resume with an immediate prompt are not interrupted. <img width="544" height="111" alt="image" src="https://github.com/user-attachments/assets/0ac9de1c-6ee6-47ba-b223-c03c8eb4c192" />
Eric Traut ·
2026-05-04 09:04:30 -07:00 -
Speed up /side parent restore replay (#20815)
## Why Returning from a `/side` conversation restores the parent thread by replaying its snapshot into the TUI. For very long parent threads, replaying every transcript row can take noticeable time even though most rows immediately scroll out of terminal history. ## What Changed - Buffer thread-switch replay for parent restores when terminal resize reflow is enabled. - Reuse the existing resize-reflow tail renderer so only the retained transcript tail is written back to scrollback when a row cap is configured.
Eric Traut ·
2026-05-04 09:00:30 -07:00 -
Keep paused goals paused on thread resume (#20790)
## Summary Early adopters of the `/goal` feature have provided feedback that they expect a goal they explicitly paused to remain paused when they resume a thread. Previously, resuming a thread would reactivate a paused goal. This PR keeps persisted goal status unchanged during thread resume. This honors the user feedback while also simplifying the core goal logic. Rather than have the core logic automatically resume a paused goal, that responsibility is transferred to the client. The TUI now detects a resumed thread with a paused goal and asks the user whether to `Resume goal` or `Leave paused`. The prompt appears only for quiet resume flows, so users who resume with an immediate prompt are not interrupted. <img width="544" height="111" alt="image" src="https://github.com/user-attachments/assets/0ac9de1c-6ee6-47ba-b223-c03c8eb4c192" />
Eric Traut ·
2026-05-04 08:58:07 -07:00 -
jif-oai ·
2026-05-04 16:04:29 +02:00 -
feat: support multi-query memories search (#21004)
## Why The memories MCP `search` tool only accepts a single substring today, which makes it hard for clients to express combined queries or explain why a line matched. This change adds the richer search shape needed for the next client iteration while keeping the legacy single-`query` call working. ## What changed - accept either the legacy `query` field or a new `queries` array, plus `match_mode: any|all` - teach the local memories backend to evaluate multi-query line matches and return `matched_queries` on each hit - update the MCP input/output schema and add coverage for parser behavior, ordering, pagination, case sensitivity, and match modes ## Testing - added unit coverage in `memories/mcp/src/local_tests.rs` and `memories/mcp/src/server.rs`
jif-oai ·
2026-05-04 15:55:06 +02:00