UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

92 lines (91 loc) • 3.23 kB
/** * Shared constants and utilities for init modules. * Kept separate to avoid circular dependencies between init-config and init-setup. */ import * as fs from "fs"; import * as path from "path"; import { execFileSync } from "child_process"; import { homePath, EXEC_TIMEOUT_QUICK_MS, debugLog } from "../shared.js"; import { errorMessage } from "../utils.js"; import { nonInteractiveGitEnv } from "../utils-helpers.js"; import { ROOT as PACKAGE_ROOT, VERSION } from "../package-metadata.js"; export const ROOT = PACKAGE_ROOT; export { VERSION }; export const STARTER_DIR = path.join(ROOT, "starter"); export const DEFAULT_PHREN_PATH = homePath(".phren"); export function resolveEntryScript() { return path.join(ROOT, "dist", "index.js"); } export function log(msg) { process.stdout.write(msg + "\n"); } export function commandVersion(cmd, args = ["--version"]) { const effectiveCmd = process.platform === "win32" && (cmd === "npm" || cmd === "npx") ? `${cmd}.cmd` : cmd; try { return execFileSync(effectiveCmd, args, { env: cmd === "git" ? nonInteractiveGitEnv() : process.env, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], shell: process.platform === "win32" && effectiveCmd.endsWith(".cmd"), timeout: EXEC_TIMEOUT_QUICK_MS, }).trim(); } catch (err) { debugLog(`commandVersion ${effectiveCmd} failed: ${errorMessage(err)}`); return null; } } function parseSemverTriple(raw) { const match = raw.match(/(\d+)\.(\d+)\.(\d+)/); if (!match) return null; return [Number.parseInt(match[1], 10), Number.parseInt(match[2], 10), Number.parseInt(match[3], 10)]; } export function versionAtLeast(raw, major, minor = 0) { if (!raw) return false; const parsed = parseSemverTriple(raw); if (!parsed) return false; const [m, n] = parsed; if (m !== major) return m > major; return n >= minor; } export function nearestWritableTarget(filePath) { let probe = fs.existsSync(filePath) ? filePath : path.dirname(filePath); while (!fs.existsSync(probe)) { const parent = path.dirname(probe); if (parent === probe) return false; probe = parent; } try { fs.accessSync(probe, fs.constants.W_OK); return true; } catch (err) { debugLog(`nearestWritableTarget failed for ${filePath}: ${errorMessage(err)}`); return false; } } export function parseMcpMode(raw) { if (!raw) return undefined; const normalized = raw.trim().toLowerCase(); if (normalized === "on" || normalized === "off") return normalized; return undefined; } export async function confirmPrompt(message) { if (process.env.CI === "true" || !process.stdin.isTTY) return true; const readline = await import("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); return new Promise((resolve) => { rl.question(`${message} [y/N] `, (answer) => { rl.close(); resolve(answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes"); }); }); }