| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- import { createMessage } from '@deepseek-ai/dsh-llm'
- import type { SessionEvent } from '@deepseek-ai/dsh-session/types'
- import { describe, expect, it } from 'vitest'
- import { projectConversationHistory } from '../src/client/session-history/history-fold.ts'
- import { compactHistoryInspectionEntries } from '../src/client/sessions/history.ts'
- import { inspectRequests } from '../src/client/sessions/request-inspection.ts'
- import { ev } from './event-script.ts'
- const at = (seq: number, event: Record<string, unknown>): SessionEvent =>
- ({ seq, time: 1_700_000_000_000 + seq, ...event }) as unknown as SessionEvent
- describe('projectConversationHistory', () => {
- it('projects a high-sequence history window without synthesizing its unloaded prefix', () => {
- const baseSeq = 400_000
- const events = [
- ev.user(baseSeq, 'loaded tail'),
- at(baseSeq + 1, {
- type: 'assistant/message',
- surfaceOp: { op: 'replace', start: baseSeq, end: baseSeq },
- sourceEventSeqs: [baseSeq],
- data: {
- turn: 80,
- step: 1,
- message: createMessage({
- role: 'assistant',
- content: [{ type: 'text', text: 'tail summary' }],
- source: { kind: 'model', provider: 'fake', model: 'fake' },
- }),
- },
- }),
- ]
- const projection = projectConversationHistory(events.map(event => ({ event })))
- expect(projection.eventNodes.map(node => node.seq)).toEqual([baseSeq, baseSeq + 1])
- expect(projection.contexts.map(context => ({
- originSeq: context.originSeq,
- nodes: context.nodes.map(node => node.seq),
- }))).toEqual([
- { originSeq: undefined, nodes: [baseSeq] },
- { originSeq: baseSeq + 1, nodes: [baseSeq + 1] },
- ])
- })
- it('projects frozen surface generations without widening the core live surface', () => {
- const events = [
- ev.user(0, 'a'),
- ev.user(1, 'b'),
- at(2, {
- type: 'assistant/message',
- surfaceOp: { op: 'replace', start: 0, end: 0 },
- sourceEventSeqs: [0],
- data: {
- turn: 1,
- step: 1,
- message: createMessage({
- role: 'assistant',
- content: [{ type: 'text', text: 'summary' }],
- source: { kind: 'model', provider: 'fake', model: 'fake' },
- }),
- },
- }),
- at(3, {
- type: 'assistant/message',
- surfaceOp: { op: 'replace', start: 2, end: 1 },
- sourceEventSeqs: [2, 1],
- data: {
- turn: 1,
- step: 2,
- message: createMessage({
- role: 'assistant',
- content: [{ type: 'text', text: 'summary 2' }],
- source: { kind: 'model', provider: 'fake', model: 'fake' },
- }),
- },
- }),
- ]
- expect(projectConversationHistory(events.map(event => ({ event }))).contexts.map(context => ({
- id: context.id,
- parentId: context.parentId,
- originSeq: context.originSeq,
- nodes: context.nodes.map(node => node.seq),
- }))).toEqual([
- { id: 0, parentId: undefined, originSeq: undefined, nodes: [0, 1] },
- { id: 1, parentId: 0, originSeq: 2, nodes: [2, 1] },
- { id: 2, parentId: 1, originSeq: 3, nodes: [3] },
- ])
- })
- it('projects assistant timing and the active request header from history', () => {
- const projection = projectConversationHistory([
- ev.stepStart(0, 1, 2),
- at(1, { type: 'request/header', data: {
- reason: 'initial',
- header: {
- config: { provider: 'fake', model: 'first' },
- tools: [],
- },
- } }),
- ev.chunkStart(2, 1, 2),
- ev.chunkText(3, 1, 'token', 2),
- ev.assistant(4, 1, 'done', 2),
- ev.stepStart(5, 2, 1),
- ev.chunkText(6, 2, 'next', 1),
- ev.assistant(7, 2, 'next done', 1),
- ].map(event => ({ event })))
- expect(projection.eventNodes[0]).toMatchObject({
- kind: 'assistant',
- timing: {
- stepStartTime: 1_700_000_000_000,
- firstTokenTime: 1_700_000_000_003,
- completedTime: 1_700_000_000_004,
- },
- requestConfig: { provider: 'fake', model: 'first' },
- })
- expect(projection.eventNodes.at(-1)).toMatchObject({
- timing: {
- stepStartTime: 1_700_000_000_005,
- firstTokenTime: 1_700_000_000_006,
- completedTime: 1_700_000_000_007,
- },
- requestConfig: { provider: 'fake', model: 'first' },
- })
- })
- it('drops completed token payloads without changing inspection projections', () => {
- const events = [
- ev.user(0, 'before'),
- ev.stepStart(1, 1, 0),
- ev.chunkStart(2, 1),
- ev.chunkText(3, 1, ''),
- ev.chunkText(4, 1, 'first'),
- ev.chunkText(5, 1, ' discarded'),
- at(6, { type: 'assistant/chunk', data: {
- turn: 1,
- step: 0,
- chunk: { type: 'usage', usage: { inputTokens: 4, outputTokens: 2 } },
- } }),
- ev.assistant(7, 1, 'first discarded'),
- ev.compactSummary(8, 'summary', 0, 7),
- ev.compactCheckpoint(9, 8, 0, 7),
- ev.stepStart(10, 2, 0),
- ev.chunkStart(11, 2),
- ev.chunkText(12, 2, 'interrupted'),
- ev.turnEnd(13, 2, 'aborted'),
- ]
- const raw = events.map(event => ({ event }))
- const compacted = compactHistoryInspectionEntries(raw)
- expect(compacted.map(entry => entry.event.seq)).toEqual([
- 0, 1, 4, 6, 7, 8, 9, 10, 11, 12, 13,
- ])
- expect(projectConversationHistory(compacted)).toEqual(projectConversationHistory(raw))
- expect(inspectRequests(compacted)).toEqual(inspectRequests(raw))
- })
- })
|