Commit Graph
643 Commits
Author SHA1 Message Date
Dylan Hurd a57b398351 Require approval for input to escalated terminals (#40978)
## What changed

- Add the `write_stdin_approval` feature flag, disabled by default, to require a fresh approval before sending non-empty input to an escalated unified-exec terminal.
- Route these reviews through hooks, Guardian, app-server, and the TUI as `writeStdin` approvals while keeping the parent command item unchanged.
- Preserve the terminal environment, launch directory, and escalation state across turns, and revalidate the process identity after approval before writing input.

## Testing

- Cover approval routing, policy decisions, process reuse, terminal identity preservation, app-server events, analytics, and TUI rendering.

GitOrigin-RevId: 4ba29eaae6208e934737ba078c96e589c7c2164d
2026-08-26 21:39:05 +00:00
Benjamin Carlsson d47e5cc0e2 Add Vim buffer jump motions (#40958)
## What changed

- Add `gg` and `G` motions to jump to the first and last buffer lines.
- Support the motions with delete, change, and yank operators, including dot-repeat for edits.
- Expose normal-mode and operator-motion bindings in the configurable keymap while preserving conflicting user bindings.

## Testing

- Cover buffer jumps, operator combinations, repeat behavior, chord routing, and custom remapping.

GitOrigin-RevId: 24a9178cf7964053aaf9a8cd268c5434dda0778e
2026-08-26 19:31:52 +00:00
Benjamin Carlsson 98ee29c7cd Add Vim character find and till motions (#40785)
## What changed

- Add line-local `f`, `F`, `t`, and `T` motions to Vim normal mode.
- Support the motions with `c`, `d`, and `y`, including dot-repeat for changes.
- Expose separate configurable normal-mode and operator-motion bindings, while preserving existing custom keymaps that use the new defaults.
- Keep character targeting aligned to extended grapheme boundaries and skip embedded composer elements.

## Testing

- Cover forward and backward motion and operator ranges, missing and adjacent targets, cancellation, dot-repeat, custom bindings, shifted terminal key events, grapheme clusters, and embedded elements.

GitOrigin-RevId: 2610cf9a13538d9ae9b890c01417ca25316c1d60
2026-08-26 04:18:49 +00:00
Charlie Marsh d6174a8798 Preserve composer hyperlinks across wrapped lines (#40720)
## What changed

- Detect visible HTTP(S) URLs in the composer and attach the complete OSC 8 destination to every wrapped fragment, including when part of the URL is scrolled offscreen.
- Cache hyperlink metadata with the textarea wrap state while leaving masked input and destinations larger than 8 KiB unannotated.
- Make shared hyperlink mapping grapheme-aware, recognize Unicode whitespace boundaries, and scan URLs and trailing delimiters incrementally for large inputs.

## Testing

- Add coverage for wrapped and scrolled URLs, joined emoji, Unicode whitespace, preserved highlighting, masked input, cache invalidation, oversized destinations, and drafts containing many URLs.

GitOrigin-RevId: 40facdf2fe79438c91c82bff2d849c342f1ab28a
2026-08-25 22:05:48 +00:00
Felipe Coury 6988d390b3 Generate automatic and manual conversation recaps (#40705)
## Why

Users returning to a conversation need a short summary of its recent progress and next steps.

## What changed

- Generate a recap for eligible idle, unfocused conversations and add it to the transcript.
- Add `/recap` to request the same summary on demand, with visible progress and actionable errors.
- Keep recap requests bounded and isolated, reject stale results, and retry only automatic failures.

## Testing

- Cover automatic and manual generation, request eligibility, failure handling, loading-state cleanup, and temporary-thread configuration.

GitOrigin-RevId: 926a88d6996d67a42809ce2c4091b13fca882b52
2026-08-25 21:03:11 +00:00
Felipe Coury 70b5cfc73b Probe Windows terminal colors without risking startup input (#40598)
## Why

Windows Terminal and xterm.js can render a theme that differs from the
underlying console color table. Querying that visible theme through OSC shares
the console input queue with keystrokes, including input for security-sensitive
startup prompts.

## What changed

- Defer the Windows OSC color probe until protected startup decisions and the
  world-writable workspace scan have completed.
- Preserve and replay unrelated console input records around the probe, while
  removing only valid OSC 10 and 11 replies and retaining the console palette
  as a fallback.
- Require an explicit confirmation key after shortcuts select trust, sandbox,
  or world-writable warning choices, so a fragmented terminal reply cannot
  accept them.
- Accept one- through four-digit OSC RGB components so the visible terminal
  palette is applied across supported response formats.

## Testing

Added coverage for delayed startup scans, protected prompt confirmation,
console-record replay, bracketed paste and malformed OSC preservation, RGB
response parsing, and light-theme composer rendering.

GitOrigin-RevId: b8ae456fe32c701ba3af31e9cc452fc4e8bffa22
2026-08-25 12:20:41 +00:00
Benjamin Carlsson c1db22a3cd Add dot-repeat to Vim mode (#40521)
## What changed

- Bind `.` in Vim normal mode to repeat the last complete edit.
- Record semantic delete, change, replace, paste, and insert-mode actions so repeats preserve motions, text objects, inserted text, and editor actions across keymap changes.
- Expose `vim_normal.repeat_last_change` in the configurable keymap and keymap picker, including conflict handling for existing custom bindings.

## Testing

- Add coverage for repeating deletes, replacements, complete changes, pasted and literal text, insert-mode editor actions, custom bindings, unavailable motions, and cleared buffers.

GitOrigin-RevId: 3213df964811e7902377ff1d93641e59f4037914
2026-08-25 02:34:04 +00:00
Andrei Eternal cbfd999db7 Add hooks for interrupted turns (#40511)
## What changed

- Add an `Interrupt` hook event that runs for an active top-level turn before its
  interrupted abort event is emitted.
- Flush the turn transcript before invoking the hook and provide the session,
  turn, transcript, working directory, model, and permission mode in its input.
- Support command and MCP handlers, including asynchronous commands, with a
  one-second default timeout and a three-second maximum.
- Expose the event through hook configuration, managed requirements, app-server
  notifications, generated schemas, analytics, and the TUI hook views.

## Testing

- Cover handler discovery, timeout normalization, output parsing, protocol
  compatibility, TUI rendering, and interrupt execution ordering.

GitOrigin-RevId: 163fa7c098d94ac2775f6d137f8e916f8ea9b6eb
2026-08-25 01:27:18 +00:00
victor-openai 5918c743f3 Deduplicate plugin skills in unified mentions (#40501)
## Why

Unified `@` search could show a plugin alongside the skills it owns, creating duplicate entry points for the same capability.

## What changed

- Add a nullable `pluginId` to `SkillMetadata` returned by `skills/list` so clients can associate skills with their owning plugin without inspecting names or paths.
- Hide a plugin's owned skills from unified `@` results when that plugin is present, while retaining standalone skills and skills with unknown ownership.
- Keep `$` focused on individual skills and apps, and use it consistently as the skills-list shortcut. Preserve the legacy mention behavior when `mentions_v2` is disabled.

## Testing

- Cover plugin ownership in `skills/list` and the updated `@` and `$` composer results.

GitOrigin-RevId: e168cdff8d0c58f74ce4c228a683880a3167775b
2026-08-25 00:15:49 +00:00
Felipe Coury 5a51caf04d Suggest conversation-based thread titles in /rename (#40495)
## What changed

- Generate a title suggestion from the latest substantive user and assistant messages when the TUI `/rename` prompt opens.
- Prefill the prompt with the result while keeping it editable and preserving any text the user enters before generation finishes.
- Bound and escape the conversation context, omit commentary and IDE context, and correlate responses with the active thread and prompt so stale suggestions are ignored.

## Testing

- Cover conversation selection and prompt construction, generated-title delivery through the embedded app server, loading and prefilled prompt states, stale responses, and preservation of manual edits.

GitOrigin-RevId: 1e7f1d5d4f6503ff9da0548388f610c446c130ca
2026-08-24 23:15:04 +00:00
Eric Traut 76d98a771e Add task mentions to the TUI composer (#40315)
## What changed

- Include matching Codex tasks in the `@` mention popup when the active thread supports task tools, prioritizing tasks from the current working directory.
- Submit selected tasks as bounded live thread references so Codex can load their contents with `read_thread`.
- Preserve task mentions across composer history and thread start, resume, and fork flows.

## Testing

- Add coverage for task search and capability propagation, popup selection and rendering, submission encoding, history round-trips, and reference validation and limits.

GitOrigin-RevId: 17502be91bf6d4b01745668829eb69fb318cb5b9
2026-08-24 02:46:56 +00:00
Eric Traut 83d1fe0e67 Remove the Plan mode composer nudge (#40200)
## What changed

- Keep the normal composer footer visible when a draft contains the word `plan`.
- Remove the contextual “Create a plan?” prompt, its Escape dismissal behavior, and its per-thread dismissal state.

## Testing

- Update wide and narrow composer snapshots to cover the standard footer for plan-related drafts.

GitOrigin-RevId: 1a3c8cfce9d4effa2149790975133f652aa7c914
2026-08-23 07:24:57 +00:00
Benjamin Carlsson df6a54ee85 Add a response target picker to /copy (#39997)
## What changed

- Open a picker for `/copy` with the whole response plus each fenced code block and blockquote from the latest response.
- Label code blocks by language, show content previews, and preserve source whitespace and nested quote Markdown when copying an individual target.
- Keep the picker from disturbing terminal scrollback or queued input, retain clipboard leases, and avoid writing copied content to the session log.

## Testing

- Add coverage for target extraction, picker navigation and cancellation, exact copied content, plan responses, queued input, scrollback preservation, clipboard failures, and session logging.

GitOrigin-RevId: 77a35bc99f4f45932d39914f9a709b30fe8cd7c2
2026-08-21 19:23:26 +00:00
Benjamin Carlsson 9ab176f488 Limit pending input preview wrapping work (#39864)
## Why

Pending input previews display at most three wrapped rows, but previously wrapped every logical line before truncating the result. This made rendering do unnecessary work for very large multiline inputs.

## What changed

Limit pending steers, rejected steers, and queued follow-up inputs to four source lines before wrapping: three for the preview and one to detect overflow and render the ellipsis.

## Testing

Keep multiline preview coverage for queued messages and pending steers, including blank lines near the truncation boundary.

GitOrigin-RevId: 4c300b13532983ff9c3bdfbd62d6ca722ea3a5aa
2026-08-21 05:35:35 +00:00
Ian MacLeod d9fd91edab Add hostname to the configurable TUI status line (#39795)
## What changed

- Add `hostname` as a selectable status-line item and show it in setup previews.
- Read the normalized operating-system hostname without triggering DNS resolution, and omit the item when no hostname is available.

## Testing

- Cover hostname normalization, status-line rendering, and setup and surface previews.

GitOrigin-RevId: c5e4e0ee1dba6e4bfdf942562a6b037835ff9e69
2026-08-20 20:08:11 +00:00
Benjamin Carlsson c3db180493 Skip postprocessing for short composer input (#39744)
## What changed

Return the initial wrapping ranges directly when the composer input produces a
single line and its byte length is less than the available width. This avoids
the additional grapheme and word-boundary pass for input that cannot wrap.

GitOrigin-RevId: 55d990a354fcc61e9a90d5796b4b39d16742cc50
2026-08-20 17:00:05 +00:00
Benjamin Carlsson 631d5a8b02 Expand Vim change commands and add character replacement (#39661)
## What changed

- Add the configurable `vim_normal.replace_char` action, bound to `r` by default, to replace the grapheme under the cursor while remaining in normal mode.
- Support change-operator motions such as `cw`, `c$`, `cj`, and `ck`, plus the repeated `cc` command for changing the current line.
- Let `Esc` cancel a pending replacement before it reaches composer-level handling.
- Preserve existing custom Vim bindings and chord prefixes when introducing the new default.

## Testing

- Cover replacement, grapheme boundaries, remapping and unbinding, change motions, cancellation, keymap conflicts, and keymap picker snapshots.

GitOrigin-RevId: 98feb4eeb57142c37adb73abfe58d1f703b9270d
2026-08-20 08:13:56 +00:00
Benjamin Carlsson 4bb7804a23 Apply composer editing preferences to TUI text prompts (#39618)
## What changed

- Initialize custom text prompts with the main composer's editor keybindings and Vim setting.
- Support Vim mode transitions, operator sequences, cursor styles, keymap contexts, and mode-aware footer hints in these prompts.
- Start Vim prompts in insert mode, use the first `Esc` to enter normal mode, and preserve `Esc` cancellation outside Vim.

## Testing

- Cover remapped editor and Vim commands, mode and context transitions, paste handling, cancellation, and footer rendering at different widths.

GitOrigin-RevId: 7a678310639dafb938084197df23d6d2a080a051
2026-08-20 06:35:47 +00:00
Eric Traut 3434c2545b Preserve queued TUI input semantics (#39604)
## Why

Paste placeholders and deferred slash-command parsing can hide the meaning of an input until it is expanded or a session is configured. Draining such input as an ordinary message can accidentally treat pasted text beginning with `!` as a shell command or lose `/plan` behavior.

## What changed

- Track paste-expanded inputs that begin with `!` as literal model input through history, queue editing, retries, and startup queues.
- Defer `/plan` parsing when session or model state is unavailable, then submit it in plan mode with shell escapes disabled.
- Drain queued input only after session configuration, and keep later queued prompts pending when an initial prompt cannot be submitted.
- Suppress queue auto-send before applying a replayed thread session so input from the outgoing thread is not submitted during restoration.

## Testing

Add coverage for direct, recalled, edited, interrupted, rejected, startup-queued, and plan-mode paste flows, including placeholder collisions and rejected initial images.

GitOrigin-RevId: d482220d8df21754f166fea5b54e9945f622a978
2026-08-20 05:49:49 +00:00
Eric Traut 8843960ba0 Scope TUI approval requests to their threads (#39372)
## Why

Approval and item IDs can collide across concurrent threads. Tracking pending app-server approvals by ID alone can therefore resolve, submit, or dismiss a request from the wrong thread.

## What changed

- Key command execution, file change, and permissions approvals by both thread ID and approval ID.
- Route approval responses through the originating thread and require the thread to match when processing resolution notifications or dismissing approval prompts.
- Canonicalize parseable thread IDs so equivalent UUID representations still match.

## Testing

- Cover colliding approval IDs across threads, mismatched resolution notifications, prompt dismissal, and response routing for primary and background threads.

GitOrigin-RevId: c2d899a1e4b6a6413c78a0595a5311f5fabb9815
2026-08-19 02:28:42 +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
Eric Traut 0c14c73471 Harden TUI subagent navigation (#39088)
## What changed

- Use `/subagents` consistently for the subagent picker and status UI, removing the `/agent` alias.
- Rejoin already-loaded subagent threads without overriding their existing settings.
- Route notifications and approval requests only to the active thread or its known subagents, discard unrelated startup events, and avoid replaying resolved approvals.

## Testing

- Add coverage for filtering buffered startup events, dropping resolved approvals, preserving owned subagent approvals, and resuming threads without setting overrides.

GitOrigin-RevId: b4e597f7cd4756faccf31d8b964e7a172f5ab0eb
2026-08-17 22:31:13 +00:00
Benjamin Carlsson 1aa3a68e7b Restrict queued-message editing to its dedicated binding (#39064)
## What changed

- Stop treating Vim normal-mode history-up as an alias for editing the latest queued message.
- Continue to edit queued messages through the configured `chat.edit_queued_message` binding.

GitOrigin-RevId: d830e0976a38725e948d420c1a5f374bb13fe945
2026-08-17 20:02:50 +00:00
Charlie Marsh 171ae66d74 Use simulated time in the long typing test (#39026)
## Why

The 1,000-character human-like typing test waited on the wall clock after
every keypress, making the test unnecessarily slow.

## What changed

Advance an injected timestamp by the recommended paste flush delay and flush
the paste-burst detector explicitly after each character. This preserves the
coverage that slow typing appears directly without creating a paste
placeholder, without sleeping between keypresses.

GitOrigin-RevId: 0c1beb40283f7d73a381cd221725ab4227c8e233
2026-08-17 16:54:49 +00:00
Charlie Marsh 0841d9bba5 Hang soft-break whitespace in the TUI composer (#39022)
## Why

Keeping overflowing separators with the following word can add whitespace-only
rows and make composer wrapping differ from the queued-input preview.

## What changed

- Hang breakable whitespace from the preceding visual row at soft word breaks
  while preserving the underlying editable text.
- Keep indentation, trailing whitespace, mandatory breaks, and nonbreaking spaces
  visible and editable according to their existing semantics.
- Align cursor placement, scrolling, vertical navigation, masked rendering, and
  styled overlays with the visible wrapped content, including after resizes.

## Testing

Add focused wrapping, rendering, cursor, editing, scrolling, navigation, Unicode
separator, long whitespace-run, and resize coverage.

GitOrigin-RevId: 7fbdb0a4bf33cfee20c4c19dca5aee74df4f892c
2026-08-17 16:39:37 +00:00
Benjamin Carlsson 2bc43d516e Edit queued messages with Vim history-up (#38907)
## What changed

- When the composer is empty in Vim normal mode, make the configured history-up binding restore the latest queued follow-up for editing.
- Remove the restored message from the queue so submitting the edited version replaces it instead of creating a duplicate.
- Preserve normal history navigation when the composer has text or a popup is active, and honor remapped Vim bindings.

## Testing

- Add TUI tests covering repeated edit-and-requeue cycles and a remapped history-up binding.

GitOrigin-RevId: 0b04dd964d3fc6fdcd10712aa4d5fd81cbbd2255
2026-08-16 21:48:41 +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
Benjamin Carlsson 9bfaf7a076 Share editor keymaps across TUI composer components (#38837)
## What changed

- Store the editor portion of `RuntimeKeymap` in an `Arc` so the chat composer
  and its embedded textarea use the same keymap snapshot.
- Initialize the textarea from the composer's default runtime keymap and keep
  custom binding updates shared between both components.
- Use copy-on-write when tests and binding resolution need to mutate editor
  bindings.

## Testing

- Verify that applying custom editor bindings shares the same keymap allocation
  with the composer and textarea.

GitOrigin-RevId: 7f3b0afd6cc784e23deee8819e5c2c37a3709c68
2026-08-16 05:59:34 +00:00
Abhinav 85fc4def35 Add MCP tool handler support to the hooks engine (#38705)
## What changed

- Discover synchronous `mcp_tool` hook handlers and invoke their configured MCP server and tool through a supplied executor.
- Expand nested hook-event placeholders in MCP tool inputs while preserving JSON types, and process tool output through the existing hook output contract.
- Represent hook details as handler-specific metadata in `hooks/list`, including MCP server and tool fields, and show those details in the TUI hooks browser.
- Skip unsupported `SessionEnd` MCP hooks and runtimes without MCP invocation support with startup warnings.

## Testing

- Cover argument expansion, missing placeholders, MCP invocation and hook decisions, discovery warnings, `hooks/list` metadata, and TUI rendering.

GitOrigin-RevId: 295b845471fe92bd7ad7cd272fbcd2c3713912e0
2026-08-15 05:53:54 +00:00
Darius Karel 233739e76a Exclude shortcut-modified input from TUI paste bursts (#38675)
## What changed

- Treat plain, Shift-modified, and Windows AltGr character events as text-producing input for paste-burst detection.
- Exclude Super, Hyper, and Meta character events from paste bursts, flushing any pending text before handling them as shortcuts.

## Testing

- Add coverage for plain and Shift-modified spaces, shortcut-modified spaces, pending burst flushes, and platform-specific AltGr input.

GitOrigin-RevId: 3c43224966307fd014eb1586dce0c53ee56c75aa
2026-08-15 00:32:58 +00:00
kevinlin-openai 274727d37f Delete Thai combining marks one at a time in the composer (#38662)
## Why

Backspace should let users remove Thai vowel and tone marks without deleting the
entire grapheme cluster.

## What changed

- Treat Thai nonspacing marks as individual backward-deletion boundaries.
- Keep embedded text elements atomic and preserve the existing behavior for
  other grapheme clusters, including decomposed Latin text and joined emoji.

## Testing

Add coverage for successive deletion of Thai marks, cursor rendering after
deletion, unchanged non-Thai grapheme handling, and atomic Thai text elements.

GitOrigin-RevId: f4834183909d93f4b4dd92f5d93e89235dc2b621
2026-08-14 22:35:23 +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
Benjamin Carlsson 1426592fcc Open notes when accepting the request input Other option (#38624)
## What changed

When the generated `None of the above` option is selected in a request user
input prompt, route Enter and configured accept actions to the notes editor
instead of submitting the response. Tab continues to open the same editor.

## Testing

Add a regression test confirming that both Tab and Enter reveal the notes editor
without submitting the response.

GitOrigin-RevId: 8a563d81a82a11ca0b26c2b1100053f13be8e8f4
2026-08-14 19:02:27 +00:00
Felipe Coury 1e71e35df6 Add thread usage to TUI status surfaces (#38282)
## What changed

- Add `thread-credits` and `estimated-thread-cost` items to the configurable
  status line and terminal title for Enterprise workspaces.
- Fetch one shared thread usage estimate only when either item is selected,
  omit unavailable values, and refresh the display after turns complete.
- Preserve the last nonzero estimate while usage settles, with bounded delayed
  refreshes and retries for transient failures.

## Testing

- Add coverage for configuration, rendering, previews, plan availability,
  replay handling, retries, and post-turn settlement.

GitOrigin-RevId: dd69ee621c5bca0e5d9edd32b2bba42487eb1500
2026-08-13 00:34:39 +00:00
Owen Lin cbb7e82a8b Unify turn input submission and routing (#38275)
## What changed

- Add `TurnInputRequest` and typed submission results for atomically starting a turn, steering the active turn, or declining input with a specific reason.
- Expose `start_or_steer_turn`, `start_turn_if_idle`, and `steer_turn` on `CodexThread`, and migrate Core consumers to these APIs.
- Make app-server `turn/start` steer an active regular turn and return that turn's ID. Reject incompatible output schemas and non-steerable turns without applying settings or enqueueing input.

## Testing

- Cover concurrent start-or-steer submissions, accepted and rejected settings updates, output-schema compatibility, idle-start rejection, and app-server steering.

GitOrigin-RevId: dd9b5528d76ec650c019e97af420bc13190ea86a
2026-08-13 00:00:16 +00:00
Tamir Duberstein 91d6f48992 Avoid allocations when sanitizing TUI user text (#38214)
## Why

Sanitizing user messages and pasted text always allocated a new string, even
when the input contained no terminal control characters.

## What changed

- Return a `Cow<str>` from `sanitize_user_text` so clean borrowed input remains
  borrowed.
- Reuse owned input buffers when sanitization leaves the text intact or only
  removes content at the edges.
- Update transcript rendering, history cells, and paste handling to consume the
  borrowed-or-owned result without unnecessary cloning.

## Testing

Add sanitizer coverage for clean text, control sequences, Unicode control
characters, incomplete escape sequences, buffer reuse, and multi-fragment
output.

GitOrigin-RevId: 9e39cbc0d83c5791941b37a7eb4bb918c1a05f68
2026-08-12 16:33:32 +00:00
Charlie Marsh a16863f870 Keep wrapped composer whitespace with following text (#37709)
## Why

Overflowing whitespace in the TUI composer could occupy a separate blank row
instead of remaining attached to the text that follows it.

## What changed

- Add composer-specific, grapheme-safe wrapping that keeps breakable Unicode
  whitespace with the following word while preserving semantic breakpoints such
  as hyphens and nonbreaking spaces.
- Preserve cursor insertion rows and positions as content reflows, including
  across full lines and wrapped fragments.
- Keep wrapping linear for maximum-length unbroken input.

## Testing

Add focused rendering and cursor tests for ASCII and Unicode whitespace,
hyphenated words, reflowed fragments, and maximum-length input.

GitOrigin-RevId: fb7713e33bfddf37460b6c2f6f0c9700f31d86bf
2026-08-09 15:49:17 +00:00
Abhinav 3aae5d885b Expose execution mode in hook listings (#37538)
## What changed

- Add `executionMode` to `HookMetadata` returned by `hooks/list`, with `sync` as the default for compatibility.
- Propagate each discovered hook's `sync` or `async` mode through the app-server protocol and generated schemas.
- Show the execution mode in the TUI hooks browser.

## Testing

- Cover async and default-sync modes in `hooks/list` tests and TUI snapshots.

GitOrigin-RevId: 9c9f2890798fe417face76c15847616b2dea9db4
2026-08-08 04:57:06 +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
Charlie Marsh ad6e48ddd3 Keep textarea cursors and rendering inside the viewport (#37166)
## What changed

- Reserve a continuation row for the insertion point when a logical line exactly fills the textarea width.
- Wrap overflowing spaces and keep cursor movement aligned with the resulting visual rows.
- Clip plain, masked, and styled text rendering to the textarea bounds, and return no cursor position for empty viewports.

## Testing

Add regression coverage for full lines, trailing spaces, scrolling, multi-width graphemes, empty areas, and styled overlays at textarea boundaries.

GitOrigin-RevId: 4147530b523cf4bc300e50221d25d22dbfdfbefe
2026-08-05 21:40:50 +00:00
jacobzhou-oai 56b82e676c Enforce Agent Plugin runtime boundaries (#37027)
## What changed

- Track Agent Plugin manifests through plugin, skill, and MCP loading so their capabilities use format-specific behavior without changing legacy plugins.
- Discover only direct-child skills, exclude app and hook capabilities, isolate MCP data, and reject MCP configuration files that are non-regular or resolve outside the plugin root.
- Bound model-visible skill instructions, plugin instructions, MCP descriptions, schemas, individual tools, and the aggregate Agent Plugin MCP tool set.
- Stop MCP and OAuth redirects when Agent Plugins send configured or authorization headers, while retaining existing redirect behavior for legacy MCP servers.

## Testing

- Add coverage for capability filtering, skill discovery, isolated MCP data and reserved-path expansion, unsafe MCP configuration files, context limits, and redirect handling.

GitOrigin-RevId: c9af66b051269f3226628ca280a58d32c808c38f
2026-08-05 04:54:33 +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
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
Shijie Rao e2c0837923 Make user input blocking behavior explicit (#36410)
## Why

Clients need to know whether a `request_user_input` request must wait for an
explicit response or may auto-resolve. Using `autoResolutionMs` as that signal
conflated the blocking decision with timeout policy.

## What changed

- Add required `isBlocking` fields to user input protocol and app-server
  request payloads. Plan-mode requests are blocking, while requests from other
  enabled modes are non-blocking.
- Drive the TUI's auto-resolution behavior from `isBlocking` and remove
  `autoResolutionMs` from the model-facing tool schema.
- Deprecate `autoResolutionMs` while retaining it for compatibility, and treat
  legacy payloads without `isBlocking` as blocking.

## Testing

- Cover mode-derived blocking behavior, legacy deserialization, app-server
  forwarding, delegated requests, and TUI auto-resolution.

GitOrigin-RevId: 29aade657ef743065ec264376ba567a9b353d7d7
2026-08-01 00:38:10 +00:00
Charlie Marsh 3725f02cf3 Fix TUI layout for halfwidth Japanese sound marks (#35962)
## What changed

- Use Ratatui-compatible terminal widths throughout TUI layout, preserving
  full-width counters for long lines.
- Wrap and truncate on grapheme boundaries so halfwidth kana sound marks and
  emoji sequences stay intact.
- Apply the corrected sizing to text input, selection popups, status and
  history cells, Markdown, hyperlinks, and scrollable cloud diffs.

## Testing

- Add focused unit and snapshot coverage for wrapping, truncation, cursor and
  mask alignment, popup columns, status output, session headers, Markdown
  tables, process output, and scrollable diffs.

GitOrigin-RevId: 294ec0bcff743c6bb16d55ec26308524ce741879
2026-07-29 14:01:31 +00:00
Charlie Marsh 00cb5c465b Upgrade Ratatui to 0.30.2 (#35959)
## What changed

- Upgrade `ratatui`, `ratatui-macros`, `crossterm`, and `ansi-to-tui`, and adapt the TUI to their updated rendering, backend, color-conversion, and cell APIs.
- Use Ratatui's cell-width and continuation-cell metadata when mapping OSC 8 hyperlinks so links remain aligned across wrapped wide glyphs and halfwidth characters with dakuten.
- Preserve explicit hyperlinks in the sign-in success screen and empty MCP state without embedding escape sequences in the text passed to Ratatui.

## Testing

- Add regression coverage for hyperlink placement across wide glyphs and halfwidth dakuten, hyperlink preservation in onboarding and MCP output, and display-width handling.

GitOrigin-RevId: 8460873e5a266923acd0417bc46264845eab0134
2026-07-29 13:53:15 +00:00
Eric Traut b96ebfb312 Show blocked goals as stalled in the TUI (#35886)
## What changed

- Display `Blocked` goal statuses as “stalled” in the goal menu and goal status footer.
- Update the goal menu snapshot and footer formatting test expectations.

GitOrigin-RevId: f3d8212d939f0d76354048231346328972226274
2026-07-29 03:50:00 +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
Felipe Coury 20dafe201d Make the keymap action menu responsive (#35375)
## What changed

- Stack action descriptions below their labels when the keymap action menu is too narrow for a readable description column.
- Keep descriptions column-aligned at wider terminal widths.
- Show a dash instead of a number beside the disabled remove-binding action.

## Testing

- Add snapshot coverage for the action menu at 48, 64, and 96 columns.

GitOrigin-RevId: 25b97fd2d8764563e0a0c36d436711f2429093c4
2026-07-25 19:28:57 +00:00