fix(tui): address Copilot review comments

- stringWidth: true LRU on cache hit (touch-on-read via delete+set) so
  hot strings stay resident under long sessions; was insertion-order
  FIFO before
- virtualHeights: include todos, panel sections, and intro version in
  messageHeightKey so height-cache reuse correctly invalidates when
  todo content / panel sections change
- virtualHeights: estimate trail+todos rows at todos.length+2 (or 2
  collapsed) instead of the generic ~1-line fallback, so initial
  virtualization offsets are closer to reality
- useInputHandlers: clearTimeout on unmount for scrollIdleTimer so
  pending relaxStreaming() never fires after teardown
- render-node-to-output: drop unused declined.noHint counter from
  scrollFastPathStats; it was always 0 (the "hint missing" branch is
  outside the diagnostics block)
- perfPane / hermes-ink.d.ts: follow the noHint removal
- wheelAccel: replace ~/claude-code path comment with generic
  attribution that doesn't reference a developer-local checkout
This commit is contained in:
Brooklyn Nicholson 2026-04-26 20:07:41 -05:00
parent b115ea62da
commit 527ac351b4
7 changed files with 42 additions and 13 deletions

View file

@ -12,8 +12,22 @@ export const hashText = (text: string) => {
return (h >>> 0).toString(36)
}
export const messageHeightKey = (msg: Msg) =>
[msg.role, msg.kind ?? '', hashText([msg.text, msg.thinking ?? '', msg.tools?.join('\n') ?? ''].join('\0'))].join(':')
export const messageHeightKey = (msg: Msg) => {
const todoSig = msg.todos?.map(t => `${t.status}:${t.content}`).join('\u0001') ?? ''
const panelSig =
msg.panelData?.sections
.map(s => `${s.title ?? ''}:${s.text?.length ?? 0}:${s.items?.length ?? 0}:${s.rows?.length ?? 0}`)
.join('\u0001') ?? ''
const introSig = msg.kind === 'intro' ? (msg.info?.version ?? '') : ''
return [
msg.role,
msg.kind ?? '',
hashText(
[msg.text, msg.thinking ?? '', msg.tools?.join('\n') ?? '', todoSig, panelSig, introSig].join('\0')
)
].join(':')
}
export const wrappedLines = (text: string, width: number) => {
const w = Math.max(1, width)
@ -34,6 +48,14 @@ export const estimatedMsgHeight = (
return Math.max(3, (msg.panelData?.sections.length ?? 1) * 2 + 1)
}
if (msg.kind === 'trail' && msg.todos?.length) {
if (msg.todoCollapsedByDefault) {
return 2
}
return Math.max(2, msg.todos.length + 2)
}
const bodyWidth = Math.max(20, cols - 5)
const text = msg.role === 'assistant' && limitHistory ? boundedHistoryRenderText(msg.text) : msg.text
let h = wrappedLines(text || ' ', bodyWidth)