From d948d88d0aeb5fe374da99145fa8be540c5ca2e5 Mon Sep 17 00:00:00 2001 From: Alex Blank Date: Wed, 10 Jun 2026 16:32:08 +0200 Subject: [PATCH] feat: add live progress streaming to init/reinit tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - InitOptions.onProgress callback for directory-level progress - generateDirectoryMap reports per-file progress (→ filename) - initProject reports [N/M] Analyzing (X files)... - pi-extension wires _onUpdate to onProgress for live Pi UI updates - User sees real-time feedback instead of silent long waits --- pi-extension.ts | 14 ++++++++++++-- src/init.ts | 11 +++++++++-- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/pi-extension.ts b/pi-extension.ts index 5383734..dbf4ecf 100644 --- a/pi-extension.ts +++ b/pi-extension.ts @@ -78,7 +78,12 @@ export default function (pi: ExtensionAPI) { try { const targetPath = params.path || ctx.cwd; const client = getPiLLMClient(ctx); - await initProject(targetPath, { verbose: false, llmClient: client, cacheDir: ctx.cwd }); + await initProject(targetPath, { + verbose: false, + llmClient: client, + cacheDir: ctx.cwd, + onProgress: (msg) => _onUpdate?.({ content: [{ type: "text", text: msg }] }), + }); return { content: [ { @@ -199,7 +204,12 @@ export default function (pi: ExtensionAPI) { try { const targetPath = params.path || ctx.cwd; const client = getPiLLMClient(ctx); - await reinitPath(targetPath, { verbose: false, llmClient: client, cacheDir: ctx.cwd }); + await reinitPath(targetPath, { + verbose: false, + llmClient: client, + cacheDir: ctx.cwd, + onProgress: (msg) => _onUpdate?.({ content: [{ type: "text", text: msg }] }), + }); return { content: [ { diff --git a/src/init.ts b/src/init.ts index a3f1f89..8eff58d 100644 --- a/src/init.ts +++ b/src/init.ts @@ -16,6 +16,7 @@ export interface InitOptions { verbose?: boolean; llmClient?: LLMClient; cacheDir?: string; + onProgress?: (message: string) => void; } export async function initProject( @@ -23,11 +24,15 @@ export async function initProject( options: InitOptions = {}, ): Promise { const entries = discoverProject(rootPath); + options.onProgress?.(`Scanning ${entries.length} directories...`); - for (const entry of entries) { - await generateDirectoryMap(entry, options.llmClient, options.cacheDir); + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + options.onProgress?.(`[${i + 1}/${entries.length}] Analyzing ${entry.relativePath} (${entry.files.length} files)...`); + await generateDirectoryMap(entry, options.llmClient, options.cacheDir, options.onProgress); } + options.onProgress?.(`Generated ${entries.length} .pi-map.md files`); if (options.verbose !== false) { console.log(`Generated ${entries.length} .pi-map.md files`); } @@ -37,12 +42,14 @@ export async function generateDirectoryMap( entry: DirectoryEntry, llmClient?: LLMClient, cacheDir?: string, + onProgress?: (message: string) => void, ): Promise { // Process files in parallel (4 concurrent) with retry logic const fileData = await processFiles( entry.files, async (file) => { const filePath = join(entry.dirPath, file); + onProgress?.(` → ${file}`); const llmData = await extractFileLLM(filePath, llmClient, cacheDir); const astData = await extractFileAST(filePath); return mergeFileData(file, llmData, astData);