Files
dsh-context/tests/client/components/nodes.spec.ts
T
Bowen Liang fe7d8dafb9 feat(client): replace the Messages card with a File Activity card
The bottom-right card no longer lists model-visible messages; it answers
what the agent DID to the user's files up to the picked step. Tool-result
nodes (live + archive) join the conversation snapshot for call arguments
and fold into one row per file with per-purpose counts (read/written/
searched), estimated line deltas from edit/write arguments, multimodal
and directory form glyphs, and failure dots. Header chips double as
purpose/form filters next to a path search box; a row expands into the
file's operation log, and each operation reveals the exact tool result
in the Context browser. The card scrubs live with the trend chart pick
(exclusive next-request bound); ops whose paths aged out of retention
are honestly counted in a footnote.
2026-08-26 08:36:02 +08:00

43 lines
2.2 KiB
TypeScript

// The node-text label cascade (src/client/components/nodes.tsx), pure and
// driven directly — the Context browser's element-row previews.
import assert from 'node:assert/strict'
import { describe, test } from 'vitest'
import { makeNodeText } from '../../../src/client/components/nodes'
import { makeKit } from '../helpers/kit'
const kit = makeKit()
const nodeText = makeNodeText(kit)
describe('makeNodeText', () => {
test('tool results name the tool; failures carry the warning glyph', () => {
assert.equal(nodeText({ seq: 1, cat: 'tool', tokens: 1, tool: 'bash' }), 'Tool Result ← bash')
assert.equal(nodeText({ seq: 1, cat: 'tool', tokens: 1 }), 'Tool Result')
assert.equal(nodeText({ seq: 1, cat: 'tool', tokens: 1, tool: 'bash', err: true }), 'Tool Result ← bash ⚠')
})
test('skill-tagged nodes lead with the skill name', () => {
// The skill branch follows the tool branch: skill results keep their
// tool-result label; the skill name leads on injected nodes.
assert.equal(nodeText({ seq: 1, cat: 'tool', tokens: 1, skill: 'code-review' }), 'Tool Result')
assert.equal(nodeText({ seq: 1, cat: 'inject', tokens: 1, skill: 'code-review' }), 'Skill: code-review')
})
test('assistant replies show text, a calls breadcrumb, or the empty marker', () => {
assert.equal(nodeText({ seq: 1, cat: 'assistant', tokens: 1, text: 'hi' }), 'hi')
assert.equal(nodeText({ seq: 1, cat: 'assistant', tokens: 1, calls: ['bash', 'read'] }), 'Calls bash, read')
assert.equal(nodeText({ seq: 1, cat: 'assistant', tokens: 1 }), '(empty reply)')
})
test('snapshot-form text gets the snapshot prefix; plain text shows as-is', () => {
assert.equal(nodeText({ seq: 1, cat: 'inject', tokens: 1, form: 'snapshot', text: 'a, b' }), 'Snapshot: a, b')
assert.equal(nodeText({ seq: 1, cat: 'user', tokens: 1, text: 'plain' }), 'plain')
})
test('textless injects label their form; anything else is a non-text message', () => {
assert.equal(nodeText({ seq: 1, cat: 'inject', tokens: 1, form: 'notice' }), 'Notice')
assert.equal(nodeText({ seq: 1, cat: 'inject', tokens: 1 }), 'Context Injection')
assert.equal(nodeText({ seq: 1, cat: 'user', tokens: 1 }), '(non-text message)')
})
})