test(agent-loop): align consumers with direct wakeup
This commit is contained in:
@@ -82,18 +82,15 @@ describe('ACP prompt lifecycle', () => {
|
|||||||
.resolves.toEqual({ stopReason: 'end_turn' })
|
.resolves.toEqual({ stopReason: 'end_turn' })
|
||||||
})
|
})
|
||||||
|
|
||||||
it('ignores an injection turn while correlating the owning message turn', async () => {
|
it('correlates the owning prompt when a synchronous injection joins its first step', async () => {
|
||||||
harness = await makeBridgeHarness({ script: [textResponse('real answer')] })
|
harness = await makeBridgeHarness({ script: [textResponse('real answer')] })
|
||||||
const sessionId = await newSession(harness)
|
const sessionId = await newSession(harness)
|
||||||
const agent = harness.ctx.agents.get(SessionId(sessionId))!
|
const agent = harness.ctx.agents.get(SessionId(sessionId))!
|
||||||
let injected = false
|
let injected = false
|
||||||
harness.ctx.on('session/event', (session, event) => {
|
harness.ctx.on('agent/inbox/inserted', (subject, { message }) => {
|
||||||
if (session === agent.session && event.type === 'agent/inbox/spliced'
|
if (subject === agent && message.source.kind === 'user' && !injected) {
|
||||||
&& event.data.inserted.some(message => message.source.kind === 'user') && !injected) {
|
|
||||||
injected = true
|
injected = true
|
||||||
queueMicrotask(() => {
|
agent.inject(createUserMessage({ content: [{ type: 'text', text: 'context' }], source: { kind: 'plugin', plugin: 'test' } }))
|
||||||
agent.inject(createUserMessage({ content: [{ type: 'text', text: 'context' }], source: { kind: 'plugin', plugin: 'test' } }))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -101,14 +101,14 @@ async function harness(script: ScriptEntry[]): Promise<Harness> {
|
|||||||
return { ctx, adapter, agent, driver }
|
return { ctx, adapter, agent, driver }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Observe inserted inbox messages after the insertion call completes. */
|
/** Observe inserted inbox messages after the live projection accepts them. */
|
||||||
function onInboxMessage(
|
function onInboxMessage(
|
||||||
ctx: Context,
|
ctx: Context,
|
||||||
agent: Agent,
|
agent: Agent,
|
||||||
listener: (message: UserMessage) => void,
|
listener: (message: UserMessage) => void,
|
||||||
): () => void {
|
): () => void {
|
||||||
return ctx.on('agent/inbox/inserted', (subject, { message }) => {
|
return ctx.on('agent/inbox/inserted', (subject, { message }) => {
|
||||||
if (subject === agent) queueMicrotask(() => { listener(message) })
|
if (subject === agent) listener(message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -200,22 +200,6 @@ describe('dsh-subagent-spawn', () => {
|
|||||||
expect(published).toEqual([])
|
expect(published).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('a cancel after the child prompt is queued maps a no-turn child log to aborted', async () => {
|
|
||||||
const { ctx, parent } = await setup([])
|
|
||||||
const controller = new AbortController()
|
|
||||||
ctx.on('session/event', (_session, event) => {
|
|
||||||
if (event.type === 'agent/inbox/spliced' && event.data.inserted.length > 0) {
|
|
||||||
queueMicrotask(() => { controller.abort('queued-window') })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const run = await start(ctx, 'spawn', { prompt: [{ type: 'text', text: 'p' }], parent, signal: controller.signal })
|
|
||||||
const result = await run.result
|
|
||||||
expect(result).toMatchObject({ stopReason: 'aborted', output: [] })
|
|
||||||
const child = ctx.agents.get(run.id)!
|
|
||||||
expect(child.session.events.some(event => event.type === 'turn/end')).toBe(false)
|
|
||||||
await run.dispose()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('cancelling a running child settles the run as aborted (the abort bridge + cancel())', async () => {
|
it('cancelling a running child settles the run as aborted (the abort bridge + cancel())', async () => {
|
||||||
// 'hang' makes the child's model stream one chunk then wait until aborted.
|
// 'hang' makes the child's model stream one chunk then wait until aborted.
|
||||||
const controller = new AbortController()
|
const controller = new AbortController()
|
||||||
|
|||||||
Reference in New Issue
Block a user