Skip to content

feat(tui): show long file writes and diffs as a preview - #60741

Open
bercedev wants to merge 2 commits into
anomalyco:devfrom
bercedev:feat/tui-file-preview
Open

bercedev wants to merge 2 commits into
anomalyco:devfrom
bercedev:feat/tui-file-preview

Conversation

@bercedev

@bercedev bercedev commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Issue for this PR

Related to #40096

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Writes and edits render in full, so one 500 line write pushes the rest of the turn out of view. Shell output already gets a short preview, file contents don't.

Now Write, Edit and apply_patch show the first 10 rows when there are more than 10 lines, with a hint under them. Click the block to expand or collapse, the same way a shell block works. Shorter files look the same as before, and diagnostics stay visible when collapsed.

I didn't add a new setting. session.verbosity: "high" starts them expanded, since it's already the "show me more" level, and low still folds the whole run into one line.

I know UI changes are meant to get a design review first, so this is small on purpose and easy to move behind a setting if you'd prefer that. #42552 did something similar with a setting and got closed by the cleanup bot, and #54039 was v1 only and was told to come back for v2.

Limits:

  • the expanded state is local to the block like in Shell, so it resets if the row remounts
  • rows and lines aren't the same thing. A patch with more than 10 lines that fits in 10 rows in split view still shows the hint, and clicking changes nothing
  • with mouse: false the only way to see more is verbosity: high
  • mini mode isn't touched

How did you verify your code works?

Real TUI in tmux against a small mock OpenAI-compatible server, which wrote a 135 line file and a 1 line file, then replaced 30 lines of the first one:

  • default: both long blocks show 10 rows and a hint, the short one has no hint
  • click on the edit: all 30 lines plus Click to collapse. Click again: back to 10
  • session.verbosity: "high" in cli.json: open from the start

New test/cli/tui/file-preview.test.tsx for the clipping and patchBodyLines cases in collapse-tool-output.test.ts. bun test in packages/tui: 1595 pass, 3 fail, all 3 Node reloads the local ESM graph with Export named 'registerHooks' not found in module 'node:module' from the node fallback in the bun docker image. Typecheck is clean.

Only ran on linux. apply_patch wasn't in that run, it goes through the same component as the other two.

Screenshots / recordings

tmux capture instead of a screenshot:

  ┃     9 export const value9 = 9
  ┃    10 export const value10 = 10
  ┃
  ┃  Click to expand · 135 lines

  ┃  # Wrote small.ts
  ┃
  ┃   1 export const small = 1
  ┃   2

  ┃  ← Edit long.ts
  ┃
  ┃     1 - export const value1 = 1
  ┃     2 - export const value2 = 2
  ┃     ...
  ┃    10 - export const value10 = 10
  ┃
  ┃  Click to expand · +30 -30

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Related: #40096

Write, Edit and apply_patch render everything, so one long file pushes the rest
of the turn out of view. Show 10 rows and expand on click like shell output does.
session.verbosity high starts them expanded.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works as described, with one off-by-one to fix (inline). I ran the TUI from source with a simulated model that applied a patch creating a 40-line file and a 1-line file. On the base the long file is drawn in full. With this PR it shows 10 rows plus Click to expand · +40 -0, the short file has no hint, and clicking expands to all 40 lines with Click to collapse. Write and Edit go through the same FileBlock but weren't available to the simulated model. The new tests pass and tsc -b in packages/tui is clean.

Public API: unchanged. Only the description of the existing session.verbosity config key was reworded; no keys were added, removed or changed.

Other concerns:

  • Design: the behaviour is tied to session.verbosity: "high" rather than its own setting, and with mouse: false there is no way to expand a block except changing verbosity. A maintainer needs to sign off on that.
  • Off-by-one: the line count includes @@ hunk headers, so an exact 10-line change shows a hint that does nothing (inline).

Related: #40096

Before

After

}

/** Lines of a patch without its file headers, which is what a unified diff view renders. */
export function patchBodyLines(patch: string) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This counts the @@ ... @@ hunk header lines, but the diff view doesn't draw them (in my run the created file showed only the + rows). So a created file or edit with exactly 10 changed lines counts as 11, gets Click to expand, and clicking does nothing. The new test confirms it: a 3-line hunk returns 4. Multi-hunk patches add one extra per hunk. Counting only the body lines (skip lines starting with @@, and probably \ No newline at end of file) would match what is rendered.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in dbf5884, hunk headers and the \ No newline line aren't counted now. test covers both, plus a second hunk

a file with exactly 10 changed lines counted as 11 and got a hint that did nothing

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hunk-header off-by-one is fixed: patchBodyLines now skips @@ and \ No newline lines. With the simulated model, a patch creating an exactly 10-line file renders in full with no expand hint, and the updated tests pass.

Public API: unchanged.

No new concerns. The design question from the earlier review still needs a maintainer: the behaviour is tied to session.verbosity, and with mouse: false the only way to expand a block is raising verbosity.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant