Commit Graph
912 Commits
Author SHA1 Message Date
sayan-oai 6fcfa75a9f Preserve MCP registration scope across client operations (#61257)
## Why

MCP servers registered under the same name in different environments need distinct inventory, routing, and status reporting.

## What changed

- Keep MCP inventory and runtime status keyed by registration scope so same-named servers remain separate.
- Add optional `environmentId` selectors for status lookup, tool calls, resource reads, and OAuth login. Omitting the selector preserves existing name-only routing.
- Carry environment identity through startup notifications, elicitation requests, and tool-call history, and display it in the TUI.
- Support `/mcp login <name> --environment <id>` and update generated protocol schemas and SDK types.

## Testing

Add integration coverage for two environments with identically named MCP servers, tools, and resource URIs. Verify separate inventory, explicit environment routing, legacy routing when the selector is omitted, and errors for unknown environments. Update protocol and TUI tests for environment identity.

GitOrigin-RevId: 074a3db10549438cb6aff33eb7bed10791adae4d
2026-11-13 04:51:06 +00:00
Joe Savona fdad70ba5d Hide TUI status details for read-only history (#61219)
## What changed

Track whether a thread is being viewed without a live attachment. Hide the status line and context usage for saved history and unavailable conversations, even when token usage updates arrive. Restore these displays when the thread resumes interactively, including sessions using read-only permissions.

Avoid a leading separator before the Vim mode indicator when context usage is hidden.

## Testing

Add regression coverage for history viewing, token updates, and interactive resume. Update unavailable-conversation snapshots to omit the status line.

GitOrigin-RevId: 14dfd2ee0f232001814b7fc45a5ac8a5d755669b
2026-11-13 01:07:44 +00:00
Felipe Coury 16e27626e6 Unify TUI status content and layout caching in StatusLine (#61200)
## What changed

- Replace `FooterContent` and the separate layout cache with a `StatusLine` that owns native or extension content and caches its layout by bounds.
- Move footer padding into the caller's layout and retain cached wrapping for unchanged agent-labeled status lines.
- Remove extension-to-single-line conversion and render prepared UI trees directly within their allotted rectangles.

## Testing

Extend composer coverage to verify that replacing measured extension content updates the displayed rows. Adapt status-line and UI-tree tests to exercise direct rendering, clipping, hyperlinks, and viewport bounds.

GitOrigin-RevId: 72273c87d689b8b59748ab243793a9e2a45f4884
2026-11-12 22:44:19 +00:00
Benjamin Carlsson b279cfb170 Enable conversation-scoped speed selection for Cloud turns (#61178)
## What changed

- Stage Cloud speed choices for the next new turn in the conversation, alongside pending model and effort selections. Update the displayed conversation speed after admission without changing the local default.
- Offer speed commands supported by the pending model. Clear an incompatible pending speed change with a warning when switching models.
- Carry `service_tier` through Cloud message requests, preserving omission to inherit the thread tier and explicit null to clear it. Translate `default` to null and reject tier overrides on queued requests.

## Testing

Add tests for Cloud speed toggling, model-dependent speed choices, admission-time updates, and preserving the conversation tier when selecting a model. Extend request and wire tests to cover service-tier values, explicit clearing, and queue rejection.

GitOrigin-RevId: b4daa701f1fe29593d90a938e60cc20cb980298a
2026-11-12 20:56:33 +00:00
Zahan Malkani 72532ecae5 Negotiate realtime voice calls in the TUI (#61172)
## What changed

- Create WebRTC calls using the TUI's local provider and credentials, then attach the app server through `existingCall` with the returned call ID.
- Preserve the effective voice preference and share realtime prompt preparation and thread headers between call creation and the backend observer.
- Run negotiation asynchronously, cancel pending startup when voice stops, and ignore results from stale startup attempts.

## Testing

Update voice request and handoff tests for client-created calls. Add coverage ensuring that canceling and restarting voice attaches only the new attempt, including when an earlier result is already queued.

GitOrigin-RevId: b704976f4918dddd24a17fbaa868a7c62e81885b
2026-11-12 19:43:12 +00:00
Felipe Coury d0edb0b1fa Preserve multiline status lines in unfocused chat panes (#61141)
## Why

Unfocused chat panes reduced status content to a single dim line, hiding rows that were visible while focused.

## What changed

- Share status measurement, wrapping, rendering, and footer row allocation between the main conversation and side chats.
- Retain structured status content in inactive side chats so native and extension status lines can use the available rows and reflow when resized.
- Keep unfocused status content dimmed with hyperlinks suppressed, while respecting space reserved for the draft and footer hints.

## Testing

Add regression coverage for status reflow across split-pane focus switches and resizing, and update extension status coverage to verify multiple dimmed rows when unfocused.

GitOrigin-RevId: f4def37259fe106d6a3fac9fe4c6cc2d4972f244
2026-11-12 15:09:13 +00:00
Benjamin Carlsson f988ada4bf Reconnect idle Cloud conversations after transient stream loss (#60969)
## Why

A lost Cloud reply stream previously required reopening the conversation, even when it was idle. Recover the displayed conversation automatically while holding queued input until its reply stream is usable.

## What changed

- Add bounded retries for transient stream failures in the displayed, idle conversation, with credential and network-policy checks. Keep explicit reopen behavior when recovery is unavailable or fails.
- Enable HTTP/2 keepalive pings for Cloud connections.
- Queue input while disconnected and resume ordinary submission after recovery. Mark recovered history as potentially incomplete so an explicit reopen reloads missed turns while preserving drafts and reconciling pending submissions.
- Store retained input per backend and apply background settings updates to the owning backend's drafts.

## Testing

Add regression coverage for queued input during disconnection and extend resume and backend-handoff tests to cover history refresh, draft preservation, and retained settings.

GitOrigin-RevId: 3d753e53d3c0d594680a90cac8a75fe33b91e219
2026-11-12 01:57:33 +00:00
Benjamin Carlsson 82e6bacb9c Enable model and reasoning effort selection for Cloud conversations (#60651)
## Why

Cloud conversations previously used the model returned on activation without exposing model discovery or supporting model changes from the TUI.

## What changed

- Fetch the account-scoped Cloud catalog on demand through `/v2/models`, independently of the submission and attachment queue.
- Let users stage a supported model and reasoning effort for the next new turn in the current conversation. Send these settings with the user message and show acceptance after successful admission.
- Show a loading picker when the catalog is empty, preserve compatibility with Cloud servers that lack discovery, and discard stale catalog results and selections when the account changes.

## Testing

Add coverage for catalog request parameters and queue bypass, deferred discovery and compatibility, model and effort serialization, admission outcomes, account invalidation, and opening the picker after discovery.

GitOrigin-RevId: 2cd0e7fe5f760d4da9258eefe9f0dcbcd23f9b07
2026-11-10 19:52:49 +00:00
Eric Traut 2df465732a Use app-server MCP configuration and startup events in the TUI (#60622)
## Why

Locally configured MCP servers may differ from those reported by the app server. Waiting for unreported servers can leave startup progress busy after the observed servers have finished.

## What changed

- Track startup progress from received server status updates, settling when no observed starts remain pending. Handle standalone outcomes after attachment or lag, deduplicate repeated diagnostics, and reactivate progress on new starts.
- Read effective MCP configuration through `config/read` to prevent task tools from shadowing the `codex_tui` namespace, including when configuration changes after startup.
- Use the same configuration reader to disable MCP servers for temporary structured threads.
- Remove client-side MCP requirement checks for the task-tools server and MCP requirements from debug configuration output, leaving enforcement to the app server.

## Testing

Update regression coverage for unreported local servers, startup rounds after lag, diagnostic handling, namespace conflicts, and server-enforced managed requirements.

GitOrigin-RevId: 370767b90ee55f8b0b1403872ef437d53257586b
2026-11-10 16:44:23 +00:00
smurching-oai 36e074a2fb Add local diagnostic ZIP saves to the TUI (#60542)
## What changed

- Let users press `Ctrl+S` in the report note editor to save a diagnostic ZIP locally without sending it to OpenAI, including when uploads are disabled. Keep `Enter` for sending reports when uploads are enabled.
- Apply the attachment consent choice to both destinations, clarify the disclosures, and show the saved archive path on completion.
- Require a local app server for ZIP saves, report unsupported servers with an upgrade hint, and stop before collecting a note when no report destination is available.

## Testing

Add coverage for ZIP creation with and without log consent, no upload requests on save success or failure, destination availability, keyboard actions, and saved-path receipts. Update report UI snapshots.

GitOrigin-RevId: cbc0142988840e5e3f6475f31678915bf25d56a2
2026-11-10 07:06:53 +00:00
Eric Traut 05cf8eeb14 Dismiss the model switch prompt when account usage recovers (#60435)
## Why

The rate-limit model switch prompt can remain visible after account usage falls below the warning threshold.

## What changed

Use fresh account usage reads to clear pending prompts when all reported usage windows fall below 90%. If the prompt is already visible, replace it with a recovery notice that counts down for five seconds before dismissing. Users can also dismiss the notice with Enter or Esc.

Ignore stale account reads when detecting recovery and preserve the recovery state when backend banners replace the prompt.

## Testing

Add regression tests and a snapshot covering pending prompt cancellation, stale reads, the recovery notice countdown, automatic dismissal, and manual dismissal with Enter or Esc.

GitOrigin-RevId: 9408f7cc7b49c52535f00d8a476f208fe4872bdf
2026-11-09 19:37:04 +00:00
Charlie Marsh ee51bb132e Fix MCP startup tracking when attaching to shared app servers (#60280)
## Why

Clients attaching to a shared app server can miss startup notifications and have a different local MCP configuration. Waiting for locally configured servers can leave the TUI stuck in a busy state.

## What changed

- Track only reported MCP servers for shared app servers and subagents, settling startup once observed starts complete.
- Handle standalone terminal updates without reopening startup, while reporting failures and cancellations even when their starts were missed.
- Suppress duplicate diagnostics until an observed retry or notification lag, and include all received outcomes in each active round's summary.

## Testing

Add regression coverage for attachment before, during, and after startup; idle keyboard behavior after startup settles; terminal-only failures and cancellations; and repeated failures after retries or notification lag.

GitOrigin-RevId: e19f23c212f2f3cee1adeb5c3b94a508aa599242
2026-11-08 19:04:10 +00:00
Benjamin Carlsson e6bf88ae02 Support Cloud image messages and editable draft handoffs (#60061)
## Why

Cloud messages previously accepted only plain text, and switching a draft to Cloud waited for session preparation without processing composer input.

## What changed

- Support ordered text and image parts in Cloud submissions and user-message summaries, preserving attachment placeholders, image detail, and client message IDs.
- Accept inline data URLs and uploaded file IDs, including image-only messages. Reject invalid references and text spans locally, and cap encoded image requests at 3.75 MiB while retaining the existing plain-text limit.
- Keep the composer editable and redraw the TUI while Cloud prepares a conversation. Carry the latest draft, attachments, and Vim mode into the destination, retain drafts on failure, and prevent submission to the outgoing session during the handoff.
- Preserve buffered paste input and pending clipboard reads across the handoff, with connection and failure hints.

## Testing

Add regression coverage for image wire encoding, receipt identity, validation and size boundaries, draft editing during successful and failed handoffs, clipboard completion, Vim state, and attachment recovery after rejected submissions.

GitOrigin-RevId: 0cbcde0ab89ba961780b5f88456057e6b6a19cd5
2026-11-07 04:48:30 +00:00
Charlie Marsh af9a98b074 Add opt-in lazy startup for cached stdio MCP servers (#60039)
## Why

Regular chats start MCP servers eagerly even when cached tool definitions are available and the servers go unused. Allow those chats to use the cached catalog and defer eligible stdio servers until first use.

## What changed

- Add the disabled-by-default `mcp_lazy_stdio_startup` feature and expose it through experimental feature configuration.
- Defer cached stdio servers in regular chats when enabled, while keeping servers that require a live startup connection eager. Required servers with `startup_readiness = "catalog"` may defer; explicit reconnects remain eager.
- Announce the full eager startup batch before terminal statuses and exclude dormant servers from the initial startup summary. Update TUI tracking so deferred servers can report startup independently in later rounds.

## Testing

Add scenario coverage for a cached server staying dormant during unrelated work, starting on first use, and refreshing tool definitions and visibility. Cover required live startup, eager event ordering, experimental feature configuration, and TUI status handling.

GitOrigin-RevId: 74075fcd4f26c8c79b5901b6a8cb03fdb9e35a7f
2026-11-07 02:28:44 +00:00
Benjamin Carlsson a142c90e26 Handle TUI message submission receipts and preserve uncertain drafts (#59817)
## Why

The TUI's cached active turn can be stale when a cloud message is submitted. A lost reply also leaves delivery uncertain, so automatically resending the draft risks submitting it twice.

## What changed

- Let the cloud server choose whether an Enter submission starts or steers a turn, and apply its receipt to the matching client message ID.
- Keep Tab-queued input waiting until the admitted turn finishes, including before its start notification arrives.
- Restore rejected submissions to the composer. Hold duplicate or unconfirmed submissions out of automatic delivery until history confirms them.
- Reconcile saved drafts and pending steers by client message ID when resuming sessions, and preserve submissions belonging to other turns during interruption recovery.
- Classify cloud preflight failures as invalid parameters so rejected queued input can be restored safely.

## Testing

Add regression coverage for cloud receipt outcomes, queued-input ordering, rejected drafts, lost replies, interruption recovery, and session resume with identical message text but distinct client IDs.

GitOrigin-RevId: ec4eb581e450488434bc4614ec59273d73ffd0a1
2026-11-06 03:51:37 +00:00
Felipe Coury e8e3197e84 Make side conversation panes resizable and interactive (#59527)
## What changed

- Allow dragging the pane divider and save the preferred width in `tui.sidebar_width_percent`, defaulting to one third of the terminal. Defer reflow until release when retained images are present.
- Support scrolling and loading older history in the unfocused pane, opening links, copying selections, and clicking its composer to switch focus while preserving the clicked text position.
- Keep assistant replies, running command completion, and turn status current in the unfocused pane without duplicating answers or completion metadata when focus returns.

## Testing

Add regression coverage for divider previews and saved widths, image-aware resizing, composer clicks, unfocused history pagination and copying, and streaming replies and command completion across focus changes.

GitOrigin-RevId: a26accc0f8df3c17f53bc915db29a11c8de3c480
2026-11-05 00:19:26 +00:00
Eric Traut 3a2788e6fc Restore background terminals from the displayed thread's live state (#59319)
## Why

Replaying a fork's inherited command history can make the TUI show background terminals belonging to its parent thread.

## What changed

Fetch the displayed thread's background terminals after history replay instead of treating replayed commands as live terminals. Read all pages, merge without duplicating tracked processes, and exclude terminals that exit while the request is pending. Clear terminal tracking and invalidate pending restoration when resetting thread state or stopping background terminals.

## Testing

Add a regression test verifying that `/ps` shows a resumed fork's own terminal, excludes inherited commands, and does not restore a terminal that exited during the list request.

GitOrigin-RevId: aca9ae9cde877f03143f8fbeea11affcc34dc372
2026-11-04 05:25:12 +00:00
Benjamin Carlsson 26f73fba8f Add host cycling and saved defaults for new TUI conversations (#59007)
## What changed

- With multi-backend support enabled, show the current host before the first submission and use `leader b` to cycle through available connections. Expose the shortcut as `tui.keymap.global.change_host`.
- Preserve the conversation name and composer draft, including cursor position, attachments, pending pastes, and literal versus shell-command interpretation of `!`.
- Save explicit host choices in user-only `tui.default_hosts`, scoped to the local project and user identity. Use the saved host for new conversations, falling back to the first available connection when it is unavailable.
- Prepare the destination and check directory trust before replacing the current conversation. Block switching during voice calls and active turns, and remove replaced blank conversations from the session overview.

## Testing

Add coverage for shortcut visibility and remapping, draft and name preservation, project/user preference isolation, unavailable-host fallback, destination trust and startup failures, and voice-call guards.

GitOrigin-RevId: def7b088951336bec8fe3962954fba9b861f91c6
2026-11-02 23:19:03 +00:00
Felipe Coury db227aed42 Add opt-in side conversation panes to the TUI (#58992)
## What changed

- Add the disabled-by-default `tui_workspace` feature for the owned transcript view. At terminal widths of at least 100 columns, show the parent conversation beside its side conversation, with only the focused composer accepting input.
- Retain the inactive conversation's transcript, draft, and status, and restore reading and search state when switching focus.
- Keep drawing and input paused until history replay completes, while refreshing skills in the background.

## Testing

Add snapshots and regression tests for pane resizing and composer styling, retained streaming output, history search after replay, pending skills refreshes, and modal input protection.

GitOrigin-RevId: 68938f263353b0cd3a9e9562e06293bfc8251cc6
2026-11-02 21:47:45 +00:00
Eric Traut 6ff7f31cac Avoid unnecessary rendering during TUI history loading and insertion (#58969)
## What changed

- Skip rendered-row counting during history hydration when there is no row budget or no next item page.
- Return early when checking history insertion prefixes if there is no active cell or the placeholder session header must remain active.

GitOrigin-RevId: 669ebf0ceb0fc01c8a7bfd8d2addbcbb6fc6a364
2026-11-02 20:24:40 +00:00
Felipe Coury 8a17396d13 Fix live stream reflow at the allocated conversation width (#58927)
## Why

Streaming answers and plans need to wrap to the conversation's allocated width, which can differ from the terminal width. Resizing while reading earlier output should not report new activity unless new output has arrived.

## What changed

Reflow live streams when preparing the owned conversation layout, using its allocated width. Update the observed live revision after presentation-only reflow so it does not trigger `New activity`, while preserving notifications for unseen output.

## Testing

Add regression coverage for streaming answer and plan tables across width changes, including a narrow-layout snapshot, preservation of the reading position, and activity notifications when new output arrives before a resize.

GitOrigin-RevId: a9831c5a1a5ffb7477e7868d4ecca430d6ee50f3
2026-11-02 16:56:09 +00:00
Eric Traut 8b5ce2fd61 Add local image thumbnails to the TUI composer (#58261)
## What changed

- Show draft attachment thumbnails in reference order in inline and fullscreen views on supported terminals with local workspaces. Display a `+N` count for attachments that do not fit, and preserve editable image references when previews are unavailable or space is limited.
- Refresh previews when attached files change, apply image orientation metadata, and clear frame graphics before terminal handoffs, screen switches, and shutdown.
- Finish CLI subcommand dispatch before polling interactive TUI events.

## Testing

Add a regression test and snapshot covering thumbnail order, overflow, resizing, attachment deletion, file replacement, and fallback behavior in both inline and fullscreen views.

GitOrigin-RevId: 1ea7c89e089cecc390e145c1790b6ede8bad8d5e
2026-10-30 06:37:32 +00:00
Abhinav 55c099a142 Keep chats accessible across model provider changes (#58202)
## Why

Switching model providers can hide saved chats from resume lookup or prevent them from opening. Keep their history readable when the server rejects resuming because of a provider mismatch, missing configuration, or policy conflict.

## What changed

- Include all providers in the resume picker, named resume lookup, and `resume --last`, while retaining provider filtering for fork lookup.
- Open chats with provider errors as read-only history and show an explanation with recovery shortcuts: `c` to continue in a new chat, `n` to start fresh, and `Esc` to choose another chat.
- Continuing in a new chat prepares an editable, unsent prompt referencing the saved conversation.
- Preserve drafts and rejected prompts or steers, suppress automatic submission, and retry provider admission when reopening the chat.

## Testing

Add coverage for cross-provider discovery, read-only history, configuration recovery, continuation drafts, rejected input recovery, error rendering, and Escape handling during transcript browsing.

GitOrigin-RevId: 5aaa7a404b9a6231101599adef18d2f1e4a8020a
2026-10-30 00:45:30 +00:00
Joe Savona 797bab4746 Add an experimental UI tree renderer for the status line (#57970)
## What changed

- Add the disabled-by-default `tui_extensions_statusline` feature to render configured status items and their picker preview through a shared UI tree renderer.
- Support text, HTTP(S) links, rows, spacers, dividers, and gaps with rendering budgets, text sanitization, and width-aware truncation that keeps the ellipsis outside hyperlinks.
- Use plain text for the extension status line and hide the picker's theme color toggle while preserving the saved color preference.

## Testing

Add coverage for tree serialization and URL validation, Unicode widths, hyperlink clipping, picker previews, color preference preservation, and token usage updates across renderer switches.

GitOrigin-RevId: a6b87c2b1096765d61296d73e142834fcd53ceee
2026-10-29 03:07:15 +00:00
Eric Traut 118aae2a5f Explain safety policy blocks with turn-scoped recourse in the TUI (#57363)
## What changed

- Handle `TurnModerationMetadata` for the active turn, showing a temporary block notice while an explanation is pending.
- Validate safety recourse metadata and render topic-specific explanations with safer ways to continue for biological and cybersecurity policy blocks. Apply the explanation only when the terminal policy error matches its domain; otherwise retain the existing error handling.
- Queue input while recourse is pending and preserve prepared images when queued messages are submitted.

## Testing

Add an integration test covering biological and cybersecurity blocks, the loading notice, and fallback for a mismatched policy error, plus a snapshot of the cybersecurity explanation. Extend queued-image coverage to verify submission succeeds after the original image file is removed.

GitOrigin-RevId: dd9ca57cf3b2d842e3deb8aff5d7c3c73a92e14d
2026-10-27 05:15:31 +00:00
Ian MacLeod b52a272cff Render async questions and replies with Markdown in the TUI (#57292)
## Why

Async question replies appeared as plain user text, leaving Markdown formatting literal and repeating the full question above each answer.

## What changed

- Accent question titles with a `?` prefix while preserving Markdown in titles and suggestions.
- Render replies with a `↪ Re:` question caption and a Markdown answer. Limit captions to two rows with an ellipsis on overflow, while keeping answers complete.
- Apply the same rendering to live messages and loaded transcripts, preserving inline styles, hyperlinks, and Markdown when copying selections.

## Testing

Add snapshots and assertions for matching live and loaded transcript rendering, plus tests for caption clipping, hyperlink bounds, Markdown copying, partial selections, and whitespace-only or nonprinting answers.

GitOrigin-RevId: 0290d8a2ebfb42bd5d7374c7037cde5ae8a13b5d
2026-10-26 22:12:07 +00:00
Charlie Marsh a797dd7c6f Expose lifecycle timestamps on app-server thread items (#57172)
## What changed

- Add nullable `startedAtMs` and `completedAtMs` fields to `ThreadItem` in live notifications and turn history. Values are Unix milliseconds when recorded.
- Preserve recorded item times through history reconstruction, pagination, and resume, including command start times recorded during approval.
- Separate the Rust item payload into `ThreadItemPayload` while keeping the JSON payload flat, and update consumers, schemas, and generated TypeScript and Python types.

## Testing

Extend coverage for timestamp serialization, history reconstruction, paginated reads and resume, and persisted Python SDK items.

GitOrigin-RevId: ecbcee95af52db7c807b46a6e9deb30e5fba1f80
2026-10-26 18:13:00 +00:00
Eric Traut 7389eebf45 Fix TUI permission selection and session state handling (#55682)
## Why

Queued prompts can resume before a pending permissions menu opens, and local
`/permissions` commands can bypass guards for outstanding permission changes.
Attaching to a different project can also retain model access information from
the launch directory.

## What changed

- Route `/permissions` through app permission guards and hold queued prompts
  while the menu is pending. Settle the hold when opening is rejected, discovery
  is invalidated, or a covering request is resolved.
- Apply the custom permission profile selection check beyond embedded servers.
- Refresh API-key model access when the first attached session changes the
  working directory, including with an embedded server. Propagate the widget's
  model catalog to the app and server even when the model response matches the
  widget's already-updated catalog.
- Skip sessions reported as `thread not loaded` during name lookup for all
  server types instead of falling back to unverified list metadata.

## Testing

Add regression coverage for permission guards, queued prompts across successive
permission menus, invalidated and covered menus, model catalog propagation,
project changes on initial attachment, and name lookup across server pages with
unreadable entries.

GitOrigin-RevId: eb49cb5268ce0ce1e40009b73a0180f23e61ed72
2026-10-20 21:40:30 +00:00
Channing Conger 8dd6099e26 Remove thread title generation spinners from the TUI (#55324)
## What changed

Stop showing title-generation spinners in the footer, status line, and terminal title. Remove the associated UI pending state and animation refresh logic while retaining background title generation.

## Testing

Add a snapshot covering the footer and terminal title while automatic naming is pending. Update status-surface snapshots to cover thread names and ID fallbacks without progress indicators.

GitOrigin-RevId: 061456929149c216f0a98d7214179ec69cdaeee4
2026-10-19 17:09:36 +00:00
Felipe Coury 141bf7680d Add session-only arguments to /title and /statusline (#54387)
## What changed

Allow inline item selection, such as `/title model reasoning` and `/statusline current-dir --no-colors`, without changing saved defaults. Support `--clear` for both commands and `--colors` or `--no-colors` for `/statusline`, including color-only updates that preserve the current items.

Carry overrides with per-thread input state across navigation and reconnects, and allow these local commands in parent-owned subagent threads. Reject invalid or conflicting arguments before applying changes. Saved editor selections supersede the corresponding overrides.

## Testing

Add coverage for argument parsing, atomic updates, rate-limit item aliases and ambiguity, thread-state restoration, saved-setting interactions, and local command submission in parent-owned threads.

GitOrigin-RevId: 909cc2ede026fbf5c7f9cd52c8cf2ae835084f14
2026-10-15 19:11:32 +00:00
Felipe Coury 36803b180a Allow saving current permission settings as presets (#54385)
## Why

Creating a preset from current settings only offered the model. Permission presets need to preserve the profile, approval policy, and reviewer to restore the same settings.

## What changed

- Add a “Current permissions” option alongside “Current model” when creating a preset from settings.
- Extend `/permissions` with `--approval-policy` and `--reviewer`, including granular policies and quoted profile names.
- Share argument parsing between `/model` and `/permissions`, supporting quoted arguments and both `--setting=value` and `--setting value` forms.
- Keep full-access confirmation for every reviewer and reject automatic review when unavailable.

## Testing

Add parser tests, preset picker snapshots, and permission-selection tests covering complete settings restoration, invalid arguments, unavailable automatic review, and full-access confirmation.

GitOrigin-RevId: f4c9c3f6e264ee8ea4c5244c79f39f2deb15b771
2026-10-15 19:11:06 +00:00
Felipe Coury b095b2ef23 Support inline permission profile selection with /permissions (#54383)
## What changed

Allow `/permissions <profile-id>` to select a built-in or custom permission profile, for example `/permissions :read-only`. Support `:ask-for-approval` and `:approve-for-me` aliases while preserving feature gates, profile requirements, full-access confirmation, and Windows sandbox setup.

Hold queued input until the selection is confirmed, and retain it on cancellation or failure. Reload custom profile definitions on re-selection without leaving unchanged requests pending.

## Testing

Add coverage for unknown and disabled profiles, approval aliases, confirmation and cancellation, discovery retries, Windows sandbox setup, and queued prompts waiting for server confirmation.

GitOrigin-RevId: ada38d3cfc6d6ac4e84ce5645fe33432c55d63cc
2026-10-15 19:09:34 +00:00
Felipe Coury 111362a6a0 Add a keyboard shortcut menu for presets (#54381)
## What changed

Replace the `/presets` recall picker with a responsive menu above the composer. Press `0`–`9` to run a saved preset or create one in an empty slot; use `n`, `s`, `e`, and `d` to create, start from current settings, edit, and delete presets.

Add `tui.keymap.chat.open_presets` with an implicit `leader p` shortcut that yields to existing bindings and explicit configuration. Show the action in `/keymap` and add a shortcut tooltip.

Preserve the composer draft, respect popup ownership, and consume held-key repeats after menu actions.

## Testing

Add snapshots for empty, populated, and narrow preset menus, plus coverage for draft preservation, cancellation, held-key handling, transcript search precedence, and default shortcut conflicts.

GitOrigin-RevId: f438c7015dbd416c90cdeb479d2a15d9d6d24954
2026-10-15 19:02:34 +00:00
Felipe Coury dcd9e95459 Add /presets for reusable prompts and slash commands (#54380)
## What changed

- Add a TUI picker with ten numbered preset slots, an editor, and confirmation before replacement or deletion.
- Create presets from composer text or current model, reasoning effort, and speed settings. Run saved inputs through the normal queued submission path while preserving the composer draft.
- Persist presets under `tui.presets` in the active user configuration, respecting configuration layer ownership and leaving in-memory settings unchanged when writes fail.
- Preserve permissions when changing effort or speed for the effective model, keep default collaboration settings intact in Plan mode, and allow standard-speed selection with older app servers.

## Testing

Add persistence tests for save, replace, delete, configuration ownership, and write failures; picker and confirmation snapshots; and regression coverage for model permissions and standard-speed fallback.

GitOrigin-RevId: 5f11699112cd404cc8e954872d53495c6edd0c0a
2026-10-15 19:02:09 +00:00
Felipe Coury 0884c8047a Support inline model, reasoning, and speed selection in /model (#54378)
## What changed

Allow `/model [model] --reasoning <level> --speed <tier>` to update the current session without changing saved defaults. Both space-separated and `=` flag values are supported; omitting the model applies settings to the current model. Bare `/model` still opens the picker.

Validate model availability, supported reasoning levels, and speed tiers before applying changes. Reject unknown flags, duplicate settings, and missing values. Apply model, reasoning, and speed together after server acceptance.

Restore each thread's speed when switching threads, and use destination configuration defaults for new sessions instead of carrying over the active session's speed.

## Testing

Extend regression coverage for inline commands, invalid arguments, unchanged saved defaults, settings-only updates to hidden current models, destination speed defaults, and speed restoration on the next turn after switching threads.

GitOrigin-RevId: ad9cecbdb3554e34a6518367364978a37fb68439
2026-10-15 19:01:10 +00:00
Ian MacLeod c22a06c180 Record bucketed terminal sizes in TUI telemetry (#53859)
## What changed

- Add `terminal_columns` and `terminal_rows` buckets to `codex.tui.start`.
- Record `codex.tui.terminal_size` for new turns in the active thread and for resize bucket changes after the terminal size settles for 15 seconds. Reuse launch context and suppress duplicate turn notifications.
- Respect analytics consent for the built-in metrics exporter while allowing explicitly configured OTLP collectors. Apply consent checks to the active exporter across provider replacements.

## Testing

Add coverage for exporter replacement and consent after config reloads. Extend the PTY integration test to verify startup size buckets, turn-start observations, and delayed resize observations with analytics disabled and an explicit OTLP collector.

GitOrigin-RevId: e01a900cd3f04a36731078f725c75374596cb01b
2026-10-14 03:52:30 +00:00
Felipe Coury cc7ba33601 Add a searchable /config preferences panel to the TUI (#52990)
## What changed

- Group preferences into Appearance, Notifications, Input, Sessions, and Text selection tabs, with search and links to existing theme, status line, terminal title, and keyboard editors.
- Persist preference changes to the selected local configuration file, apply supported changes immediately, and show save errors, configuration overrides, and restart requirements in the panel.
- Add a delayed notification test and controls for notification timing while preserving custom event filters.
- Add `tui.copy_on_select_clear_selection`, disabled by default, to clear transcript selection highlights only after confirmed automatic clipboard delivery.
- Keep local configuration editors usable while disconnected and prevent held activation keys or buffered input from triggering actions across editor and reconnect transitions.

## Testing

Add regression tests and rendering snapshots for panel navigation, search, dependency states, editor handoffs, offline persistence, notification timers, custom filter preservation, and confirmed-copy deselection.

GitOrigin-RevId: a16d218046060fcb6e61705a803fcd9297266e6e
2026-10-10 22:28:01 +00:00
Benjamin Carlsson 322bbf4d84 Classify voice session failures and record terminal outcomes (#52756)
## 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
2026-10-10 02:54:59 +00:00
Felipe Coury 4bad6d78e9 Report terminal program status with OSC 7501 (#52725)
## Why

Lifecycle status reporting was limited to direct iTerm2 sessions. OSC 7501 lets other terminals receive Codex's program state.

## What changed

- Emit OSC 7501 with `app=codex` and states `idle`, `working`, or `blocked` whenever stdout is a terminal, including multiplexed sessions. Report `blocked` when user action is required.
- Continue emitting iTerm2's OSC 21337 status and bounded activity details in direct iTerm2 sessions.
- Clear status before handing the terminal to an external program, as well as on suspension and exit, and re-emit the current state after returning.

## Testing

Add coverage for OSC 7501 encoding, combined iTerm2 output, clearing both protocols, and protocol selection across terminal and multiplexer environments. Update lifecycle tests and status snapshots for the new protocol.

GitOrigin-RevId: 6d2a6885687b0e7af825e954fab72db0765c9a07
2026-10-09 23:43:10 +00:00
Felipe Coury 39f4277087 Enable text selection in the fullscreen TUI footer (#52270)
## What changed

Allow mouse selection and plain-text copying of rendered status and footer text, honoring `tui.copy_on_select` and existing selection keyboard controls. Keep the selected region stable while other content updates, preserve Unicode and terminal hyperlinks, and clear selections when their region becomes invalid.

Defer warning clicks until a stationary mouse release so dragging selects text without opening the warning viewer. Preserve the composer draft and cursor while selecting footer text.

## Testing

Add unit and snapshot coverage for visible-text copying, Unicode and hyperlinks, selection invalidation, keyboard ownership, and stationary clicks versus drags. Add a fullscreen integration test for warning selection and draft preservation.

GitOrigin-RevId: dd14d7ede52e97e507be24c4d6ac0299f7388a9b
2026-10-08 20:49:14 +00:00
Felipe Coury 96d238d0b9 Include foreground activity in iTerm2 session status (#52226)
## Why

The iTerm2 session status reports `Working` without describing the current activity.

## What changed

Populate the OSC 21337 `detail` field from the TUI status header during foreground work, for example `Reading source`. Leave it empty for idle, waiting, background-only work, and the generic `Working` header.

Reuse terminal-title text filtering and the 240-character limit, then escape semicolons and backslashes for the status payload. Include detail in the emission cache so activity changes update the terminal even when the lifecycle state stays the same.

## Testing

Add coverage for foreground-only details, payload encoding, text filtering and truncation, and cache updates when the detail changes.

GitOrigin-RevId: b27a287b80e0db52be6cd9d5d246f03897e2996b
2026-10-08 18:56:04 +00:00
Felipe Coury ade12342e2 Expose Codex lifecycle status in iTerm2 sessions (#52203)
## What changed

Emit `Idle`, `Working`, or `Waiting` with colored indicators through iTerm2's `OSC 21337` session status protocol. Pending user action takes precedence over running tasks and background processes.

Limit emission to direct iTerm2 TTY sessions without a terminal multiplexer. Deduplicate successful writes, refresh status after terminal handoffs and resume, and clear status on suspension and exit.

## Testing

Add coverage for lifecycle transitions, protocol encoding, terminal detection, write retries, deduplication, and re-emission after terminal handoffs.

GitOrigin-RevId: 750e9ec92aeefc57651886a08ef6aea07675d175
2026-10-08 18:07:35 +00:00
Adam Perry @ OpenAI c9870d0157 Use PathUri for skill identity and path matching (#51482)
## Why

Skill selection and disabled-path matching need to recognize equivalent Windows paths across case and separator differences while preserving literal spaces, `%`, and `#` in native filenames.

## What changed

- Carry `PathUri` through skill metadata, discovery mappings, filesystem lookups, disabled-path sets, and invocation analytics.
- Match linked skill mentions and TUI selections by parsed path identity.
- Use `LegacyAppPathString` for app-server skill paths and regenerate schemas and SDK types, preserving native path strings on the wire.
- Preserve native catalog display paths and ordering. Keep host filesystem probes and configuration writes restricted to host-compatible paths.

## Testing

Add regression tests for Windows path identity and disabled-skill matching, literal filename characters, catalog resource reads, native path ordering, and foreign-path analytics normalization.

GitOrigin-RevId: c212916dc9fef0e7616542726e107f0d6a313267
2026-10-06 21:29:35 +00:00
Eric Traut ff9ab4aed9 Suppress repeated image paste presses in legacy terminals (#51411)
## Why

Legacy terminals report key auto-repeat as new presses, which can trigger repeated image pastes when presses accumulate during a slow paste.

## What changed

Suppress repeated `Ctrl+V` and `Alt+V` image paste presses within a sliding 250 ms window, refreshed after each suppressed press and after a paste completes. Clear suppression on other ordinary key presses or key release events so a fresh paste can proceed immediately.

## Testing

Add regression coverage for repeated presses, window expiry, and resetting suppression on another key press or a key release. Update the shortcut remapping test to release the key between image pastes.

GitOrigin-RevId: 45abc056e5bda47d1c9704702e369e63dcce29db
2026-10-06 16:41:53 +00:00
Benjamin Carlsson d42aecc56b Center TUI confirmations over their retained backdrop (#50504)
## What changed

Render confirmation dialogs as centered overlays while preserving the composer or parent picker behind them. Share dialog sizing and cursor placement across stacked views and full transcript rendering, with input still routed exclusively to the active dialog.

Use the shared confirmation preset for prompts including full access, session archive/delete, goal changes, and log upload consent.

## Testing

Add coverage for backdrop retention and cursor routing at multiple terminal sizes, and for preserving the compact viewport and composer draft after dismissing a confirmation without replaying history. Update confirmation snapshots to show the retained backdrop.

GitOrigin-RevId: 026af89904ec345e2b330317b8cc844512125d0e
2026-10-03 03:00:46 +00:00
Benjamin Carlsson 37f53199a6 Use the shared text editor for command-center task renaming (#50216)
## What changed

Replace the rename field with a single-line `TextArea` that honors configured editor bindings and the composer's Vim setting. Start renaming in insert mode and support Vim Escape recovery on legacy terminals.

Strip carriage returns and newlines from titles and pasted text, keep Vim linewise pastes inline, and scroll horizontally at grapheme boundaries to keep the cursor visible.

## Testing

Add single-line editor coverage for newline filtering, Vim commands, repeat edits, and inline yanks. Extend command-center tests to cover Vim renaming across status-filter changes and cursor placement in narrow layouts.

GitOrigin-RevId: 8d320d6b6de9f77e18292169418383929ca6ceda
2026-10-02 07:22:28 +00:00
Eric Traut cb6da58876 Use the server permission catalog for TUI permission shortcuts (#50140)
## Why

Permission shortcuts checked local configuration while the picker used the connected server's catalog and requirements. Shortcuts should respect the same server restrictions, including model-specific auto-review requirements.

## What changed

- Share a cached server catalog between the permission picker and shortcuts. Show the loading picker when no catalog is available and reuse an outstanding fetch.
- Clear the cache on session, account, working-directory, or connection changes.
- Give discovery RPCs distinct request IDs for each fetch and profile page so repeated requests after timeouts do not collide.

## Testing

Add coverage for loading and catalog reuse, managed permission restrictions, and refetching after disconnect. Update timeout coverage to verify that repeated discovery attempts use distinct IDs and each reports a timeout.

GitOrigin-RevId: 7d79874294136bfe3a654bb306eb7caf36d4df1e
2026-10-02 01:34:23 +00:00
Eric Traut e1522188e9 Add a persistent /daybreak toggle to the TUI (#49858)
## What changed

- Add `/daybreak` with account-aware help and availability messages for broader access for cybersecurity work.
- Save the selection in thread metadata and the `daybreak` default for new threads, restore it on resume, and confirm that it applies to new turns.
- Select `cyberAccessProgram` from the connected server's model catalog. Require a signed-in ChatGPT account, the OpenAI provider, and confirmed model support when Daybreak is enabled, including for faster-model retries. Keep Daybreak disabled for side conversations.

## Testing

Add tests for toggle persistence, turn access-program selection, unsupported-model rejection, side-conversation behavior, command help, and the resumed-thread banner.

GitOrigin-RevId: e3c028b0a6a8e0a862c16fdc766f374aae618ef1
2026-10-01 04:17:31 +00:00
Eric Traut f58ed54a9d Use the model catalog to select TUI cyber refusal guidance (#49857)
## What changed

Select cyber refusal notices from the current model's `available_access_programs` for ChatGPT accounts using the OpenAI provider. Show Astra-specific guidance only when an Astra model offers standard cyber access without Daybreak access, and use the limited notice when Daybreak access is available. Otherwise, show application guidance.

Remove the separate account eligibility request, background prefetching, and notice cache.

## Testing

Update tests to cover catalog-based notice selection, missing model metadata, isolation from other models' access programs, and rendering the application notice for a cyber policy error.

GitOrigin-RevId: 88e9522bd6ece2d2b9caa6cff01a4178768babb7
2026-10-01 04:17:07 +00:00
dennyku 60947e2341 Add account security setup reminders to the TUI (#49715)
## What changed

Fetch optional security setup notices asynchronously for local ChatGPT sessions using the OpenAI provider. Verify that saved credentials match the connected app server, ignore stale account responses, and validate notice text and HTTPS actions on `chatgpt.com`.

Show notices as dismissible inline banners with a browser action, while giving applicable usage banners priority. Preserve notice state and dismissal across thread changes, reconnects, and banner replacement for the same account and user.

## Testing

Add authenticated HTTP fixture tests, notice validation tests, and TUI tests covering stale responses, dismissal persistence, usage banner priority, browser actions, and wrapping in narrow terminals.

GitOrigin-RevId: b8635fcf6a26b42b6a06640601c8517d8d5e47e8
2026-09-30 19:22:34 +00:00