| 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(), | |
| })); | |
| vi.mock("../process/supervisor/index.js", () => ({ | |
| getProcessSupervisor: () => ({ | |
| spawn: (...args: unknown[]) => supervisorSpawnMock(...args), | |
| cancel: vi.fn(), | |
| cancelScope: vi.fn(), | |
| reconcileOrphans: vi.fn(), | |
| getRecord: vi.fn(), | |
| }), | |
| })); | |
| afterEach(() => { | |
| resetProcessRegistryForTests(); | |
| vi.clearAllMocks(); | |
| }); | |
| test("exec cleans session state when PTY fallback spawn also fails", async () => { | |
| supervisorSpawnMock | |
| .mockRejectedValueOnce(new Error("pty spawn failed")) | |
| .mockRejectedValueOnce(new Error("child fallback failed")); | |
| const tool = createExecTool({ allowBackground: false }); | |
| await expect( | |
| tool.execute("toolcall", { | |
| command: "echo ok", | |
| pty: true, | |
| }), | |
| ).rejects.toThrow("child fallback failed"); | |
| expect(listRunningSessions()).toHaveLength(0); | |
| }); | |