Skip to content

fix(ui): wrap agent note text by terminal cells - #567

Merged
benvinegar merged 1 commit into
modem-dev:mainfrom
kataokatsuki:fix/wraptext-cell-width
Jul 18, 2026
Merged

fix(ui): wrap agent note text by terminal cells#567
benvinegar merged 1 commit into
modem-dev:mainfrom
kataokatsuki:fix/wraptext-cell-width

Conversation

@kataokatsuki

Copy link
Copy Markdown
Contributor

Summary

Plain-text agent notes (inline cards, hover popovers, static pager
inline-note lines) wrap their text with wrapText, which measures with
String#length and splits with String#slice — UTF-16 code units. The
renderers then clamp each line by terminal cells (fitText / padText),
so for CJK text (1 code unit = 2 cells) the wrapped lines come out up to
2× the box width and the clamp truncates them, silently dropping text.
Code-unit splitting can also cut an emoji's surrogate pair in half
(renders as U+FFFD).

  • measure words with measureTextWidth and track the current line's
    cell width alongside the string, so line-fit checks compare cells to
    cells
  • hard-split over-wide words with sliceTextByWidth, which walks
    grapheme clusters — wide characters and emoji are never split
  • when the width is narrower than a single cluster, keep the remainder
    on one line for the renderer's fitText to clamp instead of dropping
    it, and decide "line is empty" by string length so zero-width
    characters can't produce over-wide lines
  • add regression tests: CJK wrapping, mixed EN/JA text, odd widths,
    degenerate width 1, surrogate-pair and ZWJ emoji

Closes #566

Repro

With a 40-cell box and a 62-char / 124-cell Japanese summary:

wrapText output
Before 2 lines of 40 code units = 80 cells each; the renderer clips both lines, silently dropping ~half the text
After 4 lines of ≤ 40 cells; nothing dropped

English output is unchanged — wrapping of ASCII input is byte-identical
before and after.

Testing

All run in a clean Linux container (oven/bun + git), matching CI's
ubuntu-latest environment:

  • bun run typecheck
  • bun run lint
  • bun run format:check
  • bun test src — 1,140 tests, 0 fail
  • bun run test:tty-smoke — 9 pass, identical to a baseline run without
    this change (the harness needs util-linux script, which macOS lacks)
@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

PR author is not in the allowed authors list.

@benvinegar
benvinegar merged commit 5d1ef68 into modem-dev:main Jul 18, 2026
2 checks passed
@kataokatsuki

Copy link
Copy Markdown
Contributor Author

Thanks for the quick merge!

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

Labels

None yet

2 participants