Implement layered maps and context retrieval

This commit is contained in:
2026-06-11 12:56:18 +02:00
parent 010e4b83eb
commit c6064f8d94
35 changed files with 4410 additions and 383 deletions
+82 -15
View File
@@ -7,6 +7,7 @@ import {
patchFile,
validateMaps,
reinitPath,
retrieveContext,
} from "./src/index.js";
import { createLLMClient } from "./src/llm/llm-client.js";
import { LLMError } from "./src/llm/llm-error.js";
@@ -55,7 +56,12 @@ function isDirty(content: string): boolean {
return content.includes("## dirty") && !content.includes("## dirty\n-");
}
function renderProgressBar(completed: number, total: number, currentFile?: string, width = 20): string {
function renderProgressBar(
completed: number,
total: number,
currentFile?: string,
width = 20,
): string {
const pct = total > 0 ? completed / total : 0;
const filled = Math.round(width * pct);
const bar = "█".repeat(filled) + "░".repeat(width - filled);
@@ -68,12 +74,12 @@ export default function (pi: ExtensionAPI) {
name: "project_map_init",
label: "Project Map Init",
description:
"Generate .pi-map.md analysis files for the entire project or a subdirectory",
"Generate paired .pi-map.md and .pi-map.index.md analysis files for the entire project or a subdirectory",
promptSnippet:
"Initialize project analysis files for codebase understanding",
"Initialize paired project map/index artifacts for codebase understanding",
promptGuidelines: [
"Use project_map_init when starting work on a new project or after significant restructuring",
"Run project_map_init when .pi-map.md files are missing or severely outdated",
"Run project_map_init when .pi-map.md / .pi-map.index.md files are missing or severely outdated",
],
parameters: Type.Object({
path: Type.Optional(
@@ -91,10 +97,21 @@ export default function (pi: ExtensionAPI) {
llmClient: client,
cacheDir: ctx.cwd,
onProgress: (info) => {
const bar = renderProgressBar(info.completed, info.total, info.currentFile);
const bar = renderProgressBar(
info.completed,
info.total,
info.currentFile,
);
_onUpdate?.({
content: [{ type: "text", text: bar }],
details: { progress: info.total > 0 ? Math.round((info.completed / info.total) * 100) : 0, file: info.currentFile, dir: info.dir },
details: {
progress:
info.total > 0
? Math.round((info.completed / info.total) * 100)
: 0,
file: info.currentFile,
dir: info.dir,
},
});
},
});
@@ -121,8 +138,9 @@ export default function (pi: ExtensionAPI) {
name: "project_map_patch",
label: "Project Map Patch",
description:
"Update .pi-map.md for the directory containing a changed file",
promptSnippet: "Update project analysis after editing a source file",
"Update the paired .pi-map.md / .pi-map.index.md artifacts for the directory containing a changed file",
promptSnippet:
"Update paired project map/index artifacts after editing a source file",
promptGuidelines: [
"Use project_map_patch immediately after editing any source file",
"Pass the absolute or relative path of the modified file",
@@ -158,8 +176,9 @@ export default function (pi: ExtensionAPI) {
pi.registerTool({
name: "project_map_validate",
label: "Project Map Validate",
description: "Check all .pi-map.md files for staleness and discrepancies",
promptSnippet: "Validate project analysis files for accuracy",
description:
"Check all .pi-map.md / .pi-map.index.md files for staleness and discrepancies",
promptSnippet: "Validate paired project map/index artifacts for accuracy",
promptGuidelines: [
"Use project_map_validate before making architectural decisions if you suspect stale data",
"Use project_map_validate to detect files that were deleted or added outside the agent",
@@ -201,8 +220,10 @@ export default function (pi: ExtensionAPI) {
pi.registerTool({
name: "project_map_reinit",
label: "Project Map Reinit",
description: "Force full regeneration of all .pi-map.md files",
promptSnippet: "Force full regeneration of project analysis files",
description:
"Force full regeneration of all .pi-map.md / .pi-map.index.md artifacts",
promptSnippet:
"Force full regeneration of paired project map/index artifacts",
promptGuidelines: [
"Use project_map_reinit when validation shows widespread staleness",
"Use project_map_reinit after pulling major changes from version control",
@@ -223,10 +244,21 @@ export default function (pi: ExtensionAPI) {
llmClient: client,
cacheDir: ctx.cwd,
onProgress: (info) => {
const bar = renderProgressBar(info.completed, info.total, info.currentFile);
const bar = renderProgressBar(
info.completed,
info.total,
info.currentFile,
);
_onUpdate?.({
content: [{ type: "text", text: bar }],
details: { progress: info.total > 0 ? Math.round((info.completed / info.total) * 100) : 0, file: info.currentFile, dir: info.dir },
details: {
progress:
info.total > 0
? Math.round((info.completed / info.total) * 100)
: 0,
file: info.currentFile,
dir: info.dir,
},
});
},
});
@@ -249,6 +281,41 @@ export default function (pi: ExtensionAPI) {
},
});
pi.registerTool({
name: "project_map_context",
label: "Project Map Context",
description:
"Retrieve a compact markdown context bundle for a natural-language query using paired project map/index metadata",
promptSnippet:
"Get relevant project context for a task without reading every source file",
promptGuidelines: [
"Use project_map_context when you need to understand a task area before diving into source",
"Pass a concise query describing the feature, bug, or area you want to explore",
"Always read the suggested indexes first, then maps, then verify from source",
],
parameters: Type.Object({
query: Type.String({
description:
"Natural-language query describing the task or area to explore",
}),
}),
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
try {
const bundle = retrieveContext(params.query, ctx.cwd);
return {
content: [{ type: "text", text: bundle }],
details: { success: true },
};
} catch (err: any) {
const msg = err instanceof LLMError ? err.message : String(err);
return {
content: [{ type: "text", text: `Error: ${msg}` }],
details: { success: false, error: msg },
};
}
},
});
// Auto-load .pi-map.md files on session start
pi.on("session_start", async (_event, ctx) => {
const mapFiles = findPiMapFiles(ctx.cwd);
@@ -280,7 +347,7 @@ export default function (pi: ExtensionAPI) {
message: {
customType: "pi-project-map-hint",
content:
"📋 Project map active: If you modify any source file, run `project_map_patch` with the file path. If you suspect staleness, run `project_map_validate`.",
"📋 Project map active: Start with the root `.pi-map.index.md`, use indexes first for routing, read the local `.pi-map.md` plus source before edits, run `project_map_patch` after source edits, and run `project_map_validate` before freshness-sensitive architectural handoff.",
display: false,
},
};