## Why
Voice failure metrics lacked cause and lifecycle phase, and session durations were recorded before the final outcome was known. A failed control send could also overwrite a more specific WebRTC error.
## What changed
- Tag `codex.voice.session.failure` with bounded `cause` and `phase` values, recording at most one failure per session.
- Capture duration when stopping and emit `codex.voice.session.duration` at cleanup with a `success` or `failure` outcome.
- Carry typed WebRTC errors into the TUI, preserve existing errors when control sends fail, and avoid duplicate errors after startup failure.
- Record app-server disconnect failures for background voice sessions as well as the visible session.
## Testing
Add coverage for terminal outcome and failure metric attributes, preservation of specific startup and audio-session errors, and startup failures without duplicate control-channel errors.
GitOrigin-RevId: 5aeda6e766093e3fce7206560aa83b6f7770dddb
## What changed
Add the experimental `thread/readState/changed` notification with `threadId` and the committed `readState` receipt. Send it to existing thread subscribers when terminal activity updates read state or a revert clears a removed unread position. Emit terminal read-state updates before `turn/completed` so completion remains the last notification for that result.
Expose the notification in generated JSON schemas, TypeScript types, and Python SDK models. Document experimental capability gating, subscription lifetime, notification opt-out, and refreshing receipts when concurrent responses disagree.
## Testing
Extend the read-state integration test to assert that the notification receipt matches the receipt returned by `thread/read` after terminal activity.
GitOrigin-RevId: 28935352a881b7a5e2e7f629173c3b2061bd7941
## Why
A review can fail before the UI receives the event that enters review mode. Failed-turn completion also needs to preserve the running indicator when a queued `/review` has already been submitted and is awaiting startup.
## What changed
- Emit the review-entry lifecycle before starting the review task, after aborting existing tasks and clearing connector selection.
- When a live failed-turn completion repeats an already handled error, refresh task state only if no user turn is pending startup, and continue processing queued input.
## Testing
Add regression tests for lifecycle ordering on a server-overload response and for preserving the running indicator while a queued review awaits startup after a failed turn.
GitOrigin-RevId: 0f91d3d1a1a983542c54c2686630de9c232321b1
## What changed
Define `thread/prediction/request` with `threadId` and `sourceTurnId`, and `thread/prediction/updated` with a `completed` result containing optional text or a `failed` result.
Update generated JSON schemas, TypeScript types, and Python notification models. Route prediction notifications to their thread in the TUI and ignore them in the chat widget.
The request remains unimplemented and returns a method-not-found error.
GitOrigin-RevId: 09922f583d5c56f808d018121c651dcd92734515
## What changed
Allow users with an active session to start MCP OAuth sign-in through `/mcp login <name>`. Request login through the app server, open the authorization URL in the browser, and display success or failure in the originating thread.
Guard overlapping start requests and track login attempts per server so stale retry completions do not overwrite current results. Skip opening the browser when the attempt has already completed, and retain results across thread switches and session refreshes.
## Testing
Add command dispatch coverage and regression tests for overlapping starts, stale retry completions, rejected starts, independent server logins, and result retention across thread switches and session refreshes.
GitOrigin-RevId: aeec2dbee566660f9aa26ef23039196ef3ca49d6
## What changed
Remove automatic next-message generation after successful turns, suggestion rendering in the composer, and the associated Tab acceptance and Escape dismissal handling. Remove the `tui.prompt_suggestions` configuration option and its schema entry, along with suggestion-specific tests and snapshots.
GitOrigin-RevId: 63bf6f2ca85da6ece502c86e2a805d000bf34210
## What changed
Connect the existing composer suggestion UI to generation when `tui.prompt_suggestions` is enabled. Request suggestions after successful live turns with known reasoning-summary settings, skipping replayed or duplicate completions and turns with queued follow-ups.
Generate suggestions in hidden, ephemeral forks of the completed turn, preserving conversation context and exposed live settings. Keep fork events out of the visible conversation and reject requests for user interaction. Cancel generation after 30 seconds, interrupt unsuccessful requests, and unsubscribe temporary threads.
Clear suggestions on new submissions, thread changes, reconnects, and feature disablement. Let Escape dismiss suggestions before entering backtrack mode.
## Testing
Add tests for live-turn eligibility and deduplication, preserved request prefixes and settings, hidden fork behavior, startup cancellation, and timeout cleanup.
GitOrigin-RevId: 92ddf3b06448adcc6f4330914cbd8102bff98046
## Why
An async question notification can outlive its unanswered question and suppress the lower-priority turn completion notification.
## What changed
Clear pending `AsyncQuestion` notifications when collecting question drafts on completion, interruption, or failure, including the error-handling path. Completed turns can then queue their completion notification.
## Testing
Add regression coverage for all three turn outcomes and assertions for error handling and completion after dropped message deltas.
GitOrigin-RevId: 647b2b37acced431fc98fd4f5334c8973a0be241
## What changed
Clear pending asynchronous questions when a live turn completes, is interrupted, or fails, and append nonblank typed answers to the main composer in question order without submitting them. Preserve existing composer content and input restored after interruption, and retain large answers as paste placeholders.
Cancel history previews and pending Vim commands during recovery while preserving undo grouping and dot-repeat behavior. Skip recovery during replay and keep input cleared after a misalignment policy violation.
## Testing
Add regression tests and snapshots for open and collapsed drafts, buffered typing, answer ordering, repeated completion notifications, large pastes, interrupted queued input, and Vim undo/redo behavior. Update coverage for terminal errors and realtime question expiration.
GitOrigin-RevId: fec109fe8aecb0735a3a5410fbb063b5c5c6e9a1
## Why
Clients with a gateway sign-in UI need to control when browser authorization starts and inspect credential readiness before making authenticated requests.
## What changed
- Add `initialize.capabilities.explicitGatewayOauth` to require explicit login while allowing existing credentials to refresh. Preserve automatic authorization for clients that omit the capability, and prevent later connections from undoing explicit opt-in.
- Add `account/gatewayOAuth/read`, `account/gatewayOAuth/login`, and `account/gatewayOAuth/cancel`, plus `account/gatewayOAuth/changed` notifications. Send the authorization URL only to the initiating connection and cancel its login on disconnect.
- Check gateway authentication before returning cached results from `model/list`, with restart guidance when provider settings have changed.
- Update protocol schemas, TypeScript and Python bindings, and document capability probing and the sign-in lifecycle.
## Testing
Add tests for passive readiness reads, credential reuse after login, token exchange failures, cancellation and immediate retry, connection ownership, legacy versus explicit login, and model-list authentication checks.
GitOrigin-RevId: a26e116a62c9f3db84dc238a40b7f4e816eb1594
## What changed
- Render a rotating Codex logo in unused space above the composer on fresh conversations, without moving content or the cursor.
- Fade and pause the logo while drafting or unfocused, hide it on alternate views, and dismiss it after submission or conversation activity. Respect disabled animations and stop after three rotations with a fade out.
- Replace the onboarding ASCII frame variants with the shared logo renderer, retaining a faded logo after the animation ends and allowing the existing shortcut to replay it.
## Testing
Add rendering and integration tests for logo placement, visibility, pause/resume timing, completion, and preservation of the draft, cursor, header, and footer. Add snapshots for fresh conversations and the onboarding welcome layout.
GitOrigin-RevId: b98c7dd10acea3ef25d6c1495ed22c24202d6280
## Why
Keep diagnostics accessible without adding warning rows to the live conversation or changing the composer layout.
## What changed
- Show a deduplicated warning count in the passive footer, yielding to interactive hints.
- Open warning details with `F2`, `/warnings`, or a click on the warning notice. Support navigation, scrolling, and copying individual diagnostics while preserving the draft.
- Retain startup, runtime, MCP, and deprecation diagnostics in the full transcript. Group MCP details by server and preserve warnings during replay.
- Respect existing custom bindings and chord prefixes when enabling `F2`.
- Show an immediate explanation when `/pets` is unavailable.
## Testing
Add regression tests and snapshots for warning counts, draft preservation, viewer navigation and copying, narrow layouts, terminal scrollback, and keybinding conflicts.
GitOrigin-RevId: 2bc586430da60347cfbaa5bf128bc48f7f9dc777
## Why
The TUI ignored dynamic tool items, and replayed tool activity could differ from live output. Concurrent tool completion also needs to preserve transcript order when writing to terminal scrollback.
## What changed
- Retain dynamic tool rows, update them when calls finish out of order, and mark unfinished calls interrupted when a turn ends.
- Queue terminal output behind unfinished dynamic tools and drain settled rows in bounded batches. Preserve queued output through stream consolidation, resize, and rollback without emitting it twice.
- Align replayed file changes, MCP results, and exploration groups with live rendering. Keep hidden reasoning and terminal interaction details within compatible activity groups, and preserve finalized plan fragments.
- Ignore stale history-page responses, bound turn metadata requests to missing turns, and insert older history after session headers. Keep hidden review prompts as activity-group boundaries.
## Testing
Add regression tests and snapshots for out-of-order tool completion, interruption, ordered scrollback emission, rollback, deferred usage updates, replay consistency, overlapping history, and repeated hidden prompts.
GitOrigin-RevId: a3636cfcf4c9c43a0a5bc52a842b80a7834f1409
## Why
Retained voice captions were appended after replayed history, placing earlier speech after later typed turns when switching back to a thread.
## What changed
Anchor completed captions to the next live turn and restore them before that turn during replay. Handle buffered item, delta, and completion events even when the turn-start event has been evicted. Restore remaining captions at the end of replay.
## Testing
Extend regression coverage to verify caption order and avoid duplicates across repeated thread switches. Add coverage for inactive-thread captions replayed before a later buffered turn without its start event, with and without a message delta.
GitOrigin-RevId: 6860a649bdcdda4937afb3ab4bbd75cf4ea5b4e6
## Why
Unrecognized settings can be silently ignored, leaving typos or deprecated configuration unnoticed.
## What changed
- Collect warnings for unrecognized fields in effective configuration and requirements layers, including unknown feature keys in configuration.
- Report sources and field names without configuration values, show up to three entries, and provide migration hints for `network_proxy`, `allowed_permissions`, and `include_view_image_tool`.
- Emit project-specific warnings when starting a thread and suppress repeated startup warnings in the app server and TUI.
## Testing
Add coverage for merged configuration, disabled layers, startup and project warning delivery, omission of configuration values, and warning deduplication.
GitOrigin-RevId: 464cef87882502b19865ae10b50b6f82defb7296
## What changed
- Add `thread/attachment/add`, `thread/attachment/list`, and `thread/attachment/remove` to manage durable resource references without loading the owning thread or changing conversation history.
- Identify attachments by thread, `attachmentType`, and `identityKey`. Repeated adds return the existing attachment; repeated removals succeed without emitting another update. Listing supports cursor pagination.
- Broadcast `thread/attachment/updated` after creation or deletion, after responding to the requester. Serialize attachment mutations with thread lifecycle operations and reject stores that do not support attachments.
- Update protocol schemas, TypeScript and Python bindings, documentation, and TUI notification handling so attachment updates do not add untracked threads to the agent picker.
## Testing
Add coverage for unloaded threads, pagination, idempotent addition and removal, reattachment, invalid inputs, unsupported stores, response-before-notification ordering across clients, and TUI notification routing.
GitOrigin-RevId: 0d29cf903afd4e931a70a9cf96300475213b34aa
## What changed
- Update the status heading from the latest usable reasoning line and retain it through tool activity and empty reasoning items. Keep completed reasoning in the expanded transcript only.
- Restore active reasoning after resume, thread switches, and session refreshes, including when earlier events have left the replay buffer.
- Default new embedded TUI threads to `model_reasoning_summary = "detailed"`, honoring explicit summary settings. Keep `concurrent_reasoning_summaries` opt-in and disable it when summaries are `none`.
- Persist the request's captured reasoning summary setting in context updates and local and remote compaction checkpoints.
- Animate status text with a smooth, grapheme-aware shimmer that respects terminal colors and reduced motion.
## Testing
Add regression coverage for reasoning status updates, transcript visibility, resume and buffered replay, outbound summary configuration, and summary settings across all three compaction modes. Add shimmer snapshots and checks for smooth brightness changes and Unicode grapheme preservation.
GitOrigin-RevId: 725c7de20f23166d7a3da6daeca617add5cbc600
## What changed
- Add feature-gated `/voice`, `/voice mute`, and `/voice stop` commands with local WebRTC audio and app-server signaling.
- Show live transcripts, conversation status, and microphone and speaker levels. Preserve captions and undelivered answers across thread switches.
- Speak final answers from voice handoffs while keeping delegated reasoning and commentary hidden and typed answers unspoken.
- Retry eligible startup failures once and clean up voice sessions on thread switches and disconnects.
- Stop voice and block late handoffs after a misalignment policy violation. Remove realtime event payloads and spoken text from receipt and debug logs.
## Testing
Add coverage for voice command mapping, rejected starts, disconnect cleanup, delegated final-answer speech, late handoff rejection, and transcript and footer rendering.
GitOrigin-RevId: 11def1f86b0e023b21d0d92072d6636ccad89815
## What changed
Replace horizontal turn separators with dim completion metadata after the final answer, including plain conversational answers. Show local completion times such as `done 2:32 PM`, adding the date for other days and the year for other years. Retain `Worked for` durations above sixty seconds and runtime metrics, and wrap metadata on narrow terminals.
Restore saved completion metadata when resuming conversations or loading older history. Keep each footer after its turn's items and deduplicate it across repeated notifications and overlapping pages. Only live completions fall back to the current time when a saved timestamp is unavailable. Failed, interrupted, and in-progress turns do not receive success footers.
Avoid submitting queued input or emitting completion notifications while replaying history.
## Testing
Add unit and snapshot coverage for timestamp formatting, duration thresholds, muted styling, narrow layouts, live and replayed completions, missing metadata, and pagination boundaries with overlapping pages.
GitOrigin-RevId: 308c35c6720720da43c9a391aa5a68c1b231c9a5
## What changed
- Retain question drafts, selections, expanded state, and handled message IDs across thread input restoration and reconnects. Preserve buffered live questions during session refresh without replaying their message text.
- Enable history recall and search in question answers, honoring updated key bindings and stripping image attachments and placeholders from recalled entries. Preserve Vim mode when an answer is not accepted.
- Let forward navigation past the last question restore the latest queued message as an editable main composer draft. Keep working status and queued messages visible alongside questions.
- Show a countdown for newly arrived collapsed questions and clear it when the question editor is opened or used.
- Disable question submission and skipping while the thread is unavailable.
## Testing
Add regression tests and snapshots for draft restoration and replay deduplication, history search and key bindings, queued-message editing, countdown rendering, and question layout with working status.
GitOrigin-RevId: de016120a979db860fd0d4b8098b322b312b7d84
## What changed
- Coalesce configuration, skill, sandbox, and MCP startup diagnostics into a single summary below the session header, including MCP and sign-in counts.
- Keep the complete warning text in the transcript and update the summary's transcript shortcut when key bindings change.
- Continue rendering warnings that arrive after work begins as inline history entries.
- Hide the MCP startup status row before a turn while preserving the configured interrupt shortcut.
## Testing
- Add coverage for warning ordering and deduplication, transcript details, MCP sign-in counts, resumed sessions, runtime warnings, reflow, backtracking, and interruption without a visible status row.
GitOrigin-RevId: 009657cf04f1d3a52270cf096eebf9db7513c040
## Why
Misalignment policy failures pause the current chat. When the server provides findings and a continuation request, users should be able to inspect them and explicitly decide whether to proceed.
## What changed
- Add a `Review findings` flow that shows the detailed explanation and quoted continuation request in an overlay.
- Require explicit acknowledgement before starting a continuation turn, while preserving the active approval and sandbox settings.
- Keep ordinary input blocked and reject stale, replaced, invalid, or duplicate continuation attempts.
- Label the overlay shortcut as `q close` to match its behavior.
## Testing
- Add TUI tests covering findings review, explicit confirmation, successful and failed continuation, stale findings, duplicate events, and invalid continuation data.
GitOrigin-RevId: 36a738adf272f95db92eaee5712fb00061d0fa52
## Why
Context compaction was only reported after it completed, so the TUI did not
show when compaction was actively making room to continue.
## What changed
- Show `Compacting context` as soon as manual or server-driven compaction
starts, with an elapsed timer independent of the current turn timer.
- Preserve the compaction status across follow-up input and transient activity,
while still allowing retry errors to take precedence.
- Restore in-progress compaction timing from thread snapshots and add the live
duration to the completion message.
- Clear stale compaction state when the turn starts, completes, or terminates.
## Testing
Added TUI tests covering manual and server-driven compaction, narrow rendering,
follow-up input, replay and task switching, retry status, timer preservation,
and turn termination.
GitOrigin-RevId: 804e1bc553315da24ff1f99462e8e282818cada3
## What changed
- Emit turn-scoped authentication recovery started and completed events when a model provider refreshes expired credentials.
- Add stable `modelProvider/authRecoveryStarted` and `modelProvider/authRecoveryCompleted` app-server notifications with the thread, turn, provider, and user-facing message.
- Show recovery progress in the TUI and `codex exec`, including Amazon Bedrock session reauthentication.
## Testing
- Cover provider recovery success and failure events, app-server routing, client rendering, and Amazon Bedrock credential refresh.
GitOrigin-RevId: 3010c38d0676f18bced27761cf86dd38344d09f9
## Why
Clients need a bounded view of realtime conversations that preserves the order of speech, agent work, and turn lifecycle events without loading the full thread history.
## What changed
- Persist realtime session boundaries, transcript segments, and promoted agent items in paginated thread rollouts.
- Add the experimental `thread/timeline/list` API to page ordinary items, realtime items, and turn boundaries in canonical rollout order. Include `activeRealtimeSessionAtPageStart` so each page can be rendered independently.
- Emit typed `thread/realtime/item/started`, `thread/realtime/item/transcript/delta`, and `thread/realtime/item/completed` notifications around durable realtime items.
- Keep the existing `thread/items/list` response and legacy thread history behavior unchanged.
## Testing
- Cover mixed timeline pagination, realtime-session state at page boundaries, rollout replay, subagent history prefixes, transcript streaming, steering, and promoted agent artifacts.
GitOrigin-RevId: faa2c420192d63e060e8fb32446e3c797422656e
## What changed
- Add experimental `mcpServer/event/stream/start` and `mcpServer/event/stream/stop` requests for hosted apps, plus `mcpServer/event/stream/notification` forwarding.
- Scope subscriptions to the owning app-server connection and subscribed thread, enforce unique IDs and a per-connection limit, and clean them up when the thread is unsubscribed or the connection closes.
- Wait for the MCP active notification before completing startup, retry streams that close immediately, and terminate them when authentication or hosted runtime ownership changes.
## Testing
- Add an app-server integration test covering activation, event forwarding, duplicate subscription rejection, and explicit cancellation.
GitOrigin-RevId: 8a6fc1615adfc5af7e67def3b824fa5909ab3e7b
## What changed
- Render `StrictReviewRequired` notifications as warning history cells that explain tool calls may take extra time.
- Preserve the active command and task-running state when the notification arrives.
## Testing
- Add a TUI snapshot test covering the warning and continued command output.
GitOrigin-RevId: bf01b612a22b537b247b6df6818080fc73b5414d
## What changed
- Ignore Guardian warning notifications that report a successful automatic approval review, keeping approved reviews out of TUI history.
- Continue displaying all other Guardian warnings.
- Extend the approved-review history test to cover the notification path.
GitOrigin-RevId: 719e84bc5b20c0a5364d10f84be9c6ac96158719
## What changed
- Add the experimental `autoApprovalReview/strictReviewRequired` app-server notification with the review's `threadId`, `turnId`, and `startedAtMs`.
- Emit it when Guardian v2 leaves an approval review in progress because the action risk is elevated or its score is stale.
- Export the notification through the Rust, TypeScript, and JSON schema surfaces and route it to the associated thread.
## Testing
- Cover strict-review reason tracking for elevated and stale risk scores.
- Verify that high-risk approval routing emits one notification whose identifiers and timestamp match the review-started event.
GitOrigin-RevId: e65352894520bfb756c75b2c95e2e149f9767bb2
## Why
The app server sends sub-agent activity in both item-started and item-completed
notifications, causing the TUI to add the same activity to history twice.
## What changed
Render live sub-agent activity when the item completes instead of also rendering
it when the item starts. Preserve the existing replay behavior.
## Testing
Add a regression test that sends matching started and completed notifications
and verifies that the activity produces one history cell.
GitOrigin-RevId: 76a66f3657fe297f37067ed672ab9642997b4499
## What changed
- Group consecutive successful agent and unified-exec startup commands into a compact `Ran N commands` entry while preserving their full transcript.
- Flush command groups at interaction boundaries, after failures, and after 32 completed commands. Keep manual shell commands and failed or declined commands visible.
- Apply the same grouping rules when replaying thread history without duplicating command starts or disturbing unrelated active commands.
## Testing
- Add TUI coverage for live and replayed grouping, transcript preservation, failures, overlapping commands, group limits, and interaction boundaries.
GitOrigin-RevId: d6602a20201644012fcff3d6cecf4690024383a9
## What changed
- Add experimental `thread/queue/add`, `list`, `update`, `delete`, `reorder`, and `start` requests for persistent queued user submissions.
- Automatically dispatch queued submissions in FIFO order after completed or failed turns, while leaving the queue paused after interruption.
- Emit `thread/queue/changed` notifications and expose paginated queue contents with stable submission and client message IDs.
- Export the new protocol types through the generated JSON Schema and TypeScript bindings.
## Testing
- Add app-server integration coverage for capability gating, CRUD, pagination, capacity limits, notifications, automatic dispatch, cold-thread resume, interruption, and explicit queue starts.
GitOrigin-RevId: 89caf5577192199bda77cf6c372a59d26cdd910e
## What changed
- Add the experimental `thread/revert` request, which replaces a loaded paginated thread's durable history with the prefix before `beforeTurnId` while preserving the thread ID.
- Interrupt any active turn, reload the replacement history without unloading the thread, preserve mutable thread settings, and emit `thread/reverted`.
- Return backward pagination cursors for the retained turns and items, reject stale rollout paths after a revert, and document that local file changes are unaffected.
## Testing
- Cover history replacement, pagination, stale paths, missing turns, subsequent turns, active-turn interruption, and preserved thread settings.
GitOrigin-RevId: 435a8163ad4f310cc47219b436f6bdde21f2b83a
## What changed
- Add `thread-credits` and `estimated-thread-cost` items to the configurable
status line and terminal title for Enterprise workspaces.
- Fetch one shared thread usage estimate only when either item is selected,
omit unavailable values, and refresh the display after turns complete.
- Preserve the last nonzero estimate while usage settles, with bounded delayed
refreshes and retries for transient failures.
## Testing
- Add coverage for configuration, rendering, previews, plan availability,
replay handling, retries, and post-turn settlement.
GitOrigin-RevId: dd69ee621c5bca0e5d9edd32b2bba42487eb1500
## Why
Streamed message deltas can be dropped when the transport is saturated, leaving
clients with a truncated final response.
## What changed
- Include the last non-empty final agent message in successful `turn/completed`
notifications and mark the items as a summary.
- Treat completed message content as authoritative in the TUI, repairing an
incomplete stream while avoiding duplicate messages when `item/completed` was
already received.
- Continue backfilling full turn items for persisted `codex exec` threads when a
completion contains only the summary view.
## Testing
Added coverage for completion summaries, dropped stream deltas, duplicate item
handling, and directive-only responses.
GitOrigin-RevId: ffe9d36d683d6b6690e4a468ff68aa9189fe6ab7
## What changed
- Track connected and disconnected states across initial remote exec-server connections and reconnection attempts.
- Emit experimental `thread/environment/connected` and `thread/environment/disconnected` app-server notifications for each thread selecting the environment. Each payload identifies the thread and environment; current state is not replayed when a thread starts.
- Stop forwarding connection events when an environment selection is removed or replaced.
## Testing
- Cover connection, disconnection, reconnection, shared-environment notifications, and replacement of a selected environment.
GitOrigin-RevId: 5dd767372363c4a2a8319fc16164be117d5bd20c
## Why
Clients that account for individual upstream Responses API calls need the exact
usage for each completion rather than accumulated or estimated thread usage.
## What changed
- Add the opt-in `rawResponse/completed` app-server notification with the
`threadId`, `turnId`, `responseId`, and upstream `usage` payload.
- Emit the transient event for normal turns and compaction requests when
`experimentalRawEvents` is enabled. The event is not persisted or replayed,
and `usage` is `null` when the upstream response omits it.
- Export the notification in the app-server schemas and document its behavior.
## Testing
- Cover exact token breakdowns for turn and compaction completions.
GitOrigin-RevId: 49040a060bf1784c1ff1dd62112efb4a778428c4
## Description
This PR migrates standalone web search onto the extension-owned
turn-item path introduced in #31283.
Standalone web search now emits `ExtensionItem::WebSearch` through
generic `TurnItem::Extension`, while app-server still exposes the
existing typed `ThreadItem::WebSearch` JSON shape. Hosted Responses API
web search stays on core-owned `TurnItem::WebSearch`.
## What changed
- Added `web_search::WebSearchItem` and `WebSearchAction` to
`codex-extension-items` under the stable `web.search` kind.
- Collapsed `ExtensionTurnItem` to generic `{ item, legacy_events }` now
that no typed extension special cases remain.
- Kept the existing `WebSearchBegin` / `WebSearchEnd` compatibility
events and canonical-first ordering.
- Updated app-server projection/history and generated TypeScript; the
app-server JSON schema is unchanged.
## Description
This PR adds a `codex-extension-items` crate for extension-owned
`TurnItem` schemas, and updates standalone image generation to start
using it via `TurnItem::Extension`.
This gives us a way to prevent Core from having to be aware of all
extension items. App-server still exposes the existing public
`ThreadItem::ImageGeneration` shape, now by wrapping the same shared
`image_generation::ImageGenerationItem` type.
The new `codex-extension-items` crate is necessary because the image gen
extension item is used by:
- `codex-image-generation-extension`, which produces it.
- `codex-tools / core`, which carry it generically.
- `codex-protocol`, which serializes it into lifecycle events and
rollouts.
- `app-server protocol`, which wraps it in public
`ThreadItem::ImageGeneration`
```
extension implementation
↓
codex-extension-items
↓
protocol / tools / app-server
```
We keep the hosted Responses API image generation as
`TurnItem::ImageGeneration` because core still owns its persistence and
legacy fanout.
### Before
Standalone image generation is implemented as an extension, but its item
representation previously lived in the core protocol. This sets the
precedent that core is aware of all extension items, which would be good
to avoid.
```
image-gen extension
→ constructs codex_protocol::ImageGenerationItem
→ emits ExtensionTurnItem::ImageGeneration
→ core matches ImageGeneration specially
→ protocol stores TurnItem::ImageGeneration
```
### After
```
image-gen extension
→ constructs extension-owned ImageGenerationItem
→ emits generic ExtensionItem
→ core transports/persists it generically
→ app-server wraps ImageGenerationItem as ThreadItem::ImageGeneration
```
Future extension items can have typed app-server APIs without adding a
new `TurnItem` variant, `ExtensionTurnItem` variant, or core emitter
match arm.
## What changed
- Added `codex-extension-items` with the closed `ExtensionItem` enum and
shared `image_generation::ImageGenerationItem` schema.
- Added generic `TurnItem::Extension(ExtensionItem)` and
`ExtensionTurnItem::Extension { item, legacy_events }` paths.
- Updated standalone image generation to emit a typed extension item and
provide its existing legacy `ImageGenerationBegin` /
`ImageGenerationEnd` events explicitly.
- Kept canonical lifecycle ordering: core emits `ItemStarted` /
`ItemCompleted` before extension-provided legacy events.
## Follow-up
Standalone web search still uses its typed special-case path. Migrating
it later would let `ExtensionTurnItem` collapse into a single
extension-item struct.
Responses API safety buffering metadata currently stops at the transport
boundary, so app-server clients cannot render the in-progress safety
review state.
This change:
- decodes and deduplicates `safety_buffering` metadata from Responses
API SSE and WebSocket events without suppressing the original response
event
- emits a typed core event containing the requested model plus backend
use cases and reasons
- forwards that event as `turn/safetyBuffering/updated` through
app-server v2 and updates generated protocol schemas
- keeps the side-channel event out of persisted rollouts and turn timing
This supports the Codex Apps buffering UX and depends on the Responses
API backend work in https://github.com/openai/openai/pull/1044569 and
https://github.com/openai/openai/pull/1044571.
Validation:
- focused `codex-core` safety-buffering integration test passes
- `cargo check -p codex-core -p codex-app-server -p
codex-app-server-protocol`
- `just fix -p codex-api -p codex-protocol -p codex-core -p
codex-app-server-protocol -p codex-app-server -p codex-rollout -p
codex-rollout-trace -p codex-otel`
- `just fmt`
- broad package test run: 4,430/4,492 passed; 62 unrelated
local-environment/concurrency failures involved unavailable test
binaries, MCP subprocess setup, and app-server timeouts
## 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
Removes the realtime audio support from TUI.
## What Changed
- Removed the TUI `/realtime` and realtime `/settings` command paths.
- Deleted TUI voice capture/playback, WebRTC session handling,
audio-device selection UI, and recording-meter code.
- Removed TUI realtime tests and snapshots that covered the deleted
surfaces.
- Dropped the TUI-only `cpal` and `codex-realtime-webrtc` dependencies
and refreshed the Rust/Bazel locks.
## Why
Clients can archive and unarchive threads today, but there is no
app-server API for permanently removing a thread. Deletion also needs to
cover the full session tree: deleting a main thread should remove
spawned subagent threads and the related local metadata instead of
leaving orphaned rollout files, goals, or subagent state behind.
## What
- Adds the v2 `thread/delete` request and `thread/deleted` notification,
with the response shape kept consistent with `thread/archive`.
- Implements local hard delete for active and archived rollout files.
- Deletes the requested thread's state DB row as the commit point, then
best-effort cleans associated state including spawned descendants,
goals, spawn edges, logs, dynamic tools, and agent job assignments.
- Updates app-server API docs and generated protocol schema/TypeScript
fixtures.
## Why
MCP startup status notifications are thread-owned, but `ChatWidget`
trusted upstream routing. If routing state delivered a tagged child
notification to the active parent widget, the child MCP failure could
still mutate the parent's startup state and transcript. Rejecting it
only inside the MCP handler was also too late because shared
notification handling could already restore and consume the parent's
retry status.
## What changed
- Validate a tagged MCP status notification against the visible
`ChatWidget` thread before shared notification handling mutates any
parent state.
- Cover child `Starting` and `Failed` notifications delivered to a
retrying parent widget, asserting that they preserve its visible retry
error and saved status header while producing no history or MCP status
mutation.
## User impact
Subagent MCP startup failures remain scoped to the child transcript
instead of appearing as duplicate warnings in the parent transcript.
## Testing
- `just test -p codex-tui mcp_startup_ignores_status_for_other_thread`
- `just test -p codex-tui
primary_thread_ignores_child_mcp_startup_notifications`
- `just fmt`
## Why
Multi-agent v2 identifies agents by canonical paths, but its tool
handlers still emitted the larger legacy collaboration begin/end events
built around nickname and role metadata. App-server, rollout-trace,
analytics, and TUI consumers therefore lacked one compact path-based
completion signal that behaved consistently across live events and
replay.
The TUI also needs a bounded `/agent` status surface for v2 agents. It
should use recent local activity for previews, refresh liveness without
loading full histories, and keep the legacy picker available when no
path-backed v2 agent is known.
## What changed
- Replace the v2 `spawn_agent`, `send_message`, `followup_task`, and
`interrupt_agent` legacy lifecycle emissions with a success-only
`SubAgentActivity` event. The event records the tool call ID, occurrence
time, affected thread, canonical agent path, and `started`,
`interacted`, or `interrupted` kind.
- Expose the activity as a completion-only app-server v2
`subAgentActivity` thread item in live notifications and reconstructed
history, regenerate the protocol schemas, and count it in sub-agent tool
analytics.
- Track canonical paths from live activity and loaded-thread metadata in
the TUI, and render the activity in live and replayed transcripts.
- Make `/agent` list running path-backed agents with summaries from
bounded local event buffers. Each summary is capped at 240 graphemes,
the scan is capped at six recent items, only the last three wrapped
lines are shown, and command output is omitted. Liveness falls back to
metadata-only `thread/read` when local turn state is unavailable.
- Persist the activity as a terminal rollout-trace runtime payload and
reduce it to the corresponding spawn, send, follow-up, or close
interaction edge. `interrupt_agent` is classified as a close-edge
operation.
- Preserve the legacy picker when no path-backed v2 agent is known.
## Compatibility
App-server v2 clients that consumed `collabAgentToolCall` begin/end
pairs for these tools must handle the new completion-only
`subAgentActivity` item. Legacy v1 collaboration behavior is unchanged.
## Screenshot
<img width="684" height="288" alt="Screenshot 2026-06-08 at 15 40 47"
src="https://github.com/user-attachments/assets/194b3cd0-619d-45fb-b587-cf3e2b1b8a1d"
/>
## Testing
- `just test -p codex-app-server-protocol`
- `just test -p codex-rollout-trace`
- Added focused coverage for activity analytics, terminal trace
serialization, spawn-edge reduction, `interrupt_agent` classification,
TUI status rendering without aggregated command output, and clearing
stale running state after a completed turn.
## Why
MCP startup failures from spawned subagents were rendered as global
notifications, so a child thread's failure could pollute the visible
parent transcript. Routing the notification to the child exposed two
related replay problems: session refresh could discard the buffered
event, and a newly created child `ChatWidget` did not know the expected
MCP server set, which could leave its startup spinner running after
every server had settled.
MCP startup diagnostics should remain visible in the thread that owns
the startup without affecting other transcripts. The protocol also needs
to support a future app-scoped MCP lifecycle where startup is not owned
by any thread.
## Reported Behavior
The [originating Slack
report](https://openai.slack.com/archives/C08JZTV654K/p1780604538859939)
called out that using subagents could turn MCP startup failures into a
wall of yellow CLI warnings because repeated failures were not
deduplicated. The intended behavior is for those diagnostics to remain
visible once in the thread that owns the startup, without polluting the
parent transcript.
## What Changed
- add nullable `threadId` ownership to `mcpServer/startupStatus/updated`
- populate it from the app-server conversation ID for the current
thread-scoped lifecycle and regenerate the protocol schema and
TypeScript artifacts
- treat a missing or null `threadId` as app-scoped without injecting it
into the active chat transcript
- route and buffer thread-owned MCP startup notifications by thread in
the TUI
- preserve buffered MCP startup events across child session refresh
- seed expected MCP servers before replaying a thread snapshot so
startup reaches its terminal state
- suppress an identical repeated failure warning for the same server
within one startup round
The owning thread still renders the detailed failure and final `MCP
startup incomplete (...)` summary.
## How to Test
1. Configure an optional MCP server named `smoke` that exits during
initialization.
2. Launch the TUI with multi-agent support enabled.
3. Confirm the main thread's own startup failure renders one detailed
`smoke` warning and one incomplete-startup summary.
4. Spawn exactly one subagent.
5. Confirm the parent transcript does not receive the subagent's MCP
startup failure.
6. Switch to the subagent thread and confirm it contains exactly one
detailed `smoke` failure and one incomplete-startup summary.
7. Confirm the subagent's MCP startup spinner disappears and the thread
remains usable.
8. Switch between the parent and subagent and confirm the warnings
neither move nor duplicate.
Targeted tests:
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
thread_start_emits_mcp_server_status_updated_notifications`
- `just test -p codex-tui mcp_startup`
The parent/child behavior and spinner completion were also exercised
manually in tmux. `just argument-comment-lint` was attempted but blocked
by an unrelated local Bazel LLVM empty-glob failure; touched Rust
callsites were inspected manually.
## Why
First-party backends can supply turn-scoped moderation metadata that
app-server clients need for client-side presentation. Exposing this as
an experimental typed notification lets opted-in clients consume it
without interpreting raw Responses API events.
## What changed
- forward `response.metadata.openai_chatgpt_moderation_metadata` from
Responses API SSE and WebSocket streams as turn-scoped moderation
metadata
- emit the experimental app-server v2 `turn/moderationMetadata`
notification with `{ threadId, turnId, metadata }`
- add app-server integration coverage for the typed moderation metadata
notification
## Testing
- `just test -p codex-core
build_ws_client_metadata_includes_window_lineage_and_turn_metadata`
- `just test -p codex-core` (fails locally: 46 failures and 1 timeout,
primarily missing `test_stdio_server` and shell snapshot timeouts)
- `just test -p codex-app-server-protocol`
- `just test -p codex-app-server
turn_moderation_metadata_emits_typed_notification_v2`
- `just test -p codex-app-server` (fails locally: 792 passed, 10 failed,
and 5 timed out; failures are in existing environment-sensitive tests,
primarily because nested macOS `sandbox-exec` is not permitted)
- `just write-app-server-schema --experimental --schema-root
/tmp/codex-app-server-schema-experimental`
## Summary
- Bump the workspace Rust toolchain from `1.93.0` to `1.95.0` across
Cargo, Bazel, CI, release workflows, devcontainers, and the Codex
environment config.
- Refresh `MODULE.bazel.lock` so the Bazel Rust toolchain artifacts
match the new version.
- Leave purpose-specific toolchains unchanged, including the
`argument-comment-lint` nightly and the upstream `rusty_v8` `1.91.0`
build pin.
- Includes fixes for new lints from `just fix` and a few codex-authored
fixes for lints without a suggestion.