feat: add progress bar to init/reinit with per-file tracking

- processFiles() now accepts onProgress callback (completed, total, currentFile)
- InitOptions.onProgress receives structured ProgressInfo object
- initProject aggregates progress across all directories
- CLI renders ASCII progress bar: [████░░░░░░] 3/20 | filename.ts
- Pi extension sends structured updates with percentage + file details
- All 52 tests passing
This commit is contained in:
2026-06-10 18:43:42 +02:00
parent 78c60f9ca1
commit 9bdb862cca
5 changed files with 655 additions and 568 deletions
+32 -2
View File
@@ -63,6 +63,14 @@ function formatCount(count: number, label: string): string {
return `${pc.bold(String(count))} ${count === 1 ? label : plural}`;
}
function renderProgressBar(completed: number, total: number, currentFile?: string, width = 30): string {
const pct = total > 0 ? completed / total : 0;
const filled = Math.round(width * pct);
const bar = "█".repeat(filled) + "░".repeat(width - filled);
const file = currentFile ? ` | ${pc.dim(currentFile)}` : "";
return `[${pc.cyan(bar)}] ${completed}/${total}${file}`;
}
function parseArgs(args: string[]): {
path: string;
fix: boolean;
@@ -128,7 +136,18 @@ async function main() {
const entries = discoverProject(targetPath);
console.log(`Scanning ${formatCount(entries.length, "directory")}...`);
const client = createClientFromArgs(parsed);
await initProject(targetPath, { verbose: false, llmClient: client, cacheDir: targetPath });
let lastLine = "";
await initProject(targetPath, {
verbose: false,
llmClient: client,
cacheDir: targetPath,
onProgress: (info) => {
const line = renderProgressBar(info.completed, info.total, info.currentFile);
process.stdout.write("\r" + line.padEnd(lastLine.length));
lastLine = line;
},
});
process.stdout.write("\n");
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
console.log(
`${pc.green("✓")} Generated ${formatCount(entries.length, ".pi-map.md file")} in ${elapsed}s`,
@@ -179,7 +198,18 @@ async function main() {
`Regenerating ${formatCount(entries.length, ".pi-map.md file")}...`,
);
const client = createClientFromArgs(parsed);
await reinitPath(targetPath, { verbose: false, llmClient: client, cacheDir: targetPath });
let lastLine = "";
await reinitPath(targetPath, {
verbose: false,
llmClient: client,
cacheDir: targetPath,
onProgress: (info) => {
const line = renderProgressBar(info.completed, info.total, info.currentFile);
process.stdout.write("\r" + line.padEnd(lastLine.length));
lastLine = line;
},
});
process.stdout.write("\n");
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
console.log(`${pc.green("✓")} Regenerated in ${elapsed}s`);
break;