fix(reply): clear idle followup callbacks

This commit is contained in:
Vincent Koc 2026-03-23 10:18:54 -07:00 committed by Peter Steinberger
parent 3de42e946a
commit 02e07a157d
2 changed files with 28 additions and 0 deletions

View File

@ -178,6 +178,7 @@ export function scheduleFollowupDrain(
queue.draining = false;
if (queue.items.length === 0 && queue.droppedCount === 0) {
FOLLOWUP_QUEUES.delete(key);
clearFollowupDrainCallback(key);
} else {
scheduleFollowupDrain(key, effectiveRunFollowup);
}

View File

@ -1685,6 +1685,33 @@ describe("followup queue drain restart after idle window", () => {
expect(calls).toHaveLength(1);
expect(calls[0]?.prompt).toBe("before-clear");
});
it("clears the remembered callback after a queue drains fully", async () => {
const key = `test-auto-clear-callback-${Date.now()}`;
const calls: FollowupRun[] = [];
const settings: QueueSettings = { mode: "followup", debounceMs: 0, cap: 50 };
const firstProcessed = createDeferred<void>();
const runFollowup = async (run: FollowupRun) => {
calls.push(run);
firstProcessed.resolve();
};
enqueueFollowupRun(key, createRun({ prompt: "before-idle" }), settings);
scheduleFollowupDrain(key, runFollowup);
await firstProcessed.promise;
// Let the idle drain finish and clear its callback.
await new Promise<void>((resolve) => setImmediate(resolve));
// Enqueueing after a clean drain should not auto-start anything until a
// fresh finalize path supplies a new callback.
enqueueFollowupRun(key, createRun({ prompt: "after-idle" }), settings);
await new Promise<void>((resolve) => setImmediate(resolve));
expect(calls).toHaveLength(1);
expect(calls[0]?.prompt).toBe("before-idle");
});
});
const emptyCfg = {} as OpenClawConfig;