fix(test): cover indexed session reads

This commit is contained in:
_Kerman
2026-08-31 17:43:17 +08:00
parent 687ae5c9c0
commit febafc7ee0
8 changed files with 70 additions and 11 deletions
+4 -1
View File
@@ -68,10 +68,13 @@ describe('ACP machine permission policy', () => {
it('delegates a same-id foreign agent', async () => {
harness = await makeBridgeHarness()
const request = await ownedRequest()
const events = [{ type: 'turn/start', seq: 0, time: 0, data: { turn: 1 } }]
const foreign = {
session: {
id: request.agent.session.id,
snapshotEvents: () => [{ type: 'turn/start', seq: 0, time: 0, data: { turn: 1 } }],
seq: events.length,
eventAt: (seq: number) => events[seq],
snapshotEvents: () => events,
append: () => ({}),
},
} as unknown as Agent
@@ -310,6 +310,21 @@ describe('headless runner', () => {
await test.ctx.fiber.dispose()
})
it('fails when an event below the captured Session length cannot be read', async () => {
const test = await bench({
afterPrompt(session, message) {
appendTurn(session, 1, message, 'unreachable', true)
Object.defineProperty(session, 'eventAt', { value: () => undefined })
},
})
expect(await test.run()).toMatchObject({
code: 1,
out: '',
err: 'dsh: headless summary cannot read seq 0 below captured length 7\n',
})
await test.ctx.fiber.dispose()
})
it('reports a direct Agent creation failure', async () => {
const ctx = new Context()
let err = ''
@@ -540,7 +540,7 @@ describe('adapter registration, routing, and accepted-input ownership', () => {
send(agent, 'go')
await waitForIdle(ctx, agent)
const events = agent.session.events
const events = agent.session.snapshotEvents()
const claims = events.flatMap(event => event.type === 'agent/inbox/spliced'
&& event.data.target === 'next-step'
&& event.data.outcome !== 'canceled'
+8 -2
View File
@@ -806,12 +806,18 @@ describe('sandbox escalation API (write/edit)', () => {
/** A fake agent whose session records appends (the approval audit trail), mid-turn, carrying the given events for the fold. */
function escalationAgent(events: Array<{ type: string; data?: Record<string, unknown> }> = []): object {
const log = [
{ type: 'turn/start', data: { turn: 1 }, seq: 0 },
...events.map((event, index) => ({ ...event, seq: index + 1 })),
]
return {
id: 'agent-fs-esc',
session: {
header: { version: 0, id: 'sess-fs-esc', createdAt: 0, cwd: '/session-project' },
snapshotEvents: () => [{ type: 'turn/start', data: { turn: 1 } }, ...events],
append: (type: string, data: Record<string, unknown>) => { events.push({ type, data }) },
get seq() { return log.length },
eventAt: (seq: number) => log[seq],
snapshotEvents: () => log,
append: (type: string, data: Record<string, unknown>) => { log.push({ type, data, seq: log.length }) },
},
}
}
@@ -133,6 +133,17 @@ describe('incremental DeepSeek session-log upload', () => {
expect(reads).toBe(2)
})
it('rejects a missing event below the captured Session length', () => {
const session = {
id: SessionId('missing-event'),
seq: 1,
eventAt: () => undefined,
} as unknown as Session
expect(() => SessionLogDeepSeek.acceptedThrough(session))
.toThrow('session-log-deepseek: missing event 0 below captured length 1')
})
it('omits the field for direct or stale requests and uploads the prior acceptance marker next', async () => {
const { ctx, session } = await harness('edges')
await expect(ctx.deepseekLlmApiExtensions.prepare({ body: body(), signal: SIGNAL }))
+7 -4
View File
@@ -205,8 +205,8 @@ function sandboxAgent(
ctx?: Context,
onAppend?: (type: string) => void,
): Agent {
const events: Array<{ type: string; data?: Record<string, unknown> }> = [{ type: 'turn/start', data: { turn: 1 } }]
if (mode !== undefined) events.push({ type: 'sandbox/mode', data: { mode } })
const events: Array<{ type: string; data?: Record<string, unknown>; seq: number }> = [{ type: 'turn/start', seq: 0, data: { turn: 1 } }]
if (mode !== undefined) events.push({ type: 'sandbox/mode', seq: events.length, data: { mode } })
const id = SessionId('sandbox-session')
return {
id,
@@ -214,9 +214,11 @@ function sandboxAgent(
session: {
id,
header: { version: 0, id, createdAt: 0 },
get seq() { return events.length },
eventAt: (seq: number) => events[seq],
snapshotEvents: () => events,
append: (type: string, data: Record<string, unknown>) => {
const event = { type, data }
const event = { type, data, seq: events.length }
events.push(event)
onAppend?.(type)
return event
@@ -625,9 +627,10 @@ describe('sandbox escalation through the generic task producer', () => {
expect(prompted).not.toHaveBeenCalled()
const malformed = sandboxAgent()
;(malformed.session.snapshotEvents() as unknown as Array<{ type: string; data: { mode: string } }>).push({
;(malformed.session.snapshotEvents() as unknown as Array<{ type: string; data: { mode: string }; seq: number }>).push({
type: 'sandbox/mode',
data: { mode: 'unknown-mode' },
seq: malformed.session.seq,
})
expect(text(await call(ctx, 'bash', escalate, malformed))).toContain('not strictly wider')
})
+12 -3
View File
@@ -247,9 +247,11 @@ function sandboxAgent(
session: {
id,
header: { version: 0, id, createdAt: 0 },
get seq() { return events.length },
eventAt: (seq: number) => events[seq],
snapshotEvents: () => events,
append: (type: string, data: Record<string, unknown>) => {
const event = { type, data }
const event = { type, data, seq: events.length }
events.push(event)
onAppend?.(type)
return event
@@ -270,7 +272,13 @@ function registerFakeAgent(ctx: Context, sessionId: string): Agent {
const agent = {
id,
ctx: scopeFiber.ctx,
session: { id, header: { version: 0, id, createdAt: 0 }, snapshotEvents: () => [] },
session: {
id,
header: { version: 0, id, createdAt: 0 },
seq: 0,
eventAt: () => undefined,
snapshotEvents: () => [],
},
} as unknown as Agent
ctx.agents.register(agent)
return agent
@@ -602,9 +610,10 @@ describe('sandbox escalation through ctx.approval', () => {
expect(prompted).not.toHaveBeenCalled()
const malformed = sandboxAgent()
;(malformed.session.snapshotEvents() as unknown as Array<{ type: string; data: { mode: string } }>).push({
;(malformed.session.snapshotEvents() as unknown as Array<{ type: string; data: { mode: string }; seq: number }>).push({
type: 'sandbox/mode',
data: { mode: 'unknown-mode' },
seq: malformed.session.seq,
})
expect(text(await call(ctx, 'pwsh', escalate, malformed))).toContain('not strictly wider')
})
@@ -585,6 +585,18 @@ describe('dsh-tool-skill', () => {
expect(JSON.stringify(published[0]?.data.content)).toContain('live-skill')
})
it('rejects a missing event below the current Session length', async () => {
const home = await tempDir('tool-catalog-missing-event')
const ctx = await setup(home)
const session = Session.create(SessionId('catalog-missing-event'))
const agent = sessionAgent(session)
openMessageTurn(session)
Object.defineProperty(session, 'eventAt', { value: () => undefined })
await expect(fireStep(ctx, agent, 1, 1))
.rejects.toThrow('skill catalog cannot read seq 1 below the current Session length')
})
it('re-establishes the current catalog after compaction hides its durable message', async () => {
const home = await tempDir('tool-catalog-compaction')
const ctx = await setup(home)