UNPKG

consortium

Version:

Remote control and session sharing CLI for AI coding agents

87 lines (84 loc) 3.04 kB
import * as fs from 'node:fs/promises'; import * as os from 'node:os'; import * as path from 'node:path'; const EXTENSION_DIRNAME = "consortium-permission"; const FILES_TO_COPY_DEV = ["package.json", "index.ts"]; const FILES_TO_COPY_DIST = ["package.json", "index.js", "index.cjs", "index.mjs"]; async function pathExists(p) { try { await fs.access(p); return true; } catch { return false; } } async function readJson(p) { try { const raw = await fs.readFile(p, "utf8"); return JSON.parse(raw); } catch { return null; } } function compareVersions(a, b) { const pa = a.split(".").map((s) => parseInt(s, 10)); const pb = b.split(".").map((s) => parseInt(s, 10)); const len = Math.max(pa.length, pb.length); for (let i = 0; i < len; i++) { const na = pa[i]; const nb = pb[i]; if (Number.isNaN(na) || Number.isNaN(nb)) return a < b ? -1 : a > b ? 1 : 0; if ((na ?? 0) !== (nb ?? 0)) return (na ?? 0) - (nb ?? 0); } return 0; } async function resolveSourceDir() { const candidates = [ path.resolve(__dirname, "../ext/consortium-permission"), path.resolve(__dirname, "./pi/ext/consortium-permission"), path.resolve(__dirname, "./ext/consortium-permission"), path.resolve(__dirname, "../../pi-ext") ]; for (const dir of candidates) { if (!await pathExists(path.join(dir, "package.json"))) continue; const hasJs = await pathExists(path.join(dir, "index.js")) || await pathExists(path.join(dir, "index.cjs")); return { dir, files: hasJs ? FILES_TO_COPY_DIST : FILES_TO_COPY_DEV }; } return null; } function resolveTargetDir(piConfigDir) { const base = piConfigDir ?? process.env.PI_CODING_AGENT_DIR ?? path.join(os.homedir(), ".pi", "agent"); return path.join(base, "extensions", EXTENSION_DIRNAME); } async function atomicCopy(src, dest) { const tmp = `${dest}.tmp`; await fs.unlink(tmp).catch(() => void 0); await fs.copyFile(src, tmp); await fs.rename(tmp, dest); } async function ensurePiExtensionInstalled(opts = {}) { const targetDir = resolveTargetDir(opts.piConfigDir); if (process.env.CONSORTIUM_PI_NO_EXTENSION === "1") { return { installed: false, targetDir, skipped: "env-disabled" }; } const source = await resolveSourceDir(); if (!source) { return { installed: false, targetDir }; } const shippedPkg = await readJson(path.join(source.dir, "package.json")); const installedPkg = await readJson(path.join(targetDir, "package.json")); if (!opts.force && shippedPkg?.version && installedPkg?.version) { if (compareVersions(installedPkg.version, shippedPkg.version) >= 0) { return { installed: false, targetDir, skipped: "up-to-date" }; } } await fs.mkdir(targetDir, { recursive: true }); for (const file of source.files) { const src = path.join(source.dir, file); if (!await pathExists(src)) continue; const dest = path.join(targetDir, file); await atomicCopy(src, dest); } return { installed: true, targetDir }; } export { ensurePiExtensionInstalled };