diff --git a/packages/coding-agent/src/tools/browser/tab-worker.ts b/packages/coding-agent/src/tools/browser/tab-worker.ts index b7229bb57..4dc4a4f24 100644 --- a/packages/coding-agent/src/tools/browser/tab-worker.ts +++ b/packages/coding-agent/src/tools/browser/tab-worker.ts @@ -182,7 +182,14 @@ export async function dispatchScroll( dispatch: () => Promise, ackTimeoutMs = SCROLL_ACK_TIMEOUT_MS, ): Promise { - await Promise.race([dispatch(), Bun.sleep(ackTimeoutMs)]); + const deadline = Promise.withResolvers(); + const timer = setTimeout(() => deadline.resolve(), ackTimeoutMs); + timer.unref(); + try { + await Promise.race([dispatch(), deadline.promise]); + } finally { + clearTimeout(timer); + } } /** diff --git a/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts b/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts index 6f023146c..96d8b0e0f 100644 --- a/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts +++ b/packages/coding-agent/test/tools/browser-tab-timeouts.test.ts @@ -1,4 +1,4 @@ -import { describe, expect, it } from "bun:test"; +import { describe, expect, it, vi } from "bun:test"; import { resolvePredicateTimeout } from "@oh-my-pi/pi-coding-agent/tools/browser/run-cancellation"; import { dispatchScroll, @@ -55,6 +55,19 @@ describe("browser scroll acknowledgement", () => { "target closed", ); }); + + it("cancels the acknowledgement deadline after a prompt dispatch", async () => { + vi.useFakeTimers(); + try { + const timerCount = vi.getTimerCount(); + + await dispatchScroll(() => Promise.resolve()); + + expect(vi.getTimerCount()).toBe(timerCount); + } finally { + vi.useRealTimers(); + } + }); }); describe("browser wait-helper timeout resolution", () => {