feat: Pi extension uses Pi's internal complete() for LLM analysis
- PiLLMClient now imports @mariozechner/pi-ai's complete() function - Respects user's /model selection and /login auth - No external fetch() — Pi handles transport internally - Added src/types/pi-ai.d.ts for TypeScript declarations - Extension reverted to real LLM calls (initProject, patchFile, reinitPath) - Tests mock @mariozechner/pi-ai for verification
This commit is contained in:
+24
-41
@@ -1,39 +1,20 @@
|
||||
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
import { Type } from "typebox";
|
||||
import { readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
||||
import { join, relative, dirname } from "path";
|
||||
import { validateMaps } from "./src/index.js";
|
||||
import { discoverProject } from "./src/discover.js";
|
||||
import { extractFileAST } from "./src/ast-extract.js";
|
||||
import { extractFileHeuristic, extractPackageHeuristic } from "./src/llm-extract.js";
|
||||
import { mergeFileData } from "./src/merge.js";
|
||||
import { renderPackageMap, type FileEntry } from "./src/format.js";
|
||||
import { readFileSync, readdirSync, statSync } from "fs";
|
||||
import { join, relative } from "path";
|
||||
import { initProject, patchFile, validateMaps, reinitPath } from "./src/index.js";
|
||||
import { createLLMClient } from "./src/llm-client.js";
|
||||
import { LLMError } from "./src/llm-error.js";
|
||||
|
||||
/**
|
||||
* Generate maps using heuristics + AST only (no LLM).
|
||||
* Inside Pi, we let Pi's agent handle semantic analysis.
|
||||
* The tool does structural work; the agent can refine later.
|
||||
* Get the LLM client for Pi runtime.
|
||||
*
|
||||
* When running inside Pi, we ALWAYS use Pi's native LLM via
|
||||
* @mariozechner/pi-ai's complete() function. This respects the
|
||||
* user's /model selection and /login auth. No external fetch().
|
||||
*/
|
||||
async function generateMapHeuristic(rootPath: string): Promise<void> {
|
||||
const entries = discoverProject(rootPath);
|
||||
for (const entry of entries) {
|
||||
const fileData: FileEntry[] = [];
|
||||
for (const file of entry.files) {
|
||||
const filePath = join(entry.dirPath, file);
|
||||
const astData = await extractFileAST(filePath);
|
||||
const heuristicData = await extractFileHeuristic(filePath);
|
||||
fileData.push(mergeFileData(file, heuristicData, astData));
|
||||
}
|
||||
const packageData = await extractPackageHeuristic(entry.relativePath, fileData);
|
||||
const mapData = {
|
||||
path: entry.relativePath,
|
||||
role: packageData.role,
|
||||
files: fileData,
|
||||
arch: packageData.arch,
|
||||
dirty: "-",
|
||||
};
|
||||
writeFileSync(join(entry.dirPath, ".pi-map.md"), renderPackageMap(mapData));
|
||||
}
|
||||
function getPiLLMClient(ctx: any) {
|
||||
return createLLMClient("pi", { extensionContext: ctx });
|
||||
}
|
||||
|
||||
function findPiMapFiles(cwd: string): string[] {
|
||||
@@ -91,18 +72,19 @@ export default function (pi: ExtensionAPI) {
|
||||
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
||||
try {
|
||||
const targetPath = params.path || ctx.cwd;
|
||||
await generateMapHeuristic(targetPath);
|
||||
const client = getPiLLMClient(ctx);
|
||||
await initProject(targetPath, { verbose: false, llmClient: client });
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Generated heuristic .pi-map.md files for ${targetPath}.`,
|
||||
text: `Generated .pi-map.md files for ${targetPath}`,
|
||||
},
|
||||
],
|
||||
details: { success: true, cwd: ctx.cwd },
|
||||
};
|
||||
} catch (err: any) {
|
||||
const msg = String(err);
|
||||
const msg = err instanceof LLMError ? err.message : String(err);
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: ${msg}` }],
|
||||
details: { success: false, error: msg },
|
||||
@@ -128,8 +110,8 @@ export default function (pi: ExtensionAPI) {
|
||||
}),
|
||||
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
||||
try {
|
||||
const dirPath = dirname(params.file_path);
|
||||
await generateMapHeuristic(dirPath);
|
||||
const client = getPiLLMClient(ctx);
|
||||
await patchFile(params.file_path, client);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
@@ -140,7 +122,7 @@ export default function (pi: ExtensionAPI) {
|
||||
details: { success: true },
|
||||
};
|
||||
} catch (err: any) {
|
||||
const msg = String(err);
|
||||
const msg = err instanceof LLMError ? err.message : String(err);
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: ${msg}` }],
|
||||
details: { success: false, error: msg },
|
||||
@@ -183,7 +165,7 @@ export default function (pi: ExtensionAPI) {
|
||||
details: { success: true, clean: result.clean },
|
||||
};
|
||||
} catch (err: any) {
|
||||
const msg = String(err);
|
||||
const msg = err instanceof LLMError ? err.message : String(err);
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: ${msg}` }],
|
||||
details: { success: false, error: msg },
|
||||
@@ -211,18 +193,19 @@ export default function (pi: ExtensionAPI) {
|
||||
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
||||
try {
|
||||
const targetPath = params.path || ctx.cwd;
|
||||
await generateMapHeuristic(targetPath);
|
||||
const client = getPiLLMClient(ctx);
|
||||
await reinitPath(targetPath, { verbose: false, llmClient: client });
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `Regenerated heuristic maps for ${targetPath}`,
|
||||
text: `Regenerated maps for ${targetPath}`,
|
||||
},
|
||||
],
|
||||
details: { success: true },
|
||||
};
|
||||
} catch (err: any) {
|
||||
const msg = String(err);
|
||||
const msg = err instanceof LLMError ? err.message : String(err);
|
||||
return {
|
||||
content: [{ type: "text", text: `Error: ${msg}` }],
|
||||
details: { success: false, error: msg },
|
||||
|
||||
Reference in New Issue
Block a user