openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
94 lines (93 loc) • 3.98 kB
JavaScript
import { i as isUsableNode, o as resolveRecoveryPath } from "./node-runtime-recovery-DWYeVfMO.mjs";
import { fileURLToPath } from "node:url";
import path from "node:path";
import { spawnSync } from "node:child_process";
import { createInterface } from "node:readline";
//#region node-runtime-update.mjs
function canInstallPrivateNode() {
if (!["x64", "arm64"].includes(process.arch)) return false;
if (process.platform === "linux") return Boolean(process.report?.getReport().header.glibcVersionRuntime);
return process.platform === "darwin" || process.platform === "win32";
}
function confirmNodeUpdate() {
return new Promise((resolve) => {
const prompt = createInterface({
input: process.stdin,
output: process.stderr
});
let settled = false;
const finish = (answer) => {
if (settled) return;
settled = true;
prompt.close();
resolve(/^(y|yes)$/i.test(answer.trim()));
};
prompt.once("close", () => finish(""));
prompt.once("SIGINT", () => finish(""));
prompt.question("Update NodeJS: Y/N [N]: ", finish);
});
}
/** Returns a verified private runtime, or null when recovery was declined/unavailable. */
async function resolveUpdatedNodeRuntime(recoveryRoot, { allowInstall = true, env = process.env, acceptVersion, nodeVersion, installCommand } = {}) {
if (env.OPENCLAW_NODE_UPDATE_RESPAWNED === "1" && !installCommand) return null;
const privatePaths = {
allowMissing: true,
trustedRoot: recoveryRoot
};
const prefix = resolveRecoveryPath(path.join(recoveryRoot, "tools", "cli-node"), void 0, privatePaths);
const nodeRoot = prefix && resolveRecoveryPath(path.join(prefix, "tools", "node"), void 0, privatePaths);
if (!prefix || !nodeRoot) return null;
const nodePath = process.platform === "win32" ? path.join(nodeRoot, "node.exe") : path.join(nodeRoot, "bin", "node");
if (isUsableNode(nodePath, {
env,
trustedRoot: recoveryRoot,
acceptVersion
})) return nodePath;
if (!allowInstall || !installCommand && (!process.stdin.isTTY || !process.stderr.isTTY || env.CI || process.argv.some((arg) => [
"--non-interactive",
"--json",
"--yes"
].includes(arg))) || installCommand && !/^\d+\.\d+\.\d+$/.test(nodeVersion ?? "") || !canInstallPrivateNode()) return null;
if (!installCommand) {
process.stderr.write("Install a compatible Node.js for OpenClaw only and retry this command.\nThe Node.js installation will not change system Node.js, shell settings, or Gateway services.\n");
if (!await confirmNodeUpdate()) return null;
}
const windows = process.platform === "win32";
const installer = fileURLToPath(new URL(windows ? "./scripts/install.ps1" : "./scripts/install-cli.sh", import.meta.url));
const command = windows ? (await import("./windows-cmd-helpers-C7js546a.mjs")).resolveWindowsPowerShellPath(env) : process.platform === "darwin" ? "/bin/bash" : "bash";
const args = windows ? [
"-NoProfile",
"-NonInteractive",
"-ExecutionPolicy",
"Bypass",
"-File",
installer,
"-NodeOnly",
"-NodePrefix",
nodeRoot,
...nodeVersion ? ["-NodeVersion", nodeVersion] : []
] : [
installer,
"--node-only",
"--prefix",
prefix,
...nodeVersion ? ["--node-version", nodeVersion] : []
];
const installedRoot = (installCommand ? await installCommand(command, args, env) : spawnSync(command, args, {
stdio: "inherit",
env
}).status) === 0 ? resolveRecoveryPath(path.join(prefix, "tools", "node"), void 0, { trustedRoot: recoveryRoot }) : null;
const installedPath = installedRoot && path.join(installedRoot, ...windows ? ["node.exe"] : ["bin", "node"]);
if (!installedPath || !isUsableNode(installedPath, {
env,
trustedRoot: recoveryRoot,
acceptVersion
})) {
if (!installCommand) process.stderr.write("openclaw: Node.js update failed; install a compatible Node.js manually.\n");
return null;
}
if (!installCommand) process.stderr.write("openclaw: Node.js updated. Retrying your command.\n");
return installedPath;
}
//#endregion
export { resolveUpdatedNodeRuntime };