mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-04 02:21:47 +00:00
fix(tui): restore resumed transcript lineage
This commit is contained in:
parent
350ee1bf23
commit
d4dde6b5f2
11 changed files with 537 additions and 49 deletions
|
|
@ -1,7 +1,26 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { toTranscriptMessages } from '../domain/messages.js'
|
||||
import { upsert } from '../lib/messages.js'
|
||||
|
||||
describe('toTranscriptMessages', () => {
|
||||
it('preserves assistant tool-call rows so resume does not drop prior turns', () => {
|
||||
const rows = [
|
||||
{ role: 'user', text: 'first prompt' },
|
||||
{ role: 'tool', context: 'repo', name: 'search_files', text: 'ignored raw result' },
|
||||
{ role: 'assistant', text: 'first answer' },
|
||||
{ role: 'user', text: 'second prompt' }
|
||||
]
|
||||
|
||||
expect(toTranscriptMessages(rows).map(msg => [msg.role, msg.text])).toEqual([
|
||||
['user', 'first prompt'],
|
||||
['assistant', 'first answer'],
|
||||
['user', 'second prompt']
|
||||
])
|
||||
expect(toTranscriptMessages(rows)[1]?.tools?.[0]).toContain('Search Files')
|
||||
})
|
||||
})
|
||||
|
||||
describe('upsert', () => {
|
||||
it('appends when last role differs', () => {
|
||||
expect(upsert([{ role: 'user', text: 'hi' }], 'assistant', 'hello')).toHaveLength(2)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import {
|
||||
boundedLiveRenderText,
|
||||
buildToolTrailLine,
|
||||
edgePreview,
|
||||
estimateRows,
|
||||
estimateTokensRough,
|
||||
fmtK,
|
||||
isToolTrailResultLine,
|
||||
lastCotTrailIndex,
|
||||
parseToolTrailResultLine,
|
||||
pasteTokenLabel,
|
||||
sameToolTrailGroup
|
||||
sameToolTrailGroup,
|
||||
splitToolDuration
|
||||
} from '../lib/text.js'
|
||||
|
||||
describe('isToolTrailResultLine', () => {
|
||||
|
|
@ -19,6 +23,16 @@ describe('isToolTrailResultLine', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('buildToolTrailLine', () => {
|
||||
it('puts completion duration inline before the result marker', () => {
|
||||
const line = buildToolTrailLine('read_file', 'x', false, '', 0.94)
|
||||
|
||||
expect(line).toBe('Read File("x") (0.9s) ✓')
|
||||
expect(parseToolTrailResultLine(line)).toEqual({ call: 'Read File("x") (0.9s)', detail: '', mark: '✓' })
|
||||
expect(splitToolDuration('Read File("x") (0.9s)')).toEqual({ label: 'Read File("x")', duration: ' (0.9s)' })
|
||||
})
|
||||
})
|
||||
|
||||
describe('lastCotTrailIndex', () => {
|
||||
it('finds last non-result line', () => {
|
||||
expect(lastCotTrailIndex(['a ✓', 'thinking…'])).toBe(1)
|
||||
|
|
@ -68,6 +82,28 @@ describe('estimateTokensRough', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('boundedLiveRenderText', () => {
|
||||
it('preserves short live text verbatim', () => {
|
||||
expect(boundedLiveRenderText('one\ntwo', { maxChars: 100, maxLines: 10 })).toBe('one\ntwo')
|
||||
})
|
||||
|
||||
it('keeps the live tail by character budget', () => {
|
||||
const out = boundedLiveRenderText('abcdefghij', { maxChars: 4, maxLines: 10 })
|
||||
|
||||
expect(out).toContain('ghij')
|
||||
expect(out).toContain('omitted')
|
||||
expect(out).not.toContain('abcdef')
|
||||
})
|
||||
|
||||
it('keeps the live tail by line budget', () => {
|
||||
const out = boundedLiveRenderText(['a', 'b', 'c', 'd'].join('\n'), { maxChars: 100, maxLines: 2 })
|
||||
|
||||
expect(out).toContain('c\nd')
|
||||
expect(out).toContain('omitted 2 lines')
|
||||
expect(out).not.toContain('a\nb')
|
||||
})
|
||||
})
|
||||
|
||||
describe('edgePreview', () => {
|
||||
it('keeps both ends for long text', () => {
|
||||
expect(edgePreview('Vampire Bondage ropes slipped from her neck, still stained with blood', 8, 18)).toBe(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue