import { describe, it, expect } from "vitest"; import { extractFileLLM } from "../src/llm/llm-extract.js"; import { writeFileSync, mkdtempSync } from "fs"; import { join } from "path"; import { tmpdir } from "os"; import type { LLMClient } from "../src/llm/llm-client.js"; function createMockClient(response: string): LLMClient { return { async complete() { return response; }, }; } describe("llm-extract with mock client", () => { it("uses LLM client when provided", async () => { const dir = mkdtempSync(join(tmpdir(), "pi-map-")); const file = join(dir, "test.ts"); writeFileSync(file, `export const foo = 1;`); const mockClient = createMockClient( "PURPOSE: Test file\nDEPS: none\nCONCEPTS: testing", ); const result = await extractFileLLM(file, mockClient, tmpdir()); expect(result.purpose).toBe("Test file"); expect(result.deps).toEqual([]); expect(result.concepts).toContain("testing"); }); it("throws without LLM client", async () => { const dir = mkdtempSync(join(tmpdir(), "pi-map-")); const file = join(dir, "test.ts"); writeFileSync(file, `export const foo = 1;`); await expect(extractFileLLM(file)).rejects.toThrow("No LLM client configured"); }); it("skips large files", async () => { const dir = mkdtempSync(join(tmpdir(), "pi-map-")); const file = join(dir, "big.ts"); writeFileSync(file, "x".repeat(600 * 1024)); const mockClient = createMockClient( "PURPOSE: Should not call\nDEPS: none\nCONCEPTS: none", ); const result = await extractFileLLM(file, mockClient); expect(result.purpose).toBe("Large file"); }); it("skips binary files", async () => { const dir = mkdtempSync(join(tmpdir(), "pi-map-")); const file = join(dir, "image.png"); // Write some binary-looking content with null bytes const buf = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]); writeFileSync(file, buf); const mockClient = createMockClient( "PURPOSE: Should not call\nDEPS: none\nCONCEPTS: none", ); const result = await extractFileLLM(file, mockClient); expect(result.purpose).toBe("Binary file"); }); it("parses response with deps and concepts", async () => { const dir = mkdtempSync(join(tmpdir(), "pi-map-")); const file = join(dir, "test.ts"); writeFileSync(file, `import { foo } from "bar";\nexport const x = 1;`); const mockClient = createMockClient( "PURPOSE: Config module\nDEPS: bar, baz\nCONCEPTS: constants, config", ); const result = await extractFileLLM(file, mockClient, tmpdir()); expect(result.purpose).toBe("Config module"); expect(result.deps).toEqual(["bar", "baz"]); expect(result.concepts).toEqual(["constants", "config"]); }); });