mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-28 01:21:43 +00:00
fix(tui): sticky prompt correctness + scrollbar re-render thrash
Sticky prompt: The loop was skipping `first` (the first row in the viewport) when looking for a user message scrolled above the top edge. If `first` itself was a user row that had just ticked above the viewport, we'd fall through the early-return guard (`role === 'user' && !above`), then walk from `first - 1` backward — never rechecking `first`, never finding anything, returning '' and leaving the sticky empty. This is why it felt "stuck" at the start: one-turn sessions with the user row exactly at/near the top never surfaced the breadcrumb. Collapsed the two branches into one loop starting at `first`: nearest user wins — still-on-screen → empty (redundant to echo), already above → text. Same semantics, covers the gap. Scrollbar: `useSyncExternalStore` snapshot was `scrollTop:vp:scrollHeight` — scrollHeight ticks up by ~1 row on every streamed chunk, forcing a re-render per chunk. Quantized snapshot to the displayed values (`thumbTop:thumbSize:vp`) so we only re-render when the bar actually changes. Drops render count per turn by ~100x during streaming and stops the "constantly resizes" flicker.
This commit is contained in:
parent
40f2368875
commit
c74017f405
2 changed files with 18 additions and 8 deletions
|
|
@ -28,16 +28,15 @@ export const stickyPromptFromViewport = (
|
|||
const first = Math.max(0, Math.min(messages.length - 1, upperBound(offsets, top) - 1))
|
||||
const aboveViewport = (i: number) => (offsets[i] ?? 0) + 1 < top
|
||||
|
||||
if (messages[first]?.role === 'user' && !aboveViewport(first)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
for (let i = first - 1; i >= 0; i--) {
|
||||
if (messages[i]?.role !== 'user' || !aboveViewport(i)) {
|
||||
// Walk backward from the first visible row. The nearest user message wins:
|
||||
// if it's still on screen, no sticky is needed; if it's already scrolled
|
||||
// above the top, its text becomes the floating breadcrumb.
|
||||
for (let i = first; i >= 0; i--) {
|
||||
if (messages[i]?.role !== 'user') {
|
||||
continue
|
||||
}
|
||||
|
||||
return userDisplay(messages[i]!.text.trim()).replace(/\s+/g, ' ').trim()
|
||||
return aboveViewport(i) ? userDisplay(messages[i]!.text.trim()).replace(/\s+/g, ' ').trim() : ''
|
||||
}
|
||||
|
||||
return ''
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue