hermes-agent/ui-tui/src/app
Brooklyn Nicholson 0078f743e6 perf(tui): debounce resize RPC + column-aware useVirtualHistory
VSCode panel-drag fires 20+ SIGWINCHes/sec, each previously triggering
an unthrottled `terminal.resize` gateway RPC and a full transcript
re-virtualization with stale per-row height cache.

## Changes

### gateway RPC debounce (ui-tui/src/app/useMainApp.ts)
- `terminal.resize` RPC now trailing-debounced at 100 ms. React `cols`
  state stays synchronous (needed for Yoga / in-process rendering),
  only the round-trip to Python coalesces. Prevents gateway flood
  during panel-drag / tmux-pane-resize.

### column-aware useVirtualHistory (ui-tui/src/hooks/useVirtualHistory.ts)
- New required `columns` param, plumbed through from useMainApp.
- On column change: scale every cached row height by `oldCols/newCols`
  (Math.max 1, Math.round) instead of clearing. Clearing forces a
  pessimistic back-walk that mounts ~190 rows at once (viewport + 2x
  overscan at 1-row estimate), each a fresh marked.lexer + syntax
  highlight ≈ 3 ms — ~600 ms React commit block. Scaled heights keep
  the back-walk tight.
- `freezeRenders=2`: reuse pre-resize mount range for 2 renders so
  already-mounted MessageRows keep their warm useMemo results. Without
  this the first post-resize render would unmount + remount most rows
  (pessimistic coverage) = visible flash + 150 ms+ freeze.
- `skipMeasurement` flag: first post-resize useLayoutEffect would read
  PRE-resize Yoga heights (Yoga's stored values are still from the
  frame before this render's calculateLayout with new width) and
  poison the scaled cache. Skip the measurement loop for that one
  render; next render's Yoga is correct.

## Validation
- tsc `--noEmit` clean
- eslint clean on touched files
- `vitest run`: 15 files / 102 tests passing

The renderer-level resize patterns (sync-dim-capture + microtask-
coalesced React commit, atomic BSU/ESU erase-before-paint, mouse-
tracking reassert) already live in hermes-ink's own `handleResize`;
this patch adds the matching app-layer hygiene.
2026-04-20 18:58:44 -05:00
..
slash fix(tui): harden against Node V8 OOM + GatewayClient memory leaks 2026-04-20 18:58:44 -05:00
createGatewayEventHandler.ts fix(tui): drain message queue on every busy → false transition 2026-04-19 08:56:29 -05:00
createSlashHandler.ts feat(tui): replace /clear double-press gate with a proper confirm overlay 2026-04-18 18:04:08 -05:00
gatewayContext.tsx feat: add inline token count etc and fix venv 2026-04-15 10:20:56 -05:00
inputSelectionStore.ts fix(tui): Ctrl+C with input selection actually preserves input (lift handler to app level) 2026-04-18 16:28:51 -05:00
interfaces.ts refactor(tui): turn elapsed lives in FaceTicker; emit done-in sys line 2026-04-20 11:38:11 -05:00
overlayStore.ts feat(tui): replace /clear double-press gate with a proper confirm overlay 2026-04-18 18:04:08 -05:00
setupHandoff.ts feat(tui): /model and /setup slash commands with in-place CLI handoff 2026-04-17 10:58:18 -05:00
turnController.ts fix(tui): strip <think>…</think> tags from assistant content and route to reasoning panel 2026-04-18 14:46:38 -05:00
turnStore.ts feat(tui): interleave tool rows into live assistant turns 2026-04-17 11:33:29 -05:00
uiStore.ts feat(tui): read display.streaming / show_reasoning / show_cost / inline_diffs from config 2026-04-18 09:42:57 -05:00
useComposerState.ts fix(tui): bound retained state against idle OOM 2026-04-19 18:43:40 -07:00
useConfigSync.ts feat(tui): read display.streaming / show_reasoning / show_cost / inline_diffs from config 2026-04-18 09:42:57 -05:00
useInputHandlers.ts fix(tui): fix Linux Ctrl+C regression, remove double clipboard write 2026-04-20 07:14:33 -07:00
useLongRunToolCharms.ts refactor(tui): /clean pass across ui-tui — 49 files, −217 LOC 2026-04-16 22:32:53 -05:00
useMainApp.ts perf(tui): debounce resize RPC + column-aware useVirtualHistory 2026-04-20 18:58:44 -05:00
useSessionLifecycle.ts refactor(tui): turn elapsed lives in FaceTicker; emit done-in sys line 2026-04-20 11:38:11 -05:00
useSubmission.ts refactor(tui): turn elapsed lives in FaceTicker; emit done-in sys line 2026-04-20 11:38:11 -05:00