checkpoint: into wallentx/termux-target from release/0.142.0 @ 4eea1a100d76 - #248
Merged
unemployabot[bot] merged 74 commits intoJun 20, 2026
Conversation
## Why `ResponseItem` variants do not have a consistent internal ID shape: some variants carry required IDs, some carry optional IDs, and some cannot represent an ID at all. The existing fields also use inconsistent serde, TypeScript, and JSON-schema annotations. A single enum-level access path is needed before history recording can assign and retain IDs. This PR establishes that internal model only. It intentionally does not generate or serialize IDs; allocation and wire persistence are isolated in the stacked follow-up. ## What changed - Give every concrete `ResponseItem` variant an `Option<String>` ID field. - Apply the same internal-only annotations to every ID field: `#[serde(default, skip_serializing)]`, `#[ts(skip)]`, and `#[schemars(skip)]`. - Add `ResponseItem::id()` and `ResponseItem::set_id()` as the shared accessors. - Preserve IDs when history items are rewritten for truncation. - Adapt consumers that previously assumed reasoning and image-generation IDs were required. - Regenerate app-server schemas so the hidden fields are represented consistently. The serde catch-all `ResponseItem::Other` remains ID-less because it must remain a unit variant. ## Test plan - `cargo check --tests -p codex-core -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-protocol` - `just test -p codex-app-server-protocol` - `just test -p codex-api -p codex-rollout-trace -p codex-image-generation-extension` - `just test -p codex-core event_mapping`
## Why The standalone installer validates package checksums with an awk interval expression. Older mawk releases do not support that expression, so they reject valid 64-character digests and report that the release manifest is missing an entry. This affects both x64 and ARM64 systems on common Debian-derived environments. Fixes openai#24219. ## What Changed Replace the awk interval expression with an explicit length check plus rejection of non-hexadecimal characters. This preserves the existing SHA-256 validation and lowercase normalization while working with older awk implementations. ## How to Test 1. Build and run the checksum predicate with mawk 1.3.4 20121129. 2. Confirm the old interval predicate rejects a valid 64-character digest. 3. Confirm the updated predicate accepts that digest. 4. Put the old mawk binary first on PATH as awk and run scripts/install/install.sh with an isolated HOME, CODEX_HOME, and CODEX_INSTALL_DIR. 5. Confirm Codex installs successfully and the installed binary reports version 0.140.0. 6. Verify the predicate rejects wrong-length digests, non-hexadecimal digests, and entries for another asset while accepting uppercase hexadecimal digests.
## Why A durable realtime voice orchestrator can reconnect and resume through multiple fresh `Session` instances. Realtime handoffs were using the Session-local `auto-compact-N` counter as their turn identity, but that counter restarts at zero for every resumed Session. The durable thread could therefore accumulate duplicate turn IDs, violating the uniqueness assumptions made by app-server and web clients. In Codex Apps, a new delegated response stream could be attached to an older turn with the same ID, placing live output higher in history and putting turn-scoped actions at risk. Persisted rollout and reconstructed model-context order were already correct because raw response items remain append-only and chronological. This change restores unique identity for reconstructed and live turn surfaces. ## What changed - Generate a UUIDv7 specifically for each realtime-routed delegation. - Leave the existing `auto-compact-N` identity path unchanged for actual internal auto-compaction turns. - Extend the inbound realtime handoff integration test to require a UUID turn ID from `turn/started`. ## Verification - `just test -p codex-core inbound_handoff_request_starts_turn` - `just fix -p codex-core` - `just fmt`
## What Built on the realtime speech-control plumbing merged in openai#27917. - Add optional `codexResponseHandoffPrefix` to `thread/realtime/start`. - Apply that prefix only to automatic V1 commentary sent through `conversation.handoff.append`; final answers remain unprefixed. - Add opt-in `clientManagedHandoffs`. When true, core suppresses automatic response handoffs and completion output so delivery is controlled by explicit client append APIs. - Preserve existing automatic behavior by default. `codexResponsesAsItems: true` continues to select item routing when client-managed mode is disabled. ## Why Voice clients need two delivery policies: automatic background context with silent commentary instructions and fully client-owned handoffs. Phase-aware prefixing keeps routine commentary silent without suppressing the final answer, while client-managed mode lets an app decide exactly which updates to append. ## Validation - `just fmt` - `cargo test -p codex-app-server-protocol serialize_thread_realtime_start` - `RUST_MIN_STACK=16777216 cargo test -p codex-core --test all conversation_handoff_persists_across_item_done_until_turn_complete` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_client_managed_handoffs_disable_automatic_output` - `RUST_MIN_STACK=16777216 cargo test -p codex-app-server --test all webrtc_v1_final_automatic_handoff_omits_silent_prefix` - `cargo build -p codex-cli --bin codex` - Local Codex Apps compatibility check: 43 focused webview tests passed, and a live voice session routed through the source-built app-server. The explicit `RUST_MIN_STACK` avoids a macOS Tokio test-worker stack overflow seen with the default test environment.
## Why
Frontend realtime voice continuity needs to replay a tiny
previous-session overlap as actual conversation items, including
assistant text. The app-server `thread/realtime/appendText` API already
carries a role through to the Rust realtime websocket layer, but the
shared role enum only accepted `user` and `developer`.
## What Changed
- Added `assistant` to `ConversationTextRole` and regenerated the
app-server schema/type fixtures.
- Added `output_text` as a realtime conversation content type.
- Updated realtime websocket item creation so assistant appendText emits
`content: [{ type: "output_text", text }]`, while user and developer
continue to emit `input_text`.
- Updated app-server docs and tests to cover assistant appendText
alongside the existing developer role behavior.
## Validation
- `just write-app-server-schema`
- `just fmt` (first sandboxed attempt failed because `uv` could not
access `~/.cache/uv`; reran with filesystem access and passed)
- `just test -p codex-api` passed: 126/126
- `just test -p codex-app-server-protocol` passed: 239/239, including
generated JSON/TypeScript fixture checks
- `just test -p codex-app-server` was started locally but stopped per
request after unrelated local sandbox/Seatbelt failures (`sandbox-exec:
sandbox_apply: Operation not permitted`) and one missing local `codex`
binary failure; CI should be faster and more authoritative for the full
suite.
## Summary - add a provider API that supplies a fresh signed WebSocket URL for each remote exec-server connection - refresh the signed URL after disconnects and retry once when a handshake returns `401 Unauthorized` - allow `EnvironmentManager` consumers to register remote environments backed by the URL provider ## Tests - `just test -p codex-exec-server -E 'test(remote_websocket_client_refreshes_url_after_unauthorized_handshake) | test(remote_websocket_client_refreshes_url_after_disconnect)'` — 2 passed - `cargo check -p codex-core-api` — passed - `just fix -p codex-exec-server` — passed - `just fix -p codex-core-api` — no test targets; no-op - `just fmt` — passed - `just test -p codex-exec-server` — 187 passed; 32 unrelated macOS sandbox tests could not invoke nested `sandbox-exec` (`Operation not permitted`)
## Why Som tools, such as history and notes, must remain top-level when MCP deferral is enabled while staying unavailable through code-mode `exec`. ## What changed - Added `features.code_mode.direct_only_tool_namespaces`. - Classified matching MCP tools as `DirectModelOnly`. - Kept those tools top-level in `code_mode_only`. - Excluded them from `tool_search` deferral and the nested `exec` surface. - Updated the generated config schema. ## Validation - `code_mode_only_exposes_direct_model_only_mcp_namespaces` - `load_config_resolves_code_mode_config`
## Summary
Allow plugin manifests to declare `skills` as either a single path
string or an array of path strings in the core plugin loader.
## Why
Some plugin packages need to expose skills from more than one directory.
Before this change, `plugin.json` only accepted a single string for
`skills`, so manifests like this were ignored as an invalid `skills`
shape:
```json
{
"skills": ["./skills/abc", "./skills/edk"]
}
```
This keeps the existing single-string form working while adding support
for the list form. The final scope is intentionally limited to the core
plugin manifest/load path for `skills`; `apps`, file-backed
`mcpServers`, and the bundled plugin-creator assets are unchanged in
this PR.
## What changed
- Parse `skills` as either a string or an array of strings in
`plugin.json`.
- Store resolved skill paths as a list in `PluginManifestPaths`.
- Load manifest-declared skill roots in addition to the default
`./skills` root.
- Deduplicate exact duplicate skill roots before loading.
- Rely on existing skill-loader dedupe by canonical `SKILL.md` path for
overlapping roots such as `./skills` plus `./skills/abc`.
- Update plugin manifest tests to cover:
- single string `skills`
- list of string `skills`
- duplicate skill roots
- `./skills` as a manifest path
- explicit child roots like `./skills/abc` and `./skills/edk`
- overlapping-root dedupe
## Validation
- `just test -p codex-plugin`
- `just test -p codex-core-plugins`
- `just test -p codex-mcp-extension`
- `git diff --check`
Some common themes pulled out of both human and automated reviews from the last couple of days' migrations to `PathUri` and `LegacyAppPathString`.
## 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
## What changed - promote plugin config loading to an info-level `plugins_for_config` span - promote skill config loading to an info-level `skills_for_config` span - attach stable OpenTelemetry names to both spans ## Why `session_init.plugin_skill_warmup` currently combines plugin loading and skill loading, which makes cold-start traces unable to identify which phase dominates. These child spans preserve the existing aggregate while making the two costs independently visible. Context: https://openai.slack.com/archives/C0ARA9GF5D4/p1781639496496439?thread_ts=1781202444.891669&cid=C0ARA9GF5D4 ## Impact This is observability-only. It does not change plugin or skill loading behavior. ## Validation - `just test -p codex-core-skills -p codex-core-plugins` (347 passed) - `just fmt`
## 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`
…i#28746) ## What This PR defines the structured configuration contract for shared rollout token budgets (across ALL agent threads under 1 rollout). ```toml [features.rollout_budget] enabled = true limit_tokens = 100000 reminder_interval_tokens = 10000 sampling_token_weight = 1.0 prefill_token_weight = 0.1 ``` The reminder interval defaults to 10% of the rollout limit. Sampling and prefill weights default to `1.0`. ## Scope This PR only defines and validates configuration. It does not track usage, inject reminders, or stop a rollout. Accounting and reminders are implemented in the stacked follow-up openai#28494. The existing `token_budget` feature remains unchanged. `rollout_budget` has its own feature key and configuration type. ## Tests The config test verifies that the structured fields resolve into `RolloutBudgetConfig` and do not enable the existing `token_budget` feature. Local checks: - `just write-config-schema` - `just test -p codex-core load_config_resolves_rollout_budget` - `cargo check -p codex-thread-manager-sample` - `git diff --check` The full workspace test suite was not run locally.
## Why Prepare network approval scoping to distinguish execution environments without changing behavior yet. ## What changed - Add optional environment IDs to network policy requests. - Add optional network environment IDs to exec and sandbox request structs. - Thread default None values through existing construction points. - Fix stale constructor call sites that caused the CI compile failures. ## Not included - Per-environment proxy listeners. - Network approval cache or prompt behavior changes. - Ambiguous request attribution handling. Those behavior changes moved to stacked follow-up openai#28899. ## Validation - just fmt - CI will run tests and clippy
## Summary This keeps the apply_patch approval tests focused on approval behavior instead of macOS sandboxed filesystem helper startup. The changed cases still force patch approval with `UnlessTrusted`, but use `DangerFullAccess` after approval so the patch write is direct and cheap. Workspace-write and sandbox-helper behavior remain covered by the filesystem and apply_patch sandbox tests.
Fixes openai#28104. ## Summary Active `/goal` turns should leave the persisted goal paused whenever the TUI interrupts the running turn. The bug in openai#28104 showed this most visibly through `Esc`: some interrupt paths aborted the turn without updating the goal status, so the goal could remain active and continue automatically. This change makes `ChatWidget` pause an active goal before the TUI sends an interrupt from the status-row path, the pending-steer path, `Ctrl+C`, or a request-user-input overlay. The modal overlay now reports whether a key will interrupt the turn, which keeps modal `Esc` and `Ctrl+C` behavior aligned with the normal interrupt paths. ## Manual Testing Built the local CLI with `just codex --help`, then launched the local TUI with goals enabled. Started an active `/goal` turn and interrupted it with `Esc`, then resumed and repeated with `Ctrl+C`; both paths showed `Goal paused`, the interrupted-conversation message, and the `Goal paused (/goal resume)` footer. I also stopped the background terminal and exited the TUI cleanly after the run. I did not find a reliable standalone manual path to force the request-user-input overlay case, so that path is covered by the focused automated test.
## Summary Remote stdio MCP servers send tool calls by writing JSON-RPC bytes through `process/write`. When the exec-server websocket drops at the wrong time, the remote process can survive session recovery, but the stdin write can still fail back to RMCP as a transport send error. RMCP then closes the stdio MCP transport, so tools like `node_repl` are lost even though the process/session recovery path is working. This changes `process/write` to be safe to retry across exec-server recovery: - adds a required `writeId` to `process/write` - retries remote `Session::write` with the same `writeId` after reconnect - remembers accepted write ids per process so duplicate retries return `Accepted` without writing the same bytes to child stdin again - covers both the client retry path and server-side write id dedupe with tests In simple terms: ```text before: write to MCP stdin -> websocket closes -> write errors -> RMCP closes node_repl after: write to MCP stdin -> websocket closes -> reconnect -> retry same writeId server either writes once or recognizes it already did ```
## What Run the Windows argument-comment-lint job on the `windows-2022` hosted runner instead of the custom Windows runner pool. ## Why The custom pool recently moved from the Visual Studio 2022 Windows image to `windows-2025-vs2026`. Since that migration, the job fails while Bazel materializes LLVM external repository sources, before the argument lint itself runs. The same failure appears across unrelated PRs. This narrow change tests GitHub’s recommended mitigation for workloads that still require the Visual Studio 2022 image: actions/runner-images#14017 ## How Use the standard `windows-2022` runner for only the Windows argument-comment-lint matrix entry. No product code or lint behavior changes.
Scope MCP sandbox metadata to the MCP server's owning environment. Previously, `codex/sandbox-state-meta` always used the turn's primary cwd and rebuilt a legacy sandbox policy from that cwd. That can be wrong for MCP servers owned by a different execution environment. This now sends the owning environment cwd as a `file:` URI in `sandboxCwd`, keeps `permissionProfile` as the permission source of truth, and omits sandbox-state metadata when a non-default server environment is not selected for the turn. Local/default MCP servers keep the existing fallback cwd behavior. Tests: - `just fmt` - `just bazel-lock-update` - `just bazel-lock-check` - `just test -p codex-mcp` - `just test -p codex-core mcp_sandbox_cwd` - `cargo build -p codex-rmcp-client --bin test_stdio_server` - `just test -p codex-core stdio_mcp_tool_call_includes_sandbox_state_meta`
## Summary - keep context injection on a single ContextContributor trait - split context injection into thread-scoped and turn-scoped contribution methods - wire turn-scoped fragments into initial context assembly so extensions can contribute context from turn-local state
Fixes openai#28263. ## Why When a thread starts with `/goal`, the goal extension can update SQLite goal state before the thread has any user-turn rollout items. `thread/list` and `thread/search` rely on persisted listing metadata, so a goal-first live thread could be absent from app-server listings after restart even though the goal itself existed. This regressed when goal handling moved out of core: the core path wrote the goal update through the live thread rollout path, while the extension-backed app-server path only updated goal state and emitted the live notification. ## What - Add `GoalSetOutcome::thread_goal_updated_item()` so the goal extension owns the canonical `ThreadGoalUpdated` rollout item shape. - Expose a narrow `CodexThread::append_rollout_items()` helper that appends through the live thread and keeps derived SQLite metadata in sync. - When app-server sets a goal on an active live thread, persist the goal update through that live-thread path. - Add an app-server regression test that starts a live thread with `thread/goal/set` and verifies it appears in state-DB-only `thread/list`. ## Verification - `env -u CODEX_SQLITE_HOME just test -p codex-app-server goal_first_live_thread_appears_in_state_db_thread_list`
## Summary - Initialize stderr tracing and the configured OpenTelemetry provider for local and remote `codex exec-server` startup. - Instrument the local and remote server entrypoints with a root runtime span. - Keep raw Noise environment, registration, and stream identifiers out of exported spans while preserving them in local debug events. - Keep telemetry setup in a focused CLI module instead of growing the top-level command entrypoint. ## Stack - Previous: none (`openai#27058` has merged) - Next: openai#27466 ## Validation - `just test -p codex-exec-server --lib` (139 passed) - `just test -p codex-cli --test exec_server` (3 passed) - `just bazel-lock-check` - `just fix -p codex-exec-server -p codex-cli` - `just fmt` --------- Co-authored-by: Richard Lee <richardlee@openai.com>
## Why Codex Desktop repairs sandbox-user read/execute access for binaries copied to `%LOCALAPPDATA%\OpenAI\Codex\bin`, but Computer Use launches its bundled Node runtime from `%LOCALAPPDATA%\OpenAI\Codex\runtimes`. On fresh Windows installations, `CodexSandboxUsers` may therefore be unable to execute the bundled Node binary. The command runner starts, but `CreateProcessAsUserW` fails with error 5 (`ACCESS_DENIED`), causing the Node REPL to exit before Computer Use can discover applications. This is a follow-up to openai#21564, which added the original runtime `bin` ACL repair. ## What changed - Expand the Codex Desktop runtime ACL roots from only `bin` to both `bin` and `runtimes`. - Apply the existing inherited read/execute ACL repair to each runtime directory when it exists. - Rename the setup helper to reflect that it now handles multiple runtime paths. ## Validation - `cargo fmt -- --check` - `just test -p codex-windows-sandbox` was run: 113 tests passed and five environment-dependent legacy execution tests failed because `CreateRestrictedToken` returned error 87.
## What Deliver the scripted realtime notification batch after the assistant text append request instead of after the preceding developer text append request. ## Why The batch ends with an upstream error that closes the realtime conversation. When it is emitted after the developer append, it races the subsequent assistant append: the app-server RPC can acknowledge the append before its downstream WebSocket send completes, and the test intermittently observes three requests instead of four. Making the fake server wait for the assistant append before emitting the terminal batch establishes the ordering the test asserts without sleeps or production-code changes. ## Validation - `git diff --check` - CI (the failure is timing-dependent and most reproducible in the Windows Bazel shard)
## Summary Example: > [features.current_time_reminder] enabled = true reminder_interval_model_requests = 1 clock_source = "system" ## Testing - `just test -p codex-core varlatency` - `just test -p codex-core lock_contains_prompts_and_materializes_features` - `just fix -p codex-core -p codex-config -p codex-features`
## Stack Depends on openai#28746. This PR implements shared rollout-budget accounting and model-visible reminders using the configuration defined in openai#28746. # Description / Main changes to Core: `AgentControl` will now be the area where "rollout level" features & accounting will have to live. It is incorrectly named for this responsibility, but I think it can hold all the necessary shared state & features (rollout token budget, mutliple thread interruption responsibilitym etc) In this PR, we have one "token ledger" that each thread will subtract from when sampling. The "charge" will occur when response.completed() is done and the calculation will be done on the responses api usage carrier. The calculation will weigh sampling and pre-fill tokens as specified. Every time the budget crosses the configured reminder threshold, a developer message is appended before the thread's next request This remaining budget will _always_ be restated/reminded after a compaction event. Expiration and fan-out interruption will be in the stacked follow-up (and also live in Agent Control). ## Reminders "You have weighted {session_tokens_left} tokens left in the shared session token budget." The first request in each thread context receives the current remainder. Later reminders are emitted after aggregate weighted usage crosses a configured interval. If several intervals are crossed before a thread sends another request, Core inserts one reminder with the latest remainder. Compaction response usage is charged before the next context starts. The next reminder is appended after the compaction summary, leaving the initial context content stable. ## Tests Integration coverage verifies: - weighted output and non-cached input accounting - initial and periodic reminders - shared accounting between a root and sub-agent - post-compaction remainder and message placement Local checks: - `just fmt` - `just test -p codex-core rollout_budget` - `git diff --check` The full workspace test suite was not run locally.
# Summary Allow App Server clients to opt into `openai/form` MCP elicitations.
Make `ListItemsParams::turn_id` optional so callers can list persisted items across an entire thread or narrow the result to one turn. This aligns the thread-store API and documentation with thread-wide item listing while preserving the optional turn-filter behavior for implementations.
…#28824) Stacked on openai#28822. ## Summary - add a host-injectable current-time provider with a built-in system implementation - record UTC developer reminders in history immediately before due model requests - keep cadence state per session and force a refresh after compaction This does NOT include the app server client <-> server clock logic. This PR is only for the reminder message & system clock that will be used in prod. ## Testing - `just test -p codex-core varlatency_` - `just clippy -p codex-core -p codex-app-server -p codex-mcp-server -p codex-thread-manager-sample` - `just fmt`
## Why `built_tools` runs for every sampling request, and local plugin discovery was repeatedly rereading plugin manifests, skills, MCP configuration, and app declarations to build the same tool-suggest metadata. That source-derived metadata is stable until the existing plugin manager reloads its cache. Runtime eligibility still needs to reflect the current install, disable, policy, app-overlap, and authentication state. ## What changed - Add a bounded, in-memory tool-suggest metadata cache owned by `PluginsManager`. - Key cached metadata by plugin identity and source, while applying authentication routing each time the metadata is projected. - Invalidate the metadata alongside the existing loaded-plugin cache, including its normal configuration, marketplace refresh, and remote-installed-plugin invalidation paths. - Guard against an in-flight load repopulating stale metadata after invalidation. - Keep marketplace membership and all runtime eligibility filtering live rather than introducing a separate catalog or revision model. ## Impact Repeated sampling requests reuse already-loaded plugin capability metadata while retaining the existing plugin-manager lifecycle as the single freshness boundary. ## Validation - `just test -p codex-core-plugins` — 252 passed - Added focused coverage for cache invalidation and authentication reprojection.
## Summary - skip the legacy `openai-curated` startup repository sync when remote plugins are enabled and the current auth uses the Codex backend - keep the curated sync for API-key, Bedrock, and unauthenticated sessions that fall back to the local marketplace - preserve configured marketplace upgrades and all remote plugin startup warmups ## Why The remote catalog owns plugin discovery and materialization only when it is usable for the current auth mode. Starting the legacy curated repository sync in that case performs an unnecessary Git/HTTP/archive download and cache refresh. API-key and Bedrock sessions still require the local curated marketplace, so they must continue syncing it. ## User impact Codex startup no longer downloads or refreshes the local `openai-curated` snapshot when the remote catalog is active. Behavior is unchanged for auth modes that use the local curated marketplace. ## Validation - `just fmt` - `git diff --check` Rust tests were not run per the repository's local verification policy for this narrow conditional change.
## Summary
- expose `clock.curr_time` when current-time reminders are enabled
- query the session's configured time provider with the calling thread
id
- return the existing UTC reminder text for direct model calls
- return `{ "current_time": "YYYY-MM-DD HH:MM:SS UTC" }` in Code Mode
Clock lookup failures remain fatal, matching pre-inference reminder
behavior.
## Testing
- `just test -p codex-core current_time_tool_returns_the_latest_time`
- `just test -p codex-core
code_mode_current_time_returns_structured_result`
- `just fix -p codex-core`
## Why Remote v2 compaction can return replacement-history items without IDs. Because replacement history is installed directly, those items bypass normal history preparation and remain ID-less in later Responses requests even when the `item_ids` feature is enabled. ## What changed - Pass the active `TurnContext` into `replace_compacted_history`. - When `item_ids` is enabled, assign missing IDs before installing and persisting replacement history. - Rebuild `CompactedItem` from the prepared history so live and persisted replacement histories match. - Add integration coverage requiring IDs on every ID-capable input item in the initial, remote v2 compaction, and post-compaction requests. ## Test plan - `just test -p codex-core response_item_ids` - `just test -p codex-core websocket_v2_test_codex_shell_chain` - `just test -p codex-core remote_compaction_parity_pre_turn_auto` - `just test -p codex-app-server thread_inject_items_adds_raw_response_items_to_thread_history`
## Why Plugin-install preflight and the actual OAuth login flow used different discovery implementations. Preflight had a Codex-specific implementation that only queried authorization-server metadata on the MCP host, while login already used the upstream `rmcp` Rust MCP SDK. As a result, servers that advertise a separate authorization server through RFC 9728 Protected Resource Metadata were classified as OAuth-unsupported during plugin installation, so login was skipped. ## What changed - delegate plugin-install OAuth discovery to `rmcp::transport::AuthorizationManager`, the same implementation used by the login flow - let `rmcp` follow Protected Resource Metadata first and perform direct RFC 8414 authorization-server discovery when protected-resource discovery does not yield usable metadata - retain Codex's existing HTTP headers, timeout, `no_proxy` behavior, and scope normalization around that discovery - add unit coverage and a pure-MCP plugin-install integration test that proves the protected-resource path reaches OAuth client registration This only changes shared MCP OAuth discovery. App declarations and `appsNeedingAuth` behavior are unchanged. ## Verification - `just test -p codex-rmcp-client auth_status` - `just test -p codex-app-server plugin_install_starts_mcp_oauth` - real plugin-install smoke test with an isolated `CODEX_HOME`: both DigitalOcean MCP servers started OAuth callback listeners, while Linear continued to start its existing direct-discovery OAuth flow
## Why Remote environments can be registered before their exec-server is first used. Starting the connection at registration time uses that startup window, while sharing one startup result prevents background work and capability calls from opening competing connections. Keep initial startup simple: each environment makes one connection attempt using its configured transport timeout. A failed initial attempt is final for that environment, while an environment that disconnects after connecting can still recover on a later operation. ## What changed - Start URL and Noise environments in the background when they are added to `EnvironmentManager`. Provider snapshots are fully validated before connection work begins. - Share one initial connection attempt and its saved result across metadata, process, filesystem, and HTTP callers. - Keep configured stdio environments lazy until first use so registration does not launch a process. - Tie background startup work to the environment lifetime so replacing or dropping an environment cancels unfinished work. - After an established client disconnects, share one fresh connection attempt across concurrent callers. A failed attempt fails the current operation without permanently preventing a later attempt. - Store the shared lazy client directly on `Environment` and expose small methods for starting, observing, and awaiting startup. ## Test plan - `just test -p codex-exec-server` - `just test -p codex-app-server turn_start_resolves_sticky_thread_local_environment_and_turn_overrides`
## Why Remote environments may still be resolving when Codex creates a session or turn. Waiting for the existing all-or-nothing environment snapshot can hold startup until the selected environment is usable. Behind the default-off `deferred_executor` feature, let callers take a useful snapshot immediately: completed environments remain available normally, while unfinished environments are reported without blocking startup. With the feature disabled, snapshots preserve the existing blocking behavior. Depends on openai#28674. ## What changed - Store one ordered list of selected environments in `ThreadEnvironments`. Each selection owns one shared resolution that produces its complete `TurnEnvironment`. - Start new resolutions in the background with `remote_handle()`, allowing snapshots and the future wait tool to share the same result while cancellation follows the retained handles. - Make `snapshot()` a read-only operation: nonblocking snapshots collect completed resolutions and retain handles for unfinished ones, while blocking snapshots await every resolution. - Replace completed failed resolutions from the current manager entry and log when failed environments are omitted. - Return attached and starting environments as a point-in-time view, and count starting environments when deciding whether a snapshot is local-only. - Keep existing consumers attached-only. `to_selections()` derives from attached environments, so child threads do not inherit an environment that is still starting. ## Test plan - `just test -p codex-core environment_selection` - `just test -p codex-core deferred_executor_reaches_model_before_remote_environment_is_ready` ## Landing note Keep `deferred_executor` disabled for slow-starting executors until configurable `environment/add` connection timeouts and caller support land. When enabled, an environment that attaches after session startup may remain absent from environment-derived model context, tools, instructions, skills, and related state until follow-up refresh work lands.
) ## Why Remote environments registered through `environment/add` currently use the fixed 10-second WebSocket connection timeout. Slow-starting executors need a caller-selected connection window, but this should not add retry policy or couple exec-server behavior to Core’s `deferred_executor` feature. Make the timeout an optional part of the existing experimental request. Existing clients continue using the current default, while callers that know an executor may take longer can request a larger window explicitly. Depends on openai#28683. ## What changed - Add optional `connectTimeoutMs` to `EnvironmentAddParams` and document it in the app-server README. - Pass the optional timeout through `EnvironmentRequestProcessor` into one `EnvironmentManager::upsert_environment()` path; the manager applies the existing default when it is omitted. - Preserve the existing single-attempt lifecycle. The configured value controls WebSocket connection and handshake time for both initial connection and later reconnects; initialization retains its separate timeout. - Add an app-server integration test that sends the real JSON-RPC request and verifies a stalled handshake observes the requested timeout. ## Test plan - `just test -p codex-app-server-protocol` - `just test -p codex-exec-server` - `just test -p codex-app-server environment_add_applies_connect_timeout` ## Rollout This is additive and does not enable `deferred_executor`. Callers should send a non-default timeout only after a compatible app-server is deployed; omitted or `null` values retain the existing 10-second default.
## Why Multi-agent v2 currently carries an explicit-request-only delegation rule in its static usage hint. That provides a safe default, but it prevents clients from selecting proactive delegation per turn without changing static guidance or rewriting prior model context. This change makes delegation mode a session selection that can be updated through `turn/start`, while deriving the effective model-visible mode separately for each turn. Eligible multi-agent v2 turns remain explicit-request-only unless proactive mode is both selected and enabled. ## What changed - Add the experimental `turn/start.multiAgentMode` parameter with `explicitRequestOnly` and `proactive` values. Omission retains the loaded session's current optional selection. - Add the default-off `features.multi_agent_mode` feature gate. Eligible multi-agent v2 turns use the selected mode when enabled; an unset selection or disabled gate resolves to `explicitRequestOnly`. - Treat mode prompting as inapplicable for multi-agent v1 and other unsupported session configurations, producing no multi-agent mode developer message rather than rejecting the turn. - Move the explicit-request-only rule out of the static v2 usage hint and into a bounded, tagged developer context fragment. - Emit the effective mode in initial context and only when that effective mode changes on later turns. - Persist the effective mode in `TurnContextItem` as the durable baseline for resume and context-update comparisons. Historical rollout items are not rewritten. Later mode developer messages establish the current rule incrementally. ## Not covered - Initial selection through `thread/start` and selected-mode reporting from thread lifecycle/settings APIs; those are isolated in the stacked openai#28792. - A TUI control or slash command for selecting the mode. - Persisting a preferred mode to `config.toml`; selection remains session/turn scoped. - Changes to multi-agent concurrency limits, tool availability, or model catalog capability declarations. - Rewriting historical rollout prompt items. Cold resume restores the latest persisted effective mode when available while leaving historical developer messages intact. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-core multi_agent_mode` - Focused app-server coverage verifies that `turn/start.multiAgentMode` produces proactive developer instructions for an eligible v2 turn. ## Stack Followed by openai#28792, which adds `thread/start` initialization and lifecycle/settings observability.
## Why Once multi-agent mode can be selected per turn, clients also need to choose the initial selection when creating a thread and observe that selection through lifecycle and settings APIs. The selected value is intentionally distinct from the effective model-visible value: no client selection is represented as `null`, even though an eligible multi-agent v2 turn derives `explicitRequestOnly` as its effective default. ## What changed - Add the optional experimental `thread/start.multiAgentMode` parameter and pass it through thread creation. - Preserve an omitted initial value as an unset selection rather than eagerly storing `explicitRequestOnly`. - Apply an explicit `thread/start` selection to the first turn through the session configuration established at thread creation. - Restore the latest persisted effective mode as the selected baseline on cold resume when rollout history contains one. - Inherit the optional selected mode from a loaded parent when creating related runtime threads. - Return the current selected `multiAgentMode` from `thread/start`, `thread/resume`, `thread/fork`, and thread settings, using `null` when no mode is selected. - Keep lifecycle reporting independent from model capability and feature eligibility; core turn construction remains responsible for calculating and persisting the effective mode. ## Not covered - Clearing an existing loaded-session selection back to unset through `turn/start`; omitted or `null` currently retains the session's selection. - A TUI control, slash command, or `config.toml` preference. ## Verification - `CARGO_INCREMENTAL=0 just test -p codex-app-server-protocol` - `CARGO_INCREMENTAL=0 just test -p codex-app-server multi_agent_mode` The focused app-server coverage verifies explicit `thread/start` initialization, first-turn prompting, nullable reporting for an omitted selection, and retention of selections that are not currently runtime-eligible. ## Stack Stacked on openai#28685. This PR contains only the thread initialization and lifecycle/settings API layer.
…penai#28707) ## Stack Depends on openai#28494. ## Description This PR propagates shared rollout-budget exhaustion through the existing `CodexErr::TurnAborted` task result. Each thread records its model usage against the same ledger. Once the ledger is exhausted, that usage update and all later usage updates return `TurnAborted`. The task wrapper emits the normal aborted-turn event and lifecycle instead of completing the turn. This is intentionally a soft boundary: there is no cross-thread `Op::Interrupt` fanout. An in-flight thread can finish its current response before it observes the exhausted ledger, but every thread aborts at its next usage-accounting boundary. ## Tests The integration coverage verifies that: - the response that exhausts the budget aborts its turn; - a later response also aborts because the shared ledger remains exhausted; and - sub-agent usage draws from the same shared ledger; and - local and remote-v2 compaction abort without retrying or emitting a generic error. Local checks: - `just test -p codex-core exhausted_budget_aborts_current_and_later_turns` - `just test -p codex-core subagent_usage_draws_from_the_shared_budget` - `just test -p codex-core abort_regular_task_emits_marker_before_turn_aborted` - `just test -p codex-core compaction_budget_exhaustion_aborts_without_error_or_retry` - `just fix -p codex-core` - `just fmt` - `git diff --check` The full workspace test suite was not run locally.
Stacked on openai#28766. ## Why Network approvals are environment-scoped: allowing a host in one execution environment should not allow the same host in another environment. openai#28766 adds the inert IDs and constructor plumbing. This PR applies the behavior on top. ## What changed - Route managed network traffic through per-environment HTTP and SOCKS proxy listeners. - Stamp HTTP, HTTPS CONNECT, SOCKS TCP, and SOCKS UDP policy requests with the source environment at the proxy boundary. - Carry the selected execution environment through shell, unified exec, zsh-fork, and sandbox transform paths. - Include the environment in pending, approved-for-session, and denied-for-session network approval cache keys. - Include the environment in approval IDs and approval prompts. - Preserve legacy fallback for unattributed requests, but deny when active-call attribution is ambiguous. - Fail closed if an environment-specific proxy endpoint cannot be prepared. ## Validation - just fmt - CI will run tests and clippy
Adds a short AGENTS.md note asking reviewers to treat raw response item events as compatibility-sensitive, even while they are experimental. This keeps future app-server changes from accidentally breaking Codex Cloud consumers of raw response item events.
## Summary - Add `web_search = "indexed"` alongside `disabled`, `cached`, and `live`. - Use that same resolved mode for both hosted and standalone web search. - For hosted search, send `index_gated_web_access: true` with external web access enabled only when `indexed` is selected. - For standalone search, preserve the existing boolean wire values for existing modes (`cached` maps to `false` and `live` to `true`) and send `"indexed"` only for `indexed`; `disabled` keeps the tool unavailable. - Carry the mode through managed configuration requirements and generated schemas. ## Why Indexed search provides a middle ground between cached-only search and unrestricted live page fetching. Search queries can remain live while direct page fetches are limited to URLs admitted by the server. The existing `web_search` setting remains the single source of truth, so hosted and standalone executors cannot drift into different access modes. Without an explicit `indexed` selection, the existing model-visible tool and request shapes are unchanged. ```toml web_search = "indexed" [features] standalone_web_search = true ``` ## Validation - `just fmt` - `just test -p codex-api` (`126 passed`) - `just test -p codex-web-search-extension` (`7 passed`) - `just test -p codex-core code_mode_can_call_indexed_standalone_web_search` (`1 passed`) - Focused configuration, hosted request, standalone request, and managed-requirement coverage is included in the PR; remaining suites run in CI. The full workspace test suite was not run locally.
## Why Orchestrator-provided skills and Codex Apps MCP tools add model-visible instructions, resources, and tools beyond the local workspace. Hosts need config-level switches to disable those orchestrator-owned surfaces independently, without disabling regular skills or regular MCP servers. ## What changed - Adds `[orchestrator.skills].enabled` and `[orchestrator.mcp].enabled` config entries, both defaulting to `true`. - Includes the new settings in `config.schema.json` and in the config lock so resolved thread configuration preserves the same orchestrator exposure decisions. - Threads `orchestrator.skills.enabled` through the app-server skills extension so disabled orchestrator skills do not expose the `skills` namespace or inject orchestrator skill context. - Gates Codex Apps MCP exposure, app instructions, and app auth eligibility on `orchestrator.mcp.enabled` while leaving non-Codex-Apps MCP tools available. - Updates the thread-manager sample config to disable both orchestrator-owned surfaces. ## Verification - Added config parsing, loading, defaulting, and schema coverage for the new settings. - Added MCP exposure coverage that `orchestrator.mcp.enabled = false` removes Codex Apps tools while preserving regular MCP tools. - Added app-server coverage that `orchestrator.skills.enabled = false` prevents orchestrator skill tools, prompts, and resource reads from reaching the model turn.
## Summary
- Remote unified-exec now sends the original command argv to exec-server
instead of materializing the orchestrator's sandbox wrapper first.
- Local unified-exec keeps the existing sandbox path unchanged.
- Add a focused regression test for a macOS-selected sandbox producing
plain remote argv.
Before:
macOS orchestrator -> /usr/bin/sandbox-exec ... -> Linux exec-server
After:
macOS orchestrator -> /bin/bash -lc pwd -> Linux exec-server
This is intentionally only the first cleanup step. Remote unified-exec
commands are sent without a process sandbox until the targeted
follow-ups below land. For the macOS-to-Linux path this is not a
practical regression: the old sandboxed attempt failed before process
launch because the Linux executor could not spawn macOS sandbox paths.
## Targeted follow-ups
1. Carry sandbox intent separately from argv.
- Add an optional sandbox field to exec-server process params.
- Reuse FileSystemSandboxContext rather than introducing a new sandbox
model.
- Carry managed-network enforcement as one explicit bit.
- Keep argv plain.
2. Apply that intent inside exec-server.
- Add a small process-start adapter before LocalProcess::exec.
- Reuse the existing codex-sandboxing SandboxManager and exec-server
runtime paths.
- Follow the same shape already used by exec-server filesystem
sandboxing.
- Do not duplicate or move the sandbox implementations.
3. Report the sandbox actually used.
- Return the executor-selected sandbox type from process/start.
- Use that value in core for sandbox-denial detection and retry
behavior.
## End state
The orchestrator sends plain commands plus portable sandbox intent. The
executor chooses and applies its own native sandbox: Linux executors use
Linux sandboxing, macOS executors use Seatbelt, and Windows executors
use Windows sandboxing. Concrete wrapper argv, helper paths, and sandbox
env markers never cross the executor boundary.
## Summary - Rename the string-valued external web access enum variants from `Offline` / `Online` to `Cached` / `Live`. - Align the transport names with the existing `web_search = "cached"` / `"live"` configuration vocabulary. Existing behavior is unchanged: `WebSearchMode::Cached` and `WebSearchMode::Live` continue to send the backward-compatible boolean values `false` and `true`; `Indexed` remains the only mode currently sent as a string. ## Validation - `just fmt` - `just test -p codex-api` (127 passed)
## Why Responses websocket connections use `tokio-tungstenite`. When DNS returns an unusable native IPv6 address before a working IPv4 address, sequential dialing can consume Codex's outer websocket timeout before reaching IPv4. The merged fork change adds Happy Eyeballs-style alternate-family racing so websocket dialing matches the recovery behavior already present in the HTTP path. ## What Changed Advance the workspace `tokio-tungstenite` patch from `132f5b39` to merged commit `e5e64b86`, and update the matching lockfile source. The new revision comes from [openai-oss-forks/tokio-tungstenite#1](openai-oss-forks/tokio-tungstenite#1).
## Why Skill descriptions are used in model-visible lists: the default available-skills catalog that supports implicit selection, and the on-demand `skills.list` tool response used to discover orchestrator skills. A single overlong description should not consume a disproportionate share of either list. Enforcing the 1024-character limit while loading or migrating skills is the wrong boundary: it rejects otherwise-valid skills and discards metadata that non-model consumers and full skill reads may need. Skill metadata and `SKILL.md` content should remain intact; the cap belongs at model-visible list rendering boundaries. ## What changed - Preserve full `description` and `metadata.short-description` values when loading skills. - Preserve full external-agent command descriptions during `source-command-*` migration instead of skipping commands solely because their descriptions exceed 1024 characters. - Preserve full normalized orchestrator descriptions in the underlying skills catalog. - Cap each description at 1024 Unicode characters when rendering the default available-skills context in `codex-core-skills` and `codex-skills-extension`. - Apply the same cap when serializing descriptions in the model-visible `skills.list` response. - Render truncated descriptions as 1021 original characters plus `...`. - Leave explicit `$skill` injection, `skills.read`, underlying metadata, and on-disk `SKILL.md` files unchanged and full-fidelity. ## Implicit skill selection Codex injects a bounded catalog containing each implicitly allowed skill's name, description, and source locator, together with instructions to use a skill when the task clearly matches its description. The model makes that semantic choice; after selecting a skill, it reads the full `SKILL.md` from its filesystem or provider resource. Explicit `$skill` mentions remain a separate path that injects the full skill instructions. For orchestrator skills, `skills.list` provides bounded discovery metadata before `skills.read` returns the full selected resource. ## Test plan - `just test -p codex-core-skills` - `just test -p codex-skills-extension` - `just test -p codex-external-agent-migration` The focused regressions verify that overlong metadata is preserved at load and migration boundaries while default available-skills rendering and `skills.list` output produce the 1021-character prefix plus `...`.
# Conflicts: # .github/workflows/rust-ci.yml # codex-rs/core/src/compact_remote_v2.rs # codex-rs/core/src/exec.rs # codex-rs/core/src/rollout_budget.rs # codex-rs/core/src/session/mod.rs # codex-rs/core/src/session/rollout_budget.rs # codex-rs/core/src/tools/handlers/shell/shell_command.rs # codex-rs/core/src/tools/runtimes/shell/unix_escalation.rs # codex-rs/core/src/tools/sandboxing.rs # codex-rs/core/tests/suite/mod.rs # codex-rs/core/tests/suite/rollout_budget.rs # codex-rs/network-proxy/src/http_proxy.rs # codex-rs/network-proxy/src/socks5.rs # codex-rs/protocol/src/config_types.rs
Termux rust-v0.142.0-alpha.7
…nt/wallentx_termux-target_from_release_0.142.0_4eea1a100d76
unemployabot
Bot
deleted the
checkpoint/wallentx_termux-target_from_release_0.142.0_4eea1a100d76
branch
June 20, 2026 04:37
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.
Termux release checkpoint
release/0.142.04eea1a100d76a3b0b698a6e06ccd691ce000b161wallentx/termux-targetThis PR carries release-train conflict fixes and follow-up changes back into the reusable Termux patch branch.
Release-only workflow files and metadata under
.githubwere restored to the destination branch versions before opening this PR.