diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-24 12:32:18 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-24 12:32:18 +0300 |
| commit | 76b1cc008afc878e7edbd46feb6680ccab6880f0 (patch) | |
| tree | ee094e5be77092ba74177cbaf6345e9665c5a91b | |
| parent | 5a7fd46fc5bc113719b2ee2871d751b0986de2f5 (diff) | |
fix(loop-scheduler): reset agentBusy when drainPending detects idle context
The agentBusy flag could get stuck if an agent_start event fired but no
matching agent_end followed (e.g. crash or forced shutdown). The
scheduler would then show 'pending' forever even though the agent was
completely idle.
Now drainPendingJobs() and drainPendingWatchJobs() ask the ExtensionContext's
isIdle() as a ground-truth fallback whenever agentBusy is true. If the
context reports idle, we reset agentBusy = false and proceed to dispatch
pending jobs instead of bailing out.
| -rw-r--r-- | pi/agent/extensions/loop-scheduler/index.ts | 6 |
1 files changed, 4 insertions, 2 deletions
diff --git a/pi/agent/extensions/loop-scheduler/index.ts b/pi/agent/extensions/loop-scheduler/index.ts index af6b003..d57d0c3 100644 --- a/pi/agent/extensions/loop-scheduler/index.ts +++ b/pi/agent/extensions/loop-scheduler/index.ts @@ -620,14 +620,16 @@ export default function loopSchedulerExtension(pi: ExtensionAPI): void { } function drainPendingWatchJobs(): void { - if (agentBusy) return; + if (agentBusy && !lastCtx?.isIdle()) return; + agentBusy = false; const nextPending = getOrderedWatchJobs().find((job) => job.pending); if (!nextPending) return; dispatchWatchJob(nextPending, nextPending.pendingReason ?? nextPending.condition.kind); } function drainPendingJobs(): void { - if (agentBusy) return; + if (agentBusy && !lastCtx?.isIdle()) return; + agentBusy = false; if (!allPaused) { const nextPendingLoop = getOrderedJobs().find((job) => job.pending); if (nextPendingLoop) { |
