import { basename, dirname, join, relative } from "node:path"; import { getAgentDir, SettingsManager, type PackageSource } from "@mariozechner/pi-coding-agent"; import type { ExtensionEntry } from "./types.js"; function updatePatterns(current: string[], pattern: string, enabled: boolean): string[] { const updated = current.filter((entry) => { const stripped = entry.startsWith("!") || entry.startsWith("+") || entry.startsWith("-") ? entry.slice(1) : entry; return stripped !== pattern; }); updated.push(`${enabled ? "+" : "-"}${pattern}`); return updated; } function getTopLevelPattern(extension: ExtensionEntry, cwd: string): string { const baseDir = extension.scope === "project" ? join(cwd, ".pi") : getAgentDir(); return relative(baseDir, extension.path); } function getPackagePattern(extension: ExtensionEntry): string { const baseDir = extension.baseDir ?? dirname(extension.path); return relative(baseDir, extension.path); } function hasPackageFilters(pkg: Exclude): boolean { return pkg.extensions !== undefined || pkg.skills !== undefined || pkg.prompts !== undefined || pkg.themes !== undefined; } export async function setExtensionEnabled(cwd: string, extension: ExtensionEntry, enabled: boolean): Promise { if (extension.scope === "temporary") { throw new Error("Temporary extensions cannot be toggled."); } const settingsManager = SettingsManager.create(cwd, getAgentDir()); if (extension.origin === "top-level") { const settings = extension.scope === "project" ? settingsManager.getProjectSettings() : settingsManager.getGlobalSettings(); const current = [...(settings.extensions ?? [])]; const updated = updatePatterns(current, getTopLevelPattern(extension, cwd), enabled); if (extension.scope === "project") settingsManager.setProjectExtensionPaths(updated); else settingsManager.setExtensionPaths(updated); await settingsManager.flush(); return; } const settings = extension.scope === "project" ? settingsManager.getProjectSettings() : settingsManager.getGlobalSettings(); const packages = [...(settings.packages ?? [])]; const packageIndex = packages.findIndex((pkg) => (typeof pkg === "string" ? pkg : pkg.source) === extension.source); if (packageIndex === -1) throw new Error("Could not find the package settings entry for this extension."); const packageEntry = packages[packageIndex]; const packageConfig = typeof packageEntry === "string" ? { source: packageEntry } : { ...packageEntry }; const current = [...(packageConfig.extensions ?? [])]; const updated = updatePatterns(current, getPackagePattern(extension), enabled); packageConfig.extensions = updated.length > 0 ? updated : undefined; packages[packageIndex] = hasPackageFilters(packageConfig) ? packageConfig : packageConfig.source; if (extension.scope === "project") settingsManager.setProjectPackages(packages); else settingsManager.setPackages(packages); await settingsManager.flush(); } export function getExtensionNameFromPath(path: string): string { const filename = basename(path); if (filename === "index.ts" || filename === "index.js") { return basename(dirname(path)); } return filename.replace(/\.[^.]+$/, ""); }