fix(session-persistence): address preparation review feedback
This commit is contained in:
@@ -15,6 +15,11 @@ import { MessageId } from '@deepseek-ai/dsh-llm'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
|
||||
import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import {
|
||||
PersistenceCoordinator,
|
||||
type PersistenceBackend,
|
||||
type StoredPrefix,
|
||||
} from '@deepseek-ai/dsh-session-persistence'
|
||||
import type { RpcRequest } from '@deepseek-ai/dsh-host-apiproxy/api/rpc'
|
||||
import { RpcId } from '@deepseek-ai/dsh-host-apiproxy/api/rpc'
|
||||
import { createApiProxy } from '@deepseek-ai/dsh-host-apiproxy'
|
||||
@@ -114,6 +119,62 @@ describe('attached updatedAt excludes end-seed', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('cold history recovery view', () => {
|
||||
it('shows in-memory interruption repair without activating the session', async () => {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(SessionStore)
|
||||
await ctx.plugin(UserInteractionService)
|
||||
const sessionId = sid('session-interrupted')
|
||||
const meta = header(sessionId, 1000)
|
||||
const stored: StoredPrefix<never> = {
|
||||
meta,
|
||||
events: [{ type: 'turn/start', seq: 0, time: 1, data: { turn: 1 } }],
|
||||
}
|
||||
const backend: PersistenceBackend<never> = {
|
||||
name: 'history-recovery-test',
|
||||
loadStored: id => Promise.resolve(id === sessionId ? structuredClone(stored) : undefined),
|
||||
appendBatch: () => Promise.resolve(),
|
||||
commitRepair: () => Promise.resolve(),
|
||||
list: () => Promise.resolve([structuredClone(meta)]),
|
||||
}
|
||||
const coordinator = new PersistenceCoordinator(ctx, backend)
|
||||
ctx.provide('sessionPersistence', {
|
||||
list: (signal?: AbortSignal) => backend.list(signal),
|
||||
inspect: (id: SessionId, signal?: AbortSignal) => coordinator.inspect(id, signal),
|
||||
locate: () => undefined,
|
||||
} as never)
|
||||
const api = createApiProxy(ctx, { provider: 'p', model: 'm', cwd: '/tmp', workspaceRoot: '/tmp' })
|
||||
|
||||
const history = await api.sessions.history(request({ sessionId, beforeSeq: 2, maxMessages: 10 }))
|
||||
if (!history.result.ok) throw new Error('history failed')
|
||||
expect(history.result.value.events.map(entry => entry.event)).toMatchInlineSnapshot(`
|
||||
[
|
||||
{
|
||||
"data": {
|
||||
"turn": 1,
|
||||
},
|
||||
"seq": 0,
|
||||
"time": 1,
|
||||
"type": "turn/start",
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"reason": {
|
||||
"kind": "interrupted",
|
||||
},
|
||||
"turn": 1,
|
||||
},
|
||||
"seq": 1,
|
||||
"time": 1,
|
||||
"type": "turn/end",
|
||||
},
|
||||
]
|
||||
`)
|
||||
expect(ctx.sessions.get(sessionId)).toBeUndefined()
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
})
|
||||
|
||||
describe('subagent ownership fence', () => {
|
||||
it('reads a cold child without an Agent and rejects generic resume or adoption', async () => {
|
||||
const ctx = new Context()
|
||||
|
||||
Reference in New Issue
Block a user