diff --git a/src/agents/bash-tools.exec.pty-cleanup.test.ts b/src/agents/bash-tools.exec.pty-cleanup.test.ts index 613c8fd0353..efe6f01d606 100644 --- a/src/agents/bash-tools.exec.pty-cleanup.test.ts +++ b/src/agents/bash-tools.exec.pty-cleanup.test.ts @@ -1,9 +1,17 @@ import { afterEach, expect, test, vi } from "vitest"; import { resetProcessRegistryForTests } from "./bash-process-registry"; +import { createExecTool } from "./bash-tools.exec"; + +const { ptySpawnMock } = vi.hoisted(() => ({ + ptySpawnMock: vi.fn(), +})); + +vi.mock("@lydell/node-pty", () => ({ + spawn: (...args: unknown[]) => ptySpawnMock(...args), +})); afterEach(() => { resetProcessRegistryForTests(); - vi.resetModules(); vi.clearAllMocks(); }); @@ -11,25 +19,20 @@ test("exec disposes PTY listeners after normal exit", async () => { const disposeData = vi.fn(); const disposeExit = vi.fn(); - vi.doMock("@lydell/node-pty", () => ({ - spawn: () => { - return { - pid: 0, - write: vi.fn(), - onData: (listener: (value: string) => void) => { - setTimeout(() => listener("ok"), 0); - return { dispose: disposeData }; - }, - onExit: (listener: (event: { exitCode: number; signal?: number }) => void) => { - setTimeout(() => listener({ exitCode: 0 }), 0); - return { dispose: disposeExit }; - }, - kill: vi.fn(), - }; + ptySpawnMock.mockImplementation(() => ({ + pid: 0, + write: vi.fn(), + onData: (listener: (value: string) => void) => { + listener("ok"); + return { dispose: disposeData }; }, + onExit: (listener: (event: { exitCode: number; signal?: number }) => void) => { + listener({ exitCode: 0 }); + return { dispose: disposeExit }; + }, + kill: vi.fn(), })); - const { createExecTool } = await import("./bash-tools.exec"); const tool = createExecTool({ allowBackground: false }); const result = await tool.execute("toolcall", { command: "echo ok", @@ -46,19 +49,14 @@ test("exec tears down PTY resources on timeout", async () => { const disposeExit = vi.fn(); const kill = vi.fn(); - vi.doMock("@lydell/node-pty", () => ({ - spawn: () => { - return { - pid: 0, - write: vi.fn(), - onData: () => ({ dispose: disposeData }), - onExit: () => ({ dispose: disposeExit }), - kill, - }; - }, + ptySpawnMock.mockImplementation(() => ({ + pid: 0, + write: vi.fn(), + onData: () => ({ dispose: disposeData }), + onExit: () => ({ dispose: disposeExit }), + kill, })); - const { createExecTool } = await import("./bash-tools.exec"); const tool = createExecTool({ allowBackground: false }); await expect( tool.execute("toolcall", { diff --git a/src/agents/bash-tools.exec.pty-fallback-failure.test.ts b/src/agents/bash-tools.exec.pty-fallback-failure.test.ts index 7f3be417387..2caad66a83f 100644 --- a/src/agents/bash-tools.exec.pty-fallback-failure.test.ts +++ b/src/agents/bash-tools.exec.pty-fallback-failure.test.ts @@ -1,5 +1,6 @@ import { afterEach, expect, test, vi } from "vitest"; import { listRunningSessions, resetProcessRegistryForTests } from "./bash-process-registry"; +import { createExecTool } from "./bash-tools.exec"; const { supervisorSpawnMock } = vi.hoisted(() => ({ supervisorSpawnMock: vi.fn(), @@ -17,7 +18,6 @@ vi.mock("../process/supervisor/index.js", () => ({ afterEach(() => { resetProcessRegistryForTests(); - vi.resetModules(); vi.clearAllMocks(); }); @@ -26,7 +26,6 @@ test("exec cleans session state when PTY fallback spawn also fails", async () => .mockRejectedValueOnce(new Error("pty spawn failed")) .mockRejectedValueOnce(new Error("child fallback failed")); - const { createExecTool } = await import("./bash-tools.exec"); const tool = createExecTool({ allowBackground: false }); await expect( diff --git a/src/cron/isolated-agent/run.skill-filter.test.ts b/src/cron/isolated-agent/run.skill-filter.test.ts index 9c0bd4300a8..407918c74ac 100644 --- a/src/cron/isolated-agent/run.skill-filter.test.ts +++ b/src/cron/isolated-agent/run.skill-filter.test.ts @@ -166,6 +166,8 @@ vi.mock("../../agents/defaults.js", () => ({ DEFAULT_PROVIDER: "openai", })); +const { runCronIsolatedAgentTurn } = await import("./run.js"); + // ---------- helpers ---------- function makeJob(overrides?: Record) { @@ -230,8 +232,6 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { it("passes agent-level skillFilter to buildWorkspaceSkillSnapshot", async () => { resolveAgentSkillsFilterMock.mockReturnValue(["meme-factory", "weather"]); - const { runCronIsolatedAgentTurn } = await import("./run.js"); - const result = await runCronIsolatedAgentTurn( makeParams({ cfg: { agents: { list: [{ id: "scout", skills: ["meme-factory", "weather"] }] } }, @@ -250,8 +250,6 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { it("omits skillFilter when agent has no skills config", async () => { resolveAgentSkillsFilterMock.mockReturnValue(undefined); - const { runCronIsolatedAgentTurn } = await import("./run.js"); - const result = await runCronIsolatedAgentTurn( makeParams({ cfg: { agents: { list: [{ id: "general" }] } }, @@ -268,8 +266,6 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { it("passes empty skillFilter when agent explicitly disables all skills", async () => { resolveAgentSkillsFilterMock.mockReturnValue([]); - const { runCronIsolatedAgentTurn } = await import("./run.js"); - const result = await runCronIsolatedAgentTurn( makeParams({ cfg: { agents: { list: [{ id: "silent", skills: [] }] } }, @@ -302,8 +298,6 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { isNewSession: true, }); - const { runCronIsolatedAgentTurn } = await import("./run.js"); - const result = await runCronIsolatedAgentTurn( makeParams({ cfg: { agents: { list: [{ id: "weather-bot", skills: ["weather"] }] } }, @@ -338,8 +332,6 @@ describe("runCronIsolatedAgentTurn — skill filter", () => { isNewSession: true, }); - const { runCronIsolatedAgentTurn } = await import("./run.js"); - const result = await runCronIsolatedAgentTurn( makeParams({ cfg: { agents: { list: [{ id: "weather-bot", skills: ["weather", "meme-factory"] }] } },