refactor: Pi extension uses heuristics+AST instead of direct LLM calls

Inside Pi, the extension no longer attempts to call the LLM directly
(which Pi's ExtensionAPI doesn't support). Instead:

- project_map_init: generates maps using AST + heuristics (fast, free)
- project_map_patch: rewrites the file's directory with heuristics
- project_map_reinit: full heuristic regeneration
- project_map_validate: unchanged (no LLM needed)

The CLI still supports real LLM calls via --llm-provider=kimi|openai.
This separates concerns:
- Pi extension: deterministic structural analysis
- CLI: rich semantic analysis with configurable LLM
This commit is contained in:
2026-06-10 10:28:15 +02:00
parent 7db9202658
commit 57c0f08210
2 changed files with 50 additions and 45 deletions
+9 -15
View File
@@ -72,29 +72,23 @@ describe("pi-extension", () => {
});
describe("project_map_init tool", () => {
it("returns error when Pi LLM is not accessible", async () => {
// Create a temp dir with a file so initProject tries to use LLM
it("generates heuristic maps successfully", async () => {
const dir = mkdtempSync(join(tmpdir(), "pi-ext-test-"));
writeFileSync(join(dir, "test.ts"), `export const x = ${Date.now()};`);
mockCtx.cwd = dir;
const tool = registeredTools.project_map_init;
const result = await tool.execute("tool-1", {}, null, null, mockCtx);
expect(result.details.success).toBe(false);
expect(result.content[0].text).toContain("Pi LLM not accessible");
expect(result.details.success).toBe(true);
expect(result.content[0].text).toContain("Generated heuristic");
});
});
describe("project_map_patch tool", () => {
it("returns error when Pi LLM is not accessible", async () => {
it("patches map successfully using heuristics", async () => {
const dir = mkdtempSync(join(tmpdir(), "pi-ext-test-"));
const file = join(dir, "test.ts");
writeFileSync(file, `export const x = ${Date.now()};`);
// Create a .pi-map.md so patchFile doesn't return early
writeFileSync(
join(dir, ".pi-map.md"),
"# .\n## role\nTest\n## files\n## arch\n## dirty\n-\n",
);
mockCtx.cwd = dir;
const tool = registeredTools.project_map_patch;
@@ -105,8 +99,8 @@ describe("pi-extension", () => {
null,
mockCtx,
);
expect(result.details.success).toBe(false);
expect(result.content[0].text).toContain("Pi LLM not accessible");
expect(result.details.success).toBe(true);
expect(result.content[0].text).toContain("Patched map");
});
});
@@ -138,15 +132,15 @@ describe("pi-extension", () => {
});
describe("project_map_reinit tool", () => {
it("returns error when Pi LLM is not accessible", async () => {
it("regenerates heuristic maps successfully", async () => {
const dir = mkdtempSync(join(tmpdir(), "pi-ext-test-"));
writeFileSync(join(dir, "test.ts"), `export const x = ${Date.now()};`);
mockCtx.cwd = dir;
const tool = registeredTools.project_map_reinit;
const result = await tool.execute("tool-1", {}, null, null, mockCtx);
expect(result.details.success).toBe(false);
expect(result.content[0].text).toContain("Pi LLM not accessible");
expect(result.details.success).toBe(true);
expect(result.content[0].text).toContain("Regenerated heuristic");
});
});