Sync upstream rust-v0.142.0#104
Merged
dkropachev merged 184 commits intoJul 5, 2026
Merged
Conversation
## Summary - restore `externalAgentConfig/import/progress` notifications while keeping `externalAgentConfig/import/completed` as the must-deliver event - persist completed external-agent config imports in state DB by `importId`, including concrete success/failure details for config, AGENTS.md, skills, plugins, MCP servers, subagents, hooks, commands, and sessions - add `externalAgentConfig/import/readHistories` so clients can recover persisted import results after missing the live completion notification - include `errorType` on import failures in protocol responses/notifications and persisted DB JSON so future code can classify failures without another wire/storage shape change ## Validation - `git diff --check` - `just test -p codex-state external_agent_config_imports` - `just test -p codex-app-server-protocol` - `CODEX_SQLITE_HOME=/private/tmp/codex-app-server-sqlite-read-details just test -p codex-app-server external_agent_config_import_sends_completion_notification_for_sync_only_import` Also ran earlier broader checks before publishing: - `just test -p codex-state` - `CODEX_SQLITE_HOME=/private/tmp/codex-app-server-external-agent-test-sqlite just test -p codex-app-server external_agent_config` - `just test -p codex-external-agent-migration`
## Why `account/read` currently reports only `type: "amazonBedrock"`, so clients cannot distinguish a Codex-managed Bedrock API key from credentials supplied by AWS. The app UI needs that distinction to render the appropriate account state without duplicating provider-auth logic. Credential-source selection belongs to the Bedrock model provider because it already owns the precedence between managed Bedrock auth and the external AWS credential path. This builds on openai#27443 and openai#27689. ## What changed - Added `AmazonBedrockCredentialSource` with `codexManaged` and `awsManaged` values. - Included the selected credential source in `ProviderAccount::AmazonBedrock` and the app-server `Account` response. - Made `AmazonBedrockModelProvider::account_state()` classify the source from its managed-auth state. - Regenerated the app-server JSON and TypeScript schemas. - Updated app-server account documentation and downstream TUI matches. `codexManaged` means the provider found a managed Bedrock API key. `awsManaged` identifies the provider's external AWS credential path; it does not assert that the AWS credential chain has been validated. ## Testing - Added model-provider coverage for Codex-managed precedence and AWS-managed fallback. - Added app-server protocol serialization coverage for both wire values. - Added app-server integration coverage for both `account/read` responses. - `just test -p codex-protocol -p codex-model-provider -p codex-app-server-protocol` (497 tests passed). After rebasing onto openai#27711, the `codex-app-server` test target compiled past the image-generation `PathUri` migration. Local linking was then interrupted by disk exhaustion (`No space left on device`).
## Why The local rollout compression worker currently scans only `archived_sessions`, so cold unarchived thread history remains expanded indefinitely. ## What changed - Scan `sessions` after `archived_sessions` within the existing worker runtime budget. - Update rollout compression coverage to require both cold active and archived rollouts to be compressed while fresh active rollouts remain plain. The worker remains behind the disabled-by-default `local_thread_store_compression` feature, and the existing seven-day cold-file threshold is unchanged. ## Validation - `just test -p codex-rollout` (69 passed) - `just fmt` - `git diff --check`
## Why
Multi-agent v2 messages need a consistent, model-visible envelope that
identifies what kind of interaction occurred, who sent it, and which
agent it targets. Previously, encrypted deliveries exposed only
`encrypted_content`, while child completion used the legacy
`<subagent_notification>` shape. That meant the client could not
consistently present `NEW_TASK`, `MESSAGE`, and `FINAL_ANSWER` using the
same format.
This change adds the routing envelope as plaintext while keeping task
and message payloads encrypted. No new Responses API field is required:
an encrypted delivery is represented as an `input_text` header
immediately followed by its existing `encrypted_content` item.
Every envelope now follows this shape:
```text
Message Type: <NEW_TASK | MESSAGE | FINAL_ANSWER>
Task name: <recipient agent path>
Sender: <author agent path>
Payload:
<message payload>
```
## Message types
### `NEW_TASK`
`NEW_TASK` is used when the recipient should begin a new turn, including
an initial `spawn_agent` task and a later `followup_task`.
For a root agent spawning `/root/worker`, the request contains a
plaintext envelope followed by the encrypted task:
```json
{
"type": "agent_message",
"author": "/root",
"recipient": "/root/worker",
"content": [
{
"type": "input_text",
"text": "Message Type: NEW_TASK\nTask name: /root/worker\nSender: /root\nPayload:\n"
},
{
"type": "encrypted_content",
"encrypted_content": "<encrypted task payload>"
}
]
}
```
Conceptually, the model receives:
```text
Message Type: NEW_TASK
Task name: /root/worker
Sender: /root
Payload:
Review the authentication changes and report any regressions.
```
### `MESSAGE`
`MESSAGE` is used for a queued `send_message` delivery. It communicates
with an existing agent without starting a new turn.
For `/root/worker` reporting progress to the root agent, the request
contains:
```json
{
"type": "agent_message",
"author": "/root/worker",
"recipient": "/root",
"content": [
{
"type": "input_text",
"text": "Message Type: MESSAGE\nTask name: /root\nSender: /root/worker\nPayload:\n"
},
{
"type": "encrypted_content",
"encrypted_content": "<encrypted message payload>"
}
]
}
```
Conceptually, the model receives:
```text
Message Type: MESSAGE
Task name: /root
Sender: /root/worker
Payload:
The protocol tests pass; I am checking the resume path now.
```
### `FINAL_ANSWER`
`FINAL_ANSWER` is emitted when a child agent reaches a terminal state
and reports its result to its parent. Completion payloads are already
available locally, so the complete envelope is represented as plaintext
rather than as a plaintext header plus encrypted content.
For `/root/worker` completing work for the root agent, the request
contains:
```json
{
"type": "agent_message",
"author": "/root/worker",
"recipient": "/root",
"content": [
{
"type": "input_text",
"text": "Message Type: FINAL_ANSWER\nTask name: /root\nSender: /root/worker\nPayload:\nNo regressions found."
}
]
}
```
The model-visible form is:
```text
Message Type: FINAL_ANSWER
Task name: /root
Sender: /root/worker
Payload:
No regressions found.
```
Errored, shut down, and missing agents also use `FINAL_ANSWER`, with a
terminal-status description in the payload.
## What changed
- Render `NEW_TASK` or `MESSAGE` in
`InterAgentCommunication::to_model_input_item`, based on whether the
encrypted delivery starts a turn.
- Replace the multi-agent v2 `<subagent_notification>` completion
payload with a model-visible `FINAL_ANSWER` envelope.
- Document `Task name`, `Sender`, and `Payload` consistently in the
multi-agent developer instructions.
- Prevent local-only history projections from treating an encrypted
message's plaintext header as the complete assistant message.
- Preserve rollout-trace interaction edges when an agent message
contains both plaintext and encrypted content.
Legacy multi-agent behavior remains unchanged.
## Verification
- `just test -p codex-protocol`
- `just test -p codex-rollout-trace`
- `just test -p codex-web-search-extension`
- `just test -p codex-core
encrypted_multi_agent_v2_spawn_sends_agent_message_to_child`
- `just test -p codex-core
plaintext_multi_agent_v2_completion_sends_agent_message`
- `just test -p codex-core
multi_agent_v2_followup_task_completion_notifies_parent_on_every_turn`
- `just test -p codex-core
multi_agent_v2_completion_queues_message_for_direct_parent`
## Summary - disable the stable Apps feature in the generic `test_codex()` integration-test harness - keep Apps-specific tests explicit: their builders re-enable Apps and point it at a local mock server ## Why Generic tests that use dummy ChatGPT auth were also enabling the host-owned `codex_apps` MCP server. That made unrelated tests contact `chatgpt.com` and wait for MCP startup, causing the Bazel timeouts observed on openai#28368. The generic harness should be hermetic and should not start an external service that the test did not request. This is test-only; production Apps behavior is unchanged. The broader optional-MCP startup behavior is being handled separately in openai#28407. ## Testing - `just test -p codex-core -E 'test(pre_sampling_compact_runs_when_comp_hash_changes) | test(model_switch_to_smaller_model_updates_token_context_window) | test(codex_apps_file_params_upload_local_paths_before_mcp_tool_call)'` - `just fix -p codex-core` - `just fmt`
## Summary Plugin loading and auth projection both previously produced `PluginLoadOutcome`. That made an unfiltered load result look like runtime-ready capabilities and generated capability summaries before auth routing had run. This change keeps loaded plugin records in the cache, applies the current auth policy in `PluginsManager`, and only then builds `PluginLoadOutcome` and its summaries. Auth changes still reuse the cached disk load and re-resolve apps and MCP servers without reloading plugins. The updated tests cover cached auth changes and verify that capability summaries match the effective app/MCP surface. ## Testing - `just test -p codex-core-plugins` - `just test -p codex-plugin` - `just fix -p codex-core-plugins`
## Why
When a subagent exhausts its retries, it emits an `Error`, but the
generic task lifecycle then emits `TurnComplete(None)`. That completion
used to overwrite the subagent's `Errored` status with
`Completed(None)`, so the parent received an empty completion
notification.
This made a failed child look indistinguishable from a child that
completed without an answer. In unattended or long-running multi-agent
work, the root could silently continue without knowing that delegated
work failed or how to restart it.
## Behavior
Before, a terminal stream failure was reduced to an empty completion:
```text
<subagent_notification>
{"agent_path":"/root/worker","status":{"completed":null}}
</subagent_notification>
```
Now the parent receives the actual terminal error, bounded to 1,000
tokens, together with an actionable recovery hint:
```text
<subagent_notification>
{
"agent_path": "/root/worker",
"status": {
"errored": "stream disconnected before completion: stream closed before response.completed"
},
"next_action": "This agent's turn failed. If you still need this agent, use `followup_task` to give it another task."
}
</subagent_notification>
```
The notification remains queue-only: it does not wake the root or replay
the failed request. The root sees it at the next sampling boundary and
can use `followup_task` to start a new turn for that agent.
## What changed
- Added terminal-error precedence to the [agent status
reducer](https://github.com/openai/codex/blob/e95fcfe2bb6a02f1a75650afa20048859f556511/codex-rs/core/src/agent/status.rs#L23-L34),
so a closing `TurnComplete` cannot erase an immediately preceding
`Errored` status.
- Made MultiAgentV2 completion forwarding use the retained session
status instead of re-deriving `Completed(None)` from the final event.
- Extended the [subagent notification
fragment](https://github.com/openai/codex/blob/e95fcfe2bb6a02f1a75650afa20048859f556511/codex-rs/core/src/context/subagent_notification.rs#L6-L60)
with a `next_action` for terminal errors and a hard cap on model-visible
error text.
- Kept successful completions and interrupted turns unchanged.
## Verification
- Added a status-reducer test proving that `Errored` survives the
trailing `TurnComplete`.
- Added an integration test that exhausts a subagent's stream retries
and verifies the exact `agent_message` delivered to the parent,
including the error and `followup_task` guidance.
- Re-ran the existing successful-completion and interrupted-turn
notification tests.
## Why [openai#18763](openai#18763) added canonical hostname resolution for `remote_sandbox_config`. Requirements composition currently performs that synchronous DNS lookup on every fresh process, even when none of the loaded requirements layers contains `[[remote_sandbox_config]]`. On hosts with slow local DNS resolution, this can add several seconds to Codex startup. ## What - defer hostname resolution until a parsed requirements layer actually contains `remote_sandbox_config` - cache the resolver result once per requirements composition, preserving the existing single-lookup behavior across multiple layers - keep the existing FQDN resolution and per-layer requirements precedence unchanged - cover both the ordinary no-lookup path and the multi-layer single-lookup path ## How to Test On a host where local canonical-name resolution is slow: 1. Start Codex without `[[remote_sandbox_config]]` in any managed requirements layer and confirm startup no longer waits for hostname resolution. 2. Add a matching `[[remote_sandbox_config]]` entry and confirm its `allowed_sandbox_modes` still overrides the layer's top-level value. 3. Add remote sandbox entries to multiple requirements layers and confirm precedence remains unchanged while the hostname is resolved only once. Targeted tests: - `just test -p codex-config hostname_resolver` - `just test -p codex-config` (181 passed)
## Why Ensure a consistent string format when exposing path conversion errors to the model. ## What - Render `PathUriParseError::InvalidFileUriPath` as `'$PATH' is invalid on '$OS'`.
## Why On Linux, suspending Codex with `Ctrl+Z` and returning with `fg` can leave the composer misaligned or inject terminal response bytes such as focus reports into the prompt. Shell job-control output moves the cursor while Codex is suspended, and terminal input polling can race with the responses used to restore the inline viewport. Fixes openai#26564. ## What changed - preserve and restore keyboard reporting without disturbing the parent terminal stack - pause terminal event polling while Codex is suspended and flush buffered input before resuming it - force crossterm's cached raw-mode state back in sync after the shell completes its `fg` handoff - probe the actual post-`fg` cursor position with the tolerant terminal-response parser, then realign the inline viewport before redrawing ## How to Test 1. On Linux, start the development TUI with `just c`. 2. Type text into the composer without submitting it. 3. Press `Ctrl+Z`, run any harmless shell command, then run `fg`. 4. Confirm the composer redraws below the shell output, the draft text is preserved, and no raw escape sequences appear. 5. Repeat the suspend/resume cycle and confirm normal typing still works. Targeted tests: - `cargo test -p codex-tui --lib parses_cursor_position_as_zero_based -j 1` - `cargo test -p codex-tui --lib tui::event_stream::tests -j 1`
## Why `fs/readFile` buffers the entire file in one response, which makes large remote reads expensive and prevents callers from applying backpressure. We need an opt-in streaming path with bounded block sizes while preserving the existing single-call API for small and sandboxed reads. ## What changed - Add `ExecServerClient::stream`, returning a named `FileReadStream` that implements `futures::Stream` and yields immutable 1 MiB byte blocks. - Add internal `fs/open`, `fs/readBlock`, and `fs/close` RPCs. `fs/readBlock` accepts an explicit offset and length. - Keep unsandboxed files open between block reads, cap open handles per connection, and clean them up on EOF, error, stream drop, explicit close, or connection shutdown. - Reject platform-sandboxed streaming opens instead of turning the one-shot sandbox helper into a persistent server. Existing `fs/readFile` behavior is unchanged. ## Testing - `just test -p codex-exec-server` - Integration coverage for 1 MiB chunking, exact block-boundary EOF, sandbox rejection, and continued reads from the opened file after path replacement. - Handle-manager coverage for non-sequential offsets, variable block lengths, the 128-handle limit, and capacity release after close.
Fix side bug with prompt
…ics Smoke Test (openai#27099) ## This PR The original [combined remote plugin analytics PR openai#26281](openai#26281) mixed reusable analytics test infrastructure, two manual smoke workflows, a metadata refactor, and the final identity behavior. This PR establishes a non-mutating end-to-end plugin smoke workflow before any analytics identity semantics change. - Add `plugin-analytics-smoke` to the existing app-server test client. - Exercise plugin disable, enable, and use through production app-server RPC paths. - Isolate config writes in a temporary file and use a loopback Responses API server. - Capture analytics without sending them to the production analytics backend. - Validate the current local `plugin_id`, names, capability metadata, thread, turn, and model fields. This is intentionally a baseline smoke workflow. It does not assert `remote_plugin_id`; the final PR will update it when that field exists. Review this PR as the net diff against openai#27093. ## Testing - The test-client target compiles successfully. - The combined reference branch exercised the manual smoke against the live remote plugin service. - CI is green across the required platform matrix. ## Split Overview ```text main ├── openai#27093 Debug analytics capture │ └── openai#27099 Non-mutating plugin smoke ← you are here │ └── openai#27100 Remote install/uninstall smoke └── openai#27102 Plugin telemetry metadata refactor After openai#27093, openai#27099, openai#27100, and openai#27102 merge: └── Final PR: add remote_plugin_id to plugin analytics ``` Review order and dependencies: 1. [openai#27093 Add debug-only analytics event capture](openai#27093) (based on `main`) 2. [openai#27099 Add a plugin analytics smoke workflow](openai#27099) **(this PR, stacked on openai#27093)** 3. [openai#27100 Add a remote plugin analytics mutation smoke workflow](openai#27100) (stacked on this PR) 4. [openai#27102 Centralize plugin telemetry metadata construction](openai#27102) (independent, based on `main`) 5. Final remote-ID behavior PR (created after PRs 1-4 merge) The original [openai#26281](openai#26281) remains open as the green aggregate reference until the final PR is published.
## Why Codex syntax-highlights diffs for conventional C++ extensions such as `.cpp` and `.cxx`, but C++ module interface files using `.cppm`, `.ixx`, or `.cxxm` fall back to plain diff coloring. The bundled syntax set already includes C++, but it does not resolve those module extensions by itself. Closes openai#28223. ## What changed - map `.cppm`, `.ixx`, and `.cxxm` to the existing `cpp` syntax in `render/highlight.rs` - extend alias-resolution coverage for all three module extensions - verify `.cpp`, `.cppm`, `.ixx`, and `.cxxm` diffs produce syntax-highlighted RGB spans while unknown extensions retain the plain fallback - snapshot the syntax-colored token segmentation for the supported C++ module extensions ## How to Test 1. Ask Codex to create or modify a C++ module interface file using `.cppm`, `.ixx`, or `.cxxm`. 2. Confirm C++ tokens in the rendered diff receive syntax colors instead of only the red/green diff treatment. 3. Modify an equivalent `.cpp` file and confirm its existing highlighting remains unchanged. 4. Modify a file with an unknown extension and confirm it still uses the plain diff fallback. Targeted tests: - `just test -p codex-tui -E 'test(find_syntax_resolves_languages_and_aliases) | test(cpp_module_extensions_use_cpp_highlighting) | test(unknown_extension_falls_back_without_syntax_highlighting)'`
## 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
Add ThreadHistoryBuilder APIs for collecting incremental thread item and turn changes while applying rollout items. Batch handling coalesces repeated changes so callers can get the latest incremental thread item changes for a set of rollout items without rebuilding full history.
## Why Codex users can earn personal rate-limit reset credits, but the CLI does not currently provide a way to view or redeem them. The `/usage` command restored in openai#27925 is intended to be the entry point for usage-related actions, so reset redemption belongs there rather than in a separate dashed slash command. Depends on openai#28143 for the app-server and backend-client reset-credit APIs. ## What changed - Turn bare `/usage` into a menu with entries for token activity and earned rate-limit resets while preserving `/usage daily`, `/usage weekly`, and `/usage cumulative`. - Add loading, empty, confirmation, success, retry, and error states with a caller-generated UUID idempotency key reused across retries of the same logical reset. - Show an availability hint only for backend-classified rate-limit errors with credits available. - Hide the reset entry for workspace accounts. ## Validation - `just test -p codex-tui chatwidget::tests::usage` — 19 passed. - `just fix -p codex-tui` — passed. - `just fmt` — passed. - `cargo insta pending-snapshots` from `codex-rs/tui` — no pending snapshots. ## Examples <img width="1168" height="304" alt="image" src="https://github.com/user-attachments/assets/caa4c1e3-e996-494d-ae17-50b521f5dce8" /> <img width="908" height="260" alt="image" src="https://github.com/user-attachments/assets/e38a726b-77cc-4bd0-9ea8-9f3ad21c5768" /> ### Reset flow <img width="1509" height="312" alt="image" src="https://github.com/user-attachments/assets/d987013c-78a5-48a2-ad8d-c61ad267a327" /> <img width="585" height="190" alt="image" src="https://github.com/user-attachments/assets/de32be19-79b9-4a3e-8574-6f1c208c98ae" /> <img width="600" height="210" alt="image" src="https://github.com/user-attachments/assets/88a165cf-796d-4fdc-a7bc-ea89917573da" /> <img width="512" height="193" alt="image" src="https://github.com/user-attachments/assets/d2353998-5aa8-442e-a5f8-3a8a5b832753" />
## Why V8 should be stable under Bazel, so the `codex-code-mode` unit tests should run across the Bazel platform matrix. If these tests prove unstable, we should fix the tests rather than exclude them from CI. ## What changed - Remove the explicit `//codex-rs/code-mode:code-mode-unit-tests` exclusion from the macOS and Linux Bazel test jobs. - Remove the same exclusion from the native Windows post-merge job. - Keep the existing Windows gnullvm shard coverage. ## Bazel test coverage The target contains 26 unit tests. A fresh uncached local Bazel execution ran all 26 with 0 failures, 0 ignored tests, and 0 filtered tests. PR Bazel CI selected the target on every enabled platform and reported a cached pass: | Platform | Passing CI job | | --- | --- | | macOS aarch64 | [Bazel test passed](https://github.com/openai/codex/actions/runs/27636617545/job/81725447804) | | macOS x86_64 | [Bazel test passed in 2.2s](https://github.com/openai/codex/actions/runs/27636617545/job/81725448008) | | Linux GNU | [Bazel test passed in 0.4s](https://github.com/openai/codex/actions/runs/27636617545/job/81725447898) | | Linux musl | [Bazel test passed in 0.4s](https://github.com/openai/codex/actions/runs/27636617545/job/81725448117) | | Windows gnullvm | [Bazel test passed in shard 4/4 in 1.6s](https://github.com/openai/codex/actions/runs/27636617545/job/81725448166) |
…#27923) ## Why Codex Apps tools can mark arguments with `openai/fileParams`, but the execution path resolved and opened those files directly on the host. That bypassed the selected turn environment and prevented annotated file arguments from working with remote environments. ## What changed - resolve annotated file arguments against the primary turn environment - read file metadata and contents through that environment's sandboxed `ExecutorFileSystem` - reject files over the 512 MiB limit from metadata before reading or transferring them - retain the buffered upload-size check as defense in depth - make the OpenAI upload API accept a filename and buffered contents instead of owning local filesystem access - describe the model-visible argument as a path in the primary environment This builds on openai#27927, which added `size` to internal filesystem metadata. ## Testing - `just test -p codex-api upload_openai_file_returns_canonical_uri` - `just test -p codex-mcp tool_with_model_visible_input_schema_masks_file_params` - `just test -p codex-core mcp_openai_file` - `just test -p codex-core codex_apps_file_params_upload_environment_files_before_mcp_tool_call`
…ke Test (openai#27100) ## This PR The original [combined remote plugin analytics PR openai#26281](openai#26281) mixed reusable analytics test infrastructure, two manual smoke workflows, a metadata refactor, and the final identity behavior. This PR adds the account-mutating validation workflow separately so its cleanup and recovery guarantees can be reviewed without the final analytics behavior change. - Add a manually invoked remote plugin install/uninstall smoke workflow. - Require explicit account-mutation confirmation and an initially uninstalled plugin. - Validate the current `codex_plugin_installed` contract, where `plugin_id` is the backend ID. - Restore and verify the original uninstalled state, with a dedicated recovery command. This baseline intentionally does not require `codex_plugin_uninstalled`, because production does not emit that event yet. The final PR will update this smoke to require local `plugin_id`, `remote_plugin_id`, and uninstall emission. Review this PR as the net diff against openai#27099. ## Testing - `just test -p codex-app-server-test-client` (3 focused capture/validation tests passed) - The live workflow was previously exercised on the green combined reference branch, and the original uninstalled account state was restored. - CI is green across the required platform matrix. ## Split Overview ```text main ├── openai#27093 Debug analytics capture │ └── openai#27099 Non-mutating plugin smoke │ └── openai#27100 Remote install/uninstall smoke ← you are here └── openai#27102 Plugin telemetry metadata refactor After openai#27093, openai#27099, openai#27100, and openai#27102 merge: └── Final PR: add remote_plugin_id to plugin analytics ``` Review order and dependencies: 1. [openai#27093 Add debug-only analytics event capture](openai#27093) (based on `main`) 2. [openai#27099 Add a plugin analytics smoke workflow](openai#27099) (stacked on openai#27093) 3. [openai#27100 Add a remote plugin analytics mutation smoke workflow](openai#27100) **(this PR, stacked on openai#27099)** 4. [openai#27102 Centralize plugin telemetry metadata construction](openai#27102) (independent, based on `main`) 5. Final remote-ID behavior PR (created after PRs 1-4 merge) The original [openai#26281](openai#26281) remains open as the green aggregate reference until the final PR is published.
## Why In openai#28146 I missed the invariant that an absolute `exec_command` workdir must override the environment cwd. The existing integration test would have caught that regression, but it was ignored as flaky. ## What Re-enable `unified_exec_respects_workdir_override`. ## Validation `just test -p codex-core unified_exec_respects_workdir_override`
This PR establishes the intended behavior as an executable contract before a refactor of the cell runtime begins. It also fixes cases where a second observer or termination request could replace an existing response channel and leave the original caller unresolved. ### Behavior codified - A cell can yield output and subsequently resume to completion. - A caller can run a cell until it has no immediately runnable work, receive its accumulated output and outstanding tool-call IDs, and then resume the same cell when the awaited work is available. - Each cell admits one active observer: - a second observer receives an explicit busy error - the existing observer remains registered and is not displaced - A natural result (conclusion of the js module) that has already reached the cell controller wins over a later termination request. - Otherwise, termination preempts execution and resolves both: - the active observer, if present - the caller requesting termination - Repeated termination requests are rejected while termination is already in progress. - Terminal responses are sent only after outstanding callback work has been handled: - natural completion drains notifications and cancels outstanding tool calls - termination cancels and drains both notification and tool callbacks. - Cell removal and cell_closed notification happen after callback cleanup
## Why Review caught some would-be regressions in changes to unified_exec that weren't surfaced in CI. ## What Add coverage for requesting permissions through unified exec when there are additional permissions. Previously this flow was only tested against shell_command.
## 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.
## Why Help Codex understand how to execute the migration to support cross-OS paths. ## What Expand the path-types skill with our goals and constraints.
## Why app-server may run on a different OS from the selected exec-server environment. Parsing that environment’s cwd with the Codex host’s path rules prevents thread startup. ## What Carry environment cwd values as `LegacyAppPathString` at the app-server boundary and `PathUri` internally. Existing tool-call schemas and relative-path behavior stay host-native; remaining local-only consumers convert explicitly and leave follow-up TODOs. The Wine integration test verifies app-server can start a thread and complete an ordinary turn with a Windows environment cwd from Linux. ## Validation - `bazel test //codex-rs/core/tests/remote_env_windows:smoke-test --test_output=errors` - focused app-server environment-selection and protocol schema tests - scoped Clippy for `codex-core` and `codex-app-server-protocol`
This addresses another wrinkle I keep having to re-prompt codex about when migrating to cross-OS paths.
Summary - Add authenticated parsing for `/ps/plugins/suggested?scope=GLOBAL`, including remote plugin and connector app identities. - Validate, deduplicate, sort, and cap endpoint candidates before caching them by backend and account identity. - Deduplicate concurrent cache misses and warm recommendations from the existing remote-installed-plugin refresh path used at startup and after account changes. - Keep endpoint results model-invisible in this PR; failures and responses without `enabled: true` resolve to legacy mode. Stack - 1/3. Follow-up: openai#28400 generalizes plugin suggestion presentation without activating endpoint recommendations. - Final activation: openai#27704. Validation - `just test -p codex-core-plugins recommended_plugins` - `just fix -p codex-core-plugins` - `just fmt` - `git diff --check`
Summary - Add list-backed and developer-context presentations for plugin suggestion candidates. - Let tool planning, install validation, and request-tool copy follow the selected presentation. - Keep every production caller on the existing list-backed presentation, preserving the current list tool, request schema, connector behavior, and model-visible copy. - Leave developer-context presentation latent until the final PR in the stack. Stack - 2/3, based on openai#28399. - Follow-up: openai#27704 activates endpoint recommendations. Validation - `just test -p codex-core request_plugin_install` - `just test -p codex-core spec_plan` - `just fix -p codex-core` - `just fmt` - `git diff --check`
Summary\n- Await endpoint recommendation selection while constructing each authenticated turn, removing the first-turn cache race.\n- Snapshot and filter endpoint candidates once per turn, then use that same set for the bounded contextual user fragment, tool exposure, and exact install validation.\n- Keep recommendation selection ephemeral: do not persist recommendation state in or gate resumed threads on prior context.\n- Hide the legacy list tool in endpoint mode and preserve legacy discovery unchanged when the endpoint is disabled or unavailable.\n- Keep remote plugin and connector app identities out of model-visible context and attach them only to Codex-owned elicitation metadata.\n\nStack\n- 3/4, based on openai#28400.\n- Endpoint client and cache: openai#28399.\n- Generalized suggestion presentation: openai#28400.\n- Install-schema follow-up: openai#28403.\n\nValidation\n- \n- \n- \n- \n- Full : 2,649 passed and 88 environment-dependent tests failed because this sandbox cannot write , nest Seatbelt, or locate auxiliary test binaries.
## Summary - Add backend-client types and fetch support for active workspace messages. - Add the app-server v2 `account/workspaceMessages/read` method, generated schemas, and README documentation. - Delegate workspace-message eligibility to the Codex backend feature gate; map a backend 404 to `featureEnabled: false`. ## Testing - `just write-app-server-schema` - `just test -p codex-backend-client` - `just test -p codex-app-server-protocol` - `just test -p codex-app-server workspace_messages` - `just fix -p codex-backend-client -p codex-app-server-protocol -p codex-app-server` - `just fmt` ## Stack - Base PR for openai#28232, which adds the TUI status-line integration.
## Why Every successful Responses WebSocket event currently produces three local log records: the full payload at TRACE, an OpenTelemetry log event, and an OpenTelemetry trace event. On busy threads these records fill the 1,000-row log partition in seconds and cause continuous SQLite insert-and-prune churn. Related to https://openai.slack.com/archives/C095U48JNL9/p1782128972644209 ## What changed - Stop logging each successful Responses WebSocket payload at TRACE. - Stop emitting `codex.websocket_event` as OpenTelemetry log and trace events. - Keep WebSocket event counters, duration metrics, response timing metrics, parsing, and error handling.
## Why Nonblocking environment snapshots allow a turn to reach the model while a remote environment is still starting. The initial context can describe that environment as still loading, but nothing currently refreshes the model-visible environment context when startup finishes during the same turn. This adds the first request-scoped reconciliation slice on top of openai#28683. It is gated by `DeferredExecutor` and intentionally updates only model-visible environment context; tools and other environment-derived state will migrate separately. ## What - Add a minimal `StepContext` containing the environment snapshot captured before each sampling request. - Render attached environments with their resolved shell and starting environments with `still loading`. - Track the latest environment state recorded in model history and append a bounded update only when it changes. - Seed that baseline from full initial context so ready-at-start environments are not duplicated. - Clear the in-memory baseline when history is rewritten so replacement history can be refreshed safely. ## Testing - `just test -p codex-core deferred_executor` - `just test -p codex-core environment_context_baseline_deduplicates_until_history_is_replaced` The integration coverage verifies that a pending environment reaches the first request, the ready state reaches the next request, later requests do not duplicate it, and ready-at-start environments remain single-injected. <details> <summary>Live verification</summary> - Connected to a real remote executor with startup deliberately delayed and forced three sampling requests in one turn. - Inspected the raw model inputs: request 1 showed the remote environment as `still loading`, request 2 appended its ready shell and cwd, and request 3 contained no duplicate ready update. - With the feature disabled, startup waited for the delayed executor and the first request contained only the ready environment. - With a synchronously ready environment and the feature enabled, the first request contained one environment context with no duplicate. - Executed `pwd` and read a marker file through the remote process runner; the command exited successfully and returned the remote cwd and marker contents. </details>
## Description Restore `thread_source` in `x-codex-turn-metadata`. Inadvertently removed `thread_source` from `x-codex-turn-metadata` in openai#27122 - didn't realize it was a top-level thread app-server API field, not passed in `responsesapi_client_metadata`. This also reserves the key so `responsesapi_client_metadata` cannot override it.
## Why The local SQLite log sink currently enables TRACE for every target. This persists high-volume dependency logs bridged through `target=log` and duplicates OpenTelemetry mirror events in `codex_otel.log_only` and `codex_otel.trace_safe`. These records rapidly consume the per-partition log budget and cause unnecessary SQLite insert-and-prune churn. ## What changed - Keep TRACE persistence for other targets. - Exclude bridged `target=log` events from the SQLite sink. - Exclude the two `codex_otel` mirror targets from the SQLite sink. - Share the same filter between app-server and TUI. Remote OpenTelemetry export and metrics are unchanged.
## What - make Fjord's centralized response-item image preparation unconditional for new and resumed history - have local user images and `view_image` outputs always defer decoding and resizing to that path - retain `resize_all_images` as an ignored, removed compatibility key for released clients - delete the flag-off producer paths and obsolete policy-specific tests ## Why Centralized preparation is now the intended image path. Keeping the runtime feature checks also kept two image-processing implementations alive and allowed client config to select the legacy behavior. This is a clean replacement for openai#28975, rebuilt from the latest `main`. ## How `prepare_response_items` now runs whenever items enter history and whenever persisted history is reconstructed. Producers emit deferred image data, so malformed images become the existing model-visible placeholder instead of failing the session at the producer. ## Test plan - `just fmt` - `just fix -p codex-core -p codex-features` - `just test -p codex-features` — 52 passed - focused affected `codex-core` set — 20 passed - `just test -p codex-core handle_accepts_explicit_high_detail` — 1 passed - full `just test -p codex-core` attempt — 2,723 passed; 88 unrelated environment failures from read-only `~/.codex` SQLite state and unavailable integration helper binaries
) The custom Windows argument-comment-lint job was temporarily moved to `windows-2022` in openai#28940 after hermetic LLVM source extraction failed on the newer runner. This takes the upstream extraction fix so the job can return to the intended custom runner. This upgrades `llvm` to `0.7.9` and `rules_cc` to `0.2.18`, refreshes the module lock, rebases the remaining Windows and custom libc++ patches, drops the obsolete symlink-extraction workaround, and restores the `windows-x64` runner configuration. Validation: - Verified all LLVM patches apply cleanly against the `0.7.9` source. - Built `@llvm-project//compiler-rt:clang_rt.builtins.static`.
This PR moves construction of `PluginTelemetryMetadata` from loader and
model helpers into `PluginsManager`, which already owns installed plugin
state and will eventually perform remote identity enrichment. The
metadata type remains in `codex-plugin`, and serialized analytics events
remain unchanged.
## Before
```mermaid
flowchart LR
subgraph Events["Analytics event paths"]
direction TB
Lifecycle["Local install / uninstall"]
Config["Enable / disable"]
Remote["Remote install"]
Used["Plugin used"]
end
subgraph Construction["Metadata construction"]
direction TB
Loader["Loader telemetry helpers"]
Summary["PluginCapabilitySummary::telemetry_metadata"]
Override["Caller adds remote_plugin_id"]
end
Metadata["PluginTelemetryMetadata"]
Lifecycle --> Loader
Config --> Loader
Remote --> Loader
Loader -->|"local events"| Metadata
Loader -->|"remote install"| Override
Override --> Metadata
Used --> Summary
Summary --> Metadata
```
Telemetry metadata was constructed through loader helpers, a
capability-summary method, and a remote-install call-site override.
## After
```mermaid
flowchart LR
subgraph Events["Analytics event paths"]
direction TB
Lifecycle["Local install / uninstall"]
Config["Enable / disable"]
Remote["Remote install"]
Used["Plugin used"]
end
Manager["PluginsManager — single construction owner"]
Metadata["PluginTelemetryMetadata"]
Lifecycle --> Manager
Config --> Manager
Remote -->|"authoritative remote ID"| Manager
Used -->|"capability summary"| Manager
Manager --> Metadata
```
Every analytics path delegates metadata construction to
`PluginsManager`. Remote install still supplies its authoritative
backend ID explicitly.
## What Changes
- Make loader code return a focused plugin capability summary instead of
constructing analytics metadata.
- Centralize immutable plugin telemetry metadata construction in
`PluginsManager`.
- Route local install/uninstall, remote install, enable/disable, and
plugin-used emitters through the manager.
- Preserve the current serialized analytics contract exactly.
Normal metadata still has no remote override. Remote install continues
to provide its authoritative backend ID explicitly, so the existing
serializer continues reporting that ID through `plugin_id`.
Snapshot-based enrichment is intentionally deferred to the final PR.
## Testing
- `just test -p codex-core-plugins` (238 tests passed)
- `just test -p codex-plugin` (3 tests passed)
- Scoped Clippy/compile checks passed for `codex-plugin`,
`codex-core-plugins`, `codex-app-server`, and `codex-core`.
## Split Overview
```text
main
├── openai#27093 Debug analytics capture (merged)
├── openai#27099 Non-mutating plugin smoke (merged)
├── openai#27100 Remote install/uninstall smoke (merged)
└── openai#27102 Plugin telemetry metadata refactor ← you are here
└── openai#27669 Persist remote plugin identity
After openai#27102 and openai#27669 merge:
└── Final PR: add explicit local and remote IDs to plugin analytics
```
Review order and dependencies:
1. [openai#27093 Add debug-only analytics event
capture](openai#27093) (merged)
2. [openai#27099 Add a plugin analytics smoke
workflow](openai#27099) (merged)
3. [openai#27100 Add a remote plugin analytics mutation smoke
workflow](openai#27100) (merged)
4. This metadata refactor, independent and based on `main`
5. [openai#27669 Persist remote plugin
identity](openai#27669), stacked on this
PR
6. Final remote-ID behavior PR, created after the prerequisites merge
The original [openai#26281](openai#26281)
remains open as the aggregate reference until the final replacement PR
is published.
…26703) ## Summary [openai#26701](openai#26701) added remote plugin identity support, [openai#26702](openai#26702) added remote-section fetching and state, and [openai#28768](openai#28768) extracted the catalog rendering module. This PR builds the product-facing `/plugins` catalog on that foundation so remote records appear as OpenAI Curated, Workspace, and Shared with me sections rather than backend marketplace implementation details. Plugin details remain read-only for sharing metadata. This PR does not add share-authoring actions or change the app-server protocol. ## Changes - Renders OpenAI Curated, Workspace, and Shared with me sections with loading, empty, and error states. - Preserves section selection and stable tab ordering as remote sections transition between fallback and populated states. - Shows OpenAI Curated loading only when the explicit vertical fallback request was issued. - Centralizes remote marketplace identity matching around the existing marketplace constants. - Uses product labels for remote marketplaces and identifies the personal marketplace as Local by its path. - Shows read-only source, authentication, version, and sharing metadata in plugin detail views. - Applies narrow display deduplication for local and remote records sharing a remote plugin ID: - installed records take precedence; - local mapped sources are preferred for details only when their installed state matches the selected record. - Returns from detail and confirmation views through the current plugin cache so newly loaded remote sections are not overwritten by an older captured response. - Keeps admin-disabled plugins view-only and labels default-installed plugins as Available by default. ## Tests New tests: - `plugins_popup_admin_disabled_available_plugin_has_view_only_hint` - `plugins_popup_remote_section_fallback_states_snapshot` - `plugins_popup_installed_remote_row_keeps_remote_detail_when_local_share_is_uninstalled` Updated existing plugin catalog tests and snapshots for product labels, detail metadata, personal-marketplace labeling, and stable tab ordering. Verification: - `cargo clippy -p codex-tui --all-targets -- -D warnings` ## Follow-ups - Local/remote duplicate normalization should eventually move into app-server. This PR intentionally keeps the compatibility behavior narrow and display-only. - PR5 will sanitize sensitive components before displaying Git source URLs.
## Why openai#29113 moved remote sandbox setup and enforcement to the exec server. That gives the executor ownership of the platform-specific work: a Linux executor chooses and runs a Linux sandbox even when the Codex orchestrator is running on macOS or Windows. It also means the orchestrator no longer knows which concrete sandbox the executor selected. When that sandbox blocks a remote command, the orchestrator currently sees only a failed process and can treat the denial as an ordinary command failure. The existing sandbox approval and retry path is then skipped. This PR lets the executor report one portable fact: > This command probably failed because the executor sandbox blocked it. The executor keeps its concrete sandbox type private. The protocol sends only the semantic result. ## Example Suppose a local macOS Codex session asks a Linux devbox to write outside the allowed workspace. Before this PR: ```text Linux sandbox blocks the write -> remote process exits with "Permission denied" -> local orchestrator sees an ordinary command failure -> the normal sandbox approval and retry path can be skipped ``` With this PR: ```text Linux sandbox blocks the write -> executor reports sandboxDenied: true -> unified exec returns UnifiedExecError::SandboxDenied -> the existing approval prompt is shown -> an approved retry runs through the existing unsandboxed retry path ``` ## What changes ### The executor remembers its selected sandbox The prepared remote process now retains the executor-selected `SandboxType`. This value never crosses the executor boundary. Commands started without a sandbox retain `SandboxType::None` and are never reported as sandbox denials. ### The executor uses the existing denial heuristic The existing local denial heuristic moves from `codex-core` into the shared `codex-sandboxing` crate. When a sandboxed remote process exits, the executor: 1. waits the same short output grace period used by local unified exec; 2. reads the output currently available in the existing retained output buffer; 3. runs the existing heuristic using the exit code and common denial messages; 4. stores the yes/no result before publishing the process exit. This deliberately matches the old local unified-exec behavior. It does not add a new streaming classifier, another output buffer, or stronger output-retention guarantees. ### The protocol reports a portable boolean `process/read` gains `sandboxDenied`: ```json { "exited": true, "exitCode": 1, "closed": false, "sandboxDenied": true } ``` The field defaults to `false` when an older executor omits it. The response does not expose the executor sandbox implementation or executor-native paths. ### Unified exec uses the existing error path The exec-server client carries `sandboxDenied` into the unified process state. If it is true, unified exec returns the existing `SandboxDenied` error instead of trying to classify remote output using an orchestrator-side sandbox type. Remote process exit remains visible as soon as the process exits. This PR does not wait for stdout or stderr to close and does not change the existing process lifecycle. ## Scope This PR is intentionally limited to matching the existing local unified-exec behavior for the initial command execution path. It does not add: - incremental denial tracking across the full output stream; - new denial handling for commands completed later through `write_stdin`; - new guarantees for preserving the semantic flag during the narrow reconnect-recovery race. Those can be considered separately if the same behavior is added for local execution. ## Test coverage One remote end-to-end integration test covers the complete intended flow: ```text remote read-only sandbox -> denied write -> executor reports the denial -> Codex requests approval -> user approves -> retry succeeds on the remote executor ``` Existing lifecycle coverage continues to verify that remote process exit is reported before late output streams close.
…penai#28968) ## Description This PR cuts Codex over from generic `ResponseItem.metadata` (introduced here: openai#28355) to `ResponseItem.internal_chat_message_metadata_passthrough`, which is the blessed path and has strongly-typed keys. For now we have to drop this MAv2 usage of `metadata`: openai#28561 until we figure out where that should live.
## Summary - use generated image data URLs in the Python SDK examples and notebook - document HTTP and HTTPS image URLs as deprecated and recommend `LocalImageInput` - replace the remote-URL integration test with data-URL coverage `ImageInput` remains available for data URLs. The SDK does not duplicate app-server URL validation. ## Testing - `uv run --frozen --no-sync ruff check --output-format=full .` - `uv run --frozen --no-sync ruff format --check .` - full Python SDK test suite with an isolated writable `CODEX_SQLITE_HOME` (119 passed, 38 skipped)
## Why The reset flow introduced in openai#28154 still describes earned reset credits as "rate-limit resets" and uses generic reset-scope copy. It can also retain a stale available-credit count after redemption or an account change, leaving the reset action enabled after the last credit is used. This follow-up updates terminology only within that reset feature. Existing rate-limit wording elsewhere in the CLI and TUI is unchanged. ## What changed - Rename reset-specific `/usage` menu items, startup hints, and reset dialogs to "usage limit reset." - Describe monthly resets for Free, Go, and accounts that report a monthly usage window; otherwise describe the current 5-hour and weekly limits. - Recheck a cached zero balance when `/usage` is reopened, and refresh the balance after redemption so the final reset immediately disables the action. - Correlate async refresh results before updating snapshots and clear account-derived reset state, warnings, prompts, and status surfaces when the account changes. ## Validation - `just test -p codex-tui chatwidget::tests::usage` — 29 passed. - `just test -p codex-tui chatwidget::tests::status_command_tests` — 7 passed. - Account-boundary prompt and plan-mode prompt regression tests passed. - `cargo insta pending-snapshots` from `codex-rs/tui` — no pending snapshots.\ <img width="814" height="318" alt="image" src="https://github.com/user-attachments/assets/2a460e96-458b-4805-8d9f-c759382d21a4" /> view for monthly <img width="905" height="243" alt="image" src="https://github.com/user-attachments/assets/179f88e3-08fb-4af5-8dc6-ce6a944ed681" />
…ed (openai#27982) ## Why The first auto-review currently creates its Guardian child session on demand, adding avoidable latency before the review can begin. Creating the ordinary Guardian child during parent-session initialization lets that child use the existing session startup WebSocket prewarm before the first escalation. This does not introduce a Guardian-specific prewarm mechanism. ## What changed - initialize the existing Guardian review-session manager owned by `Session` when a thread starts with auto-review enabled and an approval policy that routes to Guardian - use the standard Guardian child-session construction and the existing session startup WebSocket prewarm - preserve the existing reuse-key invalidation and lazy creation fallback when startup initialization fails or the effective review configuration changes - add an integration test that verifies normal root-session startup emits a Guardian `generate=false` prewarm request ## Benchmark I compared release builds against main. Each prompt first ran a non-escalated `sleep 3`, then requested an escalated marker command. | binary | count | avg Guardian duration | median Guardian duration | avg Guardian TTFT | |---|---:|---:|---:|---:| | origin-main | 10 | 4008.7 ms | 3949.5 ms | 3746.5 ms | | session-fix | 10 | 2865.0 ms | 2594.0 ms | 2492.7 ms | Guardian duration fell by 28.5% and Guardian TTFT fell by 33.5%. These measurements cover Guardian review latency; they do not measure parent thread-start latency.
## Why `compile_scoped_filesystem_pattern()` accepted a `_policy_cwd` parameter even though scoped glob compilation no longer uses the policy working directory. Keeping that unused argument forced the surrounding permissions compilation path to keep forwarding `policy_cwd` through call sites that did not need it, making the API look more dependent on cwd resolution than it is. ## What changed Removed the unused cwd parameter from `compile_scoped_filesystem_pattern()` and the callers that only forwarded it: `compile_filesystem_permission()`, `compile_permission_profile()`, and `compile_permission_profile_selection()`. Workspace root resolution still keeps `policy_cwd`, because that path still resolves relative roots against the active policy cwd. Relevant code: [`codex-rs/core/src/config/permissions.rs`](https://github.com/openai/codex/blob/b8b9816102e064dae4488ec130cf560f63c1ab78/codex-rs/core/src/config/permissions.rs#L346). ## Verification - `just test -p codex-core config::permissions` - `just test -p codex-core` was also run after building `test_stdio_server`; it passed the touched permissions coverage but still reported unrelated existing failures in `cli_stream` and shell snapshot tests.
## Summary Stacked on openai#26706. Adds the shared auth/system-proxy contract that later platform resolver PRs plug into. This PR moves Codex-owned auth and startup HTTP clients through a common route-aware boundary, but does not yet add Windows or macOS system proxy resolution. The default path remains unchanged when `respect_system_proxy` is absent or disabled. ## Implementation - Adds `codex-client/src/outbound_proxy.rs` with the shared route-selection model: - `OutboundProxyConfig`; - `ClientRouteClass`; - `RouteFailureClass`; - `build_reqwest_client_for_route`. - Preserves the existing reqwest/default-client behavior when no route config is supplied. - Uses the fixed MVP routing policy when route config is supplied: platform system/PAC/WPAD discovery, then explicit env proxy variables, then direct connection. - Keeps platform-specific system discovery behind the shared client boundary. This PR provides the contract and fallback behavior; later resolver PRs plug in Windows and macOS discovery. - Adds `login::AuthRouteConfig` so auth call sites depend on a small policy type instead of platform resolver details. - Maps the resolved `Config.respect_system_proxy` boolean into `AuthRouteConfig` for auth-owned clients. - Wires the route config through browser login, device-code login, access-token login, login status, logout/revoke, token refresh, API-key exchange, app-server account login, TUI/app startup, cloud-config bootstrap, cloud tasks, plugin auth, and exec startup config loading. ## End-user behavior - No behavior changes by default. - When `respect_system_proxy = true`, auth-owned clients opt into the shared route-aware client path. - On platforms without a resolver implementation in this PR, system discovery is unavailable and the route-aware path falls back to explicit env proxy handling, then direct connection. - Custom CA handling remains separate from proxy route selection and still runs through the shared client builder. - No proxy URLs, PAC contents, or resolved platform details are exposed through the public config surface introduced here. ## Tests Adds or updates coverage for: - preserving default auth-client fallback behavior when no route config is provided; - injected environment-proxy fallback without mutating process environment; - existing login-server E2E flows using explicit `auth_route_config: None` to guard unchanged default behavior; - updated auth manager, login, logout, cloud-config, startup, and plugin-auth call sites passing route config explicitly.
# Summary Codex required every ChatGPT account to have an email address. A service-account personal access token can return valid account metadata without one, so PAT login failed while decoding the metadata response. This change makes email optional in the account metadata type that owns it and preserves that absence through authentication, provider account state, the app-server API, generated clients, and TUI bootstrap. Existing accounts with email addresses keep the same behavior. ## Behavior-changing call sites | Call site | Behavior after this change | | --- | --- | | `login/src/auth/personal_access_token.rs` | PAT metadata accepts a missing or null email and retains `None`. | | `agent-identity/src/lib.rs` | Agent Identity JWT claims accept an omitted email. | | `login/src/auth/storage.rs` and `login/src/auth/agent_identity.rs` | Stored and managed Agent Identity records carry `Option<String>`. Deserialization maps the legacy empty-string sentinel to `None`. | | `login/src/auth/manager.rs` | `get_account_email` returns the stored option, and managed identity bootstrap no longer converts `None` to an empty string. | | `model-provider/src/provider.rs` and `protocol/src/account.rs` | A ChatGPT provider account requires a plan type but may carry no email. | | `app-server-protocol/src/protocol/v2/account.rs` | `account/read` keeps the `email` field on the wire and returns `null` when the account has no email. Generated TypeScript and JSON schemas describe a required, nullable field. | | `sdk/python/src/openai_codex/generated/v2_all.py` | The generated Python `ChatgptAccount` model accepts `None` for email. | | `tui/src/app_server_session.rs` | Email-less ChatGPT accounts bootstrap normally, keep external feedback routing, omit account-email telemetry, and display the plan in account status. | ## Design decisions - Missing email remains `None` at every layer. The code never uses an empty string as a substitute. - The app-server response includes `"email": null` instead of omitting the field. Clients retain a stable response shape. - Plan type remains required for provider account state. This change relaxes only the email assumption. ## Testing Tests: affected test targets compile, scoped Clippy and formatting pass, a focused TUI snapshot covers plan-only account status, real before/after PAT login smoke covers metadata without email, app-server smoke covers `account/read` with `email: null`, and a regression smoke covers an existing email-bearing PAT. Unit tests run in CI. ## Evidence Visual smoke evidence will be attached here.
## Summary
Instead of:
reminder_interval_tokens = 65_536
allow users to configure explicit remaining-token reminder thresholds:
reminder_at_remaining_tokens = [65_536, 32_768, 16_384, 8_192, 4_096,
2_048, 1_024, 512]
## Validation
- CARGO_INCREMENTAL=0 just test -p codex-core rollout_budget: 9 passed
- just fix -p codex-core
- just fmt
## Why `permissionProfile/list` currently advertises every built-in and configured profile even when effective enterprise requirements prevent selecting it. That forces each client to reconstruct policy from lower-level requirement fields, which is easy to miss and difficult to keep consistent. The catalog should remain complete so clients can explain that an option was disabled by an administrator, while also reporting whether each profile is selectable. ## What - Add an `allowed` field to each permission profile summary. - Build a shared catalog from the effective config and current requirements, including `allowed_sandbox_modes`, `allowed_permissions`, and filesystem restrictions. - Use the shared catalog in app-server and the TUI so disallowed profiles remain visible but cannot be selected. - Use the canonical `:danger-full-access` profile ID in the TUI. - Update the app-server schemas, API documentation, behavioral tests, and TUI snapshots. ## Scope This PR targets `main` directly and is independent of openai#24852. It preserves the current behavior where built-in profiles are constrained by sandbox-mode requirements and `allowed_permissions` applies to configured profiles. ## Testing - `just test -p codex-core permission_profile_catalog_marks_profiles_disallowed_by_requirements` - `just test -p codex-app-server permission_profile_list` - `just test -p codex-app-server-protocol` - `just test -p codex-tui profile_permissions` - `just fix -p codex-core` - `just fix -p codex-app-server-protocol` - `just fix -p codex-app-server` - `just fix -p codex-tui` - `just fmt` --------- Co-authored-by: Codex <noreply@openai.com> Co-authored-by: Joey Trasatti <joey.trasatti@openai.com>
…9476) ## Why `codex-app-server-test-client` previously treated `item/tool/requestUserInput` as an unsupported server request and terminated the connection. That made it impossible to use the client for end-to-end testing of interactive turns: an operator could observe the request, but could not answer it and confirm that the same turn resumed. ## What changed - Handle `ToolRequestUserInput` server requests in the test client's central request dispatcher. - Render numbered terminal choices, accept exact option labels, support free-form `Other` and text-only questions, and collect multiple answers. - Send a protocol-native `ToolRequestUserInputResponse` and continue streaming the active turn. - Fail clearly when interactive input is requested without a terminal. - Document the interactive behavior and add focused tests for option selection, free-form answers, multiple questions, and invalid-selection retries. ## Testing - `just test -p codex-app-server-test-client` - `just bazel-lock-check` - Manually exercised the app-server flow, selected `TUI`, observed `serverRequest/resolved`, and verified that the same turn completed with the selected answer.
## Summary - rename `Config::permission_profile_allowed` to `is_permission_profile_allowed` - use `BUILT_IN_PERMISSION_PROFILE_DANGER_FULL_ACCESS` in the TUI and its assertion - follow up on the late review comments from openai#26678 The previous `:danger-no-sandbox` value was an invalid built-in profile ID. openai#26678 corrected it to `:danger-full-access`; this PR centralizes the value to prevent future drift. ## Testing - Not run per request; `cargo fmt` only Co-authored-by: Codex <noreply@openai.com>
## Why When Codex starts with a custom CA override such as `SSL_CERT_FILE=/path/to/corp-ca.pem codex`, `rustls-native-certs` treats that override as a replacement for the platform trust store. The managed proxy then rewrites child CA variables to its generated bundle, so the custom root or the ordinary platform roots can be lost. The proxy's upstream TLS connector must trust the same roots or private and corporate upstream certificates still fail after interception. ## What - load platform-native roots without consulting inherited CA override variables - append certificates from the existing curated startup CA file variables and `SSL_CERT_DIR` - share those platform and startup roots with the MITM upstream rustls connector - exclude the Codex managed MITM CA from upstream trust - normalize OpenSSL `TRUSTED CERTIFICATE` blocks while dropping trailing trust metadata - skip an inherited current Codex-managed bundle so nested launches do not duplicate it - append the Codex managed MITM CA to the child-facing bundle - copy certificate material only, so a private key or unrelated text colocated in a startup file is never exposed through the public bundle This is intentionally limited to CA paths present when Codex starts. It does not parse inline shell assignments or add per-command bundle materialization. This changes only `codex-network-proxy` and dependency metadata; it does not touch `codex-core` or sandbox orchestration. ## Validation - `just test -p codex-network-proxy` - includes an end-to-end upstream TLS test using a server trusted only by the startup custom CA - `just fix -p codex-network-proxy` - `just bazel-lock-check`
## Why `openai-oss-forks/tokio-tungstenite` now includes the updated `tungstenite` fork revision from [openai-oss-forks/tokio-tungstenite#3](openai-oss-forks/tokio-tungstenite#3). Codex should consume the merged fork commit and resolve its direct and transitive `tungstenite` dependencies to the same revision instead of retaining the older pins. ## What Changed - Advanced the `tokio-tungstenite` git pin to `0e5b2d73aa18dd9f0a50ee9ff199d5aef7594186`. - Advanced the `tungstenite` fork pin to `4fffad30fe373adbdcffab9545e9e9bf4f2fc19f` and adjusted the patch source so the transitive dependency resolves to that revision. - Updated `Cargo.lock` and `MODULE.bazel.lock` to match the dependency graph.
## This PR
Remote plugin analytics cannot rely only on the in-memory
installed-plugin snapshot because that snapshot is refreshed
asynchronously after startup. This PR persists the authoritative backend
identity alongside each cached remote plugin bundle so later consumers
can resolve it without a network request.
### Behavior
- Store Codex-owned remote installation metadata in an atomic
`.codex-remote-plugin-install.json` sidecar under the plugin cache root.
- Use a versioned, snake_case schema:
```json
{
"schema_version": 1,
"remote_plugin_id": "plugins~Plugin_..."
}
```
- Write the metadata during remote bundle installation.
- Backfill it when bundle sync finds an already-current cached bundle.
- Clear it when a generic/local install replaces the cache.
- Let existing uninstall and stale-cache removal delete it with the
plugin cache root.
- Reject unsupported schema versions rather than silently misreading
future formats.
This PR does not change analytics serialization or event behavior.
### Review surface
The implementation is limited to four `codex-core-plugins` files:
- `store.rs`: owns the versioned sidecar read/write/remove lifecycle.
- `remote_bundle.rs`: persists the backend ID after a remote bundle
install.
- `remote/remote_installed_plugin_sync.rs`: backfills metadata for an
already-current cached bundle.
- Tests cover the storage lifecycle and both remote write paths.
## Testing / Validation
### Automated
- `just test -p codex-core-plugins` (268 tests passed)
- `just fix -p codex-core-plugins` passes with one pre-existing
`large_enum_variant` warning in `manifest.rs`.
- Coverage verifies the exact filename and JSON schema, identity
replacement, local reinstall clearing, uninstall cleanup, remote bundle
installation, unsupported schema rejection, and installed-plugin sync
backfill.
### Live manual validation
Validated the production app-server RPC path with an isolated temporary
`CODEX_HOME` and the PR-built Codex binary. The app-server communicated
over stdio and did not bind a port.
Test plugin: `plugins~Plugin_b80dd84519148191a409cde181c9b3d6`
(`build-macos-apps@openai-curated-remote`).
1. Confirmed `plugin/read` initially reported the plugin uninstalled.
2. Installed it through `plugin/install` and confirmed version `0.1.4`
was cached.
3. Verified
`$CODEX_HOME/plugins/cache/openai-curated-remote/build-macos-apps/.codex-remote-plugin-install.json`
was created beside the `0.1.4/` bundle directory with mode `0600` and
the expected contents:
```json
{
"schema_version": 1,
"remote_plugin_id": "plugins~Plugin_b80dd84519148191a409cde181c9b3d6"
}
```
4. Deleted only the sidecar, restarted the app-server, and confirmed
installed-plugin startup sync recreated it with the same contents.
5. Uninstalled through `plugin/uninstall`, confirmed `plugin/read`
returned `installed: false`, and verified the local plugin cache root
was removed.
6. Restored the account's original uninstalled state and removed the
isolated home and copied credentials.
## Split Overview
```text
main
├── openai#27093 Debug analytics capture merged
│ └── openai#27099 Non-mutating plugin smoke merged
│ └── openai#27100 Remote install/uninstall smoke merged
└── openai#27102 Plugin telemetry metadata refactor merged
└── openai#27669 Persist remote plugin identity ← this PR
Next:
└── Final PR: add explicit local and remote IDs to plugin analytics
```
This PR is based directly on `main`; prerequisite
[openai#27102](openai#27102) has merged. The
original combined [openai#26281](openai#26281)
remains the aggregate reference until the final replacement PR is
published.
- `/usage` can now show and redeem earned usage-limit reset credits, with confirmation, retry, and refreshed availability states. (openai#28154, openai#28793) - `/plugins` now organizes remote plugins into OpenAI Curated, Workspace, and Shared with me sections, while eligible turns can recommend and install relevant plugins. (openai#26703, openai#28399, openai#28400, openai#27704, openai#28403) - Configurable rollout token budgets track usage across agent threads, provide remaining-budget reminders, and abort turns when exhausted. (openai#28746, openai#28494, openai#28707, openai#29423) - App-server clients can configure multi-agent delegation as disabled, explicit-request-only, or proactive at the thread and turn level. (openai#28685, openai#28792, openai#29324) - Added an indexed web-search mode that permits live searches while restricting direct page access to server-approved URLs. (openai#28489) - Codex can now receive scheduled UTC time reminders and query the current time directly, including through client-provided app-server clocks. (openai#28822, openai#28824, openai#28835, openai#29011) ## Bug Fixes - Restored reliable Linux TUI rendering after suspending with `Ctrl+Z` and resuming with `fg`. (openai#28342) - Exec-server processes and stdio MCP sessions now survive transient disconnects, including signed-URL refresh and retry-safe stdin writes. (openai#28512, openai#28374, openai#28546, openai#28895) - Remote environments now preserve executor-native paths, shells, `AGENTS.md` discovery, and sandbox behavior across operating systems. (openai#28146, openai#28152, openai#28958, openai#28983, openai#29099, openai#29108, openai#29113, openai#29424) - Plugin loading and installation now handle root marketplace layouts, manifest fallbacks, multiple skill paths, actionable download errors, and immediate tool refreshes. (openai#28771, openai#28789, openai#28790, openai#28863, openai#28951) - Parent agents now receive terminal subagent errors instead of seeing failed work as an empty successful completion. (openai#28375) - Goal-first threads are once again persisted and returned by `thread/list` and `thread/search`. (openai#28808) ## Chores - Reduced startup and session latency by deferring unnecessary DNS work, warming the model cache, reusing parsed plugin skills, parallelizing skill metadata reads, and skipping redundant catalog synchronization. (openai#28542, openai#28699, openai#28844, openai#29326, openai#29005) - Reduced persistent-log churn by removing per-event WebSocket payload logging and filtering duplicated telemetry records. (openai#29432, openai#29457) ## Changelog Full Changelog: openai/codex@rust-v0.141.0...rust-v0.142.0 - openai#28396 [codex] Record external agent import results @charlesgong-openai - openai#27751 [codex] expose Bedrock credential source in account/read @celia-oai - openai#28338 [codex] Compress cold active rollouts @jif-oai - openai#28368 feat: render typed envelopes for multi-agent v2 messages @jif-oai - openai#28508 [tests] Keep Apps out of generic core test harness @jif-oai - openai#28472 [codex] Clarify plugin load and runtime capability stages @xl-openai - openai#28375 core: surface terminal subagent errors to parent agents @jif-oai - openai#28542 perf(config): defer remote sandbox hostname lookup @fcoury-oai - openai#28473 path-uri: clarify invalid host path errors @anp-oai - openai#28342 fix(tui): restore TUI after suspend @fcoury-oai - openai#28354 [codex] exec-server: stream files in chunks @pakrym-oai - openai#28553 chore: side prompt @jif-oai - openai#27099 [codex-app-server-test-client & codex-app-server] Plugin Usage Analytics Smoke Test @jameswt-oai - openai#28554 fix(tui): highlight C++ module files @fcoury-oai - openai#28467 [codex] Warn clearly when code mode output is truncated @aibrahim-oai - openai#27750 [codex] Add incremental thread history changes @wiltzius-openai - openai#28154 feat(tui): add rate-limit reset redemption to /usage @jayp-oai - openai#28562 ci: run code-mode unit tests on all bazel targets @cconger - openai#27923 [codex] Route MCP file uploads through environment filesystem @pakrym-oai - openai#27100 [codex-app-server-test-client] Plugin Install/Uninstall Analytics Smoke Test @jameswt-oai - openai#28581 [codex] re-enable absolute workdir integration test @anp-oai - openai#28468 code-mode: extend test coverage to lock in cell lifecycle @cconger - openai#28587 [codex] test exec relative additional permissions @anp-oai - openai#28577 Clarify model-generated and legacy app path types @anp-oai - openai#28589 Record invariants for path migration. @anp-oai - openai#28146 app-server: preserve target-native environment cwd @anp-oai - openai#28595 Tell codex about PathUri serde compat. @anp-oai - openai#28399 [codex] [1/4] Add recommended plugin endpoint cache @adaley-openai - openai#28400 [codex] [2/4] Generalize plugin suggestion presentation @adaley-openai - openai#27704 [codex] [3/4] Activate endpoint plugin recommendations @adaley-openai - openai#28152 core: render remote environment cwd natively @anp-oai - openai#28403 [codex] [4/4] Simplify recommended plugin install schema @adaley-openai - openai#26706 PAC 1 - Add system proxy feature config surface @canvrno-oai - openai#27910 Add thread recencyAt for sidebar ordering @nornagon-openai - openai#28627 Revert "Tell codex about PathUri serde compat. (openai#28595)" @anp-oai - openai#28625 [codex] Gate remote plugin catalog by auth @xl-openai - openai#28629 [codex] core: restore absolute turn context cwd @anp-oai - openai#28642 thread-store: fix response fixture compilation @pakrym-oai - openai#28580 [codex] Support object-valued plugin MCP manifests @charlesgong-openai - openai#28599 code-mode: move cell state into library actor @cconger - openai#28471 [codex] Test code-mode variable truncation @aibrahim-oai - openai#28655 Revert thread recencyAt for sidebar ordering @pakrym-oai - openai#28638 core: remove redundant TurnContext and Prompt fields @pakrym-oai - openai#28656 [codex] Persist built-in image results reported as generating @won-openai - openai#28512 Resume exec-server sessions after disconnect @jif-oai - openai#28546 Back off registry retries during exec recovery @jif-oai - openai#28561 Add join key for MAv2 inter-agent messages @jif-oai - openai#28699 app-server: keep the model cache warm @jif-oai - openai#28705 Replace SkillsManager with SkillsService @jif-oai - openai#27965 [ez][codex-rs] Support apps._default.default_tools_approval_mode @zamoshchin-openai - openai#28359 Run fs helper through Windows sandbox wrapper @iceweasel-oai - openai#28628 [codex] Repair invalid skill frontmatter scalars @charlesgong-openai - openai#28632 Tell codex to avoid changing rollout format. @anp-oai - openai#28738 Scope command approvals by execution environment @jif-oai - openai#19047 feat: add run task identity primitives @adrian-openai - openai#28671 [codex] Restore thread recency with compatible migration history @nornagon-openai - openai#28768 Extract TUI plugin catalog rendering @canvrno-oai - openai#28389 [codex] Use compact OpenAI docs search queries @kkahadze-oai - openai#28681 unified-exec: preserve PathUri through exec-server @anp-oai - openai#28731 [codex] Track plugin install and import telemetry failures @charlesgong-openai - openai#28651 exec-server: expose environment registry payloads @viyatb-oai - openai#28771 fix(plugins): support root local marketplace plugins @caseychow-oai - openai#28791 bazel: refresh expired macOS SDK pin @anp-oai - openai#28782 [codex] trace tools build latency @owenlin0 - openai#28778 path-uri: decouple native path parsing @anp-oai - openai#28774 feat(exec-server): add Noise rendezvous environment @apanasenko-oai - openai#28812 [codex] Add optional IDs to response items @pakrym-oai - openai#28784 fix(install): support older awk checksum parsing @fcoury-oai - openai#28826 [codex] Use unique IDs for realtime-routed turns @guinness-oai - openai#27986 [codex] control automatic realtime handoff delivery @jiayuhuang-openai - openai#28836 [codex] Support assistant realtime append text @guinness-oai - openai#28374 Refresh signed exec-server URLs on reconnect @apanasenko-oai - openai#28825 Expose selecte namespaces as direct model tools @won-openai - openai#28790 [codex] Support plugin manifest path lists @charlesgong-openai - openai#28851 Record more path migration guidance for codex. @anp-oai - openai#28780 unified-exec: retain PathUri in command events @anp-oai - openai#28605 [codex] Split plugin and skill warmup tracing @mzeng-openai - openai#28608 [codex] Pass plugin namespace into skill loading @mzeng-openai - openai#28746 [codex] add rollout token budget configuration (1/N) @rka-oai - openai#28766 Add network environment ID plumbing @jif-oai - openai#28915 Avoid sandbox helper in apply_patch approval tests @jif-oai - openai#28813 Pause active goals before TUI interrupts @etraut-openai - openai#28895 Recover exec process stdin writes @jif-oai - openai#28940 Pin Windows argument lint to Windows 2022 @rka-oai - openai#28914 Scope MCP sandbox metadata to server environment @jif-oai - openai#28911 Add turn-scoped context contributions @jif-oai - openai#28808 Fix goal-first live threads missing from thread/list @etraut-openai - openai#25019 [codex] Initialize exec-server OpenTelemetry at startup @starr-openai - openai#28943 [codex] Fix Windows sandbox runtime ACL refresh @iceweasel-oai - openai#28946 Synchronize realtime notification test requests @rka-oai - openai#28822 Add Config for Time Reminders (1/n) @rka-oai - openai#28494 [codex] rollout budget implementation (2/N) @rka-oai - openai#27500 Support `openai/form` extended form elicitations @gpeal - openai#28949 [codex] Make thread store turn filter optional @wiltzius-openai - openai#28824 current time reminders impl for system clock (2/n) @rka-oai - openai#27812 [codex] Cache plugin metadata for tool suggestions @mzeng-openai - openai#28854 apply-patch: carry paths as PathUri @anp-oai - openai#28835 Add app-server current-time impl (3/n) @rka-oai - openai#26496 Make auto-review on-request prompt more proactive @maja-openai - openai#28947 [codex] Remove hardcoded app ID filters @ericning-o - openai#28959 TUI: improve unified mention selection visibility @canvrno-oai - openai#27132 Emit Trusted MCP App Identity on Tool-Call Items @martinauyeung-oai - openai#19049 feat: opt ChatGPT auth into agent identity @adrian-openai - openai#28770 [connectors] Ignore synthetic links for app accessibility @adaley-openai - openai#28863 [codex] Preserve remote plugin download status errors @xl-openai - openai#28958 core: load AGENTS.md from foreign environments @anp-oai - openai#28789 [codex] Support marketplace plugin manifest fallback @charlesgong-openai - openai#28993 [codex] Remove child AGENTS.md prompt experiment @pakrym-oai - openai#28989 core: log AGENTS.md paths as URIs @anp-oai - openai#28983 core: keep remote exec on reported shell @anp-oai - openai#28844 [codex] Reuse parsed plugin skills during session startup @xl-openai - openai#28953 core: add UUIDv7 context window IDs @pakrym-oai - openai#28951 [plugins] Refresh plugin and tool caches after remote install @adaley-openai - openai#28856 Always use AVAS for realtime WebRTC calls @bakks - openai#28814 [codex] Assign response item IDs when recording history @pakrym-oai - openai#29005 [codex] Skip curated repo sync for remote plugins @xl-openai - openai#29011 [codex] add clock current-time tool @rka-oai - openai#29012 core: assign item IDs to compacted replacement history @pakrym-oai - openai#29022 [codex] Support protected resource OAuth discovery @xl-openai - openai#28674 [1/3] core: add remote environment connection lifecycle @sayan-oai - openai#28683 [2/3] core: track starting environments in snapshots @sayan-oai - openai#29025 [3/3] app-server: configure environment connection timeout @sayan-oai - openai#28685 Add per-turn multi-agent mode @shijie-oai - openai#28792 Expose thread-level multi-agent mode @shijie-oai - openai#28707 [codex] abort turns when rollout budgets expire (token budget 3/3) @rka-oai - openai#28899 Scope network approvals by environment @jif-oai - openai#29086 Document raw response item compatibility @jif-oai - openai#28489 Add indexed web search mode @winston-openai - openai#28942 Add config toggles for orchestrator skills and MCP @jif-oai - openai#29099 Keep remote exec commands native to the executor @jif-oai - openai#29095 Use cached and live web access terminology @winston-openai - openai#29042 [codex] trace pre-sampling skill and persistence latency @rphilizaire-openai - openai#29132 chore(deps): advance tokio-tungstenite @apanasenko-oai - openai#29006 [codex] Preserve skill descriptions outside model context @charlesgong-openai - openai#29154 Allow resume and settings commands during tasks and MCP startup @etraut-openai - openai#29256 core: add context window lineage IDs @pakrym-oai - openai#29259 [codex] prototype mcp_history thread hint injection @pakrym-oai - openai#29255 [codex] add configurable token budget compaction reminder @pakrym-oai - openai#29295 [codex] simplify token budget context @pakrym-oai - openai#29108 Carry sandbox intent to remote exec servers @jif-oai - openai#29325 Test pipelined scalar exec-server requests @jif-oai - openai#29326 Parallelize skill metadata stats @jif-oai - openai#29329 Use controlled time for remote initialization timeout test @jif-oai - openai#29170 code-mode: define transport-neutral runtime types @cconger - openai#29285 code-mode: move session ownership into runtime @cconger - openai#29286 code-mode: linearize cell terminal state @cconger - openai#29287 code-mode: make session shutdown authoritative @cconger - openai#29301 [prompting] updated plan mode prompt @rhan-oai - openai#29288 code-mode: preserve dropped observation output @cconger - openai#29289 code-mode: preserve initial yield at completion @cconger - openai#28260 [codex] Add internal auto-compaction opt-out @rhan-oai - openai#29371 Propagate safety buffering events to app-server clients @fc-oai - openai#29393 chore: fix merge race (auto-compaction feature access) @sayan-oai - openai#29327 Persist session IDs across thread resume @jif-oai - openai#29324 Simplify multi-agent mode controls @jif-oai - openai#29113 Apply sandbox intent inside remote exec servers @jif-oai - openai#29001 Add workspace messages app-server API @xli-oai - openai#29432 Stop logging every Responses WebSocket event @jif-oai - openai#29073 core: refresh environment context before sampling @sayan-oai - openai#29455 fix(core): restore thread_source in x-codex-turn-metadata @owenlin0 - openai#29457 Filter noisy targets from persistent logs @jif-oai - openai#29429 remove flag for image preparation @rka-oai - openai#29143 ci: restore custom Windows runner with hermetic LLVM 0.7.9 @anp-oai - openai#27102 [codex] Centralize Plugin Analytics Metadata @jameswt-oai - openai#26703 TUI Plugin Sharing 3 - render remote plugin catalog sections @canvrno-oai - openai#29424 Report remote sandbox denials semantically @jif-oai - openai#28968 core: rename metadata -> internal_chat_message_metadata_passthrough @owenlin0 - openai#29464 [sdk/python] Stop advertising HTTP image URLs @rka-oai - openai#28793 [codex] Fix usage-limit reset copy and state @jayp-oai - openai#27982 [codex] Start the guardian child session when parent session is started @jgershen-oai - openai#29468 core: remove unused permissions cwd plumbing @bolinfest - openai#26707 PAC 2 - Add shared auth system proxy contract @canvrno-oai - openai#28991 Allow ChatGPT accounts without email @efrazer-oai - openai#29423 [codex] configure rollout budget reminder thresholds @rka-oai - openai#26678 permission profiles: expose availability to clients @viyatb-oai - openai#29476 [codex] handle request_user_input in app-server test client @celia-oai - openai#29479 fix(config): address permission profile review follow-ups @viyatb-oai - openai#29014 Honor startup custom CA bundles with managed MITM @winston-openai - openai#29480 chore: advance tungstenite fork pins @apanasenko-oai - openai#27669 [codex-core-plugins] Remote Plugin ID Persisted to File @jameswt-oai
# Conflicts: # .github/workflows/bazel.yml # codex-rs/Cargo.toml # codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json # codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json # codex-rs/app-server-protocol/schema/json/v2/GetAccountResponse.json # codex-rs/app-server-protocol/schema/typescript/ClientRequest.ts # codex-rs/app-server-protocol/schema/typescript/v2/Account.ts # codex-rs/app-server-protocol/src/protocol/v2/account.rs # codex-rs/app-server/README.md # codex-rs/cli/src/login.rs # codex-rs/codex-api/src/endpoint/responses_websocket.rs # codex-rs/core/config.schema.json # codex-rs/core/src/client_common.rs # codex-rs/core/src/config/mod.rs # codex-rs/core/src/context_manager/history.rs # codex-rs/core/src/session/mod.rs # codex-rs/core/src/session/turn.rs # codex-rs/core/src/session/turn_context.rs # codex-rs/core/src/tools/handlers/unified_exec/exec_command.rs # codex-rs/core/src/tools/router_tests.rs # codex-rs/core/src/unified_exec/mod.rs # codex-rs/core/src/unified_exec/mod_tests.rs # codex-rs/core/src/unified_exec/process_manager.rs # codex-rs/core/tests/common/responses.rs # codex-rs/core/tests/suite/client.rs # codex-rs/core/tests/suite/mod.rs # codex-rs/core/tests/suite/subagent_notifications.rs # codex-rs/login/src/auth/agent_identity.rs # codex-rs/login/src/auth/auth_tests.rs # codex-rs/login/src/auth/manager.rs # codex-rs/login/src/lib.rs # codex-rs/model-provider/src/provider.rs # codex-rs/protocol/src/account.rs # codex-rs/tui/Cargo.toml # codex-rs/tui/src/app_server_session.rs # codex-rs/tui/src/bottom_pane/slash_commands.rs # codex-rs/tui/src/chatwidget/tests.rs # codex-rs/tui/src/lib.rs
dkropachev
merged commit Jul 5, 2026
01569c9
into
sync/upstream-rust-v0.141.0-20260704
41 checks passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Merge upstream
rust-v0.142.0onto the stacked sync branch afterrust-v0.141.0.Notable merge resolutions:
auth_route_configthrough CLI/login callsitesValidation
just write-app-server-schemajust write-config-schemajust bazel-lock-updatejust bazel-lock-checkcargo build -p codex-rmcp-client --bin test_stdio_serverjust test -p codex-app-server-protocoljust test -p codex-loginjust test -p codex-model-providerjust test -p codex-corejust test -p codex-statejust test -p codex-app-serverjust test -p codex-tui(2994 passed, 1 flaky passed on retry, 4 skipped)just test -p codex-clijust test -p codex-mcp-serverjust fmtjust fix -p codex-clijust fix -p codex-mcp-serverjust fix -p codex-tuigit diff --checkrust-v0.143.0-alpha.35is intentionally excluded from the remaining sync list.