Commit Graph
521 Commits
Author SHA1 Message Date
Eric Traut 9d57be71ba Separate TUI preferences from server configuration (#42202)
## Why

TUI preferences and persistence paths belong to the local client, while thread
configuration and account requirements may come from the active app server.
Keeping both in the same resolved `Config` can replace live local preferences
when a thread is resumed, forked, reconnected, or switched.

## What changed

- Add `LocalSettings` as the TUI-owned source for UI, history, notice, and local
  persistence settings, and preserve it across session lifecycle transitions.
- Write preference changes to the selected user config file and reload local
  settings from disk when changing roots.
- Use the app server's account response for authentication-dependent onboarding
  and status UI instead of the local model-provider configuration.
- Retain platform family and OS metadata reported by remote app servers.

## Testing

- Cover local setting defaults, overrides, persistence destinations, reloads,
  and preservation across widget replacement and root switching.
- Cover remote platform metadata and server-controlled authentication UI.

GitOrigin-RevId: dbc2965fb1d6cbecb3f973f6133f3dcd4467b753
2026-09-02 04:20:38 +00:00
Eric Traut f40e08478c Show recent sessions in the agent command center (#42104)
## Why

The agent command center only listed sessions currently loaded by the app server, so completed or otherwise unloaded tasks could not be revisited from the overview.

## What changed

- Seed the overview with up to 20 recent root sessions in addition to loaded sessions, retain discovered sessions for the lifetime of the TUI, and update rows from thread lifecycle notifications.
- Allow unloaded sessions to be resumed from the overview using the normal working-directory selection and configuration rebuild flow. Explicit runtime permission choices carry across a cold resume, while settings inherited from the previously selected task do not.
- Fall back from `recency_at` to `updated_at` when connected to an older server, and continue showing loaded sessions when recent-history listing is unavailable.

## Testing

Added coverage for recent-session discovery and retention, notification races, legacy and failed listing fallbacks, cold-resume working-directory and permission handling, reconnect behavior, and unloaded-session rendering and selection.

GitOrigin-RevId: 668068b1594eb24b2ea7faccd0327804b8cd22ef
2026-09-01 17:28:35 +00:00
Felipe Coury 8ea297ff60 Add a TUI setting to disable automatic recaps (#42101)
## What changed

- Add the `tui.auto_recap` configuration option, enabled by default.
- When disabled, cancel scheduled automatic recap checks, reject automatic
  requests, and discard pending automatic results without retrying.
- Keep manual `/recap` requests available regardless of the setting.

## Testing

- Cover configuration defaults and command-line overrides.
- Cover scheduling cancellation, pending request cleanup, discarded results,
  and manual recaps while automatic recaps are disabled.

GitOrigin-RevId: 7d5323f58a2c84e60683a25a8c77653097efe6e2
2026-09-01 17:09:13 +00:00
Benjamin Carlsson 0e03f88a30 Clarify resume guidance in exit summaries (#41938)
## What changed

- Show the exact `codex resume <thread-id>` command on its own indented line.
- When a thread has a name, also explain that users can run `codex resume` and select the named thread from the picker.
- Apply command highlighting to both resume options when color is enabled.

## Testing

- Cover unnamed, empty-name, named, colored, and embedded-session exit summaries.

GitOrigin-RevId: d97c04db8a34376c6d9ea839b515b04a384b85d1
2026-09-01 00:02:38 +00:00
Eric Traut a7913390f7 Preserve TUI drafts after app-server disconnects (#41911)
## Why

Losing an external app-server connection can leave a submission's outcome uncertain. The TUI must preserve local work without retrying it or allowing stale server events to trigger more actions.

## What changed

- Enter an offline state when an external app-server transport disconnects during startup, event streaming, or submission.
- Keep conversation drafts, queued input, expanded pastes, attachments, and agent-overview input editable while blocking submissions, remote actions, and automatic queue replay.
- Show a connection-lost notice that directs users to copy their work and relaunch, while retaining `Ctrl-C` and an empty-composer `Ctrl-D` as quit shortcuts.
- Cancel pending views and asynchronous work, and ignore stale completions after the disconnect. Embedded app-server behavior is unchanged.

## Testing

Added unit, snapshot, and pseudo-terminal coverage for lost startup and mutation replies, offline draft editing, queued-input recovery, stale-event quarantine, agent-overview behavior, and end-to-end preservation without reconnection or resubmission.

GitOrigin-RevId: 7219a95fad676dda447d625db9e465345b469d58
2026-08-31 21:00:25 +00:00
stefanstokic-oai 79b04f1ab5 Show actionable rate-limit banners in the TUI (#41742)
## What changed

- Carry optional backend-owned banner and account identity data through
  `account/rateLimits/read`, filtering banners that do not match the authenticated
  account and user.
- Render supported rate-limit notices above the composer with actions for usage,
  credits, resets, owner notifications, and plan management while preserving the
  existing fallback UI for absent or unsupported banners.
- Refresh usage after limit errors, reject stale responses, and keep queued input
  paused until recovery completes. When instructed by the banner, switch to the
  first available fallback model without changing unrelated thread settings.

## Testing

- Add protocol, banner parsing and rendering, CTA, identity filtering, refresh
  ordering, fallback-model, account-change, and queued-input recovery coverage.

GitOrigin-RevId: e03d75a82e425deb87f4b120a71cf2286c0ef6cc
2026-08-31 00:20:06 +00:00
Eric Traut c29bc99949 Preserve restored permission profiles in TUI sessions (#41192)
## Why

Restored app-server threads can carry permission profiles that cannot be
represented without loss as legacy sandbox-mode overrides. Sending those
profiles as per-turn overrides can discard their original permission details.

## What changed

- Distinguish restored permission profiles from legacy per-turn sandbox
  overrides.
- Preserve restored profiles while routing turns and changing to compatible
  working directories.
- Reject `/cd` when a restored profile cannot be represented safely by a
  legacy sandbox mode.

## Testing

- Cover retaining a restored read-only profile across `/cd` without a turn
  override.
- Verify that lossy sandbox-mode projections are detected.

GitOrigin-RevId: 6143dca4b83ab4f59bab05f6a59b4fe841c56192
2026-08-27 19:51:10 +00:00
Felipe Coury 40ba7da7b4 Prepare automatic TUI recap generation (#40697)
## What changed

- Schedule recap eligibility checks when an unfocused thread changes, and cancel them when focus returns or recap state is replaced.
- Add bounded structured recap requests with stale-result rejection, normalized output, and one retry per turn revision.
- Harden temporary structured threads by reading the effective configuration and disabling all discovered MCP servers, tools, skills, and environment access.

## Testing

- Cover recap timers, focus changes, failed turns, output bounds, stale results, and retry behavior.

GitOrigin-RevId: eebf50059763928e9a2444b14d51648e0bdff4a8
2026-08-25 20:56:03 +00:00
Felipe Coury 7c1e36c23f Prepare the TUI for conversation recaps (#40696)
## What changed

- Forward terminal focus changes through the TUI event stream and handle them across interactive screens.
- Track completed turns and recap eligibility across active, resumed, and switched threads.
- Add bounded recent-conversation prompt construction and a wrapping `Conversation recap` history cell.
- Cover focus timing, repeat eligibility, restored progress, UTF-8 prompt limits, and recap rendering with unit and snapshot tests.

GitOrigin-RevId: d7542c18b2bb1e72f5906f563898645bb526255f
2026-08-25 20:51:34 +00:00
Eric Traut 731d969d03 Clarify session exit messages (#40670)
## What changed

- Report `Session archived: <thread-id>` after successfully archiving the current session.
- Show the session ID when no resume hint is available, including for non-fatal exits.
- Keep deleted-thread exits distinct from successful archive exits.

## Testing

- Add coverage for archive lifecycle handling and exit-message formatting.

GitOrigin-RevId: 1812374e4c74fa1b3f11feb323de18a9dbff745b
2026-08-25 18:27:42 +00:00
Tamir Duberstein a95391160a Drive TUI stream animation from the foreground loop (#40644)
## Why

Stream animation ticks generated on a background thread can accumulate while the
TUI is busy, causing stale ticks to run after the animation stops or the chat
widget is replaced.

## What changed

- Replace the animation thread and `CommitTick` app event with a Tokio interval
  owned by the foreground event loop.
- Delay missed ticks instead of replaying a burst, and let pending app events run
  before animation work.
- Drop the interval when animation stops or the chat widget is replaced, while
  preserving `CommitTick` session-log entries.

## Testing

Add a paused-time test covering stable pacing, missed ticks, restart behavior,
and chat-widget replacement.

GitOrigin-RevId: d0561d3f8962b5e05a728463e76aa8ec83cd5a31
2026-08-25 17:17:01 +00:00
Eric Traut a63cb33e8d Show reconnect guidance when disconnecting from tasks (#40629)
## Why

Exiting a TUI connected to a persistent app server can leave work running, so
the existing session-exit summary does not explain how to reconnect or stop the
active turn.

## What changed

- Distinguish disconnects, interrupted turns, and removed threads when building
  exit summaries.
- For daemon and remote sessions, report whether work may still be running and
  print commands to reconnect or stop the current turn.
- Sanitize remote WebSocket addresses in displayed commands and preserve the
  configured remote authentication environment-variable option.
- Keep the existing token-usage and resume summary for embedded sessions.

## Testing

Add coverage for daemon, remote, interrupted, embedded, archived, and deleted
session exits, including credential sanitization.

GitOrigin-RevId: 9cbbf9c7dd36423a5ed99909a2b4cb32e3e87712
2026-08-25 15:55:35 +00:00
Felipe Coury b3c7e1a47f Generate descriptive TUI thread titles (#40492)
## What changed

- Give unnamed TUI threads an immediate provisional title from the first user message, then replace it asynchronously with a normalized generated title.
- Preserve manual renames by applying a generated title only while the provisional title is still current, and keep automatic rename notifications out of the transcript.
- Run title generation in a bounded ephemeral structured request that preserves custom permission profiles, otherwise uses read-only access, and disables tools and MCP servers.

## Testing

- Cover prompt and response bounds, Unicode-safe truncation, title normalization, manual-rename races, silent automatic updates, permission preservation, and structured-response failures.

GitOrigin-RevId: 7ed73522f4f6c65a005f65f3a903974d8419e312
2026-08-24 23:06:06 +00:00
Eric Traut a8468330bb Add TUI tools for managing Codex tasks (#40308)
## Why

The TUI rejected app-server dynamic tool calls as unsupported, so agents could
not inspect or manage other Codex tasks through a TUI session.

## What changed

- Add the `codex_tui` tool namespace for listing, reading, waiting on, creating,
  forking, messaging, renaming, archiving, and restoring tasks.
- Handle tool calls through existing app-server thread operations, with bounded
  inputs and responses and cleanup when calls complete or the TUI disconnects.
- Route delegation tools through an authenticated local MCP server with explicit
  approval prompts, while respecting configured and managed MCP policies.
- Fall back to starting threads without dynamic tools when connected to an older
  app server that does not support them.

## Testing

Add coverage for tool schemas and response bounds, task lifecycle operations,
approval-gated MCP transport, namespace dispatch, cancellation, and legacy
app-server fallback behavior.

GitOrigin-RevId: c782c11f0a3edceb3fa6909a4b92d6ce01a6eed3
2026-08-24 01:50:53 +00:00
Eric Traut 2aaefa32b0 Add keybindings for cycling TUI permission modes (#39873)
## What changed

- Add unbound `previous_permission_mode` and `next_permission_mode` actions to
  `tui.keymap.chat` so users can configure shortcuts that cycle through the
  available built-in permission modes.
- Apply shortcut selections only to the active session, without writing them
  to `config.toml`, and report update failures in the transcript.
- Exclude modes disallowed by managed requirements or platform safety checks,
  reject printable-key bindings, and ignore these bindings in project config.

## Testing

- Cover mode cycling, unavailable modes, session-only updates, server errors,
  stale threads, keymap validation, and project-config sanitization.

GitOrigin-RevId: c3cfdf1e732b7b7bfe8f53fcac19a37e593bbfab
2026-08-21 06:19:23 +00:00
Jeremy Rose d944ce83a2 Prompt to unarchive sessions before resuming or forking (#39640)
## Why

Starting an archived session with `codex resume` or `codex fork` stopped with
guidance to run a separate `codex unarchive` command first.

## What changed

- Detect archived-session startup failures and offer to unarchive and retry the
  requested operation.
- Allow the user to cancel without modifying the archived session.
- Render the confirmation in the alternate screen when available and preserve
  inline terminal context when `--no-alt-screen` is set.
- Preserve `--no-alt-screen` whether it appears before or after the `resume` or
  `fork` subcommand.

## Testing

- Cover confirmation, cancellation, retry behavior, and unrelated startup
  failures for both resume and fork.
- Add prompt interaction and terminal rendering coverage, including narrow and
  inline viewports.

GitOrigin-RevId: 382cdbd15b5d12c091e554d6d3a2f9b3589654f4
2026-08-20 07:25:40 +00:00
Eric Traut e7f9fa9cd9 Show file destinations in TUI change approvals (#39285)
## What changed

- Show a description and the destination paths affected by each file-change approval.
- Include both source and target paths for moves, format cross-platform paths for display, and show `unavailable` when change details are missing.
- Recover file changes from buffered events and thread snapshots so live and replayed approvals retain their destination details.

## Testing

- Add coverage for active and replayed approvals, moved and cross-platform paths, and the missing-destination fallback.

GitOrigin-RevId: 24f90b313fd8643f90cbead1504c788b140d7fed
2026-08-18 21:43:22 +00:00
Eric Traut 4617d4d21d Add an agents overview dashboard to the TUI (#39094)
## What changed

- Add `/agents` to open a full-screen dashboard of loaded root sessions from the shared app server, with subagent status reflected in each root session.
- Support search, navigation, and grouping sessions by project or status.
- Refresh the dashboard when relevant thread notifications arrive, while preserving its selection and view preferences.
- Show a clear message when the dashboard is unavailable with the embedded app server.

## Testing

- Add coverage for dashboard rendering, status grouping, persisted view state, and restoring the conversation viewport after closing the dashboard.
- Cover `/agents` command discovery and dispatch from parent-owned threads.

GitOrigin-RevId: 6651f4c47358116e1809da3ac8844a5842026a95
2026-08-17 22:50:25 +00:00
Tamir Duberstein 9c099e94a2 Bound TUI thread replay buffers by delta size (#39081)
## Why

The per-thread replay buffer limited its event count, but streamed agent-message
deltas could still retain an unbounded amount of text while a thread was
inactive.

## What changed

- Coalesce adjacent deltas for the same thread, turn, and item into chunks of up
  to 4 KiB.
- Limit buffered agent-message deltas to 256 KiB, discard a single delta larger
  than that limit, and evict the oldest events when either buffer limit is
  exceeded.
- Keep pending input and approval state in sync when eviction removes the
  corresponding request, including clearing side-thread status indicators.

## Testing

Added coverage for delta coalescing, byte-based eviction, oversized deltas,
replaying only retained text, and side-thread status updates after eviction.

GitOrigin-RevId: 88d85353a124467d467822d2fd9854312b68d547
2026-08-17 21:03:06 +00:00
Charlie Marsh fe5889928c Use installed callable apps for TUI mentions (#39051)
## Why

The app directory is a discovery catalog and can include apps that are not
callable in the active thread. Using it for `$` suggestions can therefore
offer mentions that cannot be used.

## What changed

- Load mention candidates from `app/installed`, enrich callable apps through
  bounded `app/read` batches, and retain compatibility with app servers that
  do not support `app/installed`.
- Keep the mention catalog separate from the `/apps` directory cache and scope
  results to the current thread, workspace, and account.
- Refresh mentions after app notifications, enablement changes, configuration
  updates, and apps MCP readiness, while immediately removing disabled apps.

## Testing

Add coverage for batching and fallback behavior, stale scoped results,
notification refreshes, enablement changes, MCP startup races, and filtering
non-callable apps from mentions.

GitOrigin-RevId: 4d9e20794aed30cc97120170792fb555b86fe1e7
2026-08-17 19:11:34 +00:00
Benjamin Carlsson ed32158e90 Add working-directory commands to the TUI (#38894)
## What changed

- Add `/cd [path]` for changing an idle local session's working directory while preserving conversation history. Relative paths resolve from the current directory, and omitting the path selects `~`.
- Reload project configuration, instructions, permissions, keybindings, file search, and hooks for the destination before replacing the active session.
- Reject unsafe transitions, including active or queued work, background terminals, remote environments, untrusted destinations, and incompatible permission profiles.
- Add `/pwd` and its `/cwd` alias to display the current working directory, and discard asynchronous results left over from the previous directory.

## Testing

- Cover command parsing, aliases, default paths, session eligibility, transition failures, history preservation, destination policy loading, hooks, and stale events.

GitOrigin-RevId: 1a987c029f157a087ba02c0f26e022260409132b
2026-08-16 19:48:07 +00:00
kevinlin-openai 3685a61dad Normalize CRLF line endings in pasted text (#38704)
## Why

Replacing every carriage return with a line feed turns each CRLF pair into two
line breaks when text is pasted into the TUI composer.

## What changed

Normalize CRLF pairs before converting remaining bare carriage returns, so each
pasted line ending becomes a single line feed while existing line feeds remain
unchanged.

## Testing

Add a regression test covering mixed CRLF, bare CR, and LF line endings.

GitOrigin-RevId: 86c66d2a52fae52c9ae58c2f24a49eed685b60be
2026-08-15 05:43:44 +00:00
Charlie Marsh a0bed4be21 Keep the composer editable during TUI startup (#38642)
## Why

Configuration and app-server initialization can take time before the main TUI is ready, leaving users unable to begin drafting a prompt.

## What changed

- Show a provisional composer while startup work runs and carry its text, cursor position, paste state, and attachments into the initialized chat.
- Limit the provisional composer to safe editing and cancellation, and quarantine input around session pickers, approvals, and other actionable startup screens.
- Preserve configuration validation before terminal checks and recover terminal state cleanly from startup failures and caught panics.

## Testing

- Cover startup editing, multiline and large pastes, keymaps, cancellation, session-picker handoff, approval boundaries, and draft restoration.
- Verify non-interactive launches report configuration errors before terminal errors.

GitOrigin-RevId: fe04a85cfbbcff21ff87fa81fd17474827858575
2026-08-14 20:30:30 +00:00
Charlie Marsh 58d2daba45 Harden TUI startup input handling (#38641)
## Why

Terminal probes and other bootstrap work can leave keys or partial control
sequences buffered before an interactive startup screen is visible. Those
inputs must not accidentally select or confirm an action, while typeahead
intended for the composer should survive terminal initialization.

## What changed

- Replay user input consumed by Unix startup probes through Crossterm while
  filtering completed terminal color replies, and avoid consuming the Windows
  console input queue when detecting default colors.
- Drain decoded and unread input after rendering actionable startup screens,
  including onboarding trust, migration, update, provider, resume, and hooks
  prompts. Keep incomplete control sequences quarantined and fail closed when
  an input boundary cannot be resolved.
- Restore terminal modes if initialization exits early and bound terminal probe
  reads by time and byte limits.

## Testing

Add parser, boundary, onboarding, and PTY coverage for preserved typeahead,
split escape sequences, bracketed paste, delayed input, and fresh input after
an interactive screen becomes ready.

GitOrigin-RevId: 321198996cdd88fe9b43c4a762e750bff450482c
2026-08-14 20:23:49 +00:00
Charlie Marsh 7e65e4f330 Render the initial TUI session header before input (#38639)
## What changed

- Drain queued app events until the initial session header is installed before
  handling terminal input.
- Render the active session header without a leading separator so it starts at
  the top of the viewport.

## Testing

- Add a rendering snapshot that verifies the initial header begins on the first
  viewport row.

GitOrigin-RevId: 070417776b629c681b3f94e93ba619dfefe764b1
2026-08-14 20:19:42 +00:00
Charlie Marsh 1bb6384c19 Avoid paginated resume requests for verified legacy rollouts (#38604)
## Why

Resuming a known legacy rollout with `excludeTurns` first requires the TUI to
retry after the app server rejects paginated history loading.

## What changed

- Carry the history mode reported by the session picker into the resume flow.
- For embedded app-server sessions, resume a legacy rollout with its turns when
  the rollout is still legacy and background migration cannot race the check.
- Keep requesting paginated history when the picker metadata may be stale,
  migration is enabled or active, or the app server is remote.

## Testing

Added coverage for picker server replacement, background migration, maintenance
lock contention, stale history metadata, and paginated resume requests.

GitOrigin-RevId: 2300d1ad93a817eeeeb8f8ed60b073400ddf7106
2026-08-14 16:33:28 +00:00
Eric Traut ca83f7908c Add running-task exit choices to local daemon sessions (#38447)
## What changed

When `Ctrl-C` is pressed with an empty composer while a task is running in a local daemon session, show a menu that lets the user:

- cancel the task and stay in Codex;
- exit Codex while leaving the task running; or
- stop the task and exit Codex.

Do not offer background execution for side-thread tasks or when follow-up messages are queued. Preserve existing `Ctrl-C` behavior for non-daemon sessions, drafts, paste bursts, MCP startup, and returning from an active side thread.

## Testing

Add TUI tests for each exit action, menu dismissal, side threads, queued follow-ups, composer input, MCP startup, and non-daemon sessions.

GitOrigin-RevId: 539c33d3a4ff288a015bddbe9465d2bbdbe018d0
2026-08-13 22:38:46 +00:00
Felipe Coury f1a1fce26a Show estimated thread usage in /status (#38281)
## What changed

- Extend `account/usage/read` with an optional `threadId` request and a
  backward-compatible `threadUsage` response containing estimated credits,
  optional USD cost, and model, reasoning, speed, and token breakdowns.
- Fetch thread usage for eligible Business and Enterprise plans when `/status`
  is opened, then update the rendered status card asynchronously.
- Preserve terminal scrollback when replacing a visible status-card tail, and
  append a refreshed card when the original tail can no longer be updated.

## Testing

- Add app-server coverage for authentication, canonical thread IDs,
  unavailable billing routes, and malformed IDs.
- Add TUI coverage for usage formatting, stale responses, retries, history
  updates, terminal reflow, and scrollback preservation.

GitOrigin-RevId: 49300914b3fba917c0f08e8595363e04e5ba6d37
2026-08-13 00:30:08 +00:00
Tamir Duberstein 33aaf91366 Respect rendered width when adding TUI history (#38075)
## What changed

- Initialize new chat widgets with the current terminal width.
- Determine whether an added history cell is visible using the active history
  render mode and the width available after ambient-pet reservations.
- Saturate diff-summary width calculations so extremely narrow terminals remain
  renderable.

## Testing

- Cover width-sensitive history insertion with an ambient pet, raw-output mode,
  and a diff summary narrower than its indentation.

GitOrigin-RevId: 82d20900e0637431be7646b4f4aba61810ff74c1
2026-08-11 21:12:23 +00:00
Eric Traut 2801d12661 Add Markdown conversation export to the TUI (#37358)
## What changed

- Add `/export` with clipboard and file destinations, including a default filename prompt and support for an explicit path argument.
- Export the complete conversation history as structured Markdown, preserving user and assistant messages, plans, reasoning, activity, image labels, file changes, and MCP tool details while honoring reasoning visibility.
- Fall back to legacy history loading when pagination is unavailable, and use the visible transcript for ephemeral sessions.
- Resolve relative and home-relative paths without overwriting an existing file, and report export or copy results in the conversation.

## Testing

- Cover Markdown rendering, hidden review prompts, activity details, complete paginated and legacy history loading, destination prompts, status messages, path resolution, and overwrite protection.

GitOrigin-RevId: c2815fc2430d7a555da75d7038cc1ac08157b82e
2026-08-07 02:45:35 +00:00
Felipe Coury 449f099f1c Harden paginated history handling in the TUI (#36951)
## What changed

- Keep paginated resume, transcript, and fork workflows on bounded turn and item page requests, while preserving the legacy full-history fallback.
- Refill underfilled terminal scrollback from older pages and show a transcript shortcut when earlier history is unloaded or truncated by the row cap.
- Preserve a successfully created fork if its initial history hydration fails, keep side forks bounded, and retain the correct history boundary for nested forks and subagents.

## Testing

- Add coverage for scrollback refill and truncation notices, bounded paginated requests, fork hydration failures, nested forks, and inherited subagent history filtering.

GitOrigin-RevId: 10ba952ffb2f69717fbc71aa03cac7685f7dcf78
2026-08-04 19:18:03 +00:00
Felipe Coury dbcd837c20 Paginate TUI transcript history (#36950)
## What changed

- Load older transcript items in bounded pages as users scroll upward, and let `Home` continue fetching until the start of the thread.
- Show loading, partial-history, retry, and complete states in the transcript overlay while preserving the visible scroll position as pages are prepended.
- Use paginated history for resume, fork, retry, and prompt-edit flows, while falling back to legacy history requests when the app server does not support pagination.

## Testing

- Cover multi-page transcript loading, page-boundary prompt reconciliation, legacy-server fallback, bounded retry history, and transcript history-state rendering.

GitOrigin-RevId: cc6b764bc4185d079b2f68bedf235c1d08278dfb
2026-08-04 19:12:46 +00:00
Felipe Coury 3b8d22ec2c Improve paginated TUI history loading (#36949)
## Why

Paginated sessions can have visible messages beyond the first item page, so
bounded hydration could leave resumed history or transcript previews empty and
the transcript viewer incomplete.

## What changed

- Scan paginated history until the configured rendered-row budget is filled,
  while retaining the configured scrollback beyond the visible viewport.
- Fully hydrate transcripts opened from the resume picker and build previews
  from bounded item pages, including when non-visible items precede messages.
- Stop pagination on repeated cursors and let `Esc` cancel an in-flight
  transcript load.
- Replay restored token usage for cold metadata-only resumes when its stored
  turn can be identified.

## Testing

- Add coverage for paginated and legacy transcript loading, bounded resume
  hydration, repeated cursors, transcript cancellation, and resize reflow.

GitOrigin-RevId: 2ce69f7d5eae88e2b09a27c333b00b1830ff17bf
2026-08-04 19:05:45 +00:00
Felipe Coury 8bfa49e350 Paginate transcript history in the TUI (#36948)
## Why

Paginated threads should not require the TUI to load and render their entire
history when a session is resumed.

## What changed

- Hydrate a bounded initial history page for paginated resumes and forks,
  respecting the configured terminal reflow row budget.
- Load older transcript items in the background as users navigate upward, while
  preserving the viewport, live output, and backtrack selection.
- Reconcile review-mode prompts across page boundaries and keep restored token
  usage hidden until it can be attributed to a persisted turn.

## Testing

- Added coverage for paginated resume and fork hydration, older-page merging,
  transcript prepending, backtrack behavior, review prompt filtering, and token
  usage restoration.

GitOrigin-RevId: 42160b943a9f6a1ba0cfe4b195c24ddf410b747d
2026-08-04 18:59:32 +00:00
jif 78306a32af Clarify config layer iteration APIs (#36774)
## What changed

- Replace the ordering enum and `include_disabled` boolean with named
  `ConfigLayerStack` iterators for each precedence direction.
- Keep enabled-only iteration separate from `all_layers_*` iteration, which
  includes disabled layers.
- Update config consumers to use the iterator matching their precedence and
  disabled-layer requirements without allocating an intermediate `Vec`.

## Testing

- Add coverage that verifies ordering and disabled-layer filtering for all four
  iterators.

GitOrigin-RevId: d14df3db4a2eae80ba97cdec246bff405e6c5f3d
2026-08-03 17:29:42 +00:00
Felipe Coury 1e85ca099e Support two-stroke TUI key chords (#36511)
## What changed

- Accept two-stroke bindings such as `ctrl-x ctrl-s` in TUI keymap configuration while preserving arrays as alternative bindings.
- Route chords through the active TUI context, show pending and configured chord hints, and cancel pending chords on `esc`, context changes, or a one-second timeout.
- Extend `/keymap` to capture, add, replace, and display key chords.
- Reject chords that conflict with active single-key bindings, overlapping-context chords, or reserved terminal shortcuts.

## Testing

- Add coverage for chord parsing, validation, matching, timeout and cancellation behavior, context dispatch, key capture, and rendered shortcut hints.

GitOrigin-RevId: dfdede03f518d4936ad8621ebf5537026f2b282e
2026-08-01 17:43:03 +00:00
Felipe Coury 7dc1856685 Avoid querying terminal size on every TUI redraw (#36482)
## What changed

- Carry dimensions on resize events and reuse the cached screen size for ordinary draws.
- Refresh terminal geometry after resize settling, process resume, and external program execution.
- Pass the resolved size through transcript reflow, viewport updates, and standalone TUI screens so each frame uses consistent dimensions.

## Testing

- Cover cached draws, resize-driven rendering, settled-size rechecks, resume refreshes, and alternate-screen size updates.

GitOrigin-RevId: 9d83dbab50d7a038bd59b4c66c13abcac69ddc79
2026-08-01 14:33:12 +00:00
Eric Traut d06c7ac055 Clean up side conversations in the background (#35887)
## Why

Switching away from a side conversation should not wait for its interrupt and
unsubscribe requests to finish.

## What changed

- Remove a side conversation from local TUI state immediately when switching
  threads, then interrupt and unsubscribe it in a background task.
- Retry interruption with the active turn ID when the original turn races with
  cleanup.
- Ignore late notifications and reject server requests for abandoned side
  conversations.

## Testing

- Added coverage that background cleanup removes local state and ignores late
  events and approval requests.

GitOrigin-RevId: 7a1d1c34f16ab023d1d1e235451b55404731190c
2026-07-29 03:54:05 +00:00
Eric Traut f029bb795c Refresh the subagent picker in the background (#35693)
## Why

Opening the subagent picker could wait on thread metadata and live event-store locks, delaying terminal input. Its cached entries could also omit descendants that were not observed in the current TUI session.

## What changed

- Render the picker immediately from cached navigation state and refresh root descendants asynchronously with `thread/list`.
- Merge discovered descendants into an open picker while preserving its selection and live status, and coalesce concurrent refresh requests.
- Ignore refresh responses from a previous session and avoid blocking on busy event stores.

## Testing

- Extend session lifecycle coverage for nonblocking picker opens, refresh coalescing, descendant discovery, selection preservation, and status updates.
- Add coverage for rejecting a refresh response after navigation state is cleared.

GitOrigin-RevId: 7eae7f696f8d2d323a47b3fd2800ea1c1cdbf2a0
2026-07-28 00:38:45 +00:00
Charlie Marsh eceb3eeaf3 Cache TUI flex heights across frame passes (#34348)
## Why

Sizing, rendering, and cursor placement can query the same chat widget layout
multiple times in one frame, repeatedly measuring active transcript cells.

## What changed

- Build one chat widget renderable tree per frame and reuse it for sizing,
  rendering, and cursor placement.
- Cache each flex child's desired height by width for the lifetime of that tree.
- Reuse the bottom pane's renderable directly instead of forwarding each
  renderable operation through a wrapper.

## Testing

- Verify flex layouts measure a child once across frame passes and remeasure it
  when the width changes.
- Verify a chat widget frame measures its active transcript cell once.

GitOrigin-RevId: 5ad1a6711f4011c699b5d002b13dc3319cb4db8e
2026-07-20 13:58:17 +00:00
Anais Killian 2895d82b5e Let users remember the working directory for resumed sessions (#33950)
## What changed

- Add `tui.resume_cwd` with `current` and `session` modes for resume and fork flows.
- Let users persist either mode directly from the working-directory prompt, while preserving one-time choices when no preference is configured.
- Apply the preference consistently during startup and in-app resume, honor explicit `--cd` overrides, and reject unsupported or unavailable directory choices with a clear error.

## Testing

- Cover configuration parsing and persistence, prompt behavior, startup and in-app flows, session metadata fallback, and remote workspace constraints.

GitOrigin-RevId: 7bf144c4b8c55bdb868cc8a71caf397c7740451a
2026-07-18 03:58:20 +00:00
Felipe Coury 3f0669dbd6 Make parent-owned sub-agent threads read-only in the TUI (#33841)
## Why

Multi-agent V2 spawned threads are controlled by their parent and reject direct
app-server input. The TUI should expose that ownership instead of presenting an
input flow that the server will reject.

## What changed

- Add the experimental `Thread.canAcceptDirectInput` capability for loaded
  threads and populate it from the same policy used to validate `turn/start`
  and `turn/steer`. Stored, unloaded threads report `null`.
- Carry the capability through TUI thread discovery, selection, startup, and
  resume flows, with a compatibility fallback for older app servers.
- Present parent-owned threads as view-only, preserve drafts and queued input,
  block agent-directed commands and settings shortcuts, and keep local
  navigation and inspection commands available.

## Testing

- Cover V1 writable and V2 view-only spawned threads through selection and
  resume.
- Cover composer submission paths, queued and initial input preservation,
  allowed navigation commands, settings shortcuts, and the view-only UI.

GitOrigin-RevId: 495ad051249e5577fb0b0c1cc8c40a0998d04918
2026-07-17 15:14:47 +00:00
Adam Perry @ OpenAI d3fc1950a9 Extract TUI approval request payloads into structs (#33684)
## What changed

Give command, permissions, patch, and MCP elicitation approvals dedicated
request structs, and update TUI routing and rendering to use the wrapped
payloads.

GitOrigin-RevId: ffee4058dd27505be2a11de3758ac12bb707b6b8
2026-07-16 20:44:28 +00:00
Felipe Coury 9cddda7556 Retry safety-buffered turns on a forked thread (#33207)
## Why

Retrying a safety-buffered turn by rolling back the active thread rewrites the
source conversation and requires the TUI to repair its local transcript state.

## What changed

- Interrupt the buffered turn, then fork after the preceding completed turn and
  submit the prompt on the new thread with the faster model and low reasoning
  effort.
- Start a new thread when the buffered request is the conversation's first turn.
- Preserve committed steering input in the retry, leave the source thread
  intact, and restore the prompt alongside any existing draft if branching
  fails.
- Do not offer the retry action for side conversations or stale and in-progress
  turns.

## Testing

Added coverage for retries with prior context, first-turn retries, committed
steering input, branch failures, existing composer drafts and attachments, and
side conversations.

GitOrigin-RevId: adb49da8236e9212ef0082e033e6f715986b5cd9
2026-07-15 02:03:46 +00:00
stefanstokic-oai 4df8027a97 Honor workspace spend controls in rate-limit handling (#33187)
## Why

Sparse and out-of-order rate-limit updates can omit account metadata or let an
older full read overwrite a newer workspace hard stop. Credit availability also
does not always include a displayable balance.

## What changed

- Propagate the backend's `spendControlReached` state through rate-limit
  snapshots and the app-server protocol, preserving it across sparse updates.
- Keep workspace hard-stop classifications for error routing and ignore stale
  full-read results after a newer hard-stop notification.
- Base TUI warnings and model-switch prompts on credit availability and hard-stop
  state, and show `Credits: Available` when a finite balance is hidden.

## Testing

Added coverage for spend-control mapping, snapshot merging, out-of-order reads,
workspace error routing, warning and prompt behavior, and credit status display.

GitOrigin-RevId: 18b09d493d5a620a7c079fb721ec50b38dd5b04c
2026-07-14 22:43:26 +00:00
Felipe Coury 769a5de257 Make advanced reasoning selection explicit in the TUI (#32746)
## Why

`Max` and `Ultra` consume usage limits faster than standard reasoning levels, so they should not be selected accidentally while navigating the normal effort scale.

## What changed

- Move `Max` and `Ultra` behind a `More reasoning…` entry with a dedicated warning and descriptions.
- Keep the reasoning shortcuts from silently increasing into advanced efforts.
- Apply `Ultra` to the active conversation without changing defaults for new threads, while preserving it across mode switches and thread resumes.
- Record applied thread settings in thread metadata, including explicit clearing of reasoning effort, so resumed threads restore their latest model settings unless the user supplied an override.

## Testing

- Add TUI coverage for the advanced picker, shortcuts, Plan mode, configuration defaults, and resumed conversations.
- Add app-server and thread-store coverage for persisting, clearing, and restoring model and reasoning settings.

GitOrigin-RevId: 6708c7c2e8d38f491bf63000ea34f83476afdfe6
2026-07-13 09:40:51 +00:00
hefuc-oai cf36c688b3 [codex] Use managed defaults for TUI threads (#30147)
## Why

#29683 exposes managed defaults for new-thread model settings through
`configRequirements/read` without applying them server-wide. The TUI is
an app-server client, so it should explicitly consume those defaults
when it creates a fresh thread.

This lets plain `codex` start on the managed model while preserving the
existing ability to change model settings within the thread.

## What changed

- Read `requirements.models.newThread` during TUI app-server bootstrap.
- Apply the managed model, reasoning effort, and service tier to the
initial fresh thread and subsequent `/new` or `/clear` threads.
- Keep explicit launch overrides above the managed defaults.
- Normalize the managed `fast` service tier to the `priority` request
value.
- Leave resumed and forked threads unchanged.

The application logic lives in a small TUI-only module; app-server
`thread/start` behavior remains unchanged for other clients.

## User experience

- Plain `codex` starts with the managed new-thread settings.
- A user can still change settings with `/model` or the existing
service-tier controls.
- Starting another fresh thread reapplies the managed defaults.
- Explicit launch choices such as `codex -m <model>` continue to win.

## Validation

- `just test -p codex-tui managed_new_thread_defaults`
- `just fix -p codex-tui`

Depends on #29683.
2026-06-26 19:27:31 +00:00
Adam Perry @ OpenAI 1d65ccabd5 config: own layer provenance types (#29722)
## Why

Config layer provenance describes how effective configuration was
assembled, so it belongs with the config loader rather than in
app-server's serialized API types.

## What changed

- Moved `ConfigLayerSource`, `ConfigLayerMetadata`, and `ConfigLayer`
ownership into `codex-config`.
- Kept app-server's wire payloads unchanged and added explicit
conversions at the app boundary.
- Removed lower-level app-server-protocol dependencies from config
consumers.

## Stack

This is PR 3 of 6, stacked on [PR
#29721](https://github.com/openai/codex/pull/29721). Review only the
delta from `codex/split-auth-domain-types`. Next: [PR
#29723](https://github.com/openai/codex/pull/29723).

## Validation

- `codex-config` coverage passed.
- App-server config-manager and config RPC coverage passed.
2026-06-24 04:03:04 +00:00
jay f8f5a6e78f feat(tui): add rate-limit reset redemption to /usage (#28154)
## Why

Codex users can earn personal rate-limit reset credits, but the CLI does
not currently provide a way to view or redeem them. The `/usage` command
restored in #27925 is intended to be the entry point for usage-related
actions, so reset redemption belongs there rather than in a separate
dashed slash command.

Depends on #28143 for the app-server and backend-client reset-credit
APIs.

## What changed

- Turn bare `/usage` into a menu with entries for token activity and
earned rate-limit resets while preserving `/usage daily`, `/usage
weekly`, and `/usage cumulative`.
- Add loading, empty, confirmation, success, retry, and error states
with a caller-generated UUID idempotency key reused across retries of
the same logical reset.
- Show an availability hint only for backend-classified rate-limit
errors with credits available.
- Hide the reset entry for workspace accounts.

## Validation

- `just test -p codex-tui chatwidget::tests::usage` — 19 passed.
- `just fix -p codex-tui` — passed.
- `just fmt` — passed.
- `cargo insta pending-snapshots` from `codex-rs/tui` — no pending
snapshots.

## Examples
<img width="1168" height="304" alt="image"
src="https://github.com/user-attachments/assets/caa4c1e3-e996-494d-ae17-50b521f5dce8"
/>
<img width="908" height="260" alt="image"
src="https://github.com/user-attachments/assets/e38a726b-77cc-4bd0-9ea8-9f3ad21c5768"
/>


### Reset flow
<img width="1509" height="312" alt="image"
src="https://github.com/user-attachments/assets/d987013c-78a5-48a2-ad8d-c61ad267a327"
/>
<img width="585" height="190" alt="image"
src="https://github.com/user-attachments/assets/de32be19-79b9-4a3e-8574-6f1c208c98ae"
/>
<img width="600" height="210" alt="image"
src="https://github.com/user-attachments/assets/88a165cf-796d-4fdc-a7bc-ea89917573da"
/>

<img width="512" height="193" alt="image"
src="https://github.com/user-attachments/assets/d2353998-5aa8-442e-a5f8-3a8a5b832753"
/>
2026-06-16 17:59:40 +00:00
canvrno-oai 29224d945b TUI Plugin Sharing 2 - add remote plugin section plumbing (#26702)
This adds the background plumbing for remote-backed plugin catalog
sections while leaving the fuller directory presentation to the next PR.
The TUI can fetch section-specific remote marketplace results, keep
local plugin data available, and carry section errors forward for later
rendering.

- Fetches explicit remote marketplace kinds for curated, workspace, and
shared-with-me sections.
- Gates shared-with-me loading on the plugin sharing feature flag.
- Adds section-level error state and user-actionable error copy.
- Merges remote marketplace results into the cached plugin list without
discarding local results.
2026-06-15 10:25:37 -07:00