Files
hermes-agent/ui-tui/src/lib/liveProgress.test.ts
Brooklyn Nicholson b1c49d5e73 chore(tui): /clean recent perf work — KISS/DRY pass
24 files, -319 LoC. Behaviour preserved, 369/369 tests green.

- hermes-ink caches: shared lruEvict helper for the four parallel LRU
  caches (stringWidth, wrapText, sliceAnsi, lineWidth); touch-on-read
  stays inlined per cache; tightened output.ts skip-slice fast path.
- wheelAccel: trimmed provenance header, collapsed env parsing, ternary
  dispatch in computeWheelStep.
- perfPane: folded ensureLogDir into once-flag, spread-with-overrides
  for fastPath/phases instead of full rebuilds.
- env: extracted truthy() (used 4×).
- virtualHeights: collapsed user/diff/slash height bumps; trail+todos
  estimate.
- useInputHandlers: scrollIdleTimer cleanup on unmount, ?? undefined
  shorthand.
- useMainApp: dropped dead liveTailVisible IIFE and liveProgress
  indirection.
- appLayout, markdown, messageLine, entry: vertical rhythm, dropped
  narration comments, inlined one-shot vars.
- fix: empty catch blocks → /* best-effort */ for no-empty lint.
2026-04-26 20:38:47 -05:00

117 lines
4.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import type { Msg } from '../types.js'
import { appendToolShelfMessage, canHoldToolShelf, isTodoDone, mergeToolShelfInto } from './liveProgress.js'
describe('isTodoDone', () => {
it('only treats non-empty all-completed/cancelled lists as done', () => {
expect(isTodoDone([])).toBe(false)
expect(isTodoDone([{ content: 'x', id: 'x', status: 'completed' }])).toBe(true)
expect(isTodoDone([{ content: 'x', id: 'x', status: 'in_progress' }])).toBe(false)
expect(
isTodoDone([
{ content: 'x', id: 'x', status: 'completed' },
{ content: 'y', id: 'y', status: 'cancelled' }
])
).toBe(true)
})
})
describe('tool shelf helpers', () => {
it('recognizes contextual thinking shelves as holders', () => {
expect(canHoldToolShelf({ kind: 'trail', role: 'system', text: '', thinking: 'plan' })).toBe(true)
expect(canHoldToolShelf({ kind: 'trail', role: 'system', text: '', tools: ['one ✓'] })).toBe(true)
expect(canHoldToolShelf({ role: 'assistant', text: 'done' })).toBe(false)
})
it('merges source rows into an existing shelf', () => {
expect(
mergeToolShelfInto(
{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['one ✓'] },
{ kind: 'trail', role: 'system', text: '', tools: ['two ✓'] }
)
).toEqual({ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['one ✓', 'two ✓'] })
})
})
describe('appendToolShelfMessage', () => {
it('merges adjacent tool shelves into one contextual shelf', () => {
const merged = appendToolShelfMessage([{ kind: 'trail', role: 'system', text: '', tools: ['one ✓'] }], {
kind: 'trail',
role: 'system',
text: '',
tools: ['two ✓']
})
expect(merged).toEqual([{ kind: 'trail', role: 'system', text: '', tools: ['one ✓', 'two ✓'] }])
})
it('adds tools to the nearest contextual thinking shelf', () => {
const merged = appendToolShelfMessage(
[{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['one ✓'] }],
{ kind: 'trail', role: 'system', text: '', tools: ['two ✓'] }
)
expect(merged).toEqual([{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['one ✓', 'two ✓'] }])
})
it('merges through intervening thinking-only rows back into the nearest holder', () => {
const prev: Msg[] = [
{ kind: 'trail', role: 'system', text: '', thinking: 'plan', tools: ['one ✓'] },
{ kind: 'trail', role: 'system', text: '', thinking: 'more plan' }
]
const merged = appendToolShelfMessage(prev, {
kind: 'trail',
role: 'system',
text: '',
tools: ['two ✓']
})
expect(merged).toHaveLength(2)
expect(merged[0]).toEqual({
kind: 'trail',
role: 'system',
text: '',
thinking: 'plan',
tools: ['one ✓', 'two ✓']
})
expect(merged[1]).toEqual({ kind: 'trail', role: 'system', text: '', thinking: 'more plan' })
})
it('collapses a chronological thinking/tool/thinking/tool stream into one shelf', () => {
const events: Msg[] = [
{ kind: 'trail', role: 'system', text: '', thinking: 'plan' },
{ kind: 'trail', role: 'system', text: '', tools: ['one ✓'] },
{ kind: 'trail', role: 'system', text: '', thinking: 'more plan' },
{ kind: 'trail', role: 'system', text: '', tools: ['two ✓'] },
{ kind: 'trail', role: 'system', text: '', tools: ['three ✓'] }
]
const reduced = events.reduce<Msg[]>((acc, msg) => appendToolShelfMessage(acc, msg), [])
expect(reduced).toHaveLength(2)
expect(reduced[0]).toEqual({
kind: 'trail',
role: 'system',
text: '',
thinking: 'plan',
tools: ['one ✓', 'two ✓', 'three ✓']
})
expect(reduced[1]).toEqual({ kind: 'trail', role: 'system', text: '', thinking: 'more plan' })
})
it('starts a new shelf across assistant text boundaries', () => {
const merged = appendToolShelfMessage(
[
{ kind: 'trail', role: 'system', text: '', tools: ['one ✓'] },
{ role: 'assistant', text: 'done' }
],
{ kind: 'trail', role: 'system', text: '', tools: ['two ✓'] }
)
expect(merged).toHaveLength(3)
})
})