fix(agent-loop): nest config resume teardown

This commit is contained in:
Tianyi Cui
2026-07-11 23:45:01 +08:00
parent 06e42f439c
commit e6c7522a75
2 changed files with 23 additions and 1 deletions

View File

@@ -120,7 +120,11 @@ export class AgentLoop extends Service implements AgentFactory {
this.ctx.logger.warn(`agent "${id}": config-driven resume of "${resumeSessionId}" failed: ${String(error)}`)
})
})
return () => void fiber.dispose()
// Return the EXACT child-fiber disposer. Cordis moves a returned
// effect into this labeled owner's teardown tree by function
// identity; a wrapper would leave the child as a concurrent sibling
// and could discard its async quiescence promise.
return fiber.dispose
}, `agentLoop.resume(${id})`)
} else {
this.create(id, options, cwd === undefined ? {} : { cwd })

View File

@@ -24,6 +24,24 @@ function waitForIdle(ctx: Context, agent: ReactLoopAgent): Promise<void> {
}
describe('config-driven session id', () => {
it('identity-nests the deferred resume fiber under its labeled owner effect', async () => {
const ctx = new Context()
await ctx.plugin(LlmService)
await ctx.plugin(SessionStore)
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(AgentRegistry)
const loopFiber = await ctx.plugin(AgentLoop, {
agents: [{ id: AgentId('main'), model: 'mock', resumeSessionId: SessionId('deferred') }],
})
const resumeEffect = loopFiber.getEffects().find(effect => effect.label === 'agentLoop.resume(main)')
expect(resumeEffect?.children.map(child => child.label)).toEqual(['ctx.plugin()'])
expect(loopFiber.getEffects().filter(effect => effect.label === 'ctx.plugin()')).toEqual([])
await loopFiber.dispose()
})
it('config-driven create uses a fresh ${id}-session-<uuid> per run (restart-safe)', async () => {
const root = await mkdtemp(join(tmpdir(), 'dsh-cfg-session-'))
dirs.push(root)