mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
dev
7919 Commits
-
Unified mentions in TUI (#19068)
This PR replaces the TUI’s file-only `@mention` popup with a unified mentions experience. Typing `@...` now searches across filesystem matches, installed plugins, and skills in one popup, with result types clearly labeled and selectable from the same flow. - Adds a unified `@mentions` popup that returns: - plugins - skills - files - directories - Adds search modes so users can narrow the popup without changing their query: - All Results _(default/same as Codex App)_ - Filesystem Only - Plugins _(...and skills)_ - Preserves existing insertion behavior: - selected file paths are inserted into the prompt - paths with spaces are quoted - image file selections still attach as images when possible - selecting a plugin or skill inserts the corresponding `$name` - the composer records the canonical mention binding, such as `plugin://...` or the skill path - Expanded `@mentions` rendering: - type tags for Plugin, Skill, File, and Dir - distinct plugin/filesystem colors - stable fixed-height layout (8 rows) - truncation behavior for narrow terminals Note: - The unified mentions popup does not display app connectors under `@mention` results for Codex App parity. Connector mentions remain available through the existing `$mention` path. https://github.com/user-attachments/assets/f93781ed-57d3-4cb5-9972-675bc5f3ef3f
canvrno-oai ·
2026-05-11 11:34:52 -07:00 -
Add process-scoped SQLite telemetry (#22154)
## Summary - add SQLite init, backfill-gate, and fallback telemetry without introducing a cross-cutting state-db access wrapper - install one process-scoped telemetry sink after OTEL startup and let low-level state/rollout paths emit through it directly - add process-start metrics for the process owners that initialize SQLite --------- Co-authored-by: Owen Lin <owen@openai.com>
jif-oai ·
2026-05-11 11:32:40 -07:00 -
[codex-analytics] add turn tool counts to turn events (#21431)
## Summary - accumulate completed tool-item counts per turn from the item lifecycle - populate the reserved count fields on `codex_turn_event` - add reducer coverage for zero-count turns and mixed completed tool items ## Why PR #17090 moved tool-item analytics onto the item lifecycle, so the turn reducer can now derive the per-turn tool counts from the same completed items instead of leaving the reserved fields null. ## Validation - `just fmt` - `cargo test -p codex-analytics`
rhan-oai ·
2026-05-11 18:18:02 +00:00 -
Make auto-review denial short-circuit use a rolling review window (#22110)
## Why Long-running turns can accumulate enough denied auto-review decisions to trip the global short-circuit even when those denials are spread far apart. The breaker should still stop genuinely bad loops, but it should judge recent behavior instead of lifetime turn history. ## What changed - Replaced the lifetime `10 total denials` threshold with `10 denials in the last 50 reviews`. - Kept the existing `3 consecutive denials` interrupt behavior unchanged. - Tracked recent auto-review outcomes in the circuit breaker and updated the warning copy to report the rolling-window count. - Renamed the new rolling-window coverage to `auto_review_*` test names. - Added coverage that confirms older denials fall out of the 50-review window and no longer trigger the breaker. ## Validation - `just fmt` - `cargo test -p codex-core guardian_rejection_circuit_breaker --lib` - `cargo test -p codex-core auto_review_rejection_circuit_breaker --lib`
Won Park ·
2026-05-11 11:03:11 -07:00 -
Fix goal update and add
/goal editcommand in TUI (#21954)## Why Users have requested the ability to edit a goal's objective after a goal has been created. This PR exposes a new `/goal edit` command in the TUI to address this request. In the process of implementing this, I also noticed an existing bug in the goal runtime. When a goal's objective is updated through the `thread/goal/set` app server API, the goal runtime didn't emit a new steering prompt to tell the agent about the new objective. This PR also fixes this hole. ## What Changed - Adds `/goal edit` in the TUI, opening an edit box prefilled with the current goal objective. - Keeps active and paused goals in their current state, resets completed goals to active, keeps budget-limited goals budget-limited, and preserves the existing token budget. - Changes the existing `thread/goal/set` behavior so editing an objective preserves goal accounting instead of resetting it. The older reset-on-new-objective behavior was left over from before `thread/goal/clear`; clients that need to reset accounting can now clear the existing goal and create a new one. - Reuses the existing goal set API path; this does not add or change app-server protocol surface area. - Adds a dedicated goal runtime steering prompt when an externally persisted goal mutation changes the objective, so active turns receive the updated objective. ## Validation - Make sure `/goal edit` returns an error if no goal currently exists - Make sure `/goal edit` displays an edit box that can be optionally canceled with no side effects - Make sure that an edited goal results in a steer so the agent starts pursuing the new objective - Make sure the new objective is reflected in the goal if you use `/goal` to display the goal summary - Make sure that `/goal edit` doesn't reset the token budget, time/token accounting on the updated goal
Eric Traut ·
2026-05-11 10:49:19 -07:00 -
chore: drop built-in MCPs (#22173)
Drop something that was never used
jif-oai ·
2026-05-11 19:45:08 +02:00 -
app-server: remove TCP websocket listener (#21843)
## Why The app-server no longer needs to expose a TCP websocket listener. Keeping that transport also kept around a separate listener/auth surface that is unnecessary now that local clients can use stdio or the Unix-domain control socket, while remote connectivity is handled by `remote_control`. ## What Changed - Removed `ws://IP:PORT` parsing and the `AppServerTransport::WebSocket` startup path. - Deleted the app-server websocket listener auth module and removed related CLI flags/dependencies. - Kept websocket framing only where it is still needed: over the Unix-domain control socket and in the outbound `remote_control` connection. - Updated app-server CLI/help text and `app-server/README.md` to document only `stdio://`, `unix://`, `unix://PATH`, and `off` for local transports. - Converted affected app-server integration coverage from TCP websocket listeners to UDS-backed websocket connections, and added a parse test that rejects `ws://` listen URLs. - Removed the now-unused workspace `constant_time_eq` dependency and refreshed `Cargo.lock` after `cargo shear` caught the drift. - Moved test app-server UDS socket paths to short Unix temp paths so macOS Bazel test sandboxes do not exceed Unix socket path limits. ## Verification - Added/updated tests around UDS websocket transport behavior and `ws://` listen URL rejection. - `cargo shear` - `cargo metadata --no-deps --format-version 1` - `cargo test -p codex-app-server unix_socket_transport` - `cargo test -p codex-app-server unix_socket_disconnect` - `just fix -p codex-app-server` - `git diff --check` Local full Rust test execution was blocked before compilation by an external fetch failure for the pinned `nornagon/crossterm` git dependency. `just bazel-lock-update` and `just bazel-lock-check` were retried after the manifest cleanup but remain blocked by external BuildBuddy/V8 fetch timeouts.
Ruslan Nigmatullin ·
2026-05-11 10:17:26 -07:00 -
Use goal preview metadata for goal-first threads (#21981)
Fixes #20792 ## Why `/goal`-first threads are valid resumable threads, but they can be missing from `codex resume` and app recents because discovery depends on metadata derived from a normal first user message. PR #21489 attempted to fix this by using the goal objective as `first_user_message`. Review feedback pointed out that `first_user_message` does more than provide visible text today: it gates listing, supplies preview text, and participates in deciding whether a later title should surface as a distinct thread name. Reusing it for the goal objective could leave a `/goal`-first thread with `first_user_message=<goal>` and `title=<later prompt>`, even though the goal should only provide the initial visible preview. This PR follows that feedback by and keeps the `first_user_message` as is but introduces a new `preview` field to separate concerns. The `preview` field is populated from the first user message or the goal objective. We can extend it in the future to include other sources. ## What Changed - Added internal thread `preview` metadata in `codex-state`, including a SQLite migration that backfills from `first_user_message` and from existing `thread_goals` objectives when needed. - Treated `ThreadGoalUpdated` as preview-bearing metadata so goal-first threads can be listed and searched without mutating `first_user_message`. - Updated rollout listing, state queries, thread-store conversion, and app-server mapping to use preview metadata while continuing to expose the existing public `preview` field. - Preserved title/name distinctness behavior around literal `first_user_message`, so a later normal prompt after `/goal` does not surface as a separate name just because the goal supplied the initial preview. - Preserved compatibility for older/internal metadata writes by deriving preview from `first_user_message` when explicit preview metadata is absent. ## Verification - Manually verified that a thread that starts with a `/goal <objective>` shows up in the resume picker.
Eric Traut ·
2026-05-11 10:12:46 -07:00 -
Improve goal continuation based on feedback (#22045)
## Summary This PR updates the goal continuation prompt to address feedback from early adopters. There are two primary changes: 1. Goal continuation and budget-limit steering prompts now use hidden user-context messages instead of hidden developer messages. 2. The goal continuation prompt is refined to improve the model's ability to fully complete the active goal rather than stop at a smaller or merely passing subset. The user-message transition is important for two reasons. First, it eliminates an issue where older steering messages could be responded to again after a new turn. Second, it works better with compaction because user messages are treated differently from developer messages during compaction. The prompt refinements make persistence explicit, ground work in current evidence, encourage `update_plan` for multi-step progress visibility, and require stronger completion audits before calling `update_goal`. It also removes the elapsed-time reporting in the prompt; I saw evidence that this was causing the model to shortcut work as it became nervous about time. These changes were tested with evals. Chriss4123 has also been running independent evals in [#19910](https://github.com/openai/codex/issues/19910), and many of the improvements in this PR were suggested by him. ## Verification - Tested with evals. - Added and updated focused `codex-core` coverage for hidden goal user context, continuation and budget-limit request shape, prompt rendering, and objective delimiter escaping.
Eric Traut ·
2026-05-11 09:51:21 -07:00 -
Fix side conversation config inheritance (#22106)
Addresses #22101 ## Why Side conversations are ephemeral forks of the active thread, but `/side` was building its fork config from the app-level config after refreshing it from disk. If the parent thread had runtime settings that differed from the current persisted defaults, such as a changed model, reasoning effort, permissions, reviewer, or fast-mode selection, the side conversation could start with different behavior than its parent. ## What changed - Build side fork config from the active parent `ChatWidget` config, then overlay the parent thread's effective model, reasoning effort, service tier, and fast-mode opt-out state. - Forward model reasoning summary, verbosity, personality, web search mode, and service-tier overrides through TUI app-server start/resume/fork lifecycle params. - Add focused tests for parent runtime inheritance, side developer guardrail preservation, and lifecycle param forwarding.
Eric Traut ·
2026-05-11 09:47:51 -07:00 -
Ahmed Ibrahim ·
2026-05-11 19:33:15 +03:00 -
[codex] Harden overflow auto-compaction recovery (#22141)
## Why Dogfooder feedback exposed two correctness gaps in normal-loop overflow recovery: 1. a sampling request that hit `ContextWindowExceeded` could keep re-entering auto-compaction indefinitely if the compacted retry still did not fit, and 2. local compact-history rebuilds flattened user messages down to text, so an overflowing `[image, "what is this?"]` turn could be retried without the image after compaction. That means recovery could either fail to terminate cleanly or proceed with a materially weakened version of the user request. ## What changed - Move normal-loop `ContextWindowExceeded` handling into the sampling retry loop, so successful rescue compaction consumes the provider retry budget instead of creating an unbounded outer-turn loop. - Keep compacted user-history rebuilds structured: `collect_user_messages` now carries user `UserInput` content rather than flattened strings, and `build_compacted_history` reconstructs full user messages from that structured representation. - Preserve image inputs while retaining the existing text-budget truncation behavior for compacted user history. - Preserve existing compaction-task failure handling and client-session reset behavior while bounding repeated overflow retries. - Add focused regression coverage for: - recovery after a normal-loop overflow, - retry-budget exhaustion after repeated overflow, - local recovery preserving image + text input, - remote recovery preserving image + text input, - remote compaction v2 preserving image + text input, and - compaction failure still terminating cleanly. The main behavior changes are in `codex-rs/core/src/session/turn.rs` and `codex-rs/core/src/compact.rs`. ## Verification - Not run locally; relying on PR CI for this update. --------- Co-authored-by: Codex <noreply@openai.com>
Ahmed Ibrahim ·
2026-05-11 16:16:49 +00:00 -
Persist /goal commands in history (#21860)
## Summary A user reported that `/goal` was not saved to the TUI command history, which made it unavailable for later recall even though other accepted input paths persist history entries. This updates the TUI goal slash-command dispatch so successful `/goal` invocations append the command text to message history. The change covers the bare `/goal` menu command, goal control commands such as `/goal pause`, and objective-setting commands such as `/goal improve benchmark coverage`. ## Verification - `cargo test -p codex-tui goal_slash_command -- --nocapture`
Eric Traut ·
2026-05-11 08:43:55 -07:00 -
Add x-codex-ws-stream-request-start-ms (#22113)
For capturing client-side timing information.
Andrey Mishchenko ·
2026-05-11 08:15:52 -07:00 -
feat: move extensions tool (#22163)
This PR is just moving stuff around
jif-oai ·
2026-05-11 17:14:43 +02:00 -
feat: wire extension tool bundles into core (#22147)
## Why This is the next narrow step toward moving concrete tool families out of core. After #22138 introduced `codex-tool-api`, we still needed a real end-to-end seam that lets an extension own an executable tool definition once and have core install it without the temporary `extension-api` wrapper or a dependency on `codex-tools`. `codex-tool-api` is the small extension-facing execution contract, while `codex-tools` still has a different job: host-side shared tool metadata and planning logic that is not “run this contributed tool”, like spec shaping, namespaces, discovery, code-mode augmentation, and MCP/dynamic-to-Responses API conversion ## What changed - Moved the shared leaf tool-spec and JSON Schema types into `codex-tool-api`, so the executable contract now lives with [`ToolBundle`](https://github.com/openai/codex/blob/c538758095337d4fe0a52a172363ccede4066bda/codex-rs/tool-api/src/bundle.rs#L19-L70). - Replaced the temporary extension-side tool wrapper with direct `ToolBundle` use in `codex-extension-api`. - Taught core to collect contributed bundles, include them in spec planning, register them through [`ToolRegistryBuilder::register_tool_bundle`](https://github.com/openai/codex/blob/c538758095337d4fe0a52a172363ccede4066bda/codex-rs/core/src/tools/registry.rs#L653-L667), and dispatch them through the existing router/runtime path. - Added focused coverage for contributed tools becoming model-visible and dispatchable, plus spec-planning coverage for contributed function and freeform tools. ## Verification - Added `extension_tool_bundles_are_model_visible_and_dispatchable` in `core/src/tools/router_tests.rs`. - Added spec-plan coverage in `core/src/tools/spec_plan_tests.rs` for contributed extension bundles. ## Related - Follow-up to #22138
jif-oai ·
2026-05-11 16:42:29 +02:00 -
[codex] default unknown contributed tools to mutating (#22143)
## Summary - make the shared `ToolExecutor::is_mutating` default conservative by returning `true` - update the trait docs to say read-only tools should opt out explicitly - add a regression test covering the default behavior ## Why Hosts use this signal for serialization and approval policy. Treating unknown contributed tools as read-only lets a write-capable tool accidentally bypass mutating-tool safeguards if it forgets to override the hook. ## Validation - not run, per request
jif-oai ·
2026-05-11 14:39:21 +02:00 -
feat: drop
CodexExtension(#22140)Drop `CodexExtension` as not needed for now
jif-oai ·
2026-05-11 14:19:51 +02:00 -
refactor: extract executable tool contracts into codex-tool-api (#22138)
## Why The tool-extraction work needs one shared executable-tool seam that hosts and tool owners can depend on without reaching into `codex-core`. Landing that seam first makes the later tool-family ports incremental and keeps the reusable contract separate from any one migration. ## What changed - add a new `codex-tool-api` crate and workspace wiring - move the common executable-tool contracts into that crate: `ToolBundle`, `ToolDefinition`, `ToolExecutor`, `ToolCall`, `ToolInput`, `ToolOutput`, `JsonToolOutput`, and `ToolError` - keep host state generic through `ToolBundle<C>` / `ToolCall<C>` so later integrations can provide their own runtime context without baking core types into the API - carry the host signals the runtime will need later, including parallel-call support and mutability probing - leave existing tool families in place for now; this PR only establishes the reusable API surface - add the Bazel target and lockfile updates for the new crate ## Testing - `cargo test -p codex-tool-api`
jif-oai ·
2026-05-11 13:56:59 +02:00 -
extension: move git attribution into an extension (#21738)
## Why Git commit attribution is prompt policy, not session orchestration. After #21737 adds the extension-registry seam, this moves that prompt-only behavior out of `codex-core` so `Session` can consume extension-contributed prompt fragments instead of owning a one-off policy path itself. Before this PR, `Session` injected the trailer instruction directly from `codex-core` ([session assembly](https://github.com/openai/codex/blob/a57a747eb667753118217b8bb47dfd1fff88cbde/codex-rs/core/src/session/mod.rs#L2733-L2739), [helper module](https://github.com/openai/codex/blob/a57a747eb667753118217b8bb47dfd1fff88cbde/codex-rs/core/src/commit_attribution.rs#L1-L33)). This branch moves that same responsibility into [`codex-git-attribution`](https://github.com/openai/codex/blob/b5029a67360fe5c948aa849d4cf65fd2597ebaae/codex-rs/ext/git-attribution/src/lib.rs#L14-L100). ## What changed - Added the `codex-git-attribution` extension crate. - Snapshot `CodexGitCommit` plus `commit_attribution` at thread start, then contribute the developer-policy fragment through the extension registry. - Register the extension in app-server thread extensions. - Remove the old `codex-core` helper module and direct `Session` injection path. This keeps the existing behavior intact: the prompt is only contributed when `CodexGitCommit` is enabled, blank attribution still disables the trailer, and the default remains `Codex <noreply@openai.com>`. ## Stack - Stacked on #21737.
jif-oai ·
2026-05-11 12:53:15 +02:00 -
extension: wire extension registries into sessions (#21737)
## Why [#21736](https://github.com/openai/codex/pull/21736) introduces the typed extension API, but the runtime does not yet carry a registry through thread/session startup or give contributors host-owned stores to read from. This PR wires that host-side path so later feature migrations can move product-specific behavior behind typed contributions without adding another bespoke seam directly to `codex-core`. ## What changed - Thread `ExtensionRegistry<Config>` through `ThreadManager`, `CodexSpawnArgs`, `Session`, and sub-agent spawn paths. - Wire `ThreadStartContributor` and `ContextContributor` - Expose the small supporting surface needed by non-core callers that construct threads directly, including `empty_extension_registry()` through `codex-core-api`. This PR lands the host plumbing only: the app-server registry is still empty, and concrete feature migrations are intended to follow separately.
jif-oai ·
2026-05-11 11:38:18 +02:00 -
extension: add initial typed extension API (#21736)
## Why `codex-core` still owns a growing amount of product-specific behavior. This PR starts the extraction path by introducing a small, typed first-party extension seam: features can install the contribution families they actually own, while the host keeps lifecycle and state ownership instead of pushing a broad service locator into the API. See the `examples/` for illustration ## Known limitations * Tool contract definition will be shared with core * Fragments must be extracted * Missing some contributors
jif-oai ·
2026-05-11 11:06:24 +02:00 -
Read cached metadata for installed Git plugins (#20825)
## Summary - Populate `plugin/list` interface metadata for installed Git-sourced marketplace plugins from the active cached plugin bundle. - Preserve marketplace category precedence so list behavior matches `plugin/read`. - Keep existing fallback behavior when the cache or manifest is missing or invalid. ## Test Plan - `cd codex-rs && just fmt` - `cd codex-rs && cargo test -p codex-core-plugins list_marketplaces_installed_git_source_reads_metadata_from_cache_without_cloning` - `cd codex-rs && cargo test -p codex-app-server plugin_list_returns_installed_git_source_interface_from_cache` - `cd codex-rs && just fix -p codex-core-plugins` - `cd codex-rs && just fix -p codex-app-server` - `git diff --check` Server-truth check: OpenAI monorepo app-server generated types already expose `PluginSummary.interface`, and the webview consumes it for plugin cards. This PR keeps the protocol/schema unchanged and fills the existing field from the cached installed bundle for Git-backed cross-repo plugins.
xli-oai ·
2026-05-10 16:59:57 -07:00 -
feat(tui): render responsive Markdown tables in TUI (#22052)
## Why The TUI currently treats Markdown tables as ordinary wrapped text, which makes table-heavy responses hard to read and brittle across narrow panes and terminal resizes. This change teaches the TUI to render Markdown tables responsively while preserving the raw Markdown source needed to re-render streamed and finalized transcript content after width changes. The goal is to keep tables legible during streaming, after resize, and once a turn has finished, without corrupting scrollback ordering. ## What Changed - add table detection and responsive table rendering in the Markdown renderer - render standard tables with Unicode box-drawing borders when the pane is wide enough - add a vertical readability fallback for constrained or dense tables so narrow panes still show each row clearly - keep links and `<br>` content inside table cells instead of leaking text outside the table - avoid table normalization inside fenced or indented code blocks - preserve raw streamed Markdown source and keep the active table as a mutable tail until finalization - consolidate finalized streamed content into source-backed transcript cells so post-resize re-rendering stays correct - add snapshot and targeted streaming/resize regression coverage for the new table behavior ## How to Test 1. Start Codex TUI from this branch. 2. Paste this exact prompt: `This is a session to test codex, no need to do any thinking, just end different markdown tables, with columns exploring different markdown contents, like links, bold italic, code, etc. Make them different sizes, some 30+ rows, some not and intertwine them with some paragraphs with complex formatting as well.` 3. Confirm the response includes several Markdown tables mixed with richly formatted paragraphs. 4. Confirm wide-enough tables render with box-drawing borders instead of plain wrapped pipe text. 5. Resize the terminal narrower while the answer is still streaming and confirm the in-progress table stays coherent instead of duplicating headers or leaving broken scrollback behind. 6. Resize again after the turn finishes and confirm the finalized transcript re-renders cleanly at the new width. 7. In a narrow pane, verify dense tables fall back to the vertical per-row layout instead of producing unreadable wrapped columns. 8. Also verify pipe-heavy fenced code blocks still render as code, not as tables. Targeted tests: - `cargo test -p codex-tui table_readability_fallback --no-fail-fast` - `cargo test -p codex-tui markdown_render --no-fail-fast` - `cargo test -p codex-tui streaming::controller --no-fail-fast` - `cargo test -p codex-tui table_resize_lifecycle --no-fail-fast` ## Docs No developer docs update appears necessary.
Felipe Coury ·
2026-05-10 20:42:11 +00:00 -
Deduplicate issue digest interactions by user (#22039)
## Summary The issue digest uses recent posts, comments, and reactions to decide which issues deserve attention. A single active user could previously raise an issue's apparent importance by commenting or reacting multiple times in the window. This changes `codex-issue-digest` so `user_interactions` counts unique human GitHub users per issue across new issue posts, new comments, and new reactions. Raw reaction/comment counts are still preserved for detail output, and the skill guidance now describes `Interactions` as a unique-human-user count.
Eric Traut ·
2026-05-10 09:55:42 -07:00 -
fix(tui): suppress taskkill output for MCP teardown on Windows (#21759)
## Why On native Windows, running `/mcp` can leak `taskkill`'s normal `SUCCESS:` messages into the Codex TUI while the temporary MCP inventory process tree is being torn down. That corrupts the screen even though MCP itself is working correctly. Fixes #20845. ## What Changed - Redirect the Windows-only MCP teardown `taskkill` subprocess to null stdio so its console output cannot reach the TUI. ## How to Test 1. On native Windows, configure a stdio MCP server, for example: ```powershell codex mcp add sequential-thinking -- npx -y @modelcontextprotocol/server-sequential-thinking ``` 2. With the latest released Codex CLI, start Codex and run `/mcp`. 3. Confirm the current behavior: `taskkill` `SUCCESS:` lines appear in the TUI during the MCP refresh. 4. Switch to this branch's build, start Codex again, and run `/mcp`. 5. Confirm the MCP inventory still renders normally and the `taskkill` lines no longer appear. 6. Repeat `/mcp` once more on this branch to verify the regression does not recur on repeated inventory requests. Targeted tests: - `cargo test -p codex-rmcp-client` - `cargo test -p codex-rmcp-client --test process_group_cleanup --quiet`
Felipe Coury ·
2026-05-10 15:51:26 +00:00 -
fix(tui): preserve Shift+Enter in tmux csi-u panes (#21943)
## Why Inside tmux, `Shift+Enter` can still reach Codex as a plain `Enter` even when tmux has extended keys enabled. In `csi-u` tmux panes, Codex needs to request `modifyOtherKeys` mode 2 so tmux moves the pane from `VT10x` into extended-key mode and preserves the Shift modifier. Without that extra request, composer `Shift+Enter` submits the draft instead of inserting a newline. Fixes #21699. ## What Changed - Detect tmux sessions and read the active `extended-keys-format`, preferring the pane-local value before falling back to the global option. - Request `modifyOtherKeys` mode 2 for tmux panes using `csi-u` extended keys, and reset it when restoring keyboard reporting. - Add unit coverage for tmux detection, the format gate, and the emitted `modifyOtherKeys` escape sequence. ## How to Test 1. In tmux, configure: ```tmux set-option -g extended-keys on set-option -g extended-keys-format csi-u ``` 2. Start Codex in a fresh tmux pane from this branch. 3. From another pane, confirm the Codex pane reports `mode=Ext 2`: ```bash tmux list-panes -a -F '#{session_name}:#{window_index}.#{pane_index} mode=#{pane_key_mode} cmd=#{pane_current_command}' ``` 4. Type a draft in the composer and press `Shift+Enter`; confirm it inserts a newline instead of submitting. 5. Also confirm plain `Enter` still submits as before. Targeted tests: - `cargo test -p codex-tui` ## Notes - Manual verification used both real `Shift+Enter` in iTerm2/tmux and `tmux send-keys ... S-Enter` to confirm the tmux pane changes from `VT10x` to `Ext 2` and preserves newline behavior. - On this checkout, the broader `codex-tui` test run currently reaches unrelated existing failures in `status::tests::*` plus a later stack overflow in `tests::fork_last_filters_latest_session_by_cwd_unless_show_all`.
Felipe Coury ·
2026-05-10 11:45:49 -03:00 -
Persist 'priority' service tier as fast in config (#21991)
### Motivation - Normalize persisted service tier so selecting the request value `priority` (or legacy `fast`) is stored as `fast` while preserving unknown tier IDs and keeping request-time behavior unchanged. ### Description - Update persistence logic in `codex-rs/core/src/config/edit.rs` so `ConfigEdit::SetServiceTier` maps request values: `priority`/`fast` -> `"fast"`, `flex` -> `"flex"`, and leaves unknown strings unchanged. - Add unit tests in `codex-rs/core/src/config/edit_tests.rs` that verify a `priority` selection is written to `config.toml` as `"fast"` and that unknown tiers are preserved. - Add a config load test in `codex-rs/core/src/config/config_tests.rs` to ensure `service_tier = "priority"` still resolves to the `priority` request value at load time. - Add the required import `use codex_protocol::config_types::ServiceTier;` to the edited modules. ### Testing - Ran `just fmt` and `just fix -p codex-core` to apply formatting and lints and they completed successfully. - Ran `cargo test -p codex-core --lib service_tier` (focused unit tests for the change) and the tests passed. - Ran `cargo test -p codex-protocol` and the protocol test suite passed. - Note: an initial broader `cargo test -p codex-core service_tier` invocation matched integration tests and produced unrelated failures/hangs, so that run was interrupted and the focused `--lib` unit-test invocation was used instead. ------ [Codex Task](https://chatgpt.com/codex/cloud/tasks/task_i_69ffc5a1262c8321af91b69c9845147f)
Ahmed Ibrahim ·
2026-05-10 06:22:46 +03:00 -
Split ChatWidget state into focused modules (#21866)
## Summary `ChatWidget` has been carrying several independent domains in one large state bag: transcript bookkeeping, turn lifecycle, queued input, status surfaces, connectors, review mode, and protocol dispatch. That makes otherwise-local changes hard to reason about because unrelated fields and side effects live beside each other in `chatwidget.rs`. This is the first cleanup PR in a larger decomposition effort. It does not try to make `chatwidget.rs` small in one sweep; instead, it establishes focused state boundaries that later handler, popup, rendering, and effect-synchronization extractions can build on. This PR keeps `ChatWidget` as the composition layer while moving focused state into smaller `codex-tui` modules. The widget still owns effects that touch the bottom pane, app events, command submission, redraw scheduling, and terminal-title updates. ## Changes - Add focused state modules under `codex-rs/tui/src/chatwidget/` for input queues, turn lifecycle, transcript bookkeeping, status state, connectors, review mode, and app-server protocol dispatch. - Update `ChatWidget` to hold grouped state structs and route input/lifecycle/status operations through those focused helpers. - Move app-server notification dispatch into `chatwidget/protocol.rs` while leaving feature handlers and side effects on `ChatWidget`. - Replace the large manual `ChatWidget` test literal with the normal constructor plus narrow test overrides, so future state moves do not require every field to be restated in test setup. - Update existing tests to access the new grouped state or narrower helpers without changing snapshot behavior. ## Longer-term direction Follow-up PRs can continue shrinking `chatwidget.rs` by moving behavior, not just state, into focused modules: - Extract input/submission flow, turn/stream handling, and tool-cell lifecycles into domain modules that call the new state reducers. - Move popup/settings builders and rendering helpers out of the main widget file so `ChatWidget` stays focused on composition. - Reduce direct `BottomPane` mutation by applying domain-specific sync outputs at clearer boundaries.
Eric Traut ·
2026-05-09 15:16:01 -07:00 -
Avoid blocking TUI on agent metadata hydration (#21870)
## Why Fixes #16688. The TUI currently hydrates collab receiver metadata by awaiting `thread/read` before each active-thread notification is rendered. During large subagent fan-outs, the embedded app-server can be busy starting agents and processing spawn work, so those synchronous metadata reads queue behind the fan-out and block the TUI event loop. That makes the UI appear frozen even though the underlying agent work can continue. ## What Changed - Replaced eager `thread/read` metadata hydration on the active notification path with local receiver-thread caching. - Kept `ThreadStarted` and picker refreshes as the places that fill in agent nickname/role metadata when it is available. - Skipped caching receiver threads that are explicitly reported as `NotFound`, avoiding live-looking ghost entries for failed stale-agent calls. - Added TUI tests covering both local receiver caching and `NotFound` suppression. ## Verification - `cargo test -p codex-tui collab_receiver_notification` - `just fix -p codex-tui` I also ran the full `cargo test -p codex-tui`; the new test passed, but the full process later aborted with an unrelated stack overflow in `tests::fork_last_filters_latest_session_by_cwd_unless_show_all`.
Eric Traut ·
2026-05-09 15:15:40 -07:00 -
Improve hooks trust flow in TUI (#21755)
# Why Hooks that need trust review were easy to miss, and the existing TUI flow made users discover `/hooks` manually before they could decide whether to inspect or trust them. # What - add a startup review prompt for new or changed hooks before normal composer use - add a top-level `t` shortcut in `/hooks` to trust every review-needed hook at once - make pending-review rows and helper copy use warning styling ## TUI ### Startup review interstitial ```text Hooks need review 2 hooks are new or changed. Hooks can run outside the sandbox after you trust them. › 1. Review hooks 2. Trust all and continue 3. Continue without trusting (hooks won't run) ``` ### Top-level `/hooks` page when review is needed ```text Hooks Lifecycle hooks from config and enabled plugins. ⚠ 1 hook needs review before it can run. Event Installed Active Review Description PreToolUse 1 0 1 Before a tool executes ... Press t to trust all; enter to review hooks; esc to close ```
Abhinav ·
2026-05-09 21:17:30 +00:00 -
fix(tui): improve light-mode selection contrast (#21950)
## Why On light terminal backgrounds, selected rows in several TUI pickers were rendered with the same bright cyan accent used on dark themes. Against the light menu surface, that made the current selection hard to distinguish at a glance. <table><tr> <td> <p align="center">Before</p> <img width="1109" height="864" alt="SCR-20260509-nmtz" src="https://github.com/user-attachments/assets/b31ce0d0-19c2-4bdd-a220-7acc77bd8e8e" /> </td> <td> <p align="center">After</p> <img width="1164" height="844" alt="SCR-20260509-nmox" src="https://github.com/user-attachments/assets/7b3fede0-4739-4a9f-a979-cdbb7451841f" /> </td> </tr></table> ## What changed - Added a shared background-aware accent style for active/selected TUI controls. - Use a darker cyan-family accent on light backgrounds while preserving the existing bright cyan accent on dark or unknown backgrounds. - Reused that accent across shared picker rows and the custom selection-like surfaces that had drifted separately: picker tabs, hooks browsing, external-agent migration choices, and /keymap affordances. - Added focused tests for the light/dark accent rule and rendered selected-row styling. ## How to Test 1. Start Codex in a terminal using a light background theme. 2. Type `/` to open the slash-command picker and move the selection through a few rows. 3. Confirm that the selected row is visibly colored with strong contrast instead of blending into the popup surface. 4. Open `/keymap` and confirm the active tab, selected rows, and picker hint accents use the same light-theme accent treatment. 5. In a dark terminal theme, repeat the slash-picker check and confirm the existing bright cyan selection styling is preserved. Targeted tests: - `cargo test -p codex-tui accent_style_uses_` - `cargo test -p codex-tui selected_rows_use_the_shared_accent_style` - `cargo test -p codex-tui selected_event_rows_use_the_shared_accent_style` Notes: - A full `cargo test -p codex-tui` run reached the end of the suite but hit an unrelated existing stack overflow in `tests::fork_last_filters_latest_session_by_cwd_unless_show_all`.
Felipe Coury ·
2026-05-09 16:10:56 -03:00 -
fix(tui): preserve wrapped prose beside URLs (#21760)
## Why Mixed prose lines that contained URLs started taking the URL-preserving wrapping path, but that path could split ordinary words mid-token. A follow-up issue remained in scrollback insertion: when already-rendered indented rows were wrapped again, continuation rows could lose their margin and fall back to terminal hard wrapping. Together those bugs made normal Markdown output look broken around links, lists, blockquotes, and indented content. Separately, the local argument-comment lint wrappers failed under environments that set `PYTHONSAFEPATH=1`, because Python no longer adds the script directory to `sys.path` automatically. That prevented the lint from reaching Rust callsites at all. <img width="1778" height="1558" alt="CleanShot 2026-05-09 at 11 51 38" src="https://github.com/user-attachments/assets/9274d150-1757-4f1a-89ac-5bdc9997d8cb" /> ## What Changed - Preserve URL tokens without turning every neighboring prose word into a character-level split point. - Add a mixed URL/prose wrapper that keeps ordinary words whole, preserves leading whitespace, and re-splits long non-URL tokens against the actual width available on continuation rows. - Reuse a rendered history row's leading whitespace as the continuation indent when scrollback insertion has to pre-wrap it again. - Add regression coverage for markdown wrapping, history-cell rendering, scrollback continuation margins, leading-indent width accounting, and continuation-row re-splitting. - Make both argument-comment lint entrypoints explicitly add their own directory to `sys.path`, so sibling imports still work when `PYTHONSAFEPATH=1`. ## How to Test 1. Start Codex and render a long Markdown response that mixes prose with inline links, blockquotes, lists, and indented code-like text. 2. Confirm that ordinary words next to links stay whole instead of breaking mid-word. 3. Resize or replay the transcript and confirm wrapped continuation rows keep their expected left margin for blockquotes, lists, and indented content. 4. Run the source argument-comment lint from a shell with `PYTHONSAFEPATH=1` and confirm it starts normally instead of failing to import `wrapper_common`. Targeted tests: - `cargo test -p codex-tui mixed_line --lib` - `cargo test -p codex-tui preserves_prefix_on_wrapped_rows --lib` - `cargo test -p codex-tui agent_markdown_cell_does_not_split_words_after_inline_markdown --lib` - `cargo test -p codex-tui mixed_url_markdown_wraps_prose_without_splitting_words_snapshot --lib` - `python3 tools/argument-comment-lint/test_wrapper_common.py` - `just argument-comment-lint-from-source -p codex-tui -- --lib` Notes: - `cargo test -p codex-tui` currently reaches the new tests successfully, then still aborts in the pre-existing `tests::fork_last_filters_latest_session_by_cwd_unless_show_all` stack-overflow failure.
Felipe Coury ·
2026-05-09 13:58:10 -03:00 -
tests: cover sandbox link write behavior (#21819)
## Why [PR #1705](https://github.com/openai/codex/pull/1705) moved `apply_patch` execution under the configured sandbox and called out the need for integration coverage. We already covered textual `../` escapes, but did not have coverage for link aliases that live inside a writable workspace while pointing at, or aliasing, files visible outside it. This PR locks in the current sandbox boundary without changing production write semantics. Symlink escapes into a read-only outside root should fail and leave the outside file unchanged. Existing hard links are characterized separately: if a user-created hard link already exists inside the writable root, sandboxed writes preserve normal hard-link semantics rather than replacing the link and silently breaking that relationship. ## What Changed - Added `apply_patch_cli_does_not_write_through_symlink_escape_outside_workspace` to verify `apply_patch` cannot update a symlink that targets a file outside the writable workspace. - Added `apply_patch_cli_preserves_existing_hard_link_outside_workspace` to verify `apply_patch` intentionally writes through an existing hard link and does not unlink or replace it. - Added `file_system_sandboxed_write_preserves_existing_hard_link` to verify sandboxed `fs/writeFile` preserves an existing hard link and writes the shared inode. ## Testing - `cargo test -p codex-exec-server file_system_sandboxed_write` - `cargo test -p codex-core apply_patch_cli_does_not_write_through_symlink_escape_outside_workspace` - `cargo test -p codex-core apply_patch_cli_preserves_existing_hard_link_outside_workspace` - `just fix -p codex-exec-server -p codex-core` - `just fix -p codex-core` --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/21819). * #21845 * __->__ #21819
Michael Bolin ·
2026-05-09 08:28:15 -07:00 -
[codex] Lowercase TUI service tier commands (#21906)
## Why Service-tier slash commands are built from model-catalog metadata. If the catalog returns a name like `Fast`, the TUI currently exposes `/Fast` and exact dispatch expects that casing, which is inconsistent with the lowercase command style used elsewhere. ## What - Lowercase service-tier command names when converting catalog tiers into `ServiceTierCommand` values. - Add regression coverage that seeds a catalog tier named `Fast` and expects the generated command to be `fast`. ## Testing Not run locally per repo instruction; PR CI should run the new `service_tier_commands_lowercase_catalog_names` coverage.
Ahmed Ibrahim ·
2026-05-09 14:29:12 +03:00 -
Route Python SDK turn notifications by ID (#21778)
## Why The Python SDK previously protected the stdio transport with a single active turn-consumer guard. That avoided competing reads from stdout, but it also meant one `Codex`/`AsyncCodex` client could not stream multiple active turns at the same time. Notifications could also arrive before the caller received a `TurnHandle` and registered for streaming, so the SDK needed an explicit routing layer instead of letting individual API calls read directly from the shared transport. ## What Changed - Added a private `MessageRouter` that owns per-request response queues, per-turn notification queues, pending turn-notification replay, and global notification delivery behind a single stdout reader thread. - Generated typed notification routing metadata so turn IDs come from known payload shapes instead of router-side attribute guessing, with explicit fallback handling for unknown notification payloads. - Updated sync and async turn streaming so `TurnHandle.stream()`/`run()` and `stream_text()` consume only notifications for their own turn ID, while `AsyncAppServerClient` no longer serializes all transport calls behind one async lock. - Cleared pending turn-notification buffers when unregistered turns complete so never-consumed turn handles do not leave stale queues behind. - Removed the internal stream-until helper now that turn completion waiting can register directly with routed turn notifications. - Updated Python SDK docs and focused tests for concurrent transport calls, interleaved turn routing, buffered early notifications, unknown notification routing, async delegation, and routed turn completion behavior. ## Validation - `uv run --extra dev ruff format scripts/update_sdk_artifacts.py src/codex_app_server/_message_router.py src/codex_app_server/client.py src/codex_app_server/generated/notification_registry.py tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `uv run --extra dev ruff check scripts/update_sdk_artifacts.py src/codex_app_server/_message_router.py src/codex_app_server/client.py src/codex_app_server/generated/notification_registry.py tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `uv run --extra dev pytest tests/test_client_rpc_methods.py tests/test_public_api_runtime_behavior.py tests/test_async_client_behavior.py` - `git diff --check` --------- Co-authored-by: Codex <noreply@openai.com>
Ahmed Ibrahim ·
2026-05-09 04:16:23 +00:00 -
[codex] compact network context rendering (#21875)
## Why The model-visible `<network>` context currently repeats indentation and a pair of XML tags for every allowed or denied domain. Large domain sets spend a surprising amount of prompt budget on that scaffolding instead of the actual policy values. ## What changed - Render allowed domains as one comma-separated `<allowed>` value instead of one element per domain. - Render denied domains the same way. - Keep the full allow/deny domain sets model-visible while updating the serialization and settings-update coverage for the denser shape. ## Example Before: ```xml <network enabled="true"> <allowed>api.example.test</allowed> <allowed>cdn.example.test</allowed> <denied>blocked.example.test</denied> </network> ``` After: ```xml <network enabled="true"><allowed>api.example.test,cdn.example.test</allowed><denied>blocked.example.test</denied></network> ``` ## Validation - `cargo test -p codex-core environment_context` - `cargo test -p codex-core build_settings_update_items_emits_environment_item_for_network_changes` - Ran a local `codex` session with a real network context containing 121 allowed domains and 42 denied domains, then inspected the raw prompt with `raw_token_viewer_cli.py`. With the same domain set, the rendered `<network>` section shrank from 7,175 characters across 161 lines to 3,666 characters on one line, and the containing environment-context block fell from 6,428 tokens to 5,379 tokens.
sayan-oai ·
2026-05-09 03:52:48 +00:00 -
feat: Add role-aware plugin share context APIs (#21867)
Expose discoverability and full share principals in share context, carry roles through save/updateTargets, hydrate local shared plugin reads, and keep share URLs only under plugin.shareContext.
xl-openai ·
2026-05-08 20:46:39 -07:00 -
Move file watcher out of core (#21290)
## Why The app-server watcher relocation leaves the generic filesystem watcher as the last watcher-specific implementation still living inside `codex-core`. Moving that code to a small crate keeps `codex-core` focused on thread execution and lets app-server depend on the watcher without reaching back into core for filesystem watching primitives. This PR is stacked on #21287. ## What changed - Added a new `codex-file-watcher` crate containing the existing watcher implementation and its unit tests. - Updated app-server `fs_watch`, `skills_watcher`, and listener state to import watcher types from `codex-file-watcher`. - Removed the `file_watcher` module and `notify` dependency from `codex-core`. - Updated Cargo workspace metadata and `Cargo.lock` for the new internal crate. ## Validation - `cargo check -p codex-file-watcher -p codex-core -p codex-app-server` - `cargo test -p codex-file-watcher` - `cargo test -p codex-app-server skills_changed_notification_is_emitted_after_skill_change` - `just bazel-lock-update` - `just bazel-lock-check` - `just fix -p codex-file-watcher` - `just fix -p codex-core` - `just fix -p codex-app-server`
pakrym-oai ·
2026-05-08 18:19:23 -07:00 -
Reapply "Move skills watcher to app-server" (#21652)
## Why PR #21460 reverted the earlier move of skills change watching from `codex-core` into app-server. This reapplies that boundary change so app-server owns client-facing `skills/changed` notifications and core no longer carries the watcher. ## What - Restore the app-server `SkillsWatcher` and register it from thread listener setup. - Remove the core-owned skills watcher and its core live-reload integration surface. - Restore app-server coverage for `skills/changed` notifications after a watched skill file changes. ## Validation - `cargo test -p codex-app-server --test all suite::v2::skills_list::skills_changed_notification_is_emitted_after_skill_change -- --exact --nocapture` - `cargo test -p codex-core --lib --no-run`
pakrym-oai ·
2026-05-08 17:41:15 -07:00 -
sqlite: no more destructive version bumps (#21847)
## Why We'd like SQLite state to become required and load-bearing. As a first step, let's remove the mechanism that allows us to blow away the SQLite DB on a version bump, and instead rely on graceful migrations. The original motivation ([PR](https://github.com/openai/codex/pull/10623)) behind this mechanism was to care less about backwards compatibility while SQLite was being landed, but I'd say it's quite important now to keep the data in it. ## What changed - Make `STATE_DB_FILENAME` and `LOGS_DB_FILENAME` the full canonical filenames: `state_5.sqlite` and `logs_2.sqlite`. - Remove `STATE_DB_VERSION` / `LOGS_DB_VERSION` and the helper that constructed filenames from versions. - Stop `StateRuntime::init` from scanning for or deleting older SQLite DB filenames at startup. - Delete the tests that encoded legacy state/logs DB deletion behavior. ## Verification - `cargo test -p codex-state`
Owen Lin ·
2026-05-08 17:29:44 -07:00 -
feat: add Bedrock Mantle client agent header (#21840)
## Why Amazon Bedrock Mantle needs a stable client-agent header so requests from the built-in Bedrock provider can be identified as coming from Codex for safety stack. ## What changed - Added `x-amzn-mantle-client-agent: codex` to the built-in Amazon Bedrock provider default HTTP headers.
Celia Chen ·
2026-05-08 23:58:41 +00:00 -
[daemon] Add app-server daemon lifecycle management (#20718)
## Why Desktop and mobile Codex clients need a machine-readable way to bootstrap and manage `codex app-server` on remote machines reached over SSH. The same flow is also useful for bringing up app-server with `remote_control` enabled on a fresh developer machine and keeping that managed install current without requiring a human session. ## What changed - add the new experimental `codex-app-server-daemon` crate and wire it into `codex app-server daemon` lifecycle commands: `start`, `restart`, `stop`, `version`, and `bootstrap` - add explicit `enable-remote-control` and `disable-remote-control` commands that persist the launch setting and restart a running managed daemon so the change takes effect immediately - emit JSON success responses for daemon commands so remote callers can consume them directly - support a Unix-only pidfile-backed detached backend for lifecycle management - assume the standalone `install.sh` layout for daemon-managed binaries and always launch `CODEX_HOME/packages/standalone/current/codex` - add bootstrap support for the standalone managed install plus a detached hourly updater loop - harden lifecycle management around concurrent operations, pidfile ownership, stale state cleanup, updater ownership, managed-binary preflight, Unix-only rejection, forced shutdown after the graceful window, and updater process-group tracking/cleanup - document the experimental Unix-only support boundary plus the standalone bootstrap/update flow in `codex-rs/app-server-daemon/README.md` ## Verification - `cargo test -p codex-app-server-daemon -p codex-cli` - live pid validation on `cb4`: `bootstrap --remote-control`, `restart`, `version`, `stop` ## Follow-up - Add updater self-refresh so the long-lived `pid-update-loop` can replace its own executable image after installing a newer managed Codex binary.
Ruslan Nigmatullin ·
2026-05-08 16:51:16 -07:00 -
Increase exec-server environment transport timeouts (#21825)
## Why The environment-backed exec-server transport currently hardcodes 5 second connect and initialize timeouts in `client_transport.rs`. That is short for SSH-backed stdio environments and remote websocket environments, and there is currently no way to raise those values from `CODEX_HOME/environments.toml`. This stacked follow-up raises the default environment transport timeouts and lets each configured environment override them in `environments.toml`. ## What Changed - raise the default environment transport connect and initialize timeouts from 5s to 10s - store concrete timeout values on `ExecServerTransportParams` instead of hardcoding them in `connect_for_transport(...)` - add `connect_timeout_sec` and `initialize_timeout_sec` to `[[environments]]` entries in `environments.toml` - apply parse-time defaults so runtime transport code receives fully resolved timeout values - reject `connect_timeout_sec` on stdio environments because it only applies to websocket transports - extend parser tests to cover the new fields and defaults ## Stack - base: https://github.com/openai/codex/pull/21794 - this PR: configurable environment transport timeouts ## Validation - `cd /Users/starr/code/codex-worktrees/exec-env-timeouts-config-20260508/codex-rs && just fmt` - not run: tests --------- Co-authored-by: Codex <noreply@openai.com>
starr-openai ·
2026-05-08 16:33:29 -07:00 -
[codex] support executor registry remote environments (#21323)
## Summary Support registry-backed remote executors end to end so downstream services can resolve an executor id into an exec-server URL and make that environment available to Codex without relying on the legacy cloud environments flow. ## What changed - switch remote executor registration to the executor registry bootstrap contract - allow named remote environments to be inserted into `EnvironmentManager` at runtime - add the experimental app-server RPC `environment/add` so initialized experimental clients can register those remote environments for later `thread/start` and `turn/start` selection ## Validation Ran focused validation locally: - `cargo test -p codex-exec-server environment_manager_` - `cargo test -p codex-exec-server register_executor_posts_with_bearer_token_header` - `cargo test -p codex-app-server-protocol`
Michael Zeng ·
2026-05-08 16:30:07 -07:00 -
Support openai library tool (#20293)
Support chatgpt library tool
lt-oai ·
2026-05-08 22:56:13 +00:00 -
app-server: support daemon-safe restart handling (#21831)
## Why The app-server daemon work needs two app-server behaviors to be safe when lifecycle management is driven by a helper process: - a readiness probe must not become the process-wide client identity just because it connects first - a graceful reload signal needs to keep draining active turns even if it is delivered more than once ## What changed - Treat `codex_app_server_daemon` initialization as a probe-only client for process-global originator and user-agent suffix state. - Distinguish forceable shutdown signals from graceful-only ones, and treat Unix `SIGHUP` as graceful-only while leaving `SIGTERM` and Ctrl-C forceable. - Add regression coverage for daemon probe initialization and repeated `SIGHUP` delivery while a turn is still running. ## Testing - `cargo test -p codex-app-server` - The new daemon-probe and repeated-`SIGHUP` coverage passed. - The run still failed in the existing `suite::conversation_summary::get_conversation_summary_by_relative_rollout_path_resolves_from_codex_home` and `suite::conversation_summary::get_conversation_summary_by_thread_id_reads_rollout` tests because their initialize handshake timed out. - `cargo test -p codex-app-server --test all suite::conversation_summary::` - Reproduced the same two existing initialize-timeout failures in isolation.
Ruslan Nigmatullin ·
2026-05-08 15:47:51 -07:00 -
Make environment provider snapshots path-free (#21794)
## Summary - make EnvironmentProvider::snapshot path-free and keep providers focused on provider-owned remote environments - let provider snapshots request local inclusion via include_local, with environments.toml including local and CODEX_EXEC_SERVER_URL excluding local - move reserved local environment construction into EnvironmentManager using ExecServerRuntimePaths Follow-up to https://github.com/openai/codex/pull/20667 ## Testing - just fmt - git diff --check - devbox: bazel build --bes_backend= --bes_results_url= //codex-rs/exec-server:exec-server - devbox: bazel test --bes_backend= --bes_results_url= //codex-rs/exec-server:exec-server-unit-tests Co-authored-by: Codex <noreply@openai.com>
starr-openai ·
2026-05-08 15:30:00 -07:00 -
ci: check out PR head commits in workflows (#21835)
## Why PR CI should test the exact commit that was pushed to the PR branch. By default, GitHub's `pull_request` event checks out a synthetic merge commit from `refs/pull/<number>/merge`, so the tested tree can include an implicit merge with the current base branch instead of matching the pushed head SHA. Using the PR head SHA makes each check result correspond to a concrete commit the author submitted. This also behaves better for stacked PR workflows, including Sapling stacks and other Git stack tooling: a middle PR's head commit already contains the lower stack changes in its tree, without pulling in commits above it or GitHub's temporary merge ref. ## What Changed - Set every `actions/checkout` in `pull_request` workflows under `.github/workflows` to use `github.event.pull_request.head.sha` on PR events and `github.sha` otherwise. - Updated `blob-size-policy` to compare `github.event.pull_request.base.sha` and `github.event.pull_request.head.sha`, since it no longer checks out GitHub's merge commit where `HEAD^1`/`HEAD^2` represented the PR range. ## Verification - Parsed the edited workflow YAML files with Ruby. - Checked that every checkout block in the `pull_request` workflows has the PR-head `ref`.
Michael Bolin ·
2026-05-08 15:14:33 -07:00 -
Using cached connector directory for discoverable tools list (#21497)
## Summary Startup tool construction currently depends on connector directory metadata for `tool_suggest` discoverables. On a cold directory cache, that can put slow connector-directory requests on the blocking path even though the tools array only needs directory data for install suggestions, not for the live connector MCP tools themselves. This PR keeps the discoverables path off that cold network fetch: - read connector directory metadata from cache only when building discoverable tools - persist connector directory metadata to `~/.codex/cache/codex_app_directory/<hash>.json` and use it to hydrate the in-memory cache on later runs before the normal refresh path updates it - use connector-directory-specific cache naming to distinguish this metadata cache from the separate Codex Apps tools-spec cache This reduces first-turn startup work without changing how live connector MCP tools are sourced. Longer term, directory-backed install suggestions should move to a search-based flow so they no longer need to be inlined into the tools prompt at all. ## Testing - `cargo test -p codex-connectors` - `cargo test -p codex-chatgpt` - `cargo test -p codex-core request_plugin_install_is_available_without_search_tool_after_discovery_attempts` - `cargo test -p codex-core tool_suggest_uses_connector_id_fallback_when_directory_cache_is_empty`
Matthew Zeng ·
2026-05-08 14:14:11 -07:00