diff --git a/src/agents/code-mode-headless.test.ts b/src/agents/code-mode-headless.test.ts index 0ca9c93f39a..7a65b85a1dd 100644 --- a/src/agents/code-mode-headless.test.ts +++ b/src/agents/code-mode-headless.test.ts @@ -1,4 +1,5 @@ import { afterEach, describe, expect, it, vi } from "vitest"; +import { createDeferred } from "../shared/deferred.js"; import { runCodeModeScriptHeadless, testing, type CodeModeHeadlessResult } from "./code-mode.js"; import { createToolSearchCatalogRef, @@ -49,6 +50,7 @@ function expectFailed(result: CodeModeHeadlessResult) { describe("headless Code Mode", () => { afterEach(() => { + vi.useRealTimers(); expect(testing.activeRuns.size).toBe(0); testing.activeRuns.clear(); testing.resumingRunIds.clear(); @@ -174,7 +176,10 @@ describe("headless Code Mode", () => { }); it("enforces one wall-clock deadline across worker and tool legs", async () => { + vi.useFakeTimers({ toFake: ["setTimeout", "clearTimeout", "Date"] }); + const toolStarted = createDeferred(); const slow = fakeTool("slow_leg", async (_toolCallId, _input, signal) => { + toolStarted.resolve(); await new Promise((resolve, reject) => { const timer = setTimeout(resolve, 30_000); signal?.addEventListener( @@ -188,16 +193,19 @@ describe("headless Code Mode", () => { }); return jsonResult({ ok: true }); }); - const result = expectFailed( - await runCodeModeScriptHeadless({ - ctx: createHeadlessHarness([slow]), - code: ` - await tools.call("openclaw:core:slow_leg", {}); - return true; - `, - wallClockMs: 15_000, - }), - ); + const resultPromise = runCodeModeScriptHeadless({ + ctx: createHeadlessHarness([slow]), + code: ` + await tools.call("openclaw:core:slow_leg", {}); + return true; + `, + wallClockMs: 15_000, + }); + + // Advance the shared deadline only after the real worker reaches the tool leg. + await toolStarted.promise; + await vi.advanceTimersByTimeAsync(15_000); + const result = expectFailed(await resultPromise); expect(result.code).toBe("timeout"); expect(result.toolCallCount).toBe(1); diff --git a/src/agents/tools/image-tool.test.ts b/src/agents/tools/image-tool.test.ts index 17ecf43b269..9c3674f51d0 100644 --- a/src/agents/tools/image-tool.test.ts +++ b/src/agents/tools/image-tool.test.ts @@ -314,11 +314,11 @@ vi.mock("../model-auth.js", () => ({ }, })); -vi.mock("../openclaw-tools.js", async (importOriginal) => { - const actual = await importOriginal(); +// Client-cap filtering has dedicated coverage; this suite only needs image-tool propagation. +vi.mock("../openclaw-tools.js", async () => { const { createImageTool: createImageToolLocal } = await import("./image-tool.js"); return { - filterToolsByClientCaps: actual.filterToolsByClientCaps, + filterToolsByClientCaps: (tools: unknown[]) => tools, createOpenClawTools: vi.fn((options?: MockOpenClawToolsOptions) => { const imageTool = createImageToolLocal({ config: options?.config,