Commit Graph
28 Commits
Author SHA1 Message Date
Joe Savona 65dbdb5f03 Wrap built-in TUI status lines within the footer row budget (#60682)
## Why

Long built-in status lines were truncated to a single row even when the footer had room for more content.

## What changed

- Wrap status text to the available width and row budget, preserving styles and hyperlink targets across rows.
- Show an unlinked ellipsis when content exceeds the available space.
- Refresh wrapped content when the status text, agent label, or width changes.
- Keep reasoning-effort transitions on one row and restore wrapping after the final animation frame.

## Testing

Add coverage for wrapping and hyperlink boundaries across footer layouts, content and agent-label updates, resizing, and wrapping restoration after an effort transition. Update transcript and startup snapshots for multiline status text.

GitOrigin-RevId: 30e0795c473efd62fc4d0dca4deb6029b625a9e8
2026-11-10 23:35:28 +00:00
Joe Savona 7cdb219883 Render UI trees directly into terminal buffers (#60029)
## What changed

Use a shared layout traversal to measure prepared UI trees and paint text directly into terminal buffers. Add natural and viewport-constrained size measurement, and use direct rendering for extension footer content.

Preserve wrapping, styles, and terminal hyperlinks while clipping at grapheme boundaries and leaving overflow ellipses unlinked.

## Testing

Add coverage for size measurement in terminal cells, wide characters at clipping boundaries, and zero-width text around overflow ellipses. Update rendering tests to check painted buffer contents and hyperlinks.

GitOrigin-RevId: 828c45d3400f9e3dfce9a7bd812d1cc0ea51642f
2026-11-07 01:52:20 +00:00
Benjamin Carlsson 78b1dda5f6 Render typed prompts as Markdown in the TUI (#59983)
## Why

Typed prompts currently display Markdown syntax literally, including emphasis, lists, and code fences.

## What changed

- Render Markdown in typed prompts while retaining the prompt gutter, background, and hyperlinks.
- Preserve literal rendering for spoken prompts, prompts with inline text elements, and text without visible Markdown formatting.
- Keep the original Markdown when copying a whole prompt, and preserve source text for code block and blockquote copy targets.
- Preserve bold styling when leaving the dim prompt marker and track hyperlink columns incrementally across styled spans.

## Testing

Add regression coverage for prompt rendering at multiple widths, hyperlink positions, terminal bold styling, and copying Markdown source, code blocks, and blockquotes, including original code line endings and fenced tables with table rendering disabled.

GitOrigin-RevId: eda62043ca8a9fe012ea7e0683fe05de6ad1b898
2026-11-06 21:21:15 +00:00
Eric Traut a795f961be Make viewed image paths clickable in the TUI (#58446)
## What changed

- Add terminal file hyperlinks to viewed image filenames and transcript paths, including older history loaded through pagination.
- Enable links only for local workspaces outside SSH sessions. Require a local regular file with a recognized image extension on both the original and resolved paths, and reject Windows reparse points.
- Preserve links when summaries are truncated or transcript paths wrap.

## Testing

Add coverage for local versus remote workspace links and for hyperlink destinations and column ranges in compact and expanded image rows.

GitOrigin-RevId: a7dff255c280ad4e609644e6f5ef5e130d9a55fb
2026-10-30 22:30:53 +00:00
Joe Savona 6c776cfc8c Preserve status-line hyperlinks through footer layout and animations (#57883)
## Why

Footer hyperlinks must follow their text when the status line is truncated or animated. Inferring link targets from underlined cells loses that association, and Unicode width differences can shift links onto the wrong cells.

## What changed

- Carry explicit hyperlink ranges with status-line content through footer layout and reasoning-effort transitions.
- Fit content to the space allocated beside right-hand indicators, keeping the truncation ellipsis outside links.
- Measure and truncate rendered graphemes consistently while preserving source columns for transcript tab expansion.
- Box the composer's footer state to reduce its stack footprint during session navigation.

## Testing

Add regression tests for clipped links after halfwidth katakana and Arabic prefixes, hyperlink positions during effort transitions, and narrow status rows beside the Plan mode indicator.

GitOrigin-RevId: ede62690e191daefc85f38e637f9bcc9796268b7
2026-10-29 02:10:32 +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
Benjamin Carlsson 22ebb0fb17 Clamp wrapped source ranges before remapping terminal hyperlinks (#52330)
## Why

Wrapping can retain a cursor sentinel one byte past the end of the input. Using that range to slice source text during hyperlink remapping can panic.

## What changed

Clamp wrapped range boundaries to the input length before calculating hyperlink columns and recording logical source ranges, keeping both aligned with the visible text.

## Testing

Add a regression test that extends a wrapped range past the input boundary and verifies that the line, hyperlinks, and logical source are preserved.

GitOrigin-RevId: c83c817df8d3ea790f7d126768092ae317ff9217
2026-10-09 00:04:15 +00:00
Charlie Marsh 4854cfa643 Preserve clickable URLs in pending input previews (#51471)
## What changed

Render web URLs in pending steers, rejected steers, and queued follow-up messages as terminal hyperlinks. Preserve the complete destination when the visible URL is clipped to the preview width.

Add `HyperlinkRows` to render already-wrapped rows without changing their spacing or row count, clipping text and hyperlink ranges to the viewport.

## Testing

Add regression coverage for complete URL destinations across all three preview sections, plus snapshots for oversized URLs and clipping overflow text and the edit hint in a narrow preview.

GitOrigin-RevId: 959df27bba381b1b3895f5a86cc2ecb1419806b1
2026-10-06 19:51:39 +00:00
Charlie Marsh bc3ebcb77d Preserve clickable URLs in TUI approval headers (#51439)
## What changed

Render command, permission, patch, and MCP elicitation approval headers with `HyperlinkText`, which annotates web URLs and preserves their full destinations across wrapping and clipping.

## Testing

Add a regression test covering wrapped URL destinations in all four header types, plus a snapshot of the wrapped command approval header.

GitOrigin-RevId: 7f6b79484c9297cd03514da2d6805b0d239fee63
2026-10-06 18:16:18 +00:00
Charlie Marsh 594283af5c Make URLs in asynchronous question titles clickable (#51391)
## What changed

Render web URLs in TUI asynchronous question titles as terminal hyperlinks, preserving the full destination when a URL wraps across lines or is partially clipped. Exclude trailing question punctuation such as `)?` from detected URLs while preserving balanced parentheses and query strings.

## Testing

Add a rendering regression test and snapshot for a wrapped URL, checking complete hyperlink destinations at full and reduced heights. Extend URL detection tests for trailing question punctuation and balanced parentheses in query strings.

GitOrigin-RevId: 6c9a807466d7b7e3a23bc6e86aae8410ae378161
2026-10-06 15:13:05 +00:00
Felipe Coury 16c21e3f36 Preserve table cell source metadata through TUI rendering (#48548)
## What changed

- Retain table identity, column alignments, cell coordinates, source byte ranges, and inline formatting in copy metadata.
- Carry cell fragments through grid padding, wrapping, key/value layouts, and pipe output, including escaped pipes and empty cells.
- Preserve logical source metadata when remapping wrapped lines, even without hyperlinks.

## Testing

Add coverage for cell fragments across narrow and wide layouts, blank table continuations, and Markdown selection copy structure and visible transformations.

GitOrigin-RevId: 8422f224cffe2e74813394f0623b9167bdd4ac59
2026-09-26 21:58:17 +00:00
Eric Traut d7d9f2b9b5 Add selection and copying to the transcript viewer (#46732)
## What changed

- Add mouse selection, word and line selection, drag autoscrolling, and keyboard selection with `Ctrl+Space`. Support copying selected text and opening links with a modified click.
- Anchor reading positions and selections to source text so resizing, streaming completion, and history pagination preserve the displayed content. Preserve hard line breaks, indentation, tabs, and graphemes when copying, while excluding display gutters and soft wraps.
- Rejoin activity groups split across history pages while retaining the reader's displayed revision.
- Distinguish confirmed clipboard writes from unconfirmed terminal requests, and retain native clipboard ownership after the transcript overlay closes.
- Manage mouse capture and keyboard modes across overlay transitions, editor handoffs, and suspend/resume.

## Testing

Add regression tests for selection during live updates and pagination, source-text copying across resize, clipboard confirmation and lifetime, and terminal mode restoration.

GitOrigin-RevId: 6b2438f576567cbba755b2405915a25acf009b8d
2026-09-20 00:04:04 +00:00
Eric Traut 4abcb8d1da Restore rich tool details in persisted TUI transcripts (#46710)
## Why

Loaded transcripts reduce several tool calls and file changes to basic status summaries, losing details available in live history cells.

## What changed

- Reuse rich history cells for completed commands, MCP calls, patches, agent activity, image generation, and notices.
- Add dynamic tool cells with bounded output previews while retaining arguments and full output in detailed and raw views.
- Preserve last-known statuses for incomplete calls, unavailable results, and declined or failed operations. Keep legacy command text and terminal interaction output when rich reconstruction is unavailable.
- Remove redundant move annotations from patch diffs and retain patch activity IDs.
- Filter untrusted control characters before emitting terminal scrollback, while preserving semantic hyperlinks.

## Testing

Add unit and snapshot coverage for compact and detailed tool rendering, status fallbacks, retained output, patch restoration, and control-character filtering with and without hyperlinks.

GitOrigin-RevId: 73d754262768cf6d91f3ea4040116bf93cf87784
2026-09-19 20:24:41 +00:00
Eric Traut 321c50fc2c Add compact activity rendering and preserve transcript source text (#46709)
## What changed

- Add compact renderers for commands, MCP calls, computer activity, patches, and plans, with bounded previews and retained transcript details.
- Preserve logical source text, styles, and hyperlink metadata across wrapping so transcript copying can exclude display gutters while retaining meaningful labels. Wrap diff text at grapheme boundaries.
- Add activity identities, ordered detail retention, and deduplicated warning metadata to history cells.
- Hide background terminal interaction notices from chat while retaining them in the transcript, and keep local image-only user messages visible without duplicating image placeholders.

## Testing

Add regression and snapshot coverage for compact previews, retained patch diagnostics, wrapped source text and hyperlinks, question-and-answer labels, and local image placeholders.

GitOrigin-RevId: fd82fadd8ed3418eaba2bc74c4327d9c63d7e997
2026-09-19 20:24:20 +00:00
Eric Traut fcaa035438 Preserve logical source text and styles across TUI wrapping (#46708)
## Why

Display wrapping removes whitespace and adds gutters, so rendered rows alone cannot reliably describe the original logical text. Streaming previews also need to detect source changes that leave visible rows unchanged.

## What changed

- Retain shared logical text, styles, exact byte ranges, and display margins alongside wrapped rows; remap hyperlinks using those ranges.
- Preserve source metadata through prompt, Markdown, and prefixed history rendering, including spoken artifact annotations. Clear it when split-flap animation replaces the text.
- Include source metadata when comparing streaming previews and agent or plan tails.
- Keep compound graphemes intact, preserve explicit span styles, and reuse first-fit wrapping results when safe.
- Use the lighter history prompt background for submitted messages.

## Testing

Add regression coverage for source ranges and styles across widths and gutters, distinct repeated lines, source-only streaming updates, compound graphemes, and equivalence between reused and generic wrapping results. Extend Markdown, spoken artifact, and animation tests to check retained source metadata.

GitOrigin-RevId: 9e60746642fc9a8f91c1abfe7c77eefc1fe421ab
2026-09-19 20:22:48 +00:00
Benjamin Carlsson 3caf9f9586 Style spoken prompts and link workspace files in voice transcripts (#43676)
## What changed

- Render spoken user prompts with a bold red chevron, preserving its color during live transcript animation. Trim leading whitespace for display while retaining the raw transcript text.
- Underline and link file references such as `src/lib.rs:42` in spoken assistant transcripts using terminal hyperlinks. Preserve existing links and support Windows-style relative separators.
- Restrict generated file links to existing files with allowed extensions inside the workspace, rejecting hidden paths, traversal, and symlink escapes.

## Testing

Add rendering and transcript tests for the spoken marker, raw text preservation, file links, Unicode column offsets, and Windows-style paths, plus validation tests for rejected file destinations.

GitOrigin-RevId: 5fa180aa606acdc579a916441520602cb2bf3655
2026-09-08 03:15:37 +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
Benjamin Carlsson bb8cada846 Render Markdown links as clickable labels in supported terminals (#40471)
## What changed

- Render web-link labels in cyan with an underline and hide the repeated destination in recognized terminals with hyperlink support.
- Keep destinations visible for unknown terminals, multiplexers, non-terminal output, and empty labels so the URL remains usable.
- Preserve OSC 8 link targets through prose and table wrapping, streaming updates, transcript clipping, and pager scrolling.

## Testing

- Add coverage for terminal detection, label formatting and fallbacks, wrapped tables and prose, streaming parity, history output, and scrolled transcript rendering.

GitOrigin-RevId: 4a09e41e349ba299022a9c00f0c25892d9aaefe3
2026-08-24 20:04:52 +00:00
Charlie Marsh d327527a3d Limit terminal hyperlink layout to the visible viewport (#39065)
## What changed

- Skip hyperlink layout for wrapped rows above the scroll offset and stop once
  processing reaches the bottom of the viewport.
- Resolve each rendered link destination once while marking its visible cells.
- Add coverage for hyperlinks that span visible wrapped rows after scrolling.

GitOrigin-RevId: c1506d47fa3f1b895966dc2cde7d5b859c201792
2026-08-17 20:06:41 +00:00
Benjamin Carlsson 49db349ffd Avoid allocating per character when decorating hyperlinks (#38823)
Encode each character into a stack buffer before appending it to the
decorated span, avoiding a temporary `String` allocation for every character.

GitOrigin-RevId: 72ec1ad5363391dffee089f04073d827d8c459bf
2026-08-16 01:34:51 +00:00
Charlie Marsh 5186e2ccc3 Skip terminal hyperlink layout when no links are present (#38657)
## What changed

Return early from `mark_buffer_hyperlinks` when none of the supplied lines
contain hyperlink metadata, avoiding unnecessary paragraph layout work.

GitOrigin-RevId: bdd6727f3dab7cef87646f97ac955e848cfcfee2
2026-08-14 21:54:14 +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 cef3910ea4 Preserve hyperlink cell widths during terminal diffing (#35960)
## What changed

- Mark OSC 8 hyperlink cells with their visible width so Ratatui's buffer diff handles wide and halfwidth characters correctly.
- Use Ratatui's diff iterator while explicitly clearing styled trailing cells when a forced-width cell replaces a wider cell.

## Testing

- Add coverage for forced-width hyperlink rendering, always-update cells, and styled trailing-cell cleanup.

GitOrigin-RevId: 041128f43beb1e09d40179a3ac16dca1fbdcbc44
2026-07-29 13:57:46 +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
Charlie Marsh 28aacbb9d9 Avoid cloning hyperlink text during TUI rendering (#34366)
## What changed

Add a borrowed `Line` conversion and use it when rendering and measuring
hyperlink-aware history and pager content. This preserves line styling and
alignment while avoiding clones of the underlying span strings.

GitOrigin-RevId: c9cd6ff5ec63cd29719ea2ae51acede7364f2bd8
2026-07-20 15:39:31 +00:00
Charlie Marsh aa982319c2 Speed up TUI Markdown layout (#34216)
## What changed

- Allocate Markdown table widths in bulk while preserving the existing column
  shrink priorities and balancing behavior.
- Reuse flattened styled-line data during adaptive wrapping and detect URLs
  across span boundaries.
- Remap wrapped terminal hyperlinks with a single forward scan.

## Testing

- Verify bulk table shrinking matches the previous one-cell-at-a-time results,
  including a token-heavy column with a million-character width.
- Cover URLs split across styled spans and multiple links on indented Unicode
  lines.

GitOrigin-RevId: 24a6fd6fdace6ca948e613d67c130a3a7f8d1a4e
2026-07-19 19:33:31 +00:00
Felipe Coury f896ab9f25 Render inline visualization links in the TUI (#33925)
## Why

Assistant-authored inline visualizations need a terminal fallback that lets users open generated artifacts in a browser.

## What changed

- Recognize `::codex-inline-vis{file="..."}` directives in assistant Markdown and replace them with browser links during streaming, finalized history rendering, and local transcript previews.
- Materialize visualization fragments in sandboxed viewer documents with a content security policy, while restricting artifacts to HTML files within the thread's visualization directory and limiting their size.
- Show an explicit unavailable message for invalid or missing artifacts, hide incomplete streaming directives, and preserve directive text in code blocks and user Markdown.
- Add a trusted file-link path for generated viewers without enabling arbitrary `file:` links in Markdown.

## Testing

Add coverage for directive rewriting, streaming and replay, artifact validation, sandboxed viewer generation, trusted terminal hyperlinks, and literal preservation.

GitOrigin-RevId: a666b4ebc82bb5798ad45bd137fd815d538e1de2
2026-07-17 23:19:12 +00:00
Felipe Coury 7a26497836 feat(tui): add OSC 8 web links to rich content (#24472)
## Why

Wrapped URLs in rich TUI output, especially URLs rendered inside
Markdown tables, are split across terminal rows. In terminals that
support OSC 8 hyperlinks, treating each visible fragment as part of the
complete destination enables reliable open-link and copy-link actions
even after table layout wraps the URL.

This addresses the semantic-link portion of #12200 and the behavior
described in
https://github.com/openai/codex/issues/12200#issuecomment-4535452980. It
does not change ordinary drag-selection across bordered table rows.

## What Changed

- Added shared TUI OSC 8 support that validates `http://` and `https://`
destinations, sanitizes terminal payloads, and applies metadata
separately from visible line width/layout.
- Added semantic web-link annotations to assistant and proposed-plan
Markdown, including explicit web links and bare web URLs in prose and
table cells while excluding code and non-web Markdown destinations.
- Preserved complete URL targets through table wrapping, narrow pipe
fallback, streaming, transcript overlay rendering, history insertion,
and resize replay.
- Routed intentional Codex-owned links in notices,
status/setup/app-link, feedback, onboarding, MCP/plugin help, memories,
and update surfaces through the shared hyperlink handling.

## How to Test

1. Run Codex in a terminal with OSC 8 link support, such as Ghostty, and
request an assistant response containing a Markdown table whose last
column contains a long `https://` URL.
2. Make the terminal narrow enough for the URL to wrap across multiple
bordered table rows.
3. Use the terminal's open-link or copy-link action on more than one
wrapped URL fragment and confirm each fragment resolves to the complete
original URL.
4. Resize the terminal after the table is rendered and repeat the link
action to confirm the destination survives scrollback replay.
5. Open the transcript overlay while rich output is present and confirm
web links remain interactive there.
6. As a regression check, render inline/fenced code containing URL text
and a Markdown link such as
`[https://example.com](mailto:support@example.com)`; confirm these do
not acquire a web OSC 8 destination.

Targeted automated coverage exercised Markdown links and exclusions,
wrapped and pipe-fallback tables, streaming/transcript overlay
propagation, status-link truncation, and rendered word-wrapping cell
alignment. `just test -p codex-tui` was also run; it passed the
hyperlink coverage and reproduced two unrelated existing guardian
feature-flag test failures.
2026-05-27 20:14:55 +00:00