import { spawn } from "node:child_process"; import { DefaultPackageManager, getAgentDir, SettingsManager } from "@mariozechner/pi-coding-agent"; function createPackageManager(cwd: string, signal?: AbortSignal): any { const settingsManager = SettingsManager.create(cwd, getAgentDir()); const packageManager: any = new DefaultPackageManager({ cwd, agentDir: getAgentDir(), settingsManager }); packageManager.runCommand = async (command: string, args: string[], options?: { cwd?: string }) => { throwIfAborted(signal); await new Promise((resolve, reject) => { const child = spawn(command, args, { cwd: options?.cwd, stdio: "ignore", shell: process.platform === "win32", }); let settled = false; const finish = (fn: () => void) => { if (settled) return; settled = true; signal?.removeEventListener("abort", onAbort); fn(); }; const onAbort = () => { child.kill(); finish(() => reject(new Error("Update cancelled."))); }; signal?.addEventListener("abort", onAbort, { once: true }); child.on("error", (error) => finish(() => reject(error))); child.on("exit", (code) => { if (signal?.aborted) { finish(() => reject(new Error("Update cancelled."))); return; } if (code === 0) { finish(() => resolve()); return; } finish(() => reject(new Error(`${command} ${args.join(" ")} failed with code ${code}`))); }); }); throwIfAborted(signal); }; return packageManager; } function throwIfAborted(signal?: AbortSignal): void { if (signal?.aborted) { throw new Error("Update cancelled."); } } export async function updatePackageSource(cwd: string, source: string, onProgress?: (message: string) => void, signal?: AbortSignal): Promise { const packageManager = createPackageManager(cwd, signal); packageManager.setProgressCallback((event: { message?: string; action: string; source: string }) => { throwIfAborted(signal); onProgress?.(event.message ? `${event.action}: ${event.message}` : `${event.action}: ${event.source}`); }); throwIfAborted(signal); await packageManager.update(source); throwIfAborted(signal); } export async function updateAllPackageSources(cwd: string, onProgress?: (message: string) => void, signal?: AbortSignal): Promise { const packageManager = createPackageManager(cwd, signal); packageManager.setProgressCallback((event: { message?: string; action: string; source: string }) => { throwIfAborted(signal); onProgress?.(event.message ? `${event.action}: ${event.message}` : `${event.action}: ${event.source}`); }); throwIfAborted(signal); await packageManager.update(); throwIfAborted(signal); }