style(installer): adopt colored tabbed step output format

This commit is contained in:
2026-03-08 06:45:32 +00:00
parent 4d50826f2a
commit a2781139b0

View File

@@ -25,20 +25,32 @@ for (let i = 2; i < process.argv.length; i++) {
}
if (!modeArg) {
console.error("Usage: node scripts/install.mjs --install|--uninstall|--update [--openclaw-profile-path <path>] [--no-reply-port <port>]");
fail("Usage: node scripts/install.mjs --install|--uninstall|--update [--openclaw-profile-path <path>] [--no-reply-port <port>]");
process.exit(2);
}
if (!Number.isFinite(argNoReplyPort) || argNoReplyPort < 1 || argNoReplyPort > 65535) {
console.error("[dirigent] invalid --no-reply-port (1-65535)");
fail("invalid --no-reply-port (1-65535)");
process.exit(2);
}
const mode = modeArg.slice(2);
function step(msg) { console.log(`${msg}`); }
function ok(msg) { console.log(`${msg}`); }
function warn(msg) { console.log(`! ${msg}`); }
const C = {
reset: "\x1b[0m",
red: "\x1b[31m",
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
cyan: "\x1b[36m",
};
function color(t, c = "reset") { return `${C[c] || ""}${t}${C.reset}`; }
function title(t) { console.log(color(`\n[dirigent] ${t}`, "cyan")); }
function step(n, total, msg) { console.log(color(`[${n}/${total}] ${msg}`, "blue")); }
function ok(msg) { console.log(color(`\t${msg}`, "green")); }
function warn(msg) { console.log(color(`\t${msg}`, "yellow")); }
function fail(msg) { console.log(color(`\t${msg}`, "red")); }
function resolveOpenClawDir() {
if (argOpenClawDir) {
@@ -59,7 +71,7 @@ function resolveOpenClawDir() {
const OPENCLAW_DIR = resolveOpenClawDir();
const OPENCLAW_CONFIG_PATH = process.env.OPENCLAW_CONFIG_PATH || path.join(OPENCLAW_DIR, "openclaw.json");
if (!fs.existsSync(OPENCLAW_CONFIG_PATH)) {
console.error(`[dirigent] config not found: ${OPENCLAW_CONFIG_PATH}`);
fail(`config not found: ${OPENCLAW_CONFIG_PATH}`);
process.exit(1);
}
@@ -116,13 +128,15 @@ function isRegistered() {
}
if (mode === "update") {
title("Update");
const branch = process.env.DIRIGENT_GIT_BRANCH || "latest";
step(`update source branch=${branch}`);
step(1, 2, `update source branch=${branch}`);
execFileSync("git", ["fetch", "origin", branch], { cwd: REPO_ROOT, stdio: "inherit" });
execFileSync("git", ["checkout", branch], { cwd: REPO_ROOT, stdio: "inherit" });
execFileSync("git", ["pull", "origin", branch], { cwd: REPO_ROOT, stdio: "inherit" });
ok("source updated");
step(2, 2, "run install after update");
const script = path.join(REPO_ROOT, "scripts", "install.mjs");
const args = [script, "--install", "--openclaw-profile-path", OPENCLAW_DIR, "--no-reply-port", String(NO_REPLY_PORT)];
const ret = spawnSync(process.execPath, args, { cwd: REPO_ROOT, stdio: "inherit", env: process.env });
@@ -130,13 +144,14 @@ if (mode === "update") {
}
if (mode === "install") {
step(`OpenClaw dir: ${OPENCLAW_DIR}`);
title("Install");
step(1, 6, `environment: ${OPENCLAW_DIR}`);
if (isRegistered()) {
warn("plugins.entries.dirigent exists; reinstalling in-place");
}
step("build dist assets");
step(2, 6, "build dist assets");
const pluginSrc = path.resolve(REPO_ROOT, "plugin");
const noReplySrc = path.resolve(REPO_ROOT, "no-reply-api");
const distPlugin = path.resolve(REPO_ROOT, "dist", "dirigent");
@@ -144,7 +159,7 @@ if (mode === "install") {
syncDirRecursive(pluginSrc, distPlugin);
syncDirRecursive(noReplySrc, distNoReply);
step(`install plugin -> ${PLUGIN_INSTALL_DIR}`);
step(3, 6, `install files -> ${PLUGIN_INSTALL_DIR}`);
fs.mkdirSync(PLUGINS_DIR, { recursive: true });
syncDirRecursive(distPlugin, PLUGIN_INSTALL_DIR);
syncDirRecursive(distNoReply, NO_REPLY_INSTALL_DIR);
@@ -155,6 +170,7 @@ if (mode === "install") {
ok(`init channel policies file: ${CHANNEL_POLICIES_FILE}`);
}
step(4, 6, "configure plugin entry/path");
const plugins = getJson("plugins") || {};
const loadPaths = Array.isArray(plugins?.load?.paths) ? plugins.load.paths : [];
if (!loadPaths.includes(PLUGIN_INSTALL_DIR)) loadPaths.push(PLUGIN_INSTALL_DIR);
@@ -180,6 +196,7 @@ if (mode === "install") {
};
setJson("plugins", plugins);
step(5, 6, "configure no-reply provider");
const providers = getJson("models.providers") || {};
providers[NO_REPLY_PROVIDER_ID] = {
baseUrl: NO_REPLY_BASE_URL,
@@ -199,6 +216,7 @@ if (mode === "install") {
};
setJson("models.providers", providers);
step(6, 6, "enable plugin in allowlist");
const allow = getJson("plugins.allow") || [];
if (!allow.includes("dirigent")) {
allow.push("dirigent");
@@ -211,8 +229,10 @@ if (mode === "install") {
}
if (mode === "uninstall") {
step(`OpenClaw dir: ${OPENCLAW_DIR}`);
title("Uninstall");
step(1, 5, `environment: ${OPENCLAW_DIR}`);
step(2, 5, "remove allowlist + plugin entry");
const allow = getJson("plugins.allow") || [];
const idx = allow.indexOf("dirigent");
if (idx >= 0) {
@@ -224,6 +244,7 @@ if (mode === "uninstall") {
unsetPath("plugins.entries.dirigent");
ok("removed plugins.entries.dirigent");
step(3, 5, "remove plugin load path");
const plugins = getJson("plugins") || {};
const paths = Array.isArray(plugins?.load?.paths) ? plugins.load.paths : [];
plugins.load = plugins.load || {};
@@ -231,11 +252,13 @@ if (mode === "uninstall") {
setJson("plugins", plugins);
ok("removed plugin path from plugins.load.paths");
step(4, 5, "remove no-reply provider");
const providers = getJson("models.providers") || {};
delete providers[NO_REPLY_PROVIDER_ID];
setJson("models.providers", providers);
ok(`removed provider ${NO_REPLY_PROVIDER_ID}`);
step(5, 5, "remove installed files");
if (fs.existsSync(PLUGIN_INSTALL_DIR)) fs.rmSync(PLUGIN_INSTALL_DIR, { recursive: true, force: true });
if (fs.existsSync(NO_REPLY_INSTALL_DIR)) fs.rmSync(NO_REPLY_INSTALL_DIR, { recursive: true, force: true });
const legacyNoReply = path.join(PLUGINS_DIR, "dirigent-no-reply-api");