From dd146c20086e95d388e22cbca907dbf68364628b Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 25 May 2026 10:42:53 +0300 Subject: fix(loop-scheduler): defer agent_busy reset after agent_end instead of isIdle polling The agent_end handler receives ExtensionContext, not the command variant, so ctx.waitForIdle() was never available (TypeError). The previous fix replaced it with an isIdle() polling loop, but isIdle() remains false while any agent_end listener is still executing (finishRun() completes only after listeners settle). This caused a 30-second busy-wait on every turn, leaving the UI stuck on 'Working...'. Defer resetting agentBusy and draining pending jobs via setTimeout(..., 0) so the work happens in a macrotask after finishRun() has completed and the agent is genuinely idle. --- pi/agent/extensions/loop-scheduler/index.ts | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/pi/agent/extensions/loop-scheduler/index.ts b/pi/agent/extensions/loop-scheduler/index.ts index cdd30a4..64da563 100644 --- a/pi/agent/extensions/loop-scheduler/index.ts +++ b/pi/agent/extensions/loop-scheduler/index.ts @@ -1209,17 +1209,11 @@ export default function loopSchedulerExtension(pi: ExtensionAPI): void { // draining the queue and our message sits there forever, visible as a // stuck "Follow-up: ..." in pi's UI. We'd also leak agentBusy=true and // block every subsequent pending job because no further agent_end fires. - // Wait for the run to actually finish before draining. - // ctx.waitForIdle() is only available on ExtensionCommandContext, not - // ExtensionContext, so we poll isIdle() instead. - let attempts = 0; - const maxAttempts = 600; // ~30s at 50ms each - while (!ctx.isIdle() && attempts < maxAttempts) { - await new Promise((r) => setTimeout(r, 50)); - attempts++; - } - agentBusy = false; - drainPendingJobs(); + // Defer draining to the next macrotask so finishRun() completes first. + setTimeout(() => { + agentBusy = false; + drainPendingJobs(); + }, 0); }); pi.on("session_shutdown", async (_event, ctx) => { -- cgit v1.2.3