UNPKG

@lunora/cli

Version:

The Lunora CLI: init, dev, deploy, codegen, run, reset, and migrate commands

106 lines (103 loc) 4.38 kB
import { existsSync, readFileSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'node:fs'; import { fileURLToPath } from 'node:url'; import { AGENT_RULES_DIR, detectAgentRules, LUNORA_SKILL_NAMES } from '@lunora/config'; import { join, relative, dirname } from '@visulima/path'; import { d as defineHandler } from '../packem_shared/command-lYnl4QyF.mjs'; const resolveBundledSkillsDirectory = (startDirectory = dirname(fileURLToPath(import.meta.url))) => { let directory = startDirectory; for (let index = 0; index < 6; index += 1) { const packageJson = join(directory, "package.json"); if (existsSync(packageJson)) { try { const parsed = JSON.parse(readFileSync(packageJson, "utf8")); if (parsed.name === "@lunora/cli") { const skills = join(directory, "skills"); return existsSync(skills) ? skills : void 0; } } catch { } } const parent = dirname(directory); if (parent === directory) { break; } directory = parent; } return void 0; }; const listBundledSkills = (skillsDirectory) => readdirSync(skillsDirectory).filter((name) => { const directory = join(skillsDirectory, name); return statSync(directory).isDirectory() && existsSync(join(directory, "SKILL.md")); }); const copySkill = (source, destination, overwrite) => { mkdirSync(destination, { recursive: true }); let wrote = false; for (const entry of readdirSync(source)) { const from = join(source, entry); const to = join(destination, entry); if (statSync(from).isDirectory()) { wrote = copySkill(from, to, overwrite) || wrote; continue; } if (existsSync(to) && !overwrite) { continue; } writeFileSync(to, readFileSync(from)); wrote = true; } return wrote; }; const runRulesInstall = (options) => { const cwd = options.cwd ?? process.cwd(); const overwrite = options.overwrite === true; const skillsDirectory = resolveBundledSkillsDirectory(); if (skillsDirectory === void 0) { options.logger.error("rules: could not locate the bundled skills (is @lunora/cli installed correctly?)."); return { code: 1, installed: [], skipped: [] }; } const installed = []; const skipped = []; for (const name of listBundledSkills(skillsDirectory)) { const destination = join(cwd, AGENT_RULES_DIR, name); const wrote = copySkill(join(skillsDirectory, name), destination, overwrite); if (wrote) { installed.push(name); } else { skipped.push(name); } } const target = relative(cwd, join(cwd, AGENT_RULES_DIR)) || AGENT_RULES_DIR; if (installed.length > 0) { options.logger.success(`Installed ${String(installed.length)} Lunora skill(s) into ${target}/: ${installed.join(", ")}.`); } if (skipped.length > 0) { options.logger.info(`Skipped ${String(skipped.length)} existing skill(s) (re-run with --overwrite to replace): ${skipped.join(", ")}.`); } options.logger.info("Your AI coding agent will pick these up automatically. Start with the `lunora` skill."); return { code: 0, installed, skipped }; }; const runRulesCheck = (options) => { const cwd = options.cwd ?? process.cwd(); const status = detectAgentRules(cwd); if (status.installed) { options.logger.success(`Lunora agent rules are installed (${String(status.present.length)}/${String(LUNORA_SKILL_NAMES.length)} skills).`); if (status.missing.length > 0) { options.logger.info(`Missing: ${status.missing.join(", ")}. Run \`lunora rules install\` to add them.`); } return { code: 0, installed: status.present, skipped: [] }; } options.logger.warn("Lunora agent rules are not installed. Run `lunora rules install` so your AI agent knows how to use Lunora."); return { code: options.strict === true ? 1 : 0, installed: status.present, skipped: [] }; }; const execute = defineHandler(({ argument, cwd, logger, options }) => { const subcommand = argument[0] ?? "check"; if (subcommand === "install") { return runRulesInstall({ cwd, logger, overwrite: options.overwrite === true }); } if (subcommand === "check") { return runRulesCheck({ cwd, logger, strict: options.strict === true }); } logger.error("rules: unknown subcommand. Usage: lunora rules <install|check>"); return { code: 1 }; }); export { execute, resolveBundledSkillsDirectory, runRulesCheck, runRulesInstall };