import * as fs from "node:fs"; import * as path from "node:path"; import * as os from "node:os"; import { ExecutorAgent } from "../agents/executor.js"; import { AgentContext } from "../agents/base.js"; import { IntelligenceBackend, BackendRequest, BackendResult } from "../backends/types.js"; import { emptyTokenUsage } from "../backends/types.js"; class MockBackend implements IntelligenceBackend { readonly name = "mock"; readonly type = "llm" as const; async isAvailable(): Promise { return true; } async execute(request: BackendRequest): Promise { return { success: true, output: `Mock backend executed: ${request.task.slice(0, 50)}`, artifacts: [], decisions: [], escalations: [], usage: emptyTokenUsage(), }; } } function createTempDir(): string { return fs.mkdtempSync(path.join(os.tmpdir(), "ciagent-executor-test-")); } function cleanup(dir: string): void { fs.rmSync(dir, { recursive: true, force: true }); } function makeContext(dir: string, backend?: IntelligenceBackend): AgentContext { return { project_path: dir, phase: 1, stage: "execute", specification: "Build a REST API for task management", config_path: path.join(dir, ".ciagent", "config.json"), backend, }; } describe("ExecutorAgent", () => { let dir: string; beforeEach(() => { dir = createTempDir(); }); afterEach(() => { cleanup(dir); }); it("returns honest failure without backend", async () => { const executor = new ExecutorAgent(); const result = await executor.execute(makeContext(dir)); expect(result.success).toBe(false); expect(result.error).toContain("intelligence backend"); }); it("delegates to backend when available", async () => { const mockBackend = new MockBackend(); const executor = new ExecutorAgent(); const result = await executor.execute(makeContext(dir, mockBackend)); expect(result.success).toBe(true); expect(result.output).toContain("Mock backend executed"); }); it("has correct agent name", () => { const executor = new ExecutorAgent(); expect(executor.name).toBe("executor"); }); it("has correct workflow", () => { const executor = new ExecutorAgent(); expect(executor.workflow).toBe("execute"); }); });