Merge pull request #13728 from NousResearch/bb/tui-history-local
fix(tui): /history shows the TUI's own transcript, scrollable
This commit is contained in:
@@ -211,6 +211,42 @@ describe('createSlashHandler', () => {
|
|||||||
expect(ctx.transcript.send).toHaveBeenCalledWith(skillMessage)
|
expect(ctx.transcript.send).toHaveBeenCalledWith(skillMessage)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('/history pages the current TUI transcript (user + assistant)', () => {
|
||||||
|
const ctx = buildCtx({
|
||||||
|
local: {
|
||||||
|
...buildLocal(),
|
||||||
|
getHistoryItems: vi.fn(() => [
|
||||||
|
{ role: 'user', text: 'hello' },
|
||||||
|
{ role: 'system', text: 'ignore me' },
|
||||||
|
{ role: 'assistant', text: 'hi there' },
|
||||||
|
{ role: 'user', text: 'test' }
|
||||||
|
])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
createSlashHandler(ctx)('/history')
|
||||||
|
expect(ctx.transcript.page).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
const [body, title] = ctx.transcript.page.mock.calls[0]!
|
||||||
|
|
||||||
|
expect(title).toBe('History')
|
||||||
|
expect(body).toContain('[You #1]')
|
||||||
|
expect(body).toContain('hello')
|
||||||
|
expect(body).toContain('[Hermes #2]')
|
||||||
|
expect(body).toContain('hi there')
|
||||||
|
expect(body).toContain('[You #3]')
|
||||||
|
expect(body).not.toContain('ignore me')
|
||||||
|
expect(ctx.gateway.gw.request).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('/history reports empty state without paging', () => {
|
||||||
|
const ctx = buildCtx()
|
||||||
|
|
||||||
|
createSlashHandler(ctx)('/history')
|
||||||
|
expect(ctx.transcript.page).not.toHaveBeenCalled()
|
||||||
|
expect(ctx.transcript.sys).toHaveBeenCalledWith('no conversation yet')
|
||||||
|
})
|
||||||
|
|
||||||
it('handles send-type dispatch for /plan command', async () => {
|
it('handles send-type dispatch for /plan command', async () => {
|
||||||
const planMessage = 'Plan skill content loaded'
|
const planMessage = 'Plan skill content loaded'
|
||||||
|
|
||||||
|
|||||||
@@ -275,6 +275,34 @@ export const coreCommands: SlashCommand[] = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
help: 'view current transcript (user + assistant messages)',
|
||||||
|
name: 'history',
|
||||||
|
run: (arg, ctx) => {
|
||||||
|
// The CLI-side `/history` runs in a detached slash-worker subprocess
|
||||||
|
// that never sees the TUI's turns — it only surfaces whatever was
|
||||||
|
// persisted before this process started. Render the TUI's own
|
||||||
|
// transcript so `/history` actually reflects what the user just did.
|
||||||
|
const items = ctx.local.getHistoryItems().filter(m => m.role === 'user' || m.role === 'assistant')
|
||||||
|
|
||||||
|
if (!items.length) {
|
||||||
|
return ctx.transcript.sys('no conversation yet')
|
||||||
|
}
|
||||||
|
|
||||||
|
const preview = Math.max(80, parseInt(arg, 10) || 400)
|
||||||
|
|
||||||
|
const lines = items.map((m, i) => {
|
||||||
|
const tag = m.role === 'user' ? `You #${i + 1}` : `Hermes #${i + 1}`
|
||||||
|
const body = m.text.trim() || (m.tools?.length ? `(${m.tools.length} tool calls)` : '(empty)')
|
||||||
|
const clipped = body.length > preview ? `${body.slice(0, preview).trimEnd()}…` : body
|
||||||
|
|
||||||
|
return `[${tag}]\n${clipped}`
|
||||||
|
})
|
||||||
|
|
||||||
|
ctx.transcript.page(lines.join('\n\n'), 'History')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
aliases: ['sb'],
|
aliases: ['sb'],
|
||||||
help: 'toggle status bar',
|
help: 'toggle status bar',
|
||||||
|
|||||||
Reference in New Issue
Block a user