mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-19 15:18:03 +00:00
Core machinery of docs/plans/opentui-transcript-windowing.md (#27): rows outside [scrollTop − viewport, scrollTop + 2·viewport) swap to an exact-height empty <box> (1 yoga node, no text buffers / native handles), so the mounted set stays ~3 viewports regardless of transcript length. Flag: HERMES_TUI_WINDOWING — unset → ON; 0/false/no/off → OFF (envFlag semantics, the bench A/B + one-env escape hatch). OFF renders the exact legacy tree (no wrapper boxes). Pieces: - logic/window.ts (pure, table-tested): computeWindow (viewport ± 1-viewport margin intersection over cumulative exact heights; null heights fall back to a per-row line-count estimate), hysteresisFor/shouldRecompute (≥ ¼ viewport between recomputes), correctionIsLegal (the jank rule: corrections only fully above the viewport with same-frame scrollTop compensation, or fully below it), estimateMessageHeight (line-count estimate; wrong values are fixed by remount only — S1 never corrects a spacer in place). - view/transcript.tsx: per-row measuring wrapper records exact heights via onSizeChange (only while the real row is mounted); window driver is a renderer frame callback (setFrameCallback — scroll always renders, so no extra timer) publishing the mounted set through one signal + createSelector so only flipped rows re-render. Stable row keys via WeakMap<Message, n> (messages have no id; store proxies are reference-stable). Solid <Show> unmount destroys the row's renderables (@opentui/solid _removeNode → destroyRecursively). Never-window rules: - streaming rows (remount would restart native markdown streaming), - the last row while a turn is running (deltas land there), - the bottom 30 rows (fixed K — sticky-bottom region; rows under viewport+margin are mounted by the window calc anyway), - rows the window has never adjudicated default to MOUNTED (new live rows paint instantly), - the whole window FREEZES while a mouse selection is active (renderer.getSelection()?.isActive — a swap would destroy highlighted renderables under the native selection walk). Tests: 30 pure window.test.ts cases + 2 headless integration cases (transcriptWindow.test.tsx) pinning the zero-jank invariant (scrollHeight identical ON vs OFF), the renderable shedding, and remount-on-scroll-back. |
||
|---|---|---|
| .. | ||
| scripts | ||
| src | ||
| .gitignore | ||
| .prettierrc | ||
| eslint.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| tsconfig.json | ||
| vitest.config.ts | ||