kimi-code / packages /transcript /test /layers.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
4e23b01 verified
Raw History Blame Contribute Delete
97.5 kB
import { describe, expect, it } from 'vitest'; import { filterOpsForGrade, isAppendOnly, redactSnapshotForGrade } from '#/granularity/filterOps'; import { detachGrades, gradeFor, needsResetOnTransition } from '#/granularity/grade'; import { paginateTurns } from '#/pagination/paginate'; import { ViewRegistry } from '#/view/registry'; import { projectTranscriptUserOrigin } from '#/contract/origin'; import { groupMessagesIntoSnapshot, type HistoryContentPart } from '#/history/groupTurns'; import { foldWireRecordFacts, type HistoryWireRecord } from '#/history/foldFacts'; import { transcriptOperationSchema, transcriptQuerySchema, transcriptResponseSchema, transcriptGradeSpecSchema, transcriptUserOriginSchema, } from '#/contract/schema'; import type { TranscriptItem } from '#/model/item'; import type { AgentTranscriptSnapshot, TranscriptOperation } from '#/ops/operation'; const idLabel = (i: TranscriptItem): string => i.kind === 'turn' ? i.turnId : i.kind === 'marker' ? i.markerId : i.refId; describe('client metadata in transcript user origins', () => { it('retains user-invoked single skill frame metadata without exposing model-triggered activations as user input', () => { const origin = { kind: 'skill_activation', trigger: 'user-slash', skillName: 'example-skill', skillArgs: 'args', clientMetadata: [{ display_text: 'Save button' }] }; expect(transcriptUserOriginSchema.parse(projectTranscriptUserOrigin(origin))).toEqual(origin); expect(projectTranscriptUserOrigin({ ...origin, trigger: 'model-tool' })).toBeUndefined(); }); it('rebuilds a user turn payload without server-local paths', () => { const clientMetadata = [{ display_text: 'Visible prompt' }]; const origin = { kind: 'user', clientMetadata, skillActivations: [{ activationId: 'a1', skillName: 'deploy', skillArgs: 'now', skillPath: '/private/deploy/SKILL.md' }], attachments: [{ name: 'notes.pdf', mediaType: 'application/pdf', size: 42, path: '/private/notes.pdf' }], }; const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'rendered skill' }, { type: 'text', text: 'visible prompt' }], toolCalls: [], origin }, { role: 'assistant', content: [{ type: 'text', text: 'reply' }], toolCalls: [] }, ]); const turn = snapshot.items.find((item) => item.kind === 'turn'); expect(turn?.origin).toEqual({ kind: 'user', payload: { kind: 'user', clientMetadata, skillActivations: [{ skillName: 'deploy', skillArgs: 'now' }] } }); expect(JSON.stringify(turn)).not.toContain('/private/'); expect(JSON.stringify(snapshot.attachments)).not.toContain('/private/'); }); it('keeps opening prompt metadata when rebuilding history turns', () => { const clientMetadata = [{ kimi_code_composer: { version: 1, doc: { type: 'doc' } } }]; const origin = { kind: 'user', clientMetadata }; const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'visible prompt' }], toolCalls: [], origin }, { role: 'assistant', content: [{ type: 'text', text: 'reply' }], toolCalls: [] }, ]); const turn = snapshot.items.find((item) => item.kind === 'turn'); expect(turn?.origin).toEqual({ kind: 'user', payload: { kind: 'user', clientMetadata } }); expect(turn?.prompt).toBe('visible prompt'); }); it('projects and validates independent document snapshots without losing their nested fields', () => { const clientMetadata = [ { kimi_code_composer: { version: 1, doc: { type: 'doc', content: [{ type: 'paragraph' }] }, captureIds: ['capture-a'] } }, { kimi_code_composer: { version: 1, captureIds: ['capture-b'] } }, ]; const projected = projectTranscriptUserOrigin({ kind: 'user', clientMetadata }); expect(transcriptUserOriginSchema.parse(projected)).toEqual({ kind: 'user', clientMetadata }); expect(projectTranscriptUserOrigin({ kind: 'user' })).toStrictEqual({ kind: 'user' }); expect(projectTranscriptUserOrigin({ kind: 'injection', clientMetadata })).toBeUndefined(); }); }); describe('user slash skill activations as transcript origins', () => { it('projects a user-invoked activation and rejects a model-triggered one', () => { const origin = { kind: 'skill_activation', trigger: 'user-slash', skillName: 'example-skill', skillArgs: 'args' }; expect(transcriptUserOriginSchema.parse(projectTranscriptUserOrigin(origin))).toEqual(origin); expect(projectTranscriptUserOrigin({ ...origin, trigger: 'model-tool' })).toBeUndefined(); expect(projectTranscriptUserOrigin({ ...origin, skillName: '' })).toBeUndefined(); expect(projectTranscriptUserOrigin({ kind: 'user' })).toStrictEqual({ kind: 'user' }); }); }); const turnOp = (n: number): TranscriptOperation => ({ op: 'turn.upsert', turn: { kind: 'turn', turnId: `t${n}`, ordinal: n, state: 'running', origin: { kind: 'user' } }, }); const stepOp: TranscriptOperation = { op: 'step.upsert', turnId: 't1', step: { kind: 'step', stepId: 't1.1', turnId: 't1', ordinal: 1, state: 'running' }, }; const frameOp: TranscriptOperation = { op: 'frame.upsert', turnId: 't1', stepId: 't1.1', frame: { kind: 'text', frameId: 't1.1.f1', role: 'assistant', text: 'full' }, }; const appendOp: TranscriptOperation = { op: 'append', target: { type: 'frame', turnId: 't1', stepId: 't1.1', frameId: 't1.1.f1' }, offset: 0, text: 'chunk', }; const promptOp: TranscriptOperation = { op: 'prompt.upsert', prompt: { promptId: 'p1', status: 'queued', createdAt: '2026-07-22T00:00:00.000Z' }, }; describe('granularity', () => { const ops: TranscriptOperation[] = [ turnOp(1), stepOp, frameOp, appendOp, promptOp, { op: 'meta.merge', meta: { activity: 'turn' } }, ]; it('off admits nothing', () => { expect(filterOpsForGrade('off', ops)).toEqual([]); }); it('turn admits headers and global state only', () => { expect(filterOpsForGrade('turn', ops).map((op) => op.op)).toEqual([ 'turn.upsert', 'prompt.upsert', 'meta.merge', ]); }); it('block admits step/frame upserts but no appends', () => { expect(filterOpsForGrade('block', ops).map((op) => op.op)).toEqual([ 'turn.upsert', 'step.upsert', 'frame.upsert', 'prompt.upsert', 'meta.merge', ]); }); it('delta admits everything', () => { expect(filterOpsForGrade('delta', ops)).toHaveLength(ops.length); }); it('gradeFor resolves agent override over wildcard default', () => { const spec = { '*': 'turn', main: 'delta' } as const; expect(gradeFor(spec, 'main')).toBe('delta'); expect(gradeFor(spec, 'sub-1')).toBe('turn'); expect(gradeFor(undefined, 'main')).toBe('off'); }); it('upgrade needs reset, downgrade does not', () => { expect(needsResetOnTransition('turn', 'delta')).toBe(true); expect(needsResetOnTransition('delta', 'turn')).toBe(false); }); it('detachGrades writes explicit off so a wildcard default cannot resurrect the agent', () => { expect(detachGrades({ '*': 'delta' }, ['main'])).toEqual({ '*': 'delta', main: 'off' }); expect(detachGrades({ '*': 'delta', main: 'turn' }, ['main'])).toEqual({ '*': 'delta', main: 'off', }); }); it('detachGrades deletes a listed wildcard entry', () => { expect(detachGrades({ '*': 'delta', main: 'turn' }, ['*'])).toEqual({ main: 'turn' }); }); it('detachGrades collapses an all-off spec to undefined', () => { expect(detachGrades({ main: 'delta' }, ['main'])).toBeUndefined(); expect(detachGrades({ '*': 'delta', main: 'off' }, ['*'])).toBeUndefined(); expect(detachGrades(undefined, ['main'])).toBeUndefined(); }); it('append-only batches are volatile-safe', () => { expect(isAppendOnly([appendOp])).toBe(true); expect(isAppendOnly([appendOp, frameOp])).toBe(false); }); it('redactSnapshotForGrade strips step detail below block, keeps it at block+', () => { const snapshot: AgentTranscriptSnapshot = { items: [ { kind: 'turn', turnId: 't1', ordinal: 1, state: 'completed', origin: { kind: 'user' }, prompt: 'hi', steps: [ { kind: 'step', stepId: 't1.1', turnId: 't1', ordinal: 1, state: 'completed', frames: [{ kind: 'text', frameId: 't1.1.f1', role: 'assistant', text: 'body' }], }, ], }, { kind: 'marker', markerId: 'm1', marker: 'skill' }, ], tasks: [], interactions: [ { interactionId: 'appr-1', interactionKind: 'approval' as const, toolCallId: 'c1', state: 'pending' as const, }, ], attachments: [ { attachmentId: 'att_1', mediaType: 'image/png', source: { kind: 'url' as const, url: 'https://example.com/a.png' } }, ], todos: [{ todoId: 'todo', items: [{ title: 'write tests', status: 'in_progress' as const }] }], prompts: [{ promptId: 'p1', status: 'running' as const, createdAt: '2026-07-22T00:00:00.000Z' }], meta: {}, }; const turnGrade = redactSnapshotForGrade('turn', snapshot); expect(turnGrade.interactions).toHaveLength(1); expect(turnGrade.attachments).toHaveLength(1); expect(turnGrade.todos).toHaveLength(1); expect(turnGrade.prompts).toHaveLength(1); const turn = turnGrade.items[0]; expect(turn?.kind === 'turn' && turn.steps).toEqual([]); expect(turn?.kind === 'turn' && turn.prompt).toBe('hi'); expect(turnGrade.items[1]?.kind).toBe('marker'); expect(redactSnapshotForGrade('block', snapshot)).toBe(snapshot); expect(redactSnapshotForGrade('delta', snapshot)).toBe(snapshot); }); }); describe('paginateTurns', () => { const items: TranscriptItem[] = [ { kind: 'marker', markerId: 'm0', marker: 'goal' }, ...[1, 2, 3, 4, 5].flatMap((n): TranscriptItem[] => [ { kind: 'turn', turnId: `t${n}`, ordinal: n, state: 'completed', origin: { kind: 'user' }, steps: [], }, { kind: 'marker', markerId: `m${n}`, marker: 'skill' }, ]), ]; it('default page is the newest N turns with trailing segment items', () => { const page = paginateTurns(items, { pageSize: 2 }); expect(page.items.map(idLabel)).toEqual(['t4', 'm4', 't5', 'm5']); expect(page.hasMore).toBe(true); }); it('before_turn pages toward older turns; head marker rides the oldest segment', () => { const page = paginateTurns(items, { beforeTurn: 't4', pageSize: 2 }); expect(page.items.map(idLabel)).toEqual(['t2', 'm2', 't3', 'm3']); expect(page.hasMore).toBe(true); const oldest = paginateTurns(items, { beforeTurn: 't2', pageSize: 5 }); expect(oldest.items[0]).toEqual({ kind: 'marker', markerId: 'm0', marker: 'goal' }); expect(oldest.hasMore).toBe(false); }); it('after_turn pages toward newer turns without the head unit', () => { const page = paginateTurns(items, { afterTurn: 't3', pageSize: 2 }); expect(page.items.map(idLabel)).toEqual(['t4', 'm4', 't5', 'm5']); expect(page.hasMore).toBe(false); }); it('keeps head non-turn items with the newest page when turns exactly fill it', () => { const page = paginateTurns(items, { pageSize: 5 }); expect(page.items[0]).toEqual({ kind: 'marker', markerId: 'm0', marker: 'goal' }); expect(page.items.map(idLabel)).toEqual(['m0', 't1', 'm1', 't2', 'm2', 't3', 'm3', 't4', 'm4', 't5', 'm5']); expect(page.hasMore).toBe(false); }); it('returns a marker-only timeline as one page with nothing older', () => { const only = paginateTurns([{ kind: 'marker', markerId: 'm0', marker: 'goal' }], { pageSize: 3 }); expect(only.items.map(idLabel)).toEqual(['m0']); expect(only.hasMore).toBe(false); }); }); describe('ViewRegistry', () => { it('dispatches on view ?? name, origin.kind and marker keys', () => { const registry = new ViewRegistry<string>({ fallbackTool: 'generic' }); registry.registerTool('read', 'readRenderer'); registry.registerTool('swarm', 'swarmRenderer'); registry.registerInput('cron', 'cronInput'); registry.registerMarker('goal', 'goalMarker'); expect( registry.resolveTool({ kind: 'tool', frameId: 'f', toolCallId: 'c1', name: 'Read', state: 'done' }), ).toBe('readRenderer'); expect( registry.resolveTool({ kind: 'tool', frameId: 'f', toolCallId: 'c2', name: 'AgentSwarm', view: 'swarm', state: 'running' }), ).toBe('swarmRenderer'); expect( registry.resolveTool({ kind: 'tool', frameId: 'f', toolCallId: 'c3', name: 'Bash', state: 'running' }), ).toBe('generic'); expect(registry.resolveInput({ kind: 'cron' })).toBe('cronInput'); expect(registry.resolveInput({ kind: 'user' })).toBeUndefined(); expect(registry.resolveMarker('goal')).toBe('goalMarker'); }); }); describe('contract schemas', () => { it('roundtrips every op kind', () => { const ops: TranscriptOperation[] = [ { op: 'reset', agentId: 'main', snapshot: { items: [], tasks: [], interactions: [], attachments: [], todos: [], prompts: [], meta: {}, hasMoreOlder: true } }, turnOp(1), stepOp, frameOp, appendOp, { op: 'marker.upsert', item: { kind: 'marker', markerId: 'm1', marker: 'goal' } }, { op: 'taskref.upsert', item: { kind: 'taskref', refId: 'r1', taskId: 'task1' } }, { op: 'task.upsert', task: { taskId: 'task1', kind: 'shell', state: 'running', detached: false, outputTail: '' } }, { op: 'interaction.upsert', interaction: { interactionId: 'appr-1', interactionKind: 'approval', toolCallId: 'c1', state: 'pending' }, }, { op: 'attachment.upsert', attachment: { attachmentId: 'att_1', mediaType: 'image/png', source: { kind: 'file', fileId: 'f1' } }, }, { op: 'todo.upsert', todo: { todoId: 'todo', items: [{ title: 'x', status: 'done' }] } }, promptOp, { op: 'meta.merge', meta: { goal: { objective: 'x', status: 'active' } } }, { op: 'items.remove', ids: ['t1'] }, ]; for (const op of ops) { expect(transcriptOperationSchema.parse(op)).toBeDefined(); } }); it('roundtrips ops carrying the extended wire detail', () => { const usage = { inputOther: 10, output: 5, inputCacheRead: 3, inputCacheCreation: 2 }; const ops: TranscriptOperation[] = [ { op: 'reset', agentId: 'main', snapshot: { items: [], tasks: [], interactions: [], attachments: [], todos: [], prompts: [ { promptId: 'p1', status: 'completed', userMessageId: 'u1', content: [{ type: 'text', text: 'hi' }], createdAt: '2026-07-22T00:00:00.000Z', finishedAt: '2026-07-22T00:01:00.000Z', steeredAt: '2026-07-22T00:00:30.000Z', }, ], meta: { agent: { model: 'k2', thinkingEffort: 'high', usage: { byModel: { k2: usage }, currentTurn: usage, total: usage }, contextTokens: 1234, maxContextTokens: 128000, contextUsage: 0.01, permission: 'auto', phase: { kind: 'retrying', turnId: 1, step: 1, stepId: 't1.1', failedAttempt: 1, nextAttempt: 2, maxAttempts: 3, delayMs: 500, since: 1000 }, }, }, }, }, { op: 'turn.upsert', turn: { kind: 'turn', turnId: 't1', triggerPromptId: 'prompt-1', ordinal: 1, state: 'failed', origin: { kind: 'user' }, usage: { inputTokens: 12, outputTokens: 5, cachedTokens: 3 }, durationMs: 1500, error: 'boom', }, }, { op: 'step.upsert', turnId: 't1', step: { kind: 'step', stepId: 't1.1', turnId: 't1', ordinal: 1, state: 'interrupted', usage, finishReason: 'stop', timing: { llmFirstTokenLatencyMs: 120, llmStreamDurationMs: 900, llmRequestBuildMs: 5, llmServerFirstTokenMs: 110, llmServerDecodeMs: 700, llmClientConsumeMs: 950, llmClientBlockedMs: 25, }, retry: { failedAttempt: 1, nextAttempt: 2, maxAttempts: 3, delayMs: 500, errorName: 'RateLimit', errorMessage: 'slow down', statusCode: 429 }, endReason: 'aborted', endMessage: 'user pressed escape', }, }, { op: 'frame.upsert', turnId: 't1', stepId: 't1.1', frame: { kind: 'tool', frameId: 't1.1.c1', toolCallId: 'c1', name: 'Bash', state: 'running', inputText: '{"command":"ls', progress: { kind: 'progress', text: 'half', percent: 50, customKind: 'bar', customData: { x: 1 } }, }, }, { op: 'task.upsert', task: { taskId: 'task1', kind: 'subagent', state: 'completed', detached: false, outputTail: '', resultSummary: 'scanned 12 files', error: 'partial failure', stateReason: 'waiting for input', usage, }, }, { op: 'meta.merge', meta: { agent: { model: 'k2', phase: { kind: 'ended', turnId: 1, reason: 'completed', durationMs: 1500, at: 2000 } } }, }, ]; for (const op of ops) { expect(transcriptOperationSchema.parse(op)).toEqual(op); } }); it('accepts provenance only on user text frames', () => { const base = { op: 'frame.upsert', turnId: 't1', stepId: 't1.1', } as const; expect(transcriptOperationSchema.safeParse({ ...base, frame: { kind: 'text', frameId: 't1.1.f1', role: 'user', text: 'steered in', origin: { kind: 'user', skillActivations: [{ skillName: 'review', skillArgs: 'strict' }] }, }, }).success).toBe(true); expect(transcriptOperationSchema.safeParse({ ...base, frame: { kind: 'text', frameId: 't1.1.f2', role: 'assistant', text: 'reply', origin: { kind: 'user' }, }, }).success).toBe(false); }); it('rejects mutually exclusive cursors and bad grades', () => { expect(() => transcriptGradeSpecSchema.parse({ '*': 'stream' })).toThrow(); const ok = transcriptResponseSchema.safeParse({ agent_id: 'main', items: [], has_more: false, tasks: [], interactions: [], attachments: [], todos: [], meta: {}, agents: [{ agentId: 'main', type: 'main' }], pending_interactions: [], }); expect(ok.success).toBe(true); }); it('rejects path-hostile agent ids in the transcript query', () => { const base = { agent_id: 'main', before_turn: undefined, after_turn: undefined, page_size: undefined }; expect(transcriptQuerySchema.safeParse({ ...base, agent_id: 'sub-1' }).success).toBe(true); expect(transcriptQuerySchema.safeParse({ ...base, agent_id: '01HF7YAT31J7SMRT1QXGJWKR8D' }).success).toBe(true); for (const hostile of ['../main', '..\\main', '..', 'a/b', 'a\\b', '.', 'a\0b', 'x'.repeat(200)]) { expect(transcriptQuerySchema.safeParse({ ...base, agent_id: hostile }).success).toBe(false); } }); }); describe('groupMessagesIntoSnapshot (cold path)', () => { const snapshotOf = (...parts: HistoryContentPart[]): AgentTranscriptSnapshot => groupMessagesIntoSnapshot([ { role: 'user', content: parts, toolCalls: [], origin: { kind: 'user' } }, ]); it('groups flat messages into turns with folded tool results', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'system', content: [{ type: 'text', text: 'sys' }] }, { role: 'user', content: [{ type: 'text', text: 'hello' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'think', think: 'hmm' }, { type: 'text', text: 'checking' }], toolCalls: [{ id: 'c1', name: 'Read', arguments: '{"path":"/a"}' }], }, { role: 'tool', content: [{ type: 'text', text: 'file body' }], toolCallId: 'c1', toolCalls: [] }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [], }, { role: 'user', content: [{ type: 'text', text: 'next' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'user', content: [{ type: 'text', text: 'summary of old' }], toolCalls: [], origin: { kind: 'compaction_summary' }, }, { role: 'user', content: [{ type: 'text', text: 'after' }], toolCalls: [], origin: { kind: 'user' } }, ]); const kinds = snapshot.items.map((i) => i.kind); expect(kinds).toEqual(['turn', 'turn', 'marker', 'turn']); const firstTurn = snapshot.items[0]; if (firstTurn?.kind !== 'turn') throw new Error('expected turn'); expect(firstTurn.prompt).toBe('hello'); expect(firstTurn.steps).toHaveLength(2); const tool = firstTurn.steps[0]?.frames.find((f) => f.kind === 'tool'); expect(tool?.kind === 'tool' && tool.output).toBe('file body'); expect(tool?.kind === 'tool' && tool.input).toEqual({ path: '/a' }); const marker = snapshot.items[2]; expect(marker?.kind === 'marker' && marker.marker).toBe('compaction'); }); it('folds task-notification user messages into the current turn instead of opening their own', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run it' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'starting' }], toolCalls: [{ id: 'c1', name: 'Bash', arguments: '{"command":"ls"}' }], }, { role: 'user', content: [{ type: 'text', text: '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">\nTitle: Background agent completed\nSeverity: info\ninspect done.\n</notification>', }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string }, }, { role: 'user', content: [{ type: 'text', text: '<notification id="task:task-8:completed"></notification>' }], toolCalls: [], origin: { kind: 'task', taskId: 'task-8' } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'continuing' }], toolCalls: [], }, ], { taskOriginTurnTaskIds: new Set() }, ); const turns = snapshot.items.filter((i) => i.kind === 'turn'); expect(turns).toHaveLength(1); const turn = turns[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const userFrames = turn.steps .flatMap((step) => step.frames) .filter((f) => f.kind === 'text' && f.role === 'user'); expect(userFrames.map((f) => f.kind === 'text' && f.taskId)).toEqual(['task-9', 'task-8']); expect(userFrames[0]).toMatchObject({ text: 'Background agent completed\ninspect done.' }); const assistantTexts = turn.steps .flatMap((step) => step.frames) .filter((f) => f.kind === 'text' && f.role === 'assistant') .map((f) => f.kind === 'text' && f.text); expect(assistantTexts).toEqual(['starting', 'continuing']); expect(turn.steps).toHaveLength(2); expect(turn.steps[1]?.frames.map((f) => f.kind === 'text' && f.role)).toEqual([ 'user', 'user', 'assistant', ]); }); it('folds a user message whose content matches a turn.steer record into the current turn as a user frame', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'steered in' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'noted' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify([{ type: 'text', text: 'steered in' }]), new Map([['user', 1]])]]) }, ); expect(snapshot.items.map((i) => i.kind)).toEqual(['turn']); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(2); expect(turn.steps[1]?.frames[0]).toMatchObject({ kind: 'text', role: 'user', text: 'steered in', }); }); it('keeps a trailing steered message visible by appending it to the last step', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'steered in' }], toolCalls: [], origin: { kind: 'user' } }, ], { steeredContents: new Map([[JSON.stringify([{ type: 'text', text: 'steered in' }]), new Map([['user', 1]])]]) }, ); expect(snapshot.items.map((i) => i.kind)).toEqual(['turn']); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const lastStep = turn.steps.at(-1); expect(lastStep?.frames.at(-1)).toMatchObject({ kind: 'text', role: 'user', text: 'steered in', }); }); it('flushes a pending steer into the closing turn when a new turn opens before any reply', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'steered in' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'user', content: [{ type: 'text', text: 'next question' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify([{ type: 'text', text: 'steered in' }]), new Map([['user', 1]])]]) }, ); const turns = snapshot.items.filter((i) => i.kind === 'turn'); expect(turns).toHaveLength(2); const first = turns[0]; if (first?.kind !== 'turn') throw new Error('expected turn'); expect(first.steps.at(-1)?.frames.at(-1)).toMatchObject({ kind: 'text', role: 'user', text: 'steered in', }); const second = turns[1]; if (second?.kind !== 'turn') throw new Error('expected turn'); expect(second.prompt).toBe('next question'); }); it('still opens its own turn for a mid-conversation user message unknown to the steer map', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'plain follow-up' }], toolCalls: [], origin: { kind: 'user' } }, ], { steeredContents: new Map([[JSON.stringify([{ type: 'text', text: 'steered in' }]), new Map([['user', 1]])]]) }, ); expect(snapshot.items.map((i) => i.kind)).toEqual(['turn', 'turn']); }); it('stops folded notification text before child output blocks', () => { const xml = [ '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">', 'Title: Background agent completed', 'Severity: info', 'inspect done.', '<output-file>/tmp/out.log</output-file>', '/tmp/out.log', 'full output here', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const frame = turn.steps.flatMap((step) => step.frames).find((f) => f.kind === 'text' && f.role === 'user'); expect(frame).toMatchObject({ text: 'Background agent completed\ninspect done.' }); }); it('stops folded notification text before an inline answer block', () => { const xml = [ '<notification id="task:question-1:completed" category="task" type="task.completed" source_kind="background_task" source_id="question-1">', 'Title: Background question answered', 'Severity: info', 'The user answered "Which database?".', '<answer>', '{"answers":{"Which database?":"Postgres"}}', '</answer>', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'question-1' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const frame = turn.steps.flatMap((step) => step.frames).find((f) => f.kind === 'text' && f.role === 'user'); expect(frame).toMatchObject({ text: 'Background question answered\nThe user answered "Which database?".' }); }); it('buffers a folded notification that arrives before the first step into that step', () => { const xml = [ '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">', 'Title: Background agent completed', 'Severity: info', 'early done.', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(1); expect(turn.steps[0]?.frames.map((f) => f.kind === 'text' && f.role)).toEqual([ 'user', 'assistant', ]); expect(turn.steps[0]?.frames[0]).toMatchObject({ text: 'Background agent completed\nearly done.', taskId: 'task-9', }); }); it('drops a folded notification when no turn is open yet', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: '<notification id="n1"></notification>' }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string }, }, ], { taskOriginTurnTaskIds: new Set() }, ); expect(snapshot.items).toHaveLength(0); }); it('keeps body lines that start with an angle bracket but are not output blocks', () => { const xml = [ '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">', 'Title: Background agent completed', 'Severity: info', 'first line.', '<div>pasted markup</div>', 'last line.', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const frame = turn.steps.flatMap((step) => step.frames).find((f) => f.kind === 'text' && f.role === 'user'); expect(frame).toMatchObject({ text: 'Background agent completed\nfirst line.\n<div>pasted markup</div>\nlast line.', }); }); it('parses only the leading header lines, keeping later Title-like lines as body', () => { const xml = [ '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">', 'Title: Background agent completed', 'Severity: info', 'first line.', 'Title: details', 'last line.', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const frame = turn.steps.flatMap((step) => step.frames).find((f) => f.kind === 'text' && f.role === 'user'); expect(frame).toMatchObject({ text: 'Background agent completed\nfirst line.\nTitle: details\nlast line.', }); }); it('keeps a body whose first line starts with Severity:', () => { const xml = [ '<notification id="task:task-9:completed" category="task" type="task.completed" source_kind="background_task" source_id="task-9">', 'Title: Background agent completed', 'Severity: info', 'Severity: this line is the task description, not a header', 'last line.', '</notification>', ].join('\n'); const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'go' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: xml }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ], { taskOriginTurnTaskIds: new Set() }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const frame = turn.steps.flatMap((step) => step.frames).find((f) => f.kind === 'text' && f.role === 'user'); expect(frame).toMatchObject({ text: 'Background agent completed\nSeverity: this line is the task description, not a header\nlast line.', }); }); it('expands a bundled prompt into per-skill markers and a caller-text turn', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'text', text: 'rendered review block' }, { type: 'text', text: 'rendered security block' }, { type: 'text', text: 'please /skill:review and /skill:security' }, ], toolCalls: [], origin: { kind: 'user', skillActivations: [ { activationId: 'act-1', skillName: 'review' }, { activationId: 'act-2', skillName: 'security', skillArgs: 'src/app.ts' }, ], } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ]); expect(snapshot.items.map((item) => item.kind)).toEqual(['marker', 'marker', 'turn']); const first = snapshot.items[0]; expect(first?.kind === 'marker' && first.marker).toBe('skill'); expect(first?.kind === 'marker' && first.payload).toMatchObject({ text: 'rendered review block', origin: { kind: 'skill_activation', trigger: 'user-slash', skillName: 'review' }, }); const second = snapshot.items[1]; expect(second?.kind === 'marker' && second.payload).toMatchObject({ text: 'rendered security block', origin: { skillName: 'security', skillArgs: 'src/app.ts' }, }); const turn = snapshot.items[2]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.prompt).toBe('please /skill:review and /skill:security'); expect(turn.steps).toHaveLength(1); }); it('maps media parts on the opening user message to attachment entities, dropping base64 bytes', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'text', text: 'what is this? [Image #1]' }, { type: 'image', source: { kind: 'base64', media_type: 'image/png', data: 'aGVsbG8=' }, name: 'inline.png' }, { type: 'image', source: { kind: 'url', url: 'https://example.com/pic.png' }, name: 'remote.png' }, { type: 'image', source: { kind: 'file', file_id: 'file_8' }, name: 'stored.png' }, { type: 'file', file_id: 'file_9', name: 'notes.txt', media_type: 'text/plain', size: 128 }, ], toolCalls: [], origin: { kind: 'user' }, }, { role: 'assistant', content: [{ type: 'text', text: 'a screenshot' }], toolCalls: [] }, ]); expect(snapshot.attachments).toHaveLength(4); expect(snapshot.attachments[0]).toMatchObject({ attachmentId: 'att_1', mediaType: 'image/png', name: 'inline.png', source: undefined, }); expect(snapshot.attachments[1]).toMatchObject({ attachmentId: 'att_2', name: 'remote.png', source: { kind: 'url', url: 'https://example.com/pic.png' }, }); expect(snapshot.attachments[2]).toMatchObject({ attachmentId: 'att_3', name: 'stored.png', source: { kind: 'file', fileId: 'file_8' }, }); expect(snapshot.attachments[3]).toMatchObject({ attachmentId: 'att_4', mediaType: 'text/plain', name: 'notes.txt', source: { kind: 'file', fileId: 'file_9' }, }); const firstTurn = snapshot.items[0]; if (firstTurn?.kind !== 'turn') throw new Error('expected turn'); expect(firstTurn.attachmentIds).toEqual(['att_1', 'att_2', 'att_3', 'att_4']); }); it('folds origin file attachments on the opening user message into path-sourced entities', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'text', text: 'Attached file "report.pdf" (application/pdf, 128 bytes): /data/report.pdf — open it with the Read tool', }, ], toolCalls: [], origin: { kind: 'user', attachments: [ { name: 'report.pdf', mediaType: 'application/pdf', size: 128, path: '/data/report.pdf' }, ], } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ]); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'application/pdf', name: 'report.pdf', size: 128, }, ]); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.attachmentIds).toEqual(['att_1']); }); it('folds origin file attachments on a skill activation message into path-sourced entities', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'text', text: 'User activated the skill "update-config".', }, ], toolCalls: [], origin: { kind: 'skill_activation', activationId: 'act_1', skillName: 'update-config', trigger: 'user-slash', attachments: [ { name: 'note.txt', mediaType: 'text/plain', size: 21, path: '/data/note.txt' }, ], } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'done' }], toolCalls: [] }, ]); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'text/plain', name: 'note.txt', size: 21, }, ]); const turn = snapshot.items[1]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.attachmentIds).toEqual(['att_1']); }); it('maps persisted kimi-file media refs to attachments', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'video_url', videoUrl: { url: 'kimi-file://file_1', name: 'clip.mp4' }, } as HistoryContentPart, ], toolCalls: [], origin: { kind: 'user' }, }, { role: 'user', content: [ { type: 'text', text: 'what is this?' }, { type: 'image_url', imageUrl: { url: 'kimi-file://file_2?path=%2Fcache%2Fshot.png', name: 'shot.png' }, } as HistoryContentPart, ], toolCalls: [], origin: { kind: 'user' }, }, ]); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'video/*', name: 'clip.mp4', source: { kind: 'session_media', fileId: 'file_1' }, }, { attachmentId: 'att_2', mediaType: 'image/*', name: 'shot.png', source: { kind: 'session_media', fileId: 'file_2' }, }, ]); const videoTurn = snapshot.items[0]; const imageTurn = snapshot.items[1]; if (videoTurn?.kind !== 'turn' || imageTurn?.kind !== 'turn') { throw new Error('expected turns'); } expect(videoTurn.attachmentIds).toEqual(['att_1']); expect(imageTurn.attachmentIds).toEqual(['att_2']); expect(videoTurn.prompt).toBe(''); expect(imageTurn.prompt).toBe('what is this?'); }); it('projects a daemon ref in a user-slash turn-opening input like a plain user turn', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [ { type: 'text', text: '/gen-docs ' }, { type: 'image_url', imageUrl: { url: 'kimi-file://file_4?path=%2Fcache%2Fshot.png' }, } as HistoryContentPart, ], toolCalls: [], origin: { kind: 'skill_activation', trigger: 'user-slash', skillName: 'gen-docs' } as { kind: string; }, }, ]); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'image/*', source: { kind: 'session_media', fileId: 'file_4' }, }, ]); expect(snapshot.items.map((item) => item.kind)).toEqual(['marker', 'turn']); const marker = snapshot.items[0]; if (marker?.kind !== 'marker') throw new Error('expected marker'); expect((marker.payload as { text: string }).text).toBe('/gen-docs '); const turn = snapshot.items[1]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.prompt).toBe('/gen-docs '); expect(turn.attachmentIds).toEqual(['att_1']); }); it('keeps a kimi-file ref as a nameless attachment and inline tags as user text', () => { const snapshot = snapshotOf( { type: 'text', text: 'open <image path="/tmp/other.png"></image> please' }, { type: 'image_url', imageUrl: { url: 'kimi-file://file_3' }, } as HistoryContentPart, ); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'image/*', source: { kind: 'session_media', fileId: 'file_3' }, }, ]); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.attachmentIds).toEqual(['att_1']); expect(turn.prompt).toBe('open <image path="/tmp/other.png"></image> please'); }); it('keeps a legacy tag+ref pair as prompt text plus the ref-derived attachment', () => { const snapshot = snapshotOf( { type: 'text', text: '<image path="/cache/shot.png"></image>' }, { type: 'image_url', imageUrl: { url: 'kimi-file://file_5?path=%2Fcache%2Fshot.png' }, } as HistoryContentPart, ); expect(snapshot.attachments).toEqual([ { attachmentId: 'att_1', mediaType: 'image/*', source: { kind: 'session_media', fileId: 'file_5' }, }, ]); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.prompt).toBe('<image path="/cache/shot.png"></image>'); expect(turn.attachmentIds).toEqual(['att_1']); }); it('keeps standalone <media path> tags as prompt text', () => { const snapshot = snapshotOf( { type: 'text', text: '<image path="/cache/shot.png">' }, { type: 'text', text: '<image path="/cache/shot.png" content_type="image/png"></image>' }, { type: 'text', text: '<video path="/cache/clip.mp4">' }, ); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.prompt).toBe( '<image path="/cache/shot.png"><image path="/cache/shot.png" content_type="image/png"></image><video path="/cache/clip.mp4">', ); expect(turn.attachmentIds).toBeUndefined(); expect(snapshot.attachments).toEqual([]); }); it('keeps cold tool calls running until a result is persisted', () => { const pending = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'run it' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [], toolCalls: [{ id: 'c1', name: 'Bash', arguments: '{}' }] }, ]); const pendingTurn = pending.items[0]; if (pendingTurn?.kind !== 'turn') throw new Error('expected turn'); const pendingTool = pendingTurn.steps[0]?.frames.find((f) => f.kind === 'tool'); expect(pendingTool?.kind === 'tool' && pendingTool.state).toBe('running'); const done = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'run it' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [], toolCalls: [{ id: 'c1', name: 'Bash', arguments: '{}' }] }, { role: 'tool', content: [{ type: 'text', text: 'done.txt' }], toolCallId: 'c1', toolCalls: [] }, ]); const doneTurn = done.items[0]; if (doneTurn?.kind !== 'turn') throw new Error('expected turn'); const doneTool = doneTurn.steps[0]?.frames.find((f) => f.kind === 'tool'); expect(doneTool?.kind === 'tool' && doneTool.state).toBe('done'); expect(doneTool?.kind === 'tool' && doneTool.output).toBe('done.txt'); }); it('opens a turn for subagent run prompts recorded as system triggers', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'scan the repo' }], toolCalls: [], origin: { kind: 'system_trigger', name: 'subagent' } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'scanning' }], toolCalls: [] }, ]); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'turn']); const subTurn = snapshot.items[1]; if (subTurn?.kind !== 'turn') throw new Error('expected turn'); expect(subTurn.ordinal).toBe(1); expect(subTurn.origin.kind).toBe('other'); expect(subTurn.prompt).toBe('scan the repo'); expect(subTurn.steps).toHaveLength(1); }); it('starts a new turn for user-slash skill activations, keeps other triggers as markers only', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'skill body' }], toolCalls: [], origin: { kind: 'skill_activation', trigger: 'user-slash', skillName: 'gen-docs' } as { kind: string; }, }, { role: 'assistant', content: [{ type: 'text', text: 'docs done' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'nested skill body' }], toolCalls: [], origin: { kind: 'skill_activation', trigger: 'model-tool', skillName: 'x' } as { kind: string; }, }, { role: 'assistant', content: [{ type: 'text', text: 'still same turn' }], toolCalls: [] }, ]); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'marker', 'turn', 'marker']); const slashTurn = snapshot.items[2]; if (slashTurn?.kind !== 'turn') throw new Error('expected turn'); expect(slashTurn.ordinal).toBe(1); expect(slashTurn.origin.kind).toBe('other'); expect(slashTurn.prompt).toBe('skill body'); expect(slashTurn.steps).toHaveLength(2); }); it('keeps model-tool skill activations as markers even when their content matches a steer record', () => { const skillContent = [{ type: 'text', text: 'skill body' }]; const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, { role: 'user', content: skillContent, toolCalls: [], origin: { kind: 'skill_activation', trigger: 'model-tool', skillName: 'write-tui' } as { kind: string; }, }, { role: 'assistant', content: [{ type: 'text', text: 'used the skill' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify(skillContent), new Map([['skill_activation', 1]])]]) }, ); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'marker']); const marker = snapshot.items[1]; if (marker?.kind !== 'marker') throw new Error('expected marker'); expect(marker.marker).toBe('skill'); }); it('still folds cron-origin steers into the running turn by content match', () => { const cronContent = [{ type: 'text', text: 'cron tick' }]; const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: cronContent, toolCalls: [], origin: { kind: 'cron_job', jobId: 'job1' } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'noted' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify(cronContent), new Map([['cron_job', 1]])]]) }, ); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn']); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(2); expect(turn.steps[1]?.frames[0]).toMatchObject({ kind: 'text', role: 'user', text: 'cron tick', }); }); it('still folds user-slash skill activations into the running turn by content match', () => { const slashContent = [{ type: 'text', text: 'slash skill body' }]; const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: slashContent, toolCalls: [], origin: { kind: 'skill_activation', trigger: 'user-slash', skillName: 'gen-docs' } as { kind: string; }, }, { role: 'assistant', content: [{ type: 'text', text: 'noted' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify(slashContent), new Map([['skill_activation', 1]])]]) }, ); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn']); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(2); expect(turn.steps[1]?.frames[0]).toMatchObject({ kind: 'text', role: 'user', text: 'slash skill body', }); }); it('consumes the steer count for marker-only activations so a later identical prompt opens its own turn', () => { const shared = [{ type: 'text', text: 'same text' }]; const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: shared, toolCalls: [], origin: { kind: 'skill_activation', trigger: 'model-tool', skillName: 'x' } as { kind: string; }, }, { role: 'user', content: shared, toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'noted' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify(shared), new Map([['skill_activation', 1]])]]) }, ); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'marker', 'turn']); }); it('does not consume a user steer count for a compaction summary with identical content', () => { const shared = [{ type: 'text', text: 'same text' }]; const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'active' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'working' }], toolCalls: [] }, { role: 'user', content: shared, toolCalls: [], origin: { kind: 'compaction_summary' } as { kind: string }, }, { role: 'user', content: shared, toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'noted' }], toolCalls: [] }, ], { steeredContents: new Map([[JSON.stringify(shared), new Map([['user', 1]])]]) }, ); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'marker']); const turn = snapshot.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); const steered = turn.steps .flatMap((step) => step.frames) .filter((frame) => frame.kind === 'text' && frame.role === 'user'); expect(steered).toHaveLength(1); }); it('starts a promptless turn for turn-opening system triggers (goal continuation)', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'continue the goal' }], toolCalls: [], origin: { kind: 'system_trigger', name: 'goal_continuation' } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'continued' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'mode reminder' }], toolCalls: [], origin: { kind: 'injection', variant: 'permission_mode' } as { kind: string }, }, { role: 'assistant', content: [{ type: 'text', text: 'still same turn' }], toolCalls: [] }, ]); expect(snapshot.items.map((item) => item.kind)).toEqual(['turn', 'turn']); const [first, second] = snapshot.items; if (first?.kind !== 'turn' || second?.kind !== 'turn') throw new Error('expected turns'); expect(first.ordinal).toBe(0); expect(first.steps.map((step) => step.frames.map((frame) => frame.kind))).toEqual([['text']]); expect(second.ordinal).toBe(1); expect(second.origin.kind).toBe('other'); expect(second.prompt).toBeUndefined(); expect(second.steps).toHaveLength(2); }); it('hides injected user messages and maps cron origins', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'secret context' }], toolCalls: [], origin: { kind: 'injection' }, }, { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'user', content: [{ type: 'text', text: 'run report' }], toolCalls: [], origin: { kind: 'cron_job', jobId: 'job1' } as { kind: string }, }, ]); expect(snapshot.items).toHaveLength(2); const cronTurn = snapshot.items[1]; expect(cronTurn?.kind === 'turn' && cronTurn.origin.kind).toBe('cron'); }); it('opens a task turn for a notification with a task-origin turn.started in the wire', () => { const snapshot = groupMessagesIntoSnapshot( [ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [], }, { role: 'user', content: [{ type: 'text', text: 'task done' }], toolCalls: [], origin: { kind: 'task', taskId: 'task-9' } as { kind: string }, }, ], { taskOriginTurnTaskIds: new Set(['task-9']) }, ); const taskTurn = snapshot.items[1]; if (taskTurn?.kind !== 'turn') throw new Error('expected turn'); expect(taskTurn.origin).toMatchObject({ kind: 'task', taskId: 'task-9' }); }); it('maps legacy background_task origins to task turns, preserving the taskId', () => { const snapshot = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'user', content: [{ type: 'text', text: 'task done' }], toolCalls: [], origin: { kind: 'background_task', taskId: 'b83rhswvs' } as { kind: string }, }, ]); const taskTurn = snapshot.items[1]; if (taskTurn?.kind !== 'turn') throw new Error('expected turn'); expect(taskTurn.origin).toMatchObject({ kind: 'task', taskId: 'b83rhswvs' }); }); }); describe('foldWireRecordFacts (cold facts)', () => { const baseWithMarker = (): AgentTranscriptSnapshot => groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'answer' }], toolCalls: [] }, { role: 'user', content: [{ type: 'text', text: 'summary of old' }], toolCalls: [], origin: { kind: 'compaction_summary' }, }, ]); it('returns the base snapshot unchanged when no fact records exist (old sessions)', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'metadata', protocol_version: '1.5', created_at: 1 }, { type: 'context.append_message', message: { role: 'user' }, time: 1 }, ], base, ); expect(folded).toEqual(base); expect(folded.items).toBe(base.items); }); it('folds todo records into the global todo document, last write wins', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'tools.update_store', key: 'todo', value: [{ title: 'old', status: 'pending' }], time: 1000 }, { type: 'tools.update_store', key: 'other', value: [{ title: 'ignored', status: 'done' }], time: 2000 }, { type: 'tools.update_store', key: 'todo', value: [ { title: 'write tests', status: 'in_progress' }, { title: 'ship', status: 'pending' }, { title: 'malformed' }, ], time: 3000, }, ], base, ); expect(folded.todos).toEqual([ { todoId: 'todo', items: [ { title: 'write tests', status: 'in_progress' }, { title: 'ship', status: 'pending' }, ], updatedAt: new Date(3000).toISOString(), }, ]); expect(folded.items).toBe(base.items); }); it('folds goal create/update/clear into meta.goal with markers, last write wins', () => { const base = baseWithMarker(); expect(base.items.some((item) => item.kind === 'marker' && item.markerId === 'm1')).toBe(true); const folded = foldWireRecordFacts( [ { type: 'goal.create', goalId: 'g1', objective: 'fix the bug', completionCriterion: 'tests pass', time: 1000, }, { type: 'goal.update', status: 'blocked', reason: 'stuck', tokensUsed: 1200, time: 2000 }, { type: 'goal.update', budgetLimits: { tokenBudget: 50000 }, time: 3000 }, ], base, ); expect(folded.meta.goal).toEqual({ objective: 'fix the bug', status: 'blocked', completionCriterion: 'tests pass', budgetUsed: 1200, budgetLimit: 50000, }); const goalMarkers = folded.items.filter( (item) => item.kind === 'marker' && item.marker === 'goal', ); expect(goalMarkers.map((item) => item.kind === 'marker' && item.markerId)).toEqual([ 'm2', 'm3', 'm4', ]); expect(goalMarkers[0]).toMatchObject({ at: new Date(1000).toISOString() }); expect(folded.items.slice(0, base.items.length)).toEqual(base.items); const cleared = foldWireRecordFacts( [ { type: 'goal.create', goalId: 'g1', objective: 'fix the bug', time: 1000 }, { type: 'goal.clear', time: 2000 }, ], base, ); expect(cleared.meta.goal).toBeUndefined(); }); it('marks user-cancelled turns with interruption markers, skipping unattributable cancels', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'turn.cancel', turnId: 0, target: 'active', reason: 'user_cancelled', time: 1000 }, { type: 'turn.cancel', turnId: 0, target: 'active', reason: 'user_cancelled', time: 1500 }, { type: 'turn.cancel', turnId: 1, target: 'queued', reason: 'user_cancelled', time: 2000 }, { type: 'turn.cancel', turnId: 2, target: 'active', reason: 'aborted', time: 3000 }, { type: 'turn.cancel', turnId: 4, target: 'active', reason: 'aborted', time: 3500 }, { type: 'turn.cancel', turnId: 4, target: 'active', reason: 'user_cancelled', time: 3600 }, { type: 'turn.cancel', turnId: 3, target: 'active', time: 4000 }, ], base, ); expect( folded.items.filter((item) => item.kind === 'marker' && item.marker === 'interruption'), ).toEqual([ { kind: 'marker', markerId: 'm2', marker: 'interruption', payload: { turnId: 0, target: 'active', reason: 'user_cancelled' }, at: new Date(1000).toISOString(), }, ]); }); it('folds plan/swarm mode records into meta.modes with enter/exit markers', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, { type: 'swarm_mode.enter', trigger: { kind: 'task' }, time: 2000 }, { type: 'plan_mode.exit', id: 'plan-1', time: 3000 }, ], base, ); expect(folded.meta.modes).toEqual({ swarm: {} }); const markers = folded.items .filter((item) => item.kind === 'marker') .map((item) => item.kind === 'marker' && item.marker); expect(markers).toEqual(['compaction', 'plan.enter', 'swarm.enter', 'plan.exit']); const cancelled = foldWireRecordFacts( [ { type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, { type: 'plan_mode.cancel', time: 2000 }, { type: 'swarm_mode.enter', trigger: { kind: 'tool' }, time: 3000 }, { type: 'swarm_mode.exit', time: 4000 }, ], base, ); expect(cancelled.meta.modes).toEqual({}); const stillPlanning = foldWireRecordFacts( [{ type: 'plan_mode.enter', id: 'plan-1', time: 1000 }], base, ); expect(stillPlanning.meta.modes).toEqual({ plan: {} }); }); it('folds tower mode records into meta.modes without markers', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'tower_mode.enter', time: 1000 }, { type: 'tower_mode.exit', time: 2000 }, { type: 'tower_mode.enter', time: 3000 }, ], base, ); expect(folded.meta.modes).toEqual({ tower: {} }); const exited = foldWireRecordFacts( [ { type: 'tower_mode.enter', time: 1000 }, { type: 'tower_mode.exit', time: 2000 }, ], base, ); expect(exited.meta.modes).toEqual({}); }); it('folds plan.revision records into the plan badge and a timeline marker', () => { const base = baseWithMarker(); const revision = { type: 'plan.revision', id: 'plan-1', version: 2, key: 'plan/plan-1/v2.md', sha256: 'deadbeef', bytes: 512, time: 2000, }; const folded = foldWireRecordFacts( [{ type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, revision], base, { resolvePlanRevisionKey: (key) => `sessions/w/s/agents/main/${key}` }, ); expect(folded.meta.modes).toEqual({ plan: { reviewPath: 'sessions/w/s/agents/main/plan/plan-1/v2.md', version: 2 }, }); const revisionMarkers = folded.items.filter( (item) => item.kind === 'marker' && item.marker === 'plan.revision', ); expect(revisionMarkers).toEqual([ { kind: 'marker', markerId: 'm3', marker: 'plan.revision', payload: { id: 'plan-1', version: 2, path: 'sessions/w/s/agents/main/plan/plan-1/v2.md', sha256: 'deadbeef', bytes: 512, }, at: new Date(2000).toISOString(), }, ]); const exited = foldWireRecordFacts( [ { type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, revision, { type: 'plan_mode.exit', id: 'plan-1', time: 3000 }, ], base, ); expect(exited.meta.modes?.plan).toBeUndefined(); expect( exited.items.filter((item) => item.kind === 'marker' && item.marker === 'plan.revision'), ).toHaveLength(1); const reentered = foldWireRecordFacts( [ { type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, revision, { type: 'plan_mode.exit', id: 'plan-1', time: 3000 }, { type: 'plan_mode.enter', id: 'plan-2', time: 4000 }, ], base, ); expect(reentered.meta.modes).toEqual({ plan: {} }); }); it('folds legacy plan.revision path records without a key', () => { const base = baseWithMarker(); const legacy = { type: 'plan.revision', id: 'plan-1', version: 1, path: 'sessions/w/s/agents/main/plan/plan-1/v1.md', sha256: 'deadbeef', bytes: 256, time: 2000, }; const folded = foldWireRecordFacts( [{ type: 'plan_mode.enter', id: 'plan-1', time: 1000 }, legacy], base, ); expect(folded.meta.modes).toEqual({ plan: { reviewPath: 'sessions/w/s/agents/main/plan/plan-1/v1.md', version: 1 }, }); const revisionMarkers = folded.items.filter( (item) => item.kind === 'marker' && item.marker === 'plan.revision', ); expect(revisionMarkers).toEqual([ { kind: 'marker', markerId: 'm3', marker: 'plan.revision', payload: { id: 'plan-1', version: 1, path: 'sessions/w/s/agents/main/plan/plan-1/v1.md', sha256: 'deadbeef', bytes: 256, }, at: new Date(2000).toISOString(), }, ]); }); it('folds task records into task entities and timeline taskrefs', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'task.started', info: { taskId: 'task_1', kind: 'process', description: 'pnpm test', status: 'running', startedAt: 1000, endedAt: null, }, time: 1000, }, { type: 'task.started', info: { taskId: 'task_2', kind: 'agent', description: 'scan the repo', status: 'running', detached: false, agentId: 'sub-1', startedAt: 2000, endedAt: null, }, time: 2000, }, { type: 'task.terminated', info: { taskId: 'task_1', kind: 'process', description: 'pnpm test', status: 'completed', startedAt: 1000, endedAt: 5000, }, outputTail: '42 passed', time: 5000, }, ], base, ); expect(folded.tasks).toEqual([ { taskId: 'task_1', kind: 'shell', state: 'completed', detached: true, description: 'pnpm test', agentId: undefined, outputTail: '42 passed', startedAt: new Date(1000).toISOString(), endedAt: new Date(5000).toISOString(), }, { taskId: 'task_2', kind: 'subagent', state: 'running', detached: false, description: 'scan the repo', agentId: 'sub-1', outputTail: '', startedAt: new Date(2000).toISOString(), endedAt: undefined, }, ]); const refs = folded.items.filter((item) => item.kind === 'taskref'); expect(refs).toEqual([ { kind: 'taskref', refId: 'ref-task_1', taskId: 'task_1', at: new Date(1000).toISOString() }, { kind: 'taskref', refId: 'ref-task_2', taskId: 'task_2', at: new Date(2000).toISOString() }, ]); }); it('maps unknown task kinds to other and survives malformed task records', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'task.started', info: { taskId: 'task_q', kind: 'question', status: 'running', startedAt: 1000, endedAt: null }, time: 1000, }, { type: 'task.started', time: 2000 }, { type: 'task.terminated', info: { kind: 'process' }, time: 3000 }, ], base, ); expect(folded.tasks).toHaveLength(1); expect(folded.tasks[0]).toMatchObject({ taskId: 'task_q', kind: 'other', state: 'running' }); }); it('folds interaction request/resolved into entities with terminal states', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'interaction.request', id: 'apr-1', kind: 'approval', toolCallId: 'call_1', request: { toolName: 'Bash' }, time: 1000, }, { type: 'interaction.request', id: 'q-1', kind: 'question', request: { questions: [] }, time: 2000, }, { type: 'interaction.resolved', id: 'apr-1', response: { decision: 'approved', scope: 'session' }, time: 3000, }, { type: 'interaction.resolved', id: 'q-1', response: null, time: 4000 }, ], base, ); expect(folded.interactions).toEqual([ { interactionId: 'apr-1', interactionKind: 'approval', toolCallId: 'call_1', state: 'approved', request: { toolName: 'Bash' }, response: { decision: 'approved', scope: 'session' }, }, { interactionId: 'q-1', interactionKind: 'question', toolCallId: undefined, state: 'dismissed', request: { questions: [] }, response: null, }, ]); }); it('cancels interactions still pending at the end of the scan (crash == cancelled)', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'interaction.request', id: 'apr-9', kind: 'approval', request: { toolCallId: 'call_9', toolName: 'Write' }, time: 1000, }, ], base, ); expect(folded.interactions).toHaveLength(1); expect(folded.interactions[0]).toMatchObject({ interactionId: 'apr-9', state: 'cancelled', toolCallId: 'call_9', }); expect(folded.interactions.every((entity) => entity.state !== 'pending')).toBe(true); }); it('skips user_tool interactions like the live path', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'interaction.request', id: 'ut-1', kind: 'user_tool', request: {}, time: 1000 }, { type: 'interaction.resolved', id: 'ut-1', response: {}, time: 2000 }, ] satisfies HistoryWireRecord[], base, ); expect(folded.interactions).toEqual([]); }); it('folds turn.ended records into the matching turn items', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'turn.ended', turnId: 0, reason: 'failed', error: { code: 'provider.overloaded', message: 'Overloaded', name: 'APIStatusError', retryable: true }, durationMs: 1234, time: 5000, }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.state).toBe('failed'); expect(turn.error).toBe('Overloaded'); expect(turn.durationMs).toBe(1234); expect(turn.endedAt).toBe(new Date(5000).toISOString()); expect(folded.items).toHaveLength(base.items.length); }); it('applies turn.ended records last-wins per turn and folds blocked into failed', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'boom' }, time: 1000 }, { type: 'turn.ended', turnId: 0, reason: 'cancelled', durationMs: 10, time: 2000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.state).toBe('cancelled'); expect(turn.error).toBeUndefined(); expect(turn.durationMs).toBe(10); expect(turn.endedAt).toBe(new Date(2000).toISOString()); const blocked = foldWireRecordFacts( [{ type: 'turn.ended', turnId: 0, reason: 'blocked', time: 3000 }], base, ); const blockedTurn = blocked.items[0]; if (blockedTurn?.kind !== 'turn') throw new Error('expected turn'); expect(blockedTurn.state).toBe('failed'); }); it('ignores turn.ended records with unknown turn ids or malformed payloads', () => { const base = baseWithMarker(); const folded = foldWireRecordFacts( [ { type: 'turn.ended', turnId: 9, reason: 'cancelled', time: 1000 }, { type: 'turn.ended', reason: 'completed', time: 2000 }, { type: 'turn.ended', turnId: 0, reason: 'not-a-reason', time: 3000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.state).toBe('completed'); expect(turn.endedAt).toBe(new Date(3000).toISOString()); expect(folded.items).toHaveLength(base.items.length); }); const baseWithSteps = (): AgentTranscriptSnapshot => groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'first' }], toolCalls: [] }, { role: 'assistant', content: [{ type: 'text', text: 'second' }], toolCalls: [] }, ]); it('folds turn.step.interrupted records into the matching step of the matching turn', () => { const base = baseWithSteps(); const folded = foldWireRecordFacts( [ { type: 'turn.step.interrupted', turnId: 0, step: 2, reason: 'user_cancelled', message: 'stopped by user', time: 4000, }, { type: 'turn.ended', turnId: 0, reason: 'cancelled', time: 5000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(2); expect(turn.steps[0]).toMatchObject({ ordinal: 1, state: 'completed' }); expect(turn.steps[0]?.endReason).toBeUndefined(); expect(turn.steps[1]).toMatchObject({ ordinal: 2, state: 'interrupted', endReason: 'user_cancelled', endMessage: 'stopped by user', endedAt: new Date(4000).toISOString(), }); expect(turn.state).toBe('cancelled'); expect(folded.items).toHaveLength(base.items.length); }); it('applies turn.step.interrupted last-wins per step and tolerates a missing message', () => { const base = baseWithSteps(); const folded = foldWireRecordFacts( [ { type: 'turn.step.interrupted', turnId: 0, step: 1, reason: 'aborted', message: 'first', time: 1000 }, { type: 'turn.step.interrupted', turnId: 0, step: 1, reason: 'max_steps', time: 2000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps[0]).toMatchObject({ ordinal: 1, state: 'interrupted', endReason: 'max_steps', endedAt: new Date(2000).toISOString(), }); expect(turn.steps[0]?.endMessage).toBeUndefined(); expect(turn.steps[1]?.state).toBe('completed'); }); it('skips turn.step.interrupted records with unknown turn ids or missing reason', () => { const base = baseWithSteps(); const folded = foldWireRecordFacts( [ { type: 'turn.step.interrupted', turnId: 9, step: 1, reason: 'error', time: 1000 }, { type: 'turn.step.interrupted', turnId: 0, step: 1, time: 3000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps.map((step) => step.state)).toEqual(['completed', 'completed']); expect(turn.steps.every((step) => step.endReason === undefined)).toBe(true); }); it('creates the interrupted step when the cold tree has no step with that ordinal', () => { const base = baseWithSteps(); const folded = foldWireRecordFacts( [ { type: 'turn.step.interrupted', turnId: 0, step: 3, reason: 'error', message: 'all retries exhausted', time: 2000, }, { type: 'turn.ended', turnId: 0, reason: 'failed', time: 3000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps.map((step) => step.ordinal)).toEqual([1, 2, 3]); expect(turn.steps[2]).toEqual({ kind: 'step', stepId: 't0.3', turnId: 't0', ordinal: 3, state: 'interrupted', frames: [], endedAt: new Date(2000).toISOString(), endReason: 'error', endMessage: 'all retries exhausted', }); }); it('creates the interrupted step for a turn that produced no steps at all', () => { const base = groupMessagesIntoSnapshot([ { role: 'user', content: [{ type: 'text', text: 'hi' }], toolCalls: [], origin: { kind: 'user' } }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.step.interrupted', turnId: 0, step: 1, reason: 'user_cancelled', time: 1000 }, { type: 'turn.ended', turnId: 0, reason: 'cancelled', time: 2000 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.steps).toHaveLength(1); expect(turn.steps[0]).toMatchObject({ stepId: 't0.1', ordinal: 1, state: 'interrupted', endReason: 'user_cancelled', endedAt: new Date(1000).toISOString(), }); expect(turn.steps[0]?.endMessage).toBeUndefined(); }); it('ignores turn.step.retrying records in the cold fold', () => { const base = baseWithSteps(); const folded = foldWireRecordFacts( [ { type: 'turn.step.retrying', turnId: 0, step: 1, failedAttempt: 1, nextAttempt: 2, maxAttempts: 10, delayMs: 500, errorName: 'APIStatusError', errorMessage: 'Overloaded', statusCode: 429, time: 1000, }, ], base, ); expect(folded).toEqual(base); expect(folded.items).toBe(base.items); }); it('matches durable turns by prompt identity after a context-only blocked prompt', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-blocked', role: 'user', content: [{ type: 'text', text: 'blocked' }], toolCalls: [], origin: { kind: 'user' } }, { id: 'prompt-live', role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'failed later' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', turnId: 2, input: [{ type: 'text', text: 'run' }], origin: { kind: 'user' }, promptId: 'prompt-live', time: 1 }, { type: 'turn.ended', turnId: 2, reason: 'failed', error: { message: 'later failure' }, time: 2 }, ], base, ); expect(folded.items).toHaveLength(2); const blocked = folded.items[0]; const live = folded.items[1]; if (blocked?.kind !== 'turn' || live?.kind !== 'turn') throw new Error('expected turns'); expect(blocked.triggerPromptId).toBe('prompt-blocked'); expect(blocked.error).toBeUndefined(); expect(live.triggerPromptId).toBe('prompt-live'); expect(live.state).toBe('failed'); expect(live.error).toBe('later failure'); }); it('recovers legacy boundary identity past a context-only blocked prompt', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-blocked', role: 'user', content: [{ type: 'text', text: 'blocked' }], toolCalls: [], origin: { kind: 'user' } }, { id: 'prompt-real', role: 'user', content: [{ type: 'text', text: 'run' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'failed later' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'context.append_message', message: { id: 'prompt-blocked', role: 'user', origin: { kind: 'user' } }, time: 1 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'run' }], origin: { kind: 'user' }, time: 2 }, { type: 'context.append_message', message: { id: 'prompt-real', role: 'user', origin: { kind: 'user' } }, time: 3 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'legacy failure' }, time: 4 }, ], base, ); const blocked = folded.items[0]; const real = folded.items[1]; if (blocked?.kind !== 'turn' || real?.kind !== 'turn') throw new Error('expected turns'); expect(blocked.error).toBeUndefined(); expect(real.triggerPromptId).toBe('prompt-real'); expect(real.state).toBe('failed'); expect(real.error).toBe('legacy failure'); }); it('retires an unmatched legacy empty boundary before a later blocked prompt', () => { const base = groupMessagesIntoSnapshot([ { role: 'assistant', content: [{ type: 'text', text: 'partial' }], toolCalls: [] }, { id: 'prompt-blocked', role: 'user', content: [{ type: 'text', text: 'blocked' }], toolCalls: [], origin: { kind: 'user' } }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [], origin: { kind: 'user' }, time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'empty failure' }, time: 2 }, { type: 'context.append_message', message: { id: 'prompt-blocked', role: 'user', origin: { kind: 'user' } }, time: 3 }, ], base, ); const empty = folded.items[0]; const blocked = folded.items[1]; if (empty?.kind !== 'turn' || blocked?.kind !== 'turn') throw new Error('expected turns'); expect(empty.state).toBe('failed'); expect(empty.error).toBe('empty failure'); expect(blocked.triggerPromptId).toBe('prompt-blocked'); expect(blocked.error).toBeUndefined(); }); it('folds terminal facts for an empty prompt turn without a context identity', () => { const base = groupMessagesIntoSnapshot([ { role: 'assistant', content: [{ type: 'text', text: 'partial' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [], origin: { kind: 'user' }, promptId: 'prompt-empty', time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'empty failure' }, time: 2 }, ], base, ); const turn = folded.items[0]; if (turn?.kind !== 'turn') throw new Error('expected turn'); expect(turn.triggerPromptId).toBeUndefined(); expect(turn.state).toBe('failed'); expect(turn.error).toBe('empty failure'); }); it('does not let an empty prompt claim a later system continuation turn', () => { const base = groupMessagesIntoSnapshot([ { id: 'internal-prompt', role: 'user', content: [{ type: 'text', text: 'continue' }], toolCalls: [], origin: { kind: 'system_trigger', name: 'goal_continuation' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'stopped' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [], origin: { kind: 'user' }, promptId: 'prompt-empty', time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'empty failure' }, time: 2 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'continue' }], origin: { kind: 'system_trigger', name: 'goal_continuation' }, promptId: 'internal-prompt', time: 3 }, { type: 'turn.ended', turnId: 1, reason: 'cancelled', durationMs: 10, time: 4 }, ], base, ); const system = folded.items[0]; if (system?.kind !== 'turn') throw new Error('expected turn'); expect(system.triggerPromptId).toBeUndefined(); expect(system.state).toBe('cancelled'); expect(system.durationMs).toBe(10); expect(system.error).toBeUndefined(); }); it('matches a system turn with internal prompt identity past a context-only blocked prompt', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-blocked', role: 'user', content: [{ type: 'text', text: 'blocked' }], toolCalls: [], origin: { kind: 'user' } }, { id: 'internal-prompt', role: 'user', content: [{ type: 'text', text: 'continue' }], toolCalls: [], origin: { kind: 'system_trigger', name: 'goal_continuation' } as { kind: string } }, { role: 'assistant', content: [{ type: 'text', text: 'continuation failed' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'continue' }], origin: { kind: 'system_trigger', name: 'goal_continuation' }, promptId: 'internal-prompt', time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'system failure' }, time: 2 }, ], base, ); const blocked = folded.items[0]; const system = folded.items[1]; if (blocked?.kind !== 'turn' || system?.kind !== 'turn') throw new Error('expected turns'); expect(blocked.triggerPromptId).toBe('prompt-blocked'); expect(blocked.error).toBeUndefined(); expect(system.triggerPromptId).toBeUndefined(); expect(system.state).toBe('failed'); expect(system.error).toBe('system failure'); }); it('maps turn.ended around hidden retry turns replayed from the turn-clock records', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-1', role: 'user', content: [{ type: 'text', text: 'one' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a1' }], toolCalls: [] }, { id: 'prompt-2', role: 'user', content: [{ type: 'text', text: 'two' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a2' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'one' }], origin: { kind: 'user' }, promptId: 'prompt-1', time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'completed', time: 2 }, { type: 'turn.prompt', input: [], origin: { kind: 'retry' }, time: 3 }, { type: 'turn.ended', turnId: 1, reason: 'failed', error: { message: 'retry boom' }, time: 4 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'two' }], origin: { kind: 'user' }, promptId: 'prompt-2', time: 5 }, { type: 'turn.ended', turnId: 2, reason: 'cancelled', durationMs: 20, time: 6 }, ], base, ); const first = folded.items[0]; if (first?.kind !== 'turn') throw new Error('expected turn'); expect(first.state).toBe('completed'); expect(first.triggerPromptId).toBe('prompt-1'); const second = folded.items[1]; if (second?.kind !== 'turn') throw new Error('expected turn'); expect(second.state).toBe('cancelled'); expect(second.triggerPromptId).toBe('prompt-2'); expect(second.error).toBeUndefined(); expect(second.durationMs).toBe(20); }); it('maps turn.ended across queued-then-cancelled turn reservations', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-1', role: 'user', content: [{ type: 'text', text: 'one' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a1' }], toolCalls: [] }, { id: 'prompt-2', role: 'user', content: [{ type: 'text', text: 'two' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a2' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'one' }], origin: { kind: 'user' }, time: 1 }, { type: 'turn.ended', turnId: 0, reason: 'completed', time: 2 }, { type: 'turn.cancel', turnId: 1, target: 'queued', time: 3 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'two' }], origin: { kind: 'user' }, promptId: 'prompt-2', time: 4 }, { type: 'turn.ended', turnId: 2, reason: 'failed', error: { message: 'boom' }, time: 5 }, ], base, ); const second = folded.items[1]; if (second?.kind !== 'turn') throw new Error('expected turn'); expect(second.state).toBe('failed'); expect(second.error).toBe('boom'); expect(second.triggerPromptId).toBe('prompt-2'); }); it('skips undone turn boundaries when mapping prompt ids and turn endings', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-1', role: 'user', content: [{ type: 'text', text: 'one' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a1' }], toolCalls: [] }, { id: 'prompt-3', role: 'user', content: [{ type: 'text', text: 'replacement' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'a3' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'one' }], origin: { kind: 'user' }, promptId: 'prompt-1', time: 1 }, { type: 'context.append_message', message: { id: 'prompt-1', role: 'user', origin: { kind: 'user' } }, time: 1.5 }, { type: 'turn.ended', turnId: 0, reason: 'completed', time: 2 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'undone' }], origin: { kind: 'user' }, promptId: 'prompt-2', time: 3 }, { type: 'context.append_message', message: { id: 'prompt-2', role: 'user', origin: { kind: 'user' } }, time: 3.5 }, { type: 'turn.ended', turnId: 1, reason: 'completed', time: 4 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'continue' }], origin: { kind: 'system_trigger', name: 'goal_continuation' }, time: 5 }, { type: 'turn.ended', turnId: 2, reason: 'completed', time: 6 }, { type: 'context.undo', count: 1, time: 7 }, { type: 'turn.prompt', input: [{ type: 'text', text: 'replacement' }], origin: { kind: 'user' }, promptId: 'prompt-3', time: 8 }, { type: 'turn.ended', turnId: 3, reason: 'failed', error: { message: 'replacement failed' }, time: 9 }, ], base, ); const replacement = folded.items[1]; if (replacement?.kind !== 'turn') throw new Error('expected turn'); expect(replacement.triggerPromptId).toBe('prompt-3'); expect(replacement.state).toBe('failed'); expect(replacement.error).toBe('replacement failed'); }); it('counts context-only blocked prompts as undo anchors', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-real', role: 'user', content: [{ type: 'text', text: 'real' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'failed' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'real' }], origin: { kind: 'user' }, promptId: 'prompt-real', time: 1 }, { type: 'context.append_message', message: { id: 'prompt-real', role: 'user', origin: { kind: 'user' } }, time: 2 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'real failure' }, time: 3 }, { type: 'context.append_message', message: { id: 'prompt-blocked', role: 'user', origin: { kind: 'user' } }, time: 4 }, { type: 'context.undo', count: 1, time: 5 }, ], base, ); const real = folded.items[0]; if (real?.kind !== 'turn') throw new Error('expected turn'); expect(real.triggerPromptId).toBe('prompt-real'); expect(real.state).toBe('failed'); expect(real.error).toBe('real failure'); }); it('does not consume a pending identity boundary for a different context-only anchor', () => { const base = groupMessagesIntoSnapshot([ { id: 'prompt-real', role: 'user', content: [{ type: 'text', text: 'real' }], toolCalls: [], origin: { kind: 'user' } }, { role: 'assistant', content: [{ type: 'text', text: 'failed' }], toolCalls: [] }, ]); const folded = foldWireRecordFacts( [ { type: 'turn.prompt', input: [{ type: 'text', text: 'real' }], origin: { kind: 'user' }, promptId: 'prompt-real', time: 1 }, { type: 'context.append_message', message: { id: 'prompt-blocked', role: 'user', origin: { kind: 'user' } }, time: 2 }, { type: 'context.undo', count: 1, time: 3 }, { type: 'context.append_message', message: { id: 'prompt-real', role: 'user', origin: { kind: 'user' } }, time: 4 }, { type: 'turn.ended', turnId: 0, reason: 'failed', error: { message: 'real failure' }, time: 5 }, ], base, ); const real = folded.items[0]; if (real?.kind !== 'turn') throw new Error('expected turn'); expect(real.state).toBe('failed'); expect(real.error).toBe('real failure'); }); });
import { describe, expect, it } from 'vitest';
import { filterOpsForGrade, isAppendOnly, redactSnapshotForGrade } from '#/granularity/filterOps';
import { detachGrades, gradeFor, needsResetOnTransition } from '#/granularity/grade';
import { paginateTurns } from '#/pagination/paginate';
import { ViewRegistry } from '#/view/registry';
import { projectTranscriptUserOrigin } from '#/contract/origin';
import { groupMessagesIntoSnapshot, type HistoryContentPart } from '#/history/groupTurns';
import { foldWireRecordFacts, type HistoryWireRecord } from '#/history/foldFacts';
import {
transcriptOperationSchema,
transcriptQuerySchema,
transcriptResponseSchema,
transcriptGradeSpecSchema,
transcriptUserOriginSchema,
} from '#/contract/schema';
import type { TranscriptItem } from '#/model/item';
import type { AgentTranscriptSnapshot, TranscriptOperation } from '#/ops/operation';
const idLabel = (i: TranscriptItem): string =>
i.kind === 'turn' ? i.turnId : i.kind === 'marker' ? i.markerId : i.refId;
describe('client metadata in transcript user origins', () => {
it('retains user-invoked single skill frame metadata without exposing model-triggered activations as user input', () => {
const origin = { kind: 'skill_activation', trigger: 'user-slash', skillName: 'example-skill', skillArgs: 'args', clientMetadata: [{ display_text: 'Save button' }] };
expect(transcriptUserOriginSchema.parse(projectTranscriptUserOrigin(origin))).toEqual(origin);
expect(projectTranscriptUserOrigin({ ...origin, trigger: 'model-tool' })).toBeUndefined();
});
it('rebuilds a user turn payload without server-local paths', () => {
const clientMetadata = [{ display_text: 'Visible prompt' }];
const origin = {
kind: 'user',
clientMetadata,
skillActivations: [{ activationId: 'a1', skillName: 'deploy', skillArgs: 'now', skillPath: '/private/deploy/SKILL.md' }],
attachments: [{ name: 'notes.pdf', mediaType: 'application/pdf', size: 42, path: '/private/notes.pdf' }],
};
const snapshot = groupMessagesIntoSnapshot([
{ role: 'user', content: [{ type: 'text', text: 'rendered skill' }, { type: 'text', text: 'visible prompt' }], toolCalls: [], origin },
{ role: 'assistant', content: [{ type: 'text', text: 'reply' }], toolCalls: [] },
]);
const turn = snapshot.items.find((item) => item.kind === 'turn');
expect(turn?.origin).toEqual({ kind: 'user', payload: { kind: 'user', clientMetadata, skillActivations: [{ skillName: 'deploy', skillArgs: 'now' }] } });
expect(JSON.stringify(turn)).not.toContain('/private/');
expect(JSON.stringify(snapshot.attachments)).not.toContain('/private/');
});
it('keeps opening prompt metadata when rebuilding history turns', () => {
const clientMetadata = [{ kimi_code_composer: { version: 1, doc: { type: 'doc' } } }];
const origin = { kind: 'user', clientMetadata };
const snapshot = groupMessagesIntoSnapshot([
{ role: 'user', content: [{ type: 'text', text: 'visible prompt' }], toolCalls: [], origin },
{ role: 'assistant', content: [{ type: 'text', text: 'reply' }], toolCalls: [] },
]);
const turn = snapshot.items.find((item) => item.kind === 'turn');
expect(turn?.origin).toEqual({ kind: 'user', payload: { kind: 'user', clientMetadata } });
expect(turn?.prompt).toBe('visible prompt');
});
it('projects and validates independent document snapshots without losing their nested fields', () => {
const clientMetadata = [
{ kimi_code_composer: { version: 1, doc: { type: 'doc', content: [{ type: 'paragraph' }] }, captureIds: ['capture-a'] } },
{ kimi_code_composer: { version: 1, captureIds: ['capture-b'] } },
];
const projected = projectTranscriptUserOrigin({ kind: 'user', clientMetadata });
expect(transcriptUserOriginSchema.parse(projected)).toEqual({ kind: 'user', clientMetadata });
expect(projectTranscriptUserOrigin({ kind: 'user' })).toStrictEqual({ kind: 'user' });
expect(projectTranscriptUserOrigin({ kind: 'injection', clientMetadata })).toBeUndefined();
});
});
describe('user slash skill activations as transcript origins', () => {
it('projects a user-invoked activation and rejects a model-triggered one', () => {
const origin = { kind: 'skill_activation', trigger: 'user-slash', skillName: 'example-skill', skillArgs: 'args' };
expect(transcriptUserOriginSchema.parse(projectTranscriptUserOrigin(origin))).toEqual(origin);
expect(projectTranscriptUserOrigin({ ...origin, trigger: 'model-tool' })).toBeUndefined();
expect(projectTranscriptUserOrigin({ ...origin, skillName: '' })).toBeUndefined();
expect(projectTranscriptUserOrigin({ kind: 'user' })).toStrictEqual({ kind: 'user' });
});
});
const turnOp = (n: number): TranscriptOperation => ({
op: 'turn.upsert',
turn: { kind: 'turn', turnId: `t${n}`, ordinal: n, state: 'running', origin: { kind: 'user' } },
});
const stepOp: TranscriptOperation = {
op: 'step.upsert',
turnId: 't1',
step: { kind: 'step', stepId: 't1.1', turnId: 't1', ordinal: 1, state: 'running' },
};
const frameOp: TranscriptOperation = {
op: 'frame.upsert',
turnId: 't1',
stepId: 't1.1',
frame: { kind: 'text', frameId: 't1.1.f1', role: 'assistant', text: 'full' },
};
const appendOp: TranscriptOperation = {