| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import { readFile, writeFile } from 'node:fs/promises'
- import { dirname, join } from 'node:path'
- import { fileURLToPath } from 'node:url'
- import { Context } from 'cordis'
- import { normalizeSessionLog, scrubRequestHeaders, type NormalizeContext } from '@deepseek-ai/dsh-acp-snapshot'
- import { LOADER_SMOKE_TEST_TIMEOUT_MS, runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
- import { createUserMessage, CallId , createMessage } from '@deepseek-ai/dsh-llm'
- import SessionStore, { SESSION_FORMAT_VERSION, SessionId, type SessionEvent, type SessionHeader } from '@deepseek-ai/dsh-session'
- import SessionPersistenceJsonl from '@deepseek-ai/dsh-session-persistence-jsonl'
- import { describe, expect, it } from 'vitest'
- const fixtureDir = join(dirname(fileURLToPath(import.meta.url)), 'semantic-checkpoint-snapshots/tool-outcome-unknown')
- const replayFixture = join(fixtureDir, 'replay.jsonl')
- const replayOverride = join(fixtureDir, 'replay.override.json')
- const sessionExpected = join(fixtureDir, 'session.expected.jsonl')
- const configPath = fileURLToPath(new URL('../semantic-checkpoint.cordis.snapshot.yml', import.meta.url))
- const binScript = fileURLToPath(new URL('../../../packages/examples/cli-demo/src/bin.ts', import.meta.url))
- const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url))
- const sessionId = SessionId('semantic-checkpoint-unknown-outcome')
- const refreshing = process.env.DSH_SNAPSHOT === 'refresh'
- const task = 'Continue safely from the interrupted operation.'
- async function seedInterruptedSession(root: string, cwd: string): Promise<string> {
- const ctx = new Context()
- await ctx.plugin(SessionStore)
- await ctx.plugin(SessionPersistenceJsonl, { root, compression: 'none' })
- const meta: SessionHeader = {
- version: SESSION_FORMAT_VERSION,
- id: sessionId,
- createdAt: 1,
- cwd,
- delegationDepth: 0,
- }
- const events: SessionEvent[] = [
- { type: 'turn/start', seq: 0, time: 10, data: { turn: 1 } },
- { type: 'user/message', seq: 1, time: 11, data: createUserMessage({
- content: [{ type: 'text', text: 'Perform one side-effecting remote mutation.' }], source: { kind: 'user' },
- }), surfaceOp: 'append' },
- { type: 'step/start', seq: 2, time: 12, data: { turn: 1, step: 1 } },
- {
- type: 'assistant/message',
- seq: 3,
- time: 13,
- data: {
- turn: 1,
- step: 1,
- message: createMessage({
- role: 'assistant',
- content: [{ type: 'tool-call', id: CallId('unknown-outcome-call'), name: 'write_remote', arguments: '{"value":1}' }],
- source: {
- kind: 'model',
- ...{ provider: 'deepseek-official', model: 'deepseek-v4-flash' },
- },
- }),
- },
- surfaceOp: 'append',
- },
- {
- type: 'tool/call',
- seq: 4,
- time: 14,
- data: {
- turn: 1,
- step: 1,
- callId: CallId('unknown-outcome-call'),
- name: 'write_remote',
- arguments: '{"value":1}',
- },
- },
- ]
- try {
- await ctx.sessionPersistence.create(meta)
- await ctx.sessionPersistence.append(sessionId, events)
- const location = ctx.sessionPersistence.locate(meta)
- if (location === undefined) throw new Error('JSONL backend did not locate the seeded session')
- return location.path
- } finally {
- await ctx.fiber.dispose()
- }
- }
- describe('semantic checkpoint recovery snapshot', () => {
- it('resumes an unknown tool outcome through the headless stream-json app', async () => {
- let cwd = ''
- let sessionPath = ''
- const result = await runLoaderSmoke({
- label: 'semantic checkpoint headless stream-json snapshot',
- tempDirPrefix: 'dsh-semantic-snapshot-',
- binScript,
- configPath,
- binArgs: ['--config', configPath, '--output-format', 'stream-json', task],
- tsconfigPath,
- env: {
- DSH_SNAPSHOT_FILE: replayFixture,
- DSH_SNAPSHOT_OVERRIDE: replayOverride,
- },
- prepare: async (runCwd) => {
- cwd = runCwd
- sessionPath = await seedInterruptedSession(join(runCwd, '.sessions'), runCwd)
- },
- inspect: async () => {
- const normalization: NormalizeContext = { sessionIds: [sessionId], cwd }
- const session = scrubRequestHeaders(normalizeSessionLog(await readFile(sessionPath, 'utf8'), normalization))
- if (refreshing) await writeFile(sessionExpected, session)
- expect(session).toBe(await readFile(sessionExpected, 'utf8'))
- expect(session).toContain('TOOL_OUTCOME_UNKNOWN')
- expect(session).toContain('Do not retry blindly.')
- },
- })
- expect(result.stderr).toBe('')
- const records = result.stdout.trimEnd().split('\n').map(line => JSON.parse(line) as Record<string, unknown>)
- expect(records.at(-1)).toMatchObject({
- type: 'result',
- sessionId,
- output: 'I will verify the external state before deciding whether to retry the side-effecting operation.',
- })
- }, LOADER_SMOKE_TEST_TIMEOUT_MS)
- })
|