diff --git a/extensions/pi-config/index.ts b/extensions/pi-config/index.ts index 554ce27..85c9b75 100644 --- a/extensions/pi-config/index.ts +++ b/extensions/pi-config/index.ts @@ -308,4 +308,101 @@ export default function (pi: ExtensionAPI) { ctx.ui.notify(output.join("\n"), "info"); }, }); + + // ── /config-setup ─────────────────────────────────────────── + pi.registerCommand("config-setup", { + description: "Set up this folder with .pi, settings.json, and memory vault. Creates what's missing and sets MEMCTX_PACKS_PATH for the current session.", + handler: async (_args, ctx: ExtensionCommandContext) => { + const cwd = ctx.cwd; + const piDir = path.join(cwd, ".pi"); + const settingsPath = path.join(piDir, "settings.json"); + const memoryPacksDir = path.join(piDir, "memory-vault", "packs"); + + const created: string[] = []; + const existed: string[] = []; + + // 1. .pi/ + if (!fs.existsSync(piDir)) { + fs.mkdirSync(piDir, { recursive: true }); + created.push(".pi/"); + } else { + existed.push(".pi/"); + } + + // 2. settings.json — load or create, ensure ~/.agents package + let settings: PiSettings; + if (fs.existsSync(settingsPath)) { + try { + settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8")); + } catch { + settings = {}; + } + existed.push(".pi/settings.json"); + } else { + settings = {}; + created.push(".pi/settings.json"); + } + ensureAgentsPackage(settings); + saveSettings(cwd, settings); + + // 3. memory-vault/packs/ + if (!fs.existsSync(memoryPacksDir)) { + fs.mkdirSync(memoryPacksDir, { recursive: true }); + created.push(".pi/memory-vault/packs/"); + } else { + existed.push(".pi/memory-vault/packs/"); + } + + // 4. Seed a minimal pack so pi-memctx finds this vault (needs at least one pack to exist) + const slug = path.basename(cwd).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || "workspace"; + const seedPackDir = path.join(memoryPacksDir, slug, "00-system", "pi-agent"); + if (!fs.existsSync(seedPackDir)) { + fs.mkdirSync(seedPackDir, { recursive: true }); + const today = new Date().toISOString().slice(0, 10); + const title = slug.replace(/-/g, " ").replace(/\b\w/g, (c: string) => c.toUpperCase()); + const manifest = `--- +type: system +id: system.${slug}.memory-manifest +title: ${title} Memory Manifest +status: active +source_of_truth: true +freshness: current +last_reviewed: ${today} +tags: + - agent-memory/system + - pack/${slug} +--- + +# ${title} Memory Manifest + +This pack stores safe durable context generated from \`${cwd}\`. + +## Retrieval Protocol + +See [[packs/${slug}/00-system/pi-agent/retrieval-protocol|Retrieval Protocol]] and [[packs/${slug}/00-system/pi-agent/resource-map|Resource Map]]. +`; + fs.writeFileSync(path.join(seedPackDir, "memory-manifest.md"), manifest); + created.push(".pi/memory-vault/packs/" + slug + "/"); + } + + // 5. Set env var so pi-memctx uses this local vault for the session + process.env.MEMCTX_PACKS_PATH = memoryPacksDir; + + const lines = [ + created.length > 0 + ? `\u2713 Created: ${created.join(", ")}` + : "", + existed.length > 0 + ? ` Already existed: ${existed.join(", ")}` + : "", + "", + `MEMCTX_PACKS_PATH set to:`, + ` ${memoryPacksDir}`, + "", + created.length > 0 ? "Next: run /memctx-init in this folder to create the memory pack." : "", + ].filter(Boolean).join("\n"); + + ctx.ui.notify(lines, "success"); + }, + }); }