diff --git a/extensions/feishu/src/async.test.ts b/extensions/feishu/src/async.test.ts index 1053b940d09..4d80592722b 100644 --- a/extensions/feishu/src/async.test.ts +++ b/extensions/feishu/src/async.test.ts @@ -1,8 +1,25 @@ +import { MAX_TIMER_TIMEOUT_MS } from "openclaw/plugin-sdk/number-runtime"; import { afterEach, describe, expect, it, vi } from "vitest"; -import { waitForAbortableDelay } from "./async.js"; +import { raceWithTimeoutAndAbort, waitForAbortableDelay } from "./async.js"; afterEach(() => { vi.useRealTimers(); + vi.restoreAllMocks(); +}); + +describe("raceWithTimeoutAndAbort", () => { + it("normalizes oversized timeouts before arming the watchdog", async () => { + const timeoutSpy = vi + .spyOn(globalThis, "setTimeout") + .mockReturnValue(1 as unknown as ReturnType); + vi.spyOn(globalThis, "clearTimeout").mockImplementation(() => undefined); + + await raceWithTimeoutAndAbort(Promise.resolve("ok"), { + timeoutMs: Number.MAX_SAFE_INTEGER, + }); + + expect(timeoutSpy).toHaveBeenCalledWith(expect.any(Function), MAX_TIMER_TIMEOUT_MS); + }); }); describe("waitForAbortableDelay", () => { diff --git a/extensions/feishu/src/async.ts b/extensions/feishu/src/async.ts index 9c59be09135..7224a4dc45a 100644 --- a/extensions/feishu/src/async.ts +++ b/extensions/feishu/src/async.ts @@ -1,3 +1,5 @@ +import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime"; + const RACE_TIMEOUT = Symbol("race-timeout"); const RACE_ABORT = Symbol("race-abort"); @@ -26,9 +28,10 @@ export async function raceWithTimeoutAndAbort( const contenders: Array> = [promise]; if (options.timeoutMs !== undefined) { + const timeoutMs = resolveTimerTimeoutMs(options.timeoutMs, 1); contenders.push( new Promise((resolve) => { - timeoutHandle = setTimeout(() => resolve(RACE_TIMEOUT), options.timeoutMs); + timeoutHandle = setTimeout(() => resolve(RACE_TIMEOUT), timeoutMs); }), ); }