test: cover reordered prompt boundaries
This commit is contained in:
@@ -57,6 +57,21 @@ describe('ACP prompt lifecycle', () => {
|
|||||||
.rejects.toThrow(/turn failed: plugin pre-step failed/)
|
.rejects.toThrow(/turn failed: plugin pre-step failed/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('rejects a turn-start failure before the prompt is claimed', async () => {
|
||||||
|
harness = await makeBridgeHarness({ script: [textResponse('must not run')] })
|
||||||
|
const sessionId = await newSession(harness)
|
||||||
|
const agent = harness.ctx.agents.get(SessionId(sessionId))!
|
||||||
|
const append = agent.session.append.bind(agent.session)
|
||||||
|
vi.spyOn(agent.session, 'append').mockImplementation(((type: string, ...rest: never[]) => {
|
||||||
|
if (type === 'turn/start') throw new Error('turn start unavailable')
|
||||||
|
return (append as (...args: never[]) => unknown)(type as never, ...rest)
|
||||||
|
}) as never)
|
||||||
|
|
||||||
|
await expect(harness.client.prompt({ sessionId, prompt: [{ type: 'text', text: 'go' }] }))
|
||||||
|
.rejects.toThrow(/turn failed: turn start unavailable/)
|
||||||
|
vi.restoreAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
it('settles even when an earlier turn observer throws', async () => {
|
it('settles even when an earlier turn observer throws', async () => {
|
||||||
harness = await makeBridgeHarness({ script: [textResponse('answer')] })
|
harness = await makeBridgeHarness({ script: [textResponse('answer')] })
|
||||||
harness.ctx.on('session/event', (_session, event) => {
|
harness.ctx.on('session/event', (_session, event) => {
|
||||||
@@ -257,6 +272,18 @@ describe('ACP prompt lifecycle', () => {
|
|||||||
expect(messageText(harness)).toBe('')
|
expect(messageText(harness)).toBe('')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('cancels a prompt removed before its turn claims it', async () => {
|
||||||
|
harness = await makeBridgeHarness({ script: [] })
|
||||||
|
const sessionId = await newSession(harness)
|
||||||
|
const dispose = harness.ctx.on('agent/inbox/inserted', (agent, { message }) => {
|
||||||
|
if (message.source.kind === 'user') agent.inbox.remove(message.id)
|
||||||
|
})
|
||||||
|
|
||||||
|
await expect(harness.client.prompt({ sessionId, prompt: [{ type: 'text', text: 'go' }] }))
|
||||||
|
.resolves.toEqual({ stopReason: 'cancelled' })
|
||||||
|
dispose()
|
||||||
|
})
|
||||||
|
|
||||||
it('rejects a prompt when pre-step fails inside its open turn', async () => {
|
it('rejects a prompt when pre-step fails inside its open turn', async () => {
|
||||||
harness = await makeBridgeHarness({ script: [] })
|
harness = await makeBridgeHarness({ script: [] })
|
||||||
harness.ctx.on('agent/pre-step', async () => { throw new Error('pre-step exploded') })
|
harness.ctx.on('agent/pre-step', async () => { throw new Error('pre-step exploded') })
|
||||||
|
|||||||
@@ -3739,6 +3739,11 @@ describe('workspace context inbox synchronization', () => {
|
|||||||
})
|
})
|
||||||
await syncWorkspaceContext(ctx, agent)
|
await syncWorkspaceContext(ctx, agent)
|
||||||
expect(blocksText(agent.inbox.nextStep[0]?.content)).toContain('pending version one')
|
expect(blocksText(agent.inbox.nextStep[0]?.content)).toContain('pending version one')
|
||||||
|
const duplicate = createUserMessage({
|
||||||
|
content: agent.inbox.nextStep[0]!.content,
|
||||||
|
source: agent.inbox.nextStep[0]!.source,
|
||||||
|
})
|
||||||
|
agent.inbox.append('next-step', duplicate)
|
||||||
|
|
||||||
await write(join(root, 'pkg/AGENTS.md'), 'pending version two with more detail')
|
await write(join(root, 'pkg/AGENTS.md'), 'pending version two with more detail')
|
||||||
await ctx.tools.execute({
|
await ctx.tools.execute({
|
||||||
@@ -3747,6 +3752,7 @@ describe('workspace context inbox synchronization', () => {
|
|||||||
})
|
})
|
||||||
await syncWorkspaceContext(ctx, agent)
|
await syncWorkspaceContext(ctx, agent)
|
||||||
expect(agent.inbox.nextStep).toHaveLength(1)
|
expect(agent.inbox.nextStep).toHaveLength(1)
|
||||||
|
expect(agent.inbox.nextStep[0]?.id).not.toBe(duplicate.id)
|
||||||
expect(blocksText(agent.inbox.nextStep[0]?.content)).toContain('pending version two with more detail')
|
expect(blocksText(agent.inbox.nextStep[0]?.content)).toContain('pending version two with more detail')
|
||||||
expect(blocksText(agent.inbox.nextStep[0]?.content)).not.toContain('pending version one')
|
expect(blocksText(agent.inbox.nextStep[0]?.content)).not.toContain('pending version one')
|
||||||
|
|
||||||
|
|||||||
@@ -328,6 +328,7 @@ function migrateLegacyTurnEndEvent(event: SessionEvent, id: SessionId): SessionE
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
/* v8 ignore next -- turn-end reasons are merge-extensible beyond the current vocabulary. */
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user