mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-21 05:11:26 +00:00
Multi-turn transcripts ran together visually because every user message got the same vertical rhythm regardless of position. Adds a short ─── in the border colour above every user message after the first, so each turn reads as its own block. Height estimator gains a `withSeparator` flag so virtual scrolling pre-allocates the extra two rows (rule + top margin) and avoids a jump on first measurement. While in the area: the busy-indicator duration was padded with `padStart(7)`, leaving five visible spaces between `·` and the digits (`⠋ · 2s`) — especially loud under the verb-less `unicode` style. Drop the padding entirely (`⠋ · 2s`); the model label now shifts a few columns as the duration grows, which is the right trade-off for the minimal indicator styles. The verb-padding test stays; the duration-padding test is removed alongside the function it covered.
42 lines
1.8 KiB
TypeScript
42 lines
1.8 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
|
||
import { estimatedMsgHeight, messageHeightKey, wrappedLines } from '../lib/virtualHeights.js'
|
||
import type { Msg } from '../types.js'
|
||
|
||
describe('virtual height estimates', () => {
|
||
it('uses stable content keys across resumed message objects', () => {
|
||
const msg: Msg = { role: 'assistant', text: 'same text', tools: ['Search Files [long message]'] }
|
||
|
||
expect(messageHeightKey(msg)).toBe(messageHeightKey({ ...msg }))
|
||
})
|
||
|
||
it('accounts for wrapping and preserved blank-block rhythm', () => {
|
||
const msg: Msg = { role: 'assistant', text: `one\n\n${'x'.repeat(90)}` }
|
||
|
||
expect(wrappedLines(msg.text, 30)).toBe(5)
|
||
expect(estimatedMsgHeight(msg, 35, { compact: false, details: false })).toBeGreaterThan(5)
|
||
})
|
||
|
||
it('uses compound user prompt width when estimating user message wrapping', () => {
|
||
const msg: Msg = { role: 'user', text: 'x'.repeat(21) }
|
||
|
||
expect(estimatedMsgHeight(msg, 26, { compact: false, details: false, userPrompt: '❯' })).toBe(3)
|
||
expect(estimatedMsgHeight(msg, 26, { compact: false, details: false, userPrompt: 'Ψ >' })).toBe(4)
|
||
})
|
||
|
||
it('includes detail sections when visible', () => {
|
||
const msg: Msg = { role: 'assistant', text: 'ok', thinking: 'line 1\nline 2', tools: ['Tool A', 'Tool B'] }
|
||
|
||
expect(estimatedMsgHeight(msg, 80, { compact: false, details: true })).toBeGreaterThan(
|
||
estimatedMsgHeight(msg, 80, { compact: false, details: false })
|
||
)
|
||
})
|
||
|
||
it('reserves two extra rows for the inter-turn separator on non-first user messages', () => {
|
||
const msg: Msg = { role: 'user', text: 'follow-up question' }
|
||
const base = estimatedMsgHeight(msg, 80, { compact: false, details: false })
|
||
const withSep = estimatedMsgHeight(msg, 80, { compact: false, details: false, withSeparator: true })
|
||
|
||
expect(withSep).toBe(base + 2)
|
||
})
|
||
})
|