mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
dev
192 Commits
-
path-uri: normalize parent segments in absolute joins (#29903)
## Why `PathUri::join` normalized `..` for relative paths, but its absolute-path branch rebuilt URIs through `url::PathSegmentsMut::push`, which skips dot segments. `/tmp/a/../b` therefore resolved to `/tmp/a/b` instead of `/tmp/b`. ## What changed Normalize absolute native path segments before constructing the file URI. Parent traversal now clamps at POSIX roots, Windows drive roots, and UNC share roots, including paths with repeated separators. Add platform-independent coverage for POSIX, drive, UNC, root-clamping, and repeated-separator cases. ## Manual validation - `just test -p codex-utils-path-uri`
Adam Perry @ OpenAI ·
2026-06-24 22:33:18 +00:00 -
[codex] fix Windows ConPTY input handling (#29734)
## Why Windows unified-exec TTY input did not behave like the non-Windows PTY path. ConPTY sessions could receive the wrong line ending or mishandle backspace, especially when sending input to a foreground program through PowerShell or cmd. The local, legacy restricted, and elevated paths also handled this normalization separately. ## What changed - share one stateful Windows TTY input normalizer across local, legacy restricted, and elevated runner paths - translate LF and split CRLF into one Windows terminal Enter, encode backspace as DEL, and preserve UTF-8 and control bytes such as Ctrl-C - add Windows integration coverage for Unicode input, backspace, Enter, and PowerShell foreground-child Ctrl-C behavior ## Validation - `just test -p codex-utils-pty` (13 tests passed; the Unicode integration test retried once) - the Unicode integration test passed five consecutive runs with retries disabled - integration coverage sends `cafeé 漢字` through cmd and PowerShell and verifies that Ctrl-C interrupts a running PowerShell foreground child
iceweasel-oai ·
2026-06-24 11:27:44 -07:00 -
Cache plugin namespace during executor skill discovery (#29831)
## Why Executor skill discovery runs before the remote skills catalog is available. For a remote environment, each `ExecutorFileSystem` operation becomes an exec-server RPC. Previously, every discovered `SKILL.md` independently resolved its plugin namespace by walking its ancestors and probing both supported manifest locations. In the common `plugin/skills/<skill>/SKILL.md` layout, that repeats 8 RPCs per skill even though every skill under the plugin root uses the same namespace. These lookups happen while skills are parsed, so their cost grows linearly with the skill count and adds directly to first-turn latency. A selected capability root can also contain standalone skills, multiple sibling plugins, nested plugins, or symlinked directories. The optimization therefore needs to retain the nearest-ancestor namespace for each skill rather than assuming the selected root represents exactly one plugin. ## What changed - record plugin-root candidates from directory entries already returned during skill discovery - prune candidates that are not ancestors of any discovered `SKILL.md` before reading manifests - resolve each relevant plugin root once, with one fallback lookup per canonical traversal root for symlinked directories - select the nearest cached plugin namespace for each discovered skill - avoid namespace lookup entirely when the root contains no skills No additional directory traversal is required. Namespace work now scales with the number of plugin roots that contain discovered skills, rather than the total number of skills or unrelated sibling plugins. Standalone and nested-plugin names keep their previous behavior. ## Benchmarks I used a temporary counting `ExecutorFileSystem` around the real local filesystem. Each filesystem operation was counted as one remote RPC and given 1 ms of injected latency. Each variant ran three times; times below are medians. ### One plugin with 100 skills | Operation | Before | After | Delta | | --- | ---: | ---: | ---: | | `get_metadata` | 1,002 | 303 | -699 | | `read_file` | 200 | 101 | -99 | | `read_directory` | 102 | 102 | 0 | | **Total filesystem RPCs** | **1,304** | **506** | **-798 (-61.2%)** | | **Median load time** | **2.890 s** | **0.997 s** | **2.90× faster** | The namespace-specific work drops from 800 RPCs to 2 in this layout. ### Multiple plugins under one selected root These runs compare the correct pre-optimization implementation with the final nearest-plugin-root cache. The total plugin skill count stays at 100 while the number of plugin roots changes. | Layout | Before RPCs | After RPCs | Reduction | Before | After | Speedup | | --- | ---: | ---: | ---: | ---: | ---: | ---: | | 2 plugins × 50 skills | 1,312 | 530 | 59.6% | 1,819 ms | 711 ms | 2.56× | | 10 plugins × 10 skills | 1,344 | 578 | 57.0% | 1,850 ms | 778 ms | 2.38× | | 50 plugins × 2 skills | 1,504 | 818 | 45.6% | 2,094 ms | 1,086 ms | 1.93× | | 10 plugins × 10 skills + 10 standalone skills | 1,596 | 630 | 60.5% | 2,209 ms | 860 ms | 2.57× | The remaining cost grows with the number of relevant plugin manifests. Each relevant manifest is read once instead of once per skill, while sibling plugins with no discovered skills are not read. Absolute latency savings depend on the executor's real RPC latency. ## Tests - `just test -p codex-core-skills` (109 passed across the library and integration-test binaries) - one integration test covers standalone, outer-plugin, nested-plugin, and unused sibling-plugin layouts, and asserts the exact set of manifests read
jif ·
2026-06-24 17:14:34 +01:00 -
Load executor skills without host path conversion (#29626)
## Why After #28918, selected skill roots are `PathUri`, but the executor skill provider still converts them to the app-server host's `AbsolutePathBuf`. A foreign Windows root therefore cannot be discovered by a Unix host, and the inverse has the same problem. This PR keeps executor skill discovery and reads on the filesystem that owns the selected root while reusing the existing skill rules. ## What changed - Generalize the existing skill traversal to operate on `PathUri` through `ExecutorFileSystem`, preserving its depth, directory, symlink, and sibling-metadata concurrency behavior. - Add a small environment skill loader that reuses the shared discovery, frontmatter validation, dependency parsing, product policy, and prompt-visibility rules. - Keep the environment id and entrypoint `PathUri` in the skill catalog, then route `skills.read` back through the same environment filesystem. - Preserve the executor's path convention when deriving catalog handles, including literal backslashes in POSIX filenames. - Resolve plugin namespaces from nearby manifests through URI-native filesystem reads. - Cover foreign Windows roots, executor-owned reads, namespaces, metadata, policy, and path identity. ```text selected root (PathUri) | v shared discovery over ExecutorFileSystem | v environment-bound catalog entry --skills.read--> same ExecutorFileSystem ``` No second filesystem abstraction or duplicate traversal implementation is introduced. ## Stack 1. #29614 — add lexical `PathUri` containment. 2. #29620 — share URI-native manifest path resolution. 3. #28918 — keep selected plugin roots and resources URI-native. 4. **This PR** — load executor skills without host path conversion. 5. #29628 — resolve executor MCP working directories without host path conversion.
jif ·
2026-06-23 23:26:06 +01:00 -
Make selected plugin roots URI-native (#28918)
## Why Selected capability roots belong to the executor filesystem, not the app-server host. Converting their path strings into the host's native `Path` breaks whenever the two machines use different path conventions, such as a Windows executor behind a Unix app-server. This PR establishes `PathUri` as the selected-plugin boundary so the executor remains authoritative for its paths. ## What changed - Require `selectedCapabilityRoots[].location.path` to be a canonical `file:` URI and deserialize it directly as `PathUri`; native path strings are rejected. - Update the app-server schema, generated TypeScript, examples, and request coverage for the URI contract. - Keep selected roots, resolved plugin locations, manifest paths, and manifest resources as `PathUri`. - Inspect and read plugin roots and manifests only through the selected environment's `ExecutorFileSystem`. - Parse executor manifests with the shared URI-native parser from #29620 instead of projecting them onto the host filesystem. - Enforce resource containment lexically and preserve the root URI's POSIX or Windows path convention. - Cover foreign Windows plugin roots and URI-native manifest resources. ```text thread/start selectedCapabilityRoots[].location.path = "file:///C:/plugins/demo" | PathUri v ExecutorFileSystem | +--> plugin.json +--> manifest resources ``` This PR stops at the shared selected-plugin representation. The next two PRs remove the remaining host-path projections in the skill and MCP consumers. ## Stack 1. #29614 — add lexical `PathUri` containment. 2. #29620 — share URI-native manifest path resolution. 3. **This PR** — keep selected plugin roots and resources URI-native. 4. #29626 — load executor skills without host path conversion. 5. #29628 — resolve executor MCP working directories without host path conversion.
jif ·
2026-06-23 22:51:19 +01:00 -
path-uri: remove legacy path deserialization (#29158)
## Why I'd originally added `PathUri` legacy path deserialization thinking we'd want it for having `PathUri` in public app-server APIs. Since then we've added `LegacyAppPathString` to handle the messy conversions that we need for backcompat. It's confusing for `PathUri` to support deserializing legacy paths when we don't yet want to actually expose app-server callers or rollout storage to the new URI format. Stacked on top of #29472 to avoid breaking compatibility in case those types ended up stored somewhere for someone. ## What changed - Parse deserialized `PathUri` values exclusively as valid `file:` URIs. - Replace legacy acceptance coverage with rejection coverage for top-level filesystem paths and sandbox working directories. - Serialize CWDs in hand-built exec-server process requests as `PathUri` values.
Adam Perry @ OpenAI ·
2026-06-23 21:47:00 +00:00 -
Decouple plugin manifest path resolution (#29620)
## Why Plugin manifests use the same schema whether the package lives on the host or in an executor. Only the path representation differs: host callers need native `Path` inputs and `AbsolutePathBuf` outputs, while executor callers need `PathUri` throughout. Maintaining separate parsing or resolver implementations would duplicate the manifest rules and allow them to drift. This PR instead makes URI-native resolution the single parsing path and keeps host conversion at the boundary. ## What changed - Make `parse_plugin_manifest_uri` the shared manifest parser and resolve every path-bearing field as `PathUri`. - Keep the existing host entrypoint as a thin adapter: convert its native root and manifest path to `PathUri`, run the shared parser, then map resources back to `AbsolutePathBuf`. - Expose `PluginManifest::try_map_resources` so callers can convert the generic resource type without duplicating manifest construction. - Resolve relative manifest paths using the root URI's convention: backslashes are separators for Windows roots and ordinary filename characters for POSIX roots. - Apply lexical containment after URI resolution, rejecting absolute paths and parent traversal outside the plugin root. - Make encoded backslashes fail containment only for Windows URIs; encoded `/` remains unsafe for every convention. - Use a host-native synthetic root for marketplace fallback manifests so the host adapter also works on Windows. ```text host Path --------> PathUri --\ +--> one manifest parser --> PluginManifest<PathUri> executor PathUri -------------/ host result: PluginManifest<PathUri> --> PluginManifest<AbsolutePathBuf> ``` Existing host manifest behavior is preserved; #28918 is the first executor consumer. ## Verification - `just test -p codex-utils-path-uri` - `just test -p codex-plugin` - `just test -p codex-core-plugins` ## Stack 1. #29614 — add lexical `PathUri` containment. 2. **This PR** — share URI-native manifest path resolution. 3. #28918 — keep selected plugin roots and resources URI-native. 4. #29626 — load executor skills without host path conversion. 5. #29628 — resolve executor MCP working directories without host path conversion.jif ·
2026-06-23 20:33:59 +00:00 -
core: resolve view_image paths in selected environment (#29526)
## Why view_image needs to support foreign OS remote executors. ## What - resolve image paths against the selected environment as `PathUri` and read them through that environment's filesystem - keep app-server's public path field wire-compatible as `LegacyAppPathString`, with purpose-specific UI rendering - cover relative and absolute target-native paths in the core integration test and run the full `view_image` suite under wine-exec without skips
Adam Perry @ OpenAI ·
2026-06-23 19:52:37 +00:00 -
chore(core) rm AskForApproval::OnFailure (#28418)
## Summary Deletes the OnFailure variant of the `AskForApproval` enum. This option has been deprecated since #11631. ## Testing - [x] Tests pass
Dylan Hurd ·
2026-06-23 12:13:54 -07:00 -
path-uri: add lexical containment (#29614)
## Why Executor-owned paths must stay portable while the orchestrator reasons about them. Converting a Windows or remote path to the orchestrator host's native path just to check containment breaks that boundary. ## What changed - Add lexical containment to `PathUri`. - Compare URI authorities and complete path segments, so `plugin-other` is not treated as a child of `plugin`. - Fail closed for encoded path separators and opaque fallback URIs. For example: ```text file:///C:/plugins/foo/assets/icon.svg is below file:///C:/plugins/foo file:///C:/plugins/foo2/icon.svg is not below file:///C:/plugins/foo ``` This is the shared foundation for keeping executor-owned plugin resources URI-native without consulting the orchestrator filesystem.
jif ·
2026-06-23 14:59:39 +01:00 -
mcp: accept foreign absolute cwd for remote stdio (#29493)
## Why Remote stdio MCP servers can run in an environment whose path convention differs from the Codex host. A Windows cwd such as `C:\Users\openai\share` is absolute for the executor but was rejected by a POSIX orchestrator. Built on #29501, now merged, which only clarifies the host-native `PathUri` constructor name. ## What changed - Deserialize MCP cwd values as `LegacyAppPathString` so config does not apply host path rules. - Interpret that spelling as host-native for local launches and convert it to `PathUri` at executor launch. - Skip host filesystem and command resolution checks for remote stdio in `codex doctor`. - Add host-independent config and executor-boundary coverage using the foreign path convention for each test platform. ## Validation - `just test -p codex-utils-path-uri -p codex-config -p codex-mcp -p codex-rmcp-client` (408 passed) - `just test -p codex-cli -p codex-rmcp-client` (372 passed) - `cargo check --workspace --tests` - `just test` (11,311 passed; 43 unrelated environment/timing failures) - `just fix -p codex-cli -p codex-config -p codex-core -p codex-mcp -p codex-mcp-extension -p codex-rmcp-client -p codex-tui`
Adam Perry @ OpenAI ·
2026-06-23 01:33:51 +00:00 -
path-uri: clarify host-native path conversion (#29501)
## Why Downstream refactors are producing confusing code with this functionality having a very generic name. Encoding the specific conversion approach in the method name makes it clearer. ## What Rename `PathUri::from_path` to `PathUri::from_host_native_path` and update its Rust call sites.
Adam Perry @ OpenAI ·
2026-06-23 00:02:33 +00:00 -
core: load AGENTS.md from foreign environments (#28958)
## Why Make it possible to load AGENTS.md from remote exec-servers whose OS is different than app-server. ## What - keep `AGENTS.md` discovery and provenance as `PathUri`, with root-aware parent and ancestor traversal - expose lifecycle instruction sources as legacy app-server path strings in events while retaining `PathUri` internally - preserve and test mixed POSIX and Windows paths in model context and TUI status output - cover remote Windows loading end to end by seeding the Wine prefix through host filesystem APIs - fix bug in `PathUri`'s parent() implementation that would erase Windows drive letters
Adam Perry @ OpenAI ·
2026-06-18 15:06:23 -07:00 -
[codex] Remove hardcoded app ID filters (#28947)
## Summary - remove the duplicated originator-specific connector ID denylists - stop filtering connector directory/accessibility results and live/cached Codex Apps MCP tools by hardcoded connector ID - remove the now-unused `codex-login` dependency from `codex-utils-plugins` - update regression coverage so formerly blocked connector IDs are preserved ## Why The client-side policy was duplicated across crates, used opaque IDs without ownership or expiry information, and could drift between app listing and MCP tool behavior. Server-provided visibility, authorization, plugin discoverability, accessibility, enabled-state handling, and consequential-tool approval templates remain unchanged. ## Validation - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `git diff --check` - confirmed the final diff contains no hardcoded denylist symbols A targeted `codex-mcp` test build spent an unusually long time in local compilation/linking. Its first attempt exposed a test-only `PartialEq` assertion issue, which was corrected. A follow-up non-linking `cargo check -p codex-mcp --tests` was still running when this draft was opened; CI should provide the complete Rust validation.
Eric Ning ·
2026-06-18 20:29:01 +00:00 -
apply-patch: carry paths as PathUri (#28854)
## Why Allows the model to edit files that are hosted on a different OS than where app-server is running. ## What * Use `PathUri` for apply_patch-internal data structures * Limit `PathUri` -> `AbsolutePathBuf` conversion to cases where the inferred path convention matches the host OS, allows requiring valid paths to pass to perms check * Adds `PathConvention::path_segments()` for iterating over path segments regardless of OS * Handle cross-platform relative paths in path filename parsing for sniffing a shell * Ensure we can apply patches in the wine e2e test
Adam Perry @ OpenAI ·
2026-06-18 19:31:19 +00:00 -
[codex] Pass plugin namespace into skill loading (#28608)
## What changed - retain the parsed plugin manifest namespace on loaded plugins - carry that namespace through `PluginSkillRoot` and `SkillRoot` - use the provided namespace when qualifying plugin skill names - include the namespace in the skills cache key ## Why Plugin loading has already parsed `plugin.json`, but skill parsing currently walks every `SKILL.md` ancestor and probes/reads the manifest again to reconstruct the same namespace. Passing the parsed namespace removes those repeated filesystem calls, which are particularly costly on remote filesystems. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact Plugin skill names remain unchanged. A regression test uses a deliberately different on-disk manifest name to verify that plugin roots use the provided parsed namespace. ## Validation - `just test -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` (352 passed) - `just fix -p codex-core-skills -p codex-core-plugins -p codex-plugin -p codex-utils-plugins` - `just fmt`
Matthew Zeng ·
2026-06-18 00:16:46 -07:00 -
unified-exec: retain PathUri in command events (#28780)
## Why App-server must report command events containing foreign-platform paths without changing existing client or rollout path-string formats. ## What changed - retain `PathUri` through exec command begin/end events - convert cwd values to `LegacyAppPathString` at the app-server compatibility boundary - drop command actions with foreign paths and log them - serialize rollout-trace cwd values using their inferred native path representation - restore Wine coverage for retained Windows cwd values and successful completion
Adam Perry @ OpenAI ·
2026-06-18 05:00:04 +00:00 -
path-uri: decouple native path parsing (#28778)
## Why `PathUri::join` should not depend on the app-server compatibility wrapper `LegacyAppPathString` to parse native paths. Native path parsing belongs to the URI abstraction that it constructs. ## What Move platform-independent native path parsing into the root `PathUri` module. `PathUri::join` and `LegacyAppPathString` now share the crate-private `PathUri::from_absolute_native_path` constructor.
Adam Perry @ OpenAI ·
2026-06-17 22:17:07 +00:00 -
unified-exec: preserve PathUri through exec-server (#28681)
## Why It should be possible for app-server to handle "foreign" OS paths in unified_exec working directories, allowing e.g. a Linux app-server to run processes on e.g. a Windows exec-server. ## What Convert the core unified_exec cwd values to use `PathUri`. Adds fallible path conversion in several places to try to minimize the scope of this change. The only time this change suppresses errors from converting `PathUri` to an `AbsolutePathBuf` is when the turn is configured with no sandboxing at all to allow us to make progress testing without sandboxing. Future changes to apply_patch and sandboxing will clean up these error paths. A tool's cwd is resolved from joining a model-provided workdir to the environment's cwd. When using `AbsolutePathBuf::join()`, an absolute-path workdir would overwrite the environment's cwd and we would resolve permissions/sandboxing against the model-provided path. This change extends `PathUri::join()` to also treat an absolute rhs as an override of the base/lhs. This also removes some coverage from the remove_env_windows tests until a follow-up converts foreign paths in command exec events correctly. ## Breaking Changes When using `AbsolutePathBuf::join()` for workdir resolution, we ended up resolving tilde-prefixed paths against the app-server's `$HOME`, e.g. `~/foo/bar` becomes `/home/anp/foo/bar`. It's difficult to do this with `PathUri` joining, so after offline discussion this PR no longer implements it. A quick check of some power users' rollouts suggests that models don't actually generate home-prefixed absolute working directories for their spawns, so this shouldn't have any real blast radius.
Adam Perry @ OpenAI ·
2026-06-17 19:36:16 +00:00 -
core: render remote environment cwd natively (#28152)
## Why Model-visible `<environment_context>` should match the environment of the executor, not of the app server. Stacked on #28146. ## What - Keep selected environment cwd values as `PathUri` while building environment context. - Render cwd text using the path convention represented by the URI, with the canonical URI as a fallback. - Preserve compatibility with legacy `TurnContextItem.cwd` values when reconstructing and diffing context. - Extend the Wine-backed remote Windows test to assert that the model sees `powershell` and `C:\windows`.
Adam Perry @ OpenAI ·
2026-06-16 16:17:47 -07:00 -
Clarify model-generated and legacy app path types (#28577)
## Why `ApiPathString` kind of implies that it can be used anywhere we pull a path out of JSON, but it's not really appropriate for tool arguments when the model might generate relative paths. Prefer `String` for model-generated paths and we can handle the conversion per feature for now and define a shared abstraction later if it makes sense. # What Rename `ApiPathString` to `AppLegacyPathString` to clarify its role. Expand the `path-types` skill to tell the model to leave tool args as bare strings.
Adam Perry @ OpenAI ·
2026-06-16 20:47:43 +00:00 -
[codex] Warn clearly when code mode output is truncated (#28467)
## Summary - make `formatted_truncate_text` prepend `Warning: truncated output (original token count: N)` above the existing `Total output lines` header - update direct formatter, unified-exec, user-shell, and code-mode expectations - add core unit coverage that runs in Bazel without requiring the skipped V8-backed code-mode integration suite ## Validation - `cargo test -p codex-utils-output-truncation -- --nocapture` (17 passed) - `cargo test -p codex-core --lib truncated_text_output_starts_with_warning -- --nocapture` - `cargo test -p codex-core --test all clamps_model_requested_max_output_tokens_to_policy -- --nocapture` (2 passed) - `cargo test -p codex-core --test all unified_exec_formats_large_output_summary -- --nocapture` - `cargo test -p codex-core --test all user_shell_command_output_is_truncated_in_history -- --nocapture` - Bazel CI exercises the shared formatter and downstream integration expectations
Ahmed Ibrahim ·
2026-06-16 10:37:06 -07:00 -
path-uri: clarify invalid host path errors (#28473)
## Why Ensure a consistent string format when exposing path conversion errors to the model. ## What - Render `PathUriParseError::InvalidFileUriPath` as `'$PATH' is invalid on '$OS'`.
Adam Perry @ OpenAI ·
2026-06-16 09:03:44 -07:00 -
Use ApiPathString in app-server filesystem permission paths (#28367)
## Why Clients running an app-server on one OS and an exec-server on another OS need to be able to pass sandbox config to app-server that refers to resources on the executor's foreign OS. ## What `AbsolutePathBuf` can't represent these paths and we don't want users to be exposed to `PathUri` yet, so this moves the public app-server API to be expressed in terms of `ApiPathString`. Stacked on #28165. - change app-server v2 filesystem permission paths, including legacy read/write roots, to `ApiPathString` - localize API paths through `PathUri` when converting into the current native core permission types - make path-bearing permission conversions fallible and surface localization failures instead of silently treating malformed grants as ordinary denials - propagate conversion failures through app-server and TUI approval handling - regenerate the app-server JSON and TypeScript schemas - leave migration TODOs on native-path conversions so they can be removed once core permission paths use `PathUri`
Adam Perry @ OpenAI ·
2026-06-15 19:25:54 -07:00 -
Use aws-lc-rs for rustls crypto provider (#27706)
## Why Some enterprise TLS proxies issue certificate chains signed with `ecdsa_secp521r1_sha512` / `ECDSA_NISTP521_SHA512`. Custom CA configuration such as `SSL_CERT_FILE` can add the right trust root, but it cannot make `rustls`'s `ring` verifier support a certificate signature algorithm it does not advertise. That can still break TLS after the CA bundle is configured, including on Rust websocket paths that call the shared `ensure_rustls_crypto_provider()` helper, such as the Responses websocket connector and remote app-server client: - [`codex-api/src/endpoint/responses_websocket.rs`](https://github.com/openai/codex/blob/eddc5c75ed527a8348bfcaa85692e53189600833/codex-rs/codex-api/src/endpoint/responses_websocket.rs#L441) - [`app-server-client/src/remote.rs`](https://github.com/openai/codex/blob/eddc5c75ed527a8348bfcaa85692e53189600833/codex-rs/app-server-client/src/remote.rs#L718) The `aws-lc-rs` `rustls` provider supports this P-521/SHA-512 certificate signature scheme, so use it as Codex's process-wide `rustls` provider. ## What Changed - Switch the workspace `rustls` feature from `ring` to `aws_lc_rs`. - Update `codex-utils-rustls-provider` to install `rustls::crypto::aws_lc_rs::default_provider()`. - Add an assertion and integration test that the installed provider supports `ECDSA_NISTP521_SHA512`. ## Verification ```shell just fmt just test -p codex-utils-rustls-provider just bazel-lock-update just bazel-lock-check ```
malsamiri-oai ·
2026-06-15 11:32:13 -07:00 -
bound prompt image cache retention (#28294)
## Why The prompt image cache was bounded to 32 entries, but not by the size of those entries. A set of large encoded images could therefore retain substantially more memory than intended. Cache hits also cloned the full encoded payload. ## What changed - cap the cache at 64 MiB of encoded image data while preserving its existing 32-entry limit - skip caching an image that exceeds the entire byte budget - evict least-recently-used entries until the cache is back within its byte budget - share cached encoded bytes with `Arc<[u8]>` so cache hits do not deep-clone image payloads ## Validation - `just test -p codex-utils-image`
jif ·
2026-06-15 19:52:30 +02:00 -
path-uri: render native paths across platforms (#27819)
## Why We're moving to `PathUri` in more places to support cross-OS app-server/exec-server, but we don't want to expose the URI encoding to users of app-server's public APIs yet. We'll need to translate at the app-server API boundary between client-visible "regular" paths that are appropriate for the OS of the environment for which the paths make sense, which means using the environment's path personality to do the conversion. `PathUri` doesn't yet attempt to encode environment ID, so for now we'll sniff the most likely path convention for a given path. ## What - Add `PathConvention` and `NativePathString` with host-independent POSIX, Windows drive, and UNC rendering. - Cover cross-host rendering, encoding, Unicode, invalid components.
Adam Perry @ OpenAI ·
2026-06-14 05:26:49 +00:00 -
build: run buildifier from just fmt (#28125)
## Intent Keep Bazel and Starlark files consistently formatted without requiring contributors to install or version buildifier themselves. ## Implementation - Add a SHA-256-pinned, cross-platform DotSlash manifest for buildifier v8.5.1. - Run buildifier from the shared `just fmt` and `just fmt-check` driver, with Windows-safe explicit DotSlash invocation. - Provision DotSlash in formatting CI and contributor devcontainers, and document the source-build prerequisite. - Apply the initial mechanical buildifier formatting baseline.
Adam Perry @ OpenAI ·
2026-06-13 21:43:39 -07:00 -
[codex] make PathUri::from_abs_path infallible (#27976)
## Why `PathUri::from_abs_path` can fail for absolute paths that do not have a normal `file:` URI representation, forcing filesystem call sites to handle a conversion error even though the original path can be preserved losslessly. ## What Make `from_abs_path` infallible and migrate its callers. Unrepresentable paths use `file:///%00/bad/path/<base64>`, encoding Unix bytes or Windows UTF-16LE; `to_abs_path` validates and decodes that fallback. The leading encoded null reserves a namespace that cannot collide with a real Unix or Windows path, and fallback URIs remain opaque to lexical path operations. ## Validation Added path-URI coverage for Unix null and non-UTF-8 paths, Windows device/verbatim and non-Unicode paths, serialization, malformed fallbacks, opaque lexical operations, invalid native payloads, and literal `/bad/path` collision resistance.
Adam Perry @ OpenAI ·
2026-06-12 16:58:42 -07:00 -
Add executor-owned plugin resolution (#27692)
## Why CCA can select a capability root that lives in an executor environment, but Codex only had a host-filesystem plugin loader. Before selected executor plugins can contribute MCP servers, we need a small package boundary that can answer: > Does this selected root contain a plugin, and if so, what does its manifest > declare? The answer must come from the selected environment's filesystem. A failed executor lookup must never fall back to the orchestrator filesystem. ## What this changes This PR introduces: ```rust PluginProvider::resolve(root) -> Result<Option<ResolvedPlugin>, Error> ``` `ExecutorPluginProvider` resolves one `SelectedCapabilityRoot` through its exact `environment_id`. It checks the recognized manifest locations, reads the manifest through that environment's `ExecutorFileSystem`, and returns an inert `ResolvedPlugin` containing: - the opaque selected-root ID; - the environment-bound plugin root; - the authority-bound manifest resource; - parsed metadata and authority-bound component locators. Descriptor construction rejects manifest or component paths outside the selected package root, so consumers cannot accidentally lose the package boundary when they receive a resolved plugin. If the root has no plugin manifest, resolution returns `None`, allowing the caller to treat it as a standalone capability such as a skill. ```text selected root: repo -> env-1:/workspace/repo | | env-1 filesystem only v .codex-plugin/plugin.json | v ResolvedPlugin { authority, root, manifest } ``` The existing host loader and the new executor provider now share the same manifest parser. Existing `codex-core-plugins::manifest` type paths remain available through re-exports, so host behavior and callers are unchanged. ## Scope This is intentionally a non-user-visible package-resolution PR. It does not: - parse or register plugin MCP server configurations; - activate skills, connectors, hooks, or MCP servers; - change app-server wiring; - introduce host fallback, caching, or lifecycle behavior. #27670 has merged, and this PR is now based directly on `main`. Together with the resolved MCP catalog from #27634, it establishes the inputs needed for the executor stdio MCP vertical without changing the existing MCP runtime. ## Follow-up The next PR will consume `ResolvedPlugin`, read its declared/default MCP config through the same executor filesystem, bind supported stdio servers to that environment, and feed those registrations into the resolved MCP catalog. An app-server E2E will prove that selecting an executor plugin exposes and invokes its tool on the owning executor. Resume/fork semantics, dynamic environment replacement, and non-stdio placement remain separate lifecycle decisions. ## Validation - `just fmt` - `cargo check --tests -p codex-plugin -p codex-core-plugins` - `just bazel-lock-check` - `git diff --check` Test targets were compiled but not executed locally; CI will run the test and Clippy suites.jif ·
2026-06-12 13:37:33 +02:00 -
[codex] Remove async_trait from first-party code (#27475)
## Why First-party async traits should expose their `Send` contracts explicitly without requiring `async_trait`. This completes the migration pattern established in #27303 and #27304. ## What changed - Replaced the remaining first-party `async_trait` traits with native return-position `impl Future + Send` where statically dispatched and explicit boxed `Send` futures where object safety is required. - Kept implementations behavior-preserving, outlining existing async bodies into inherent methods where that keeps the diff reviewable. - Removed all direct first-party `async-trait` dependencies and the workspace dependency declaration. - Added a cargo-deny policy that permits `async-trait` only through the remaining transitive wrapper crates. - Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and keep the full cargo-deny check passing. ## Validation - `just test -p codex-exec-server`: 216 passed, 2 skipped. - `just test -p codex-model-provider`: 39 passed. - `just test -p codex-core` and `just test`: changed tests passed; remaining failures are environment-sensitive suites unrelated to this migration. - `cargo deny check` - `just fix` - `just fmt` - `cargo shear` - `just bazel-lock-check`
Adam Perry @ OpenAI ·
2026-06-11 18:16:39 -07:00 -
[codex] migrate ExecutorFileSystem paths to PathUri (#27424)
## Why We're moving exec-server to use PathUri for its internal path representations. ## What Move `ExecutorFileSystem` APIs to use `PathUri` instead of `AbsolutePathBuf`. Future changes will convert higher-level parts of exec-server.
Adam Perry @ OpenAI ·
2026-06-11 18:44:18 +00:00 -
image: preserve metadata when resizing prompt images (#27266)
## Summary - Preserve ICC profiles and EXIF metadata when resizing and re-encoding prompt images. - Retain EXIF orientation metadata without rotating or otherwise modifying the pixel data locally. - Support metadata preservation for PNG, JPEG, and WebP outputs. - Continue returning the original bytes when an image does not require re-encoding. This intentionally preserves the metadata most important for rendering prompt images faithfully. Other format-specific metadata is not copied. ## Motivation Client-side resizing previously discarded image metadata during re-encoding. This could lose color-profile information and EXIF orientation needed by downstream image consumers. #### [git stack](https://github.com/magus/git-stack-cli) - ✅ `1` https://github.com/openai/codex/pull/27245 - ✅ `2` https://github.com/openai/codex/pull/27247 - ✅ `3` https://github.com/openai/codex/pull/27246 - 👉 `4` https://github.com/openai/codex/pull/27266
Curtis 'Fjord' Hawthorne ·
2026-06-10 21:17:32 -07:00 -
core: resize all history images behind a feature flag (#27247)
## Summary Adds complete client-side image preparation behind the default-off `resize_all_images` feature flag. When enabled, local image producers defer decoding and resizing. Images are prepared centrally before insertion into conversation history, covering user input, `view_image`, and structured tool-output images. ## Behavior - Processes base64 `data:` images in messages and function/custom tool outputs. - Leaves non-data URLs, including HTTP(S) URLs, unchanged. - Applies image-detail budgets: - `high` and omitted: 2048px maximum dimension and 2.5K 32px patches. - `original`: 6000px maximum dimension and 10K 32px patches. - `auto`: uses the same 2048px / 2.5K-patch budget as high. - `low`: unsupported and replaced with an actionable placeholder. - Preserves original image bytes when no resize or format conversion is needed. - Enforces the shared 1 GiB encoded and decoded data-URL sanity limits. - Replaces only an image that fails preparation, preserving sibling content and tool-output metadata. - Uses bounded placeholders distinguishing generic processing failures, oversized images, and unsupported `low` detail. - Prepares resumed and forked history before installing it as live history without modifying persisted rollouts. ## Flag-Off Behavior When `resize_all_images` is disabled: - Existing local user-input and `view_image` processing remains unchanged. - Existing decoding and error behavior remains unchanged. - Arbitrary tool-output images are not processed. - HTTP(S) image URLs continue to be forwarded unchanged. #### [git stack](https://github.com/magus/git-stack-cli) - ✅ `1` https://github.com/openai/codex/pull/27245 - 👉 `2` https://github.com/openai/codex/pull/27247 - ⏳ `3` https://github.com/openai/codex/pull/27246 - ⏳ `4` https://github.com/openai/codex/pull/27266
Curtis 'Fjord' Hawthorne ·
2026-06-10 19:21:24 -07:00 -
image: add shared data URL preparation utilities (#27245)
## Summary Add shared image-processing primitives needed for centralized image preparation in a follow-up PR. - Add `load_data_url_for_prompt` for decoding and preparing base64 image data URLs. - Add configurable maximum-dimension and 32px patch-budget resizing. - Enforce a 1 GiB sanity limit on both encoded and decoded data-URL representations. - Preserve original PNG, JPEG, and WebP bytes when resizing is unnecessary. - Preserve the existing GIF-to-PNG behavior. - Move image utility tests into the existing sidecar test module. ## Behavior This PR is intended to be runtime behavior-preserving. Existing production callers continue using `PromptImageMode::ResizeToFit` and `PromptImageMode::Original` with their existing semantics. The new data-URL entrypoint and configurable resize mode have no production callers in this PR; they are used by the next PR in the stack. This PR does not change user-input handling, `view_image`, history insertion, request construction, HTTP image URL forwarding, or app-server behavior. #### [git stack](https://github.com/magus/git-stack-cli) - 👉 `1` https://github.com/openai/codex/pull/27245 - ⏳ `2` https://github.com/openai/codex/pull/27247 - ⏳ `3` https://github.com/openai/codex/pull/27246 - ⏳ `4` https://github.com/openai/codex/pull/27266
Curtis 'Fjord' Hawthorne ·
2026-06-10 15:27:34 -07:00 -
[codex] add io PathUri native conversion APIs (#27280)
## Why Discovered some rough edges in the API while making use of it more widely within exec-server. It would be a lot more convenient for existing users of `AbsolutePathBuf` if `PathUri` conversion methods returned `std::io::Result`s. ## What * `PathUri::to_native_path()` -> `PathUri::to_abs_path()` * `PathUri::from_file_path()` -> `PathUri::from_abs_path()`
Adam Perry @ OpenAI ·
2026-06-10 08:51:17 -07:00 -
[codex] Handle Ctrl-C for non-TTY unified exec (#26734)
## Why A long-running unified exec process started with `tty: false` could not be interrupted via `write_stdin`: ordinary non-TTY stdin writes are rejected once stdin is closed, but an exact U+0003 payload should still map to a process interrupt. The interrupt should flow through the same process lifecycle path as a real signal so Codex preserves process-reported output and exit metadata instead of fabricating a Ctrl-C exit code or tearing down the session early. ## What Changed - Add `process/signal` to exec-server with `ProcessSignal::Interrupt` and an empty response. - Add a non-consuming `ProcessHandle::signal` path for spawned processes; on Unix it sends SIGINT to the process group and leaves terminate/hard-kill unchanged. - Route non-TTY U+0003 `write_stdin` through `process.signal(...)` instead of `terminate`, then let the normal post-write collection path drain output and observe exit. - Add exec-server coverage where a shell `trap INT` handler prints the signal and exits with its own code. - Add unified exec coverage where a `tty: false` process traps SIGINT, emits output, and exits with its own code. ## Validation - `just test -p codex-exec-server exec_process_signal_interrupts_process` - `just test -p codex-exec-server` - `just test -p codex-core write_stdin_ctrl_c_interrupts_non_tty_session`
pakrym-oai ·
2026-06-09 15:10:17 -07:00 -
Add typed file URIs (#26840)
## Why Codex needs stable `file:` URI identifiers that can cross process and operating-system boundaries without eagerly interpreting them as native paths. Existing fields also need to keep accepting absolute path strings during migration. ## What changed - Add `codex-utils-path-uri` with a validated, immutable `PathUri` wrapper that currently accepts only `file:` URLs. - Expose URI-level `basename`, `parent`, and `join` operations that preserve authorities and percent encoding without guessing the source operating system. - Keep native conversion explicit through `AbsolutePathBuf` and the current host rules. - Serialize as canonical URI text while accepting both URI text and legacy absolute native paths during deserialization. - Add adversarial coverage for Windows-looking and POSIX paths, UNC authorities, encoded metadata characters, non-UTF-8 POSIX paths, URI hierarchy operations, and legacy serde round trips.
Adam Perry @ OpenAI ·
2026-06-08 16:33:41 -07:00 -
[codex] Support model-defined reasoning efforts (#26444)
## Summary - accept non-empty model-defined reasoning effort values while preserving built-in effort behavior - propagate the non-Copy effort type through core, app-server, TUI, telemetry, and persistence call sites - preserve string wire encoding and expose an open-string schema for clients - update model selection and shortcut behavior for model-advertised effort values ## Root cause `ReasoningEffort` gained a string-backed custom variant, so it could no longer implement `Copy` or rely on derived closed-enum serialization. Existing consumers still moved effort values from shared references and assumed a fixed built-in value set. ## Validation - `just fmt` - Local tests and compilation were not run per request; relying on CI.
Ahmed Ibrahim ·
2026-06-04 13:36:24 -07:00 -
fix(linux-sandbox): preserve shell cleanup on interruption (#22729)
## Why Interrupted `shell_command` calls can race with the outer tool-dispatch cancellation path. When that happens, the runtime future may be dropped before the spawned process gets a chance to run `SIGTERM` cleanup. For bwrapd-backed Linux sandbox commands, that can leave synthetic protected-path mount bookkeeping such as `.git/.codex` registrations under `/tmp` behind after a TUI interruption. The relevant cancellation points are the outer dispatch race in [`core/src/tools/parallel.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/parallel.rs#L91-L132) and the process shutdown logic in [`core/src/exec.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/exec.rs#L1367-L1393). ## What changed - Keep `shell_command` dispatch alive long enough for the runtime to finish cancellation cleanup instead of immediately returning the synthetic aborted response. - Fold shell-turn cancellation into the existing `ExecExpiration` path in [`core/src/tools/runtimes/shell.rs`](https://github.com/openai/codex/blob/bd184ba84703cc924921ed883f0cf17d3dba60ff/codex-rs/core/src/tools/runtimes/shell.rs#L267-L274), so cancellation and timeout behavior stay centralized. - On cancellation, send `SIGTERM` first, wait briefly for cleanup to run, then hard-kill any remaining descendants in the original process group. - Treat `ESRCH` as an already-gone process-group cleanup case in `codex-utils-pty`, which keeps best-effort teardown from surfacing a stale-process race as an error. ## Verification - `cargo test -p codex-core cancellation` - Added regression coverage for: - `shell_tool_cancellation_waits_for_runtime_cleanup` - `process_exec_tool_call_cancellation_allows_sigterm_cleanup`
viyatb-oai ·
2026-05-27 12:59:11 -07:00 -
Uprev Rust toolchain pins to 1.95.0 (#24684)
## Summary - Bump the workspace Rust toolchain from `1.93.0` to `1.95.0` across Cargo, Bazel, CI, release workflows, devcontainers, and the Codex environment config. - Refresh `MODULE.bazel.lock` so the Bazel Rust toolchain artifacts match the new version. - Leave purpose-specific toolchains unchanged, including the `argument-comment-lint` nightly and the upstream `rusty_v8` `1.91.0` build pin. - Includes fixes for new lints from `just fix` and a few codex-authored fixes for lints without a suggestion.
Adam Perry @ OpenAI ·
2026-05-26 20:59:47 -07:00 -
[codex] Add image re-encoding benchmarks (#23935)
## Summary - add Divan benchmarks for prompt image re-encoding paths - wire the image benchmark smoke test into Rust CI workflows ## Why Image prompt handling includes re-encoding work that benefits from repeatable benchmark coverage so changes can be measured in CI and locally. This already helped identify a potential regression from changing compiler flags. ## Impact Developers can run and compare the new image re-encoding benchmarks, and CI exercises the benchmark target via the Rust benchmark smoke test.
Adam Perry @ OpenAI ·
2026-05-22 22:38:40 +00:00 -
Prefer
just testovercargo testin docs (#23910)`cargo test` for the core and other crates fails on a fresh macOS checkout without the right stack size variable. This change encourages using the just test command that sets the environment up correctly. As a bonus, this should encourage agents to get more benefit out of nextest's parallel execution.
anp-oai ·
2026-05-22 16:58:14 +00:00 -
fix: Allow plugin skills to share plugin-level icon assets (#23776)
Thread the plugin root through plugin skill loading so skill interface icons can reference shared plugin assets, such as ../../assets/logo.svg.
xl-openai ·
2026-05-21 16:11:59 -07:00 -
cli: remove legacy profile v1 plumbing (#23886)
## Why [#23883](https://github.com/openai/codex/pull/23883) moved the user-facing `--profile` flag onto profile v2. The shared CLI option layer still carried the old `config_profile` slot and several CLI entrypoints still copied that value into legacy config overrides. Leaving that path around makes the CLI surface look like it still selects legacy `[profiles.*]` state even though `--profile` now means `$CODEX_HOME/<name>.config.toml`. ## What - Remove the legacy `config_profile` field and merge/copy path from [`SharedCliOptions`](https://github.com/openai/codex/blob/95baaf72920c8db22097df8d15a0bb76c84528b6/codex-rs/utils/cli/src/shared_options.rs#L8-L177). - Stop forwarding profile-v1 overrides from CLI, exec, TUI, doctor, debug, feature, and exec-server paths; runtime profile selection remains on `config_profile_v2` through [`loader_overrides_for_profile`](https://github.com/openai/codex/blob/95baaf72920c8db22097df8d15a0bb76c84528b6/codex-rs/cli/src/main.rs#L1606-L1619). - Resolve local OSS provider selection from the base config in exec and TUI now that the legacy profile argument is gone. ## Testing - Not run (cleanup-only follow-up to #23883).
jif-oai ·
2026-05-21 17:21:37 +02:00 -
cli: rename profile v2 flag to --profile (#23883)
## Why Profile v2 is taking over the user-facing profile selection path, so the CLI no longer needs to expose the transitional `--profile-v2` spelling. This switches the public args surface to `--profile` before the remaining legacy profile plumbing is removed separately. ## What - Rebind `--profile` and `-p` to the v2 profile name argument that selects `$CODEX_HOME/<name>.config.toml`. - Stop parsing the legacy shared CLI profile argument while keeping its implementation path in place for follow-up cleanup. - Update CLI validation, profile-name parse errors, and the legacy-profile collision message/tests to refer to `--profile`. ## Testing - `cargo test -p codex-cli -p codex-config -p codex-protocol -p codex-utils-cli`
jif-oai ·
2026-05-21 16:45:27 +02:00 -
add encryptedcontent to functioncalloutput (#23500)
add new `EncryptedContent` variant to `FunctionCallOutputContentItem` ahead of standalone websearch. we need to be able to receive and pass encrypted function call output from the new web search endpoint back to responsesapi, as we cannot expose direct search results.
sayan-oai ·
2026-05-19 23:47:48 -07:00 -
Clarify resume hints for renamed threads (#23234)
Addresses #23181 ## Why Renamed threads can share names, so hints that suggest resuming directly by name are ambiguous. Issue #23181 asks for the picker hint to include the thread name and thread ID in parens so users can disambiguate safely. ## What - Adds a shared resume hint formatter for named threads: run `codex resume`, then select `<name> (<thread-id>)`. - Uses that hint for /rename confirmations, TUI session summaries, and CLI/TUI exit messages. - Keeps direct `codex resume <thread-id>` guidance for unnamed threads. ## Verification Manually verified that message after `/rename` and after `/exit` include session ID in parens. --------- Co-authored-by: Felipe Coury <felipe.coury@openai.com>
Eric Traut ·
2026-05-18 11:32:02 -07:00 -
tui: pass active permission profiles through app commands (#22891)
## Why This continues the permissions migration by keeping the TUI command boundary aligned with the app-server protocol direction from #22795: callers should select a permission profile by id instead of passing a concrete `PermissionProfile` value around as the turn configuration. `AppCommand` is internal to the TUI, but it is the path that eventually becomes `thread/turn/start`, so carrying concrete profile details there made it too easy for UI code to keep relying on the old whole-profile replacement model. ## What changed - `AppCommand::UserTurn` and `AppCommand::OverrideTurnContext` now carry `Option<ActivePermissionProfile>` instead of `PermissionProfile`. - Composer submissions copy the active permission profile id from the current session snapshot; legacy snapshots intentionally submit no active profile id. - Permission preset UI events now carry only the active built-in profile id. The app derives the concrete built-in `PermissionProfile` internally only when updating its local config/status snapshot. - Permission presets expose their built-in active profile id, and preset selection preserves that id in both the immediate turn override and the local TUI config snapshot. - Turn routing sends `TurnPermissionsOverride::ActiveProfile` when an active id is present, and only falls back to the legacy sandbox projection for the remaining runtime override path. ## How to review Start with `codex-rs/tui/src/app_command.rs` to verify the command shape no longer exposes `PermissionProfile`. Then read `codex-rs/tui/src/app/thread_routing.rs` to verify the app-server turn-start conversion: active ids go through as ids, while the legacy sandbox fallback is still constrained to the existing runtime override case. Finally, check `codex-rs/tui/src/chatwidget/permission_popups.rs`, `codex-rs/tui/src/app/event_dispatch.rs`, `codex-rs/tui/src/app/config_persistence.rs`, and `codex-rs/utils/approval-presets/src/lib.rs` to see how preset selections stay id-only across TUI events while the local display/config mirror still gets a concrete built-in profile. ## Verification Latest local verification after the id-only `AppEvent` cleanup: - `cargo check -p codex-tui --tests` - `cargo test -p codex-tui permissions_selection_sends_approvals_reviewer_in_override_turn_context` - `cargo test -p codex-tui update_feature_flags_enabling_guardian` - `cargo test -p codex-utils-approval-presets` - `just fmt` - `just fix -p codex-tui -p codex-utils-approval-presets` Earlier in the same PR, before the final event-shape cleanup: - `cargo test -p codex-tui turn_permissions_` - `cargo test -p codex-tui submission_` - `cargo test -p codex-tui session_configured_syncs_widget_config_permissions_and_cwd` - `RUST_MIN_STACK=16777216 cargo test -p codex-tui`
Michael Bolin ·
2026-05-15 22:42:35 +00:00 -
tui: recover local state db startup failures (#22734)
## Why #22580 made app-server startup fail when the local SQLite state database cannot be initialized. Embedded/local TUI startup still continued on the permissive path, which left the CLI inconsistent and could hide a real startup problem behind unrelated UI. This brings local TUI startup onto the same fail-closed behavior while keeping recovery humane for the two failure modes we are seeing in practice: damaged database files and startup stalls caused by another process holding the database write lock. ## What changed - Embedded TUI startup now uses `state_db::try_init(...)` and returns a typed `LocalStateDbStartupError` that preserves the affected database path plus the underlying failure detail. - CLI startup handles that failure before entering the interactive TUI: - lock-contention failures tell users to quit other Codex processes and try again - failures consistent with a broken local database offer a safe repair that backs up Codex-owned SQLite files, rebuilds local database files, and retries startup once - declined or unsuccessful repairs print concise guidance plus technical details - Shared startup error plumbing lives in `tui/src/startup_error.rs`, while CLI recovery policy and focused recovery tests live in `cli/src/state_db_recovery.rs`. ## Verification - `cargo test -p codex-tui embedded_state_db_failure_is_typed_for_cli_recovery` - `cargo test -p codex-cli state_db_recovery` - Manually held an exclusive SQLite lock on `state_5.sqlite` and confirmed the CLI shows lock-specific guidance without offering repair. - Manually exercised the repair path with a deliberately invalid `sqlite_home` and confirmed it backs up the blocking path and resumes startup.
Eric Traut ·
2026-05-14 18:51:36 -07:00