diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-25 10:09:11 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-25 10:09:11 +0300 |
| commit | 106f3f414802e34f2f58bdc4d9c2c92c845bab15 (patch) | |
| tree | 0df579d06e2d26dba3dc37b1ee6ccf96833045bd /lib/hyperstack/provisioning.rb | |
| parent | b1bcf57124b810b629ecb33ff651b619ff8d7178 (diff) | |
fix(loop-scheduler): await waitForIdle in agent_end before draining
Inside an agent_end listener, agent.state.isStreaming is still true —
finishRun() only clears it in the finally block of runWithLifecycle,
after all agent_end listeners settle. So when we dispatched a pending
job from agent_end and called pi.sendUserMessage(..., { deliverAs:
'followUp' }), the message was routed into agent.followUpQueue. The
agent loop had already passed its getFollowUpMessages() check, so it
exited without draining the queue. The message sat there as a stuck
'Follow-up: ...' in pi's UI, agentBusy stayed true forever, and every
subsequent pending loop was blocked because no further agent_end fired.
Await ctx.waitForIdle() in the agent_end handler before resetting
agentBusy and calling drainPendingJobs. By then finishRun() has cleared
isStreaming, so sendUserMessage starts a fresh run instead of enqueueing
into a dead followUp queue, and pending loops drain serially as designed.
Amp-Thread-ID: https://ampcode.com/threads/T-019e5de9-a0c3-7559-9cf0-f81ce751e763
Co-authored-by: Amp <amp@ampcode.com>
Diffstat (limited to 'lib/hyperstack/provisioning.rb')
0 files changed, 0 insertions, 0 deletions
