@robbiesrobotics/alice-agents 1.3.3 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/alice-install.mjs +7 -0
- package/lib/colors.mjs +102 -0
- package/lib/config-merger.mjs +56 -3
- package/lib/doctor.mjs +61 -16
- package/lib/installer.mjs +356 -95
- package/lib/skills.mjs +310 -0
- package/package.json +3 -3
- package/tools/compatibility-checker.mjs +27 -0
package/lib/installer.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { readFileSync, existsSync } from 'node:fs';
|
|
|
2
2
|
import { join, dirname } from 'node:path';
|
|
3
3
|
import { fileURLToPath } from 'node:url';
|
|
4
4
|
import { execSync } from 'node:child_process';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
5
6
|
import { configExists, mergeConfig, removeAliceAgents, detectAvailableModels } from './config-merger.mjs';
|
|
6
7
|
import { scaffoldAll } from './workspace-scaffolder.mjs';
|
|
7
8
|
import { readManifest, writeManifest } from './manifest.mjs';
|
|
@@ -19,16 +20,25 @@ import {
|
|
|
19
20
|
detectUserName,
|
|
20
21
|
detectTimezone,
|
|
21
22
|
} from './prompter.mjs';
|
|
23
|
+
import { c, bold, dim, green, greenBold, red, yellow, cyan, gray,
|
|
24
|
+
icons, separator, printSection, printSeparator, printBox,
|
|
25
|
+
printStepDone, printStepFail, printStepSkip } from './colors.mjs';
|
|
26
|
+
import { runSkillsWizardStep } from './skills.mjs';
|
|
22
27
|
|
|
23
|
-
function
|
|
28
|
+
function commandExists(cmd) {
|
|
29
|
+
const probe = process.platform === 'win32' ? 'where' : 'which';
|
|
24
30
|
try {
|
|
25
|
-
execSync(
|
|
31
|
+
execSync(`${probe} ${cmd}`, { stdio: 'pipe' });
|
|
26
32
|
return true;
|
|
27
33
|
} catch {
|
|
28
34
|
return false;
|
|
29
35
|
}
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
function isOpenClawInstalled() {
|
|
39
|
+
return commandExists('openclaw');
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
/**
|
|
33
43
|
* On Linux, Docker requires the user to be in the docker group.
|
|
34
44
|
* Detect this early and warn before OpenClaw's own preflight fails cryptically.
|
|
@@ -36,9 +46,7 @@ function isOpenClawInstalled() {
|
|
|
36
46
|
function checkLinuxDockerPermissions() {
|
|
37
47
|
if (process.platform !== 'linux') return;
|
|
38
48
|
|
|
39
|
-
|
|
40
|
-
execSync('which docker', { stdio: 'pipe' });
|
|
41
|
-
} catch {
|
|
49
|
+
if (!commandExists('docker')) {
|
|
42
50
|
return; // Docker not installed — not our problem
|
|
43
51
|
}
|
|
44
52
|
|
|
@@ -54,7 +62,7 @@ function checkLinuxDockerPermissions() {
|
|
|
54
62
|
msg.includes('connect: permission denied');
|
|
55
63
|
|
|
56
64
|
if (isPermissionIssue) {
|
|
57
|
-
console.log('
|
|
65
|
+
console.log(` ${icons.warn} ${yellow('Docker permission issue detected.')}\n`);
|
|
58
66
|
console.log(' Your user is not in the docker group. This will cause');
|
|
59
67
|
console.log(' OpenClaw to fail when it tries to access Docker.\n');
|
|
60
68
|
console.log(' Fix this now (recommended):');
|
|
@@ -75,7 +83,7 @@ async function detectRuntime() {
|
|
|
75
83
|
} catch {}
|
|
76
84
|
|
|
77
85
|
// Check for NemoClaw directory
|
|
78
|
-
const nemoclawDir = join(
|
|
86
|
+
const nemoclawDir = join(homedir(), '.nemoclaw');
|
|
79
87
|
if (existsSync(nemoclawDir)) return 'nemoclaw';
|
|
80
88
|
|
|
81
89
|
// Fall back to OpenClaw
|
|
@@ -105,16 +113,17 @@ async function checkForOpenClawUpdate(auto) {
|
|
|
105
113
|
const current = getOpenClawVersion();
|
|
106
114
|
if (!current) return;
|
|
107
115
|
|
|
108
|
-
console.log(` OpenClaw version: ${current}`);
|
|
116
|
+
console.log(` ${dim('OpenClaw version:')} ${green(current)}`);
|
|
109
117
|
|
|
110
118
|
const latest = getLatestNpmVersion();
|
|
111
119
|
if (!latest) {
|
|
112
|
-
console.log('
|
|
120
|
+
console.log(` ${icons.warn} ${yellow('Could not check for updates (npm registry unreachable)')}\n`);
|
|
113
121
|
return;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
if (current === latest) {
|
|
117
|
-
|
|
125
|
+
printStepDone('OpenClaw is up to date', latest);
|
|
126
|
+
console.log('');
|
|
118
127
|
return;
|
|
119
128
|
}
|
|
120
129
|
|
|
@@ -126,13 +135,15 @@ async function checkForOpenClawUpdate(auto) {
|
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
if (shouldUpdate) {
|
|
129
|
-
console.log(
|
|
138
|
+
console.log(` ${icons.pkg} ${bold('Updating OpenClaw...')}\n`);
|
|
130
139
|
try {
|
|
131
140
|
execSync('npm install -g openclaw@latest', { stdio: 'inherit' });
|
|
132
141
|
const updated = getOpenClawVersion();
|
|
133
|
-
console.log(
|
|
142
|
+
console.log('');
|
|
143
|
+
printStepDone('OpenClaw updated', updated || latest);
|
|
144
|
+
console.log('');
|
|
134
145
|
} catch {
|
|
135
|
-
console.log(
|
|
146
|
+
console.log(`\n ${icons.warn} ${yellow('Update failed — continuing with current version')}\n`);
|
|
136
147
|
}
|
|
137
148
|
} else {
|
|
138
149
|
console.log();
|
|
@@ -140,51 +151,267 @@ async function checkForOpenClawUpdate(auto) {
|
|
|
140
151
|
}
|
|
141
152
|
|
|
142
153
|
async function installRuntime(auto) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
console.log(
|
|
154
|
+
const plat = process.platform;
|
|
155
|
+
const isWSL = !!process.env.WSL_DISTRO_NAME || !!process.env.WSLENV;
|
|
156
|
+
|
|
157
|
+
console.log(` ${icons.warn} ${yellow('No agent runtime detected.')}\n`);
|
|
158
|
+
|
|
159
|
+
// Windows (native, not WSL)
|
|
160
|
+
if (plat === "win32") {
|
|
161
|
+
console.log(" A.L.I.C.E. requires OpenClaw or NemoClaw to run.\n");
|
|
162
|
+
console.log(" NemoClaw (the recommended runtime with enterprise sandbox) requires");
|
|
163
|
+
console.log(" Linux — but you can get it on Windows via WSL2 (Windows Subsystem for Linux).\n");
|
|
164
|
+
|
|
165
|
+
const wslAvailable = commandExists("wsl");
|
|
166
|
+
|
|
167
|
+
if (wslAvailable) {
|
|
168
|
+
let wslDistros = "";
|
|
169
|
+
try {
|
|
170
|
+
// WSL --list output on Windows can be UTF-16LE encoded — decode from Buffer
|
|
171
|
+
const raw = execSync("wsl --list --quiet", { stdio: "pipe" });
|
|
172
|
+
wslDistros = raw.toString("utf16le").replace(/\0/g, "").trim();
|
|
173
|
+
} catch {}
|
|
174
|
+
|
|
175
|
+
const hasDistro = wslDistros.length > 0 &&
|
|
176
|
+
!wslDistros.toLowerCase().includes("no installed") &&
|
|
177
|
+
!wslDistros.toLowerCase().includes("has no");
|
|
178
|
+
|
|
179
|
+
if (hasDistro) {
|
|
180
|
+
console.log(" ✔ WSL2 detected with an installed distro.\n");
|
|
181
|
+
console.log(" Recommended: Install NemoClaw inside WSL2 for full sandbox support.\n");
|
|
182
|
+
|
|
183
|
+
let choice;
|
|
184
|
+
if (auto) {
|
|
185
|
+
choice = "wsl-nemoclaw";
|
|
186
|
+
} else {
|
|
187
|
+
choice = await choose(" How would you like to proceed?", [
|
|
188
|
+
{ label: "Install NemoClaw inside WSL2 (Recommended)", value: "wsl-nemoclaw" },
|
|
189
|
+
{ label: "Install OpenClaw for Windows (no sandbox)", value: "openclaw-win" },
|
|
190
|
+
]);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (choice === "wsl-nemoclaw") {
|
|
194
|
+
console.log("\n 📦 Installing NemoClaw inside WSL2...\n");
|
|
195
|
+
console.log(" This will run the NemoClaw installer in your default WSL2 distro.\n");
|
|
196
|
+
try {
|
|
197
|
+
execSync(
|
|
198
|
+
"wsl bash -c \"curl -fsSL https://nvidia.com/nemoclaw.sh | bash\"",
|
|
199
|
+
{ stdio: "inherit" }
|
|
200
|
+
);
|
|
201
|
+
console.log("\n ✔ NemoClaw installed in WSL2.\n");
|
|
202
|
+
console.log(" ℹ️ Note: On Ubuntu 24.04 / WSL2, Docker may need a cgroup fix.");
|
|
203
|
+
console.log(" If onboard fails, run inside WSL2: nemoclaw setup-spark\n");
|
|
204
|
+
} catch {
|
|
205
|
+
console.error("\n ❌ WSL2 NemoClaw install failed. Try manually inside WSL2:");
|
|
206
|
+
console.error(" wsl bash -c \"curl -fsSL https://nvidia.com/nemoclaw.sh | bash\"\n");
|
|
207
|
+
process.exit(1);
|
|
208
|
+
}
|
|
209
|
+
} else {
|
|
210
|
+
console.log("\n 📦 Installing OpenClaw for Windows...\n");
|
|
211
|
+
try {
|
|
212
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
213
|
+
console.log("\n ✔ OpenClaw installed.\n");
|
|
214
|
+
console.log(" 💡 Tip: Set up WSL2 + NemoClaw later for sandbox mode.\n");
|
|
215
|
+
} catch {
|
|
216
|
+
console.error("\n ❌ Failed to install OpenClaw:");
|
|
217
|
+
console.error(" npm install -g openclaw\n");
|
|
218
|
+
process.exit(1);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} else {
|
|
222
|
+
console.log(" ℹ️ WSL is installed but no Linux distro is set up yet.\n");
|
|
223
|
+
|
|
224
|
+
let shouldSetup;
|
|
225
|
+
if (auto) {
|
|
226
|
+
shouldSetup = true;
|
|
227
|
+
} else {
|
|
228
|
+
shouldSetup = await confirm(
|
|
229
|
+
" Set up Ubuntu in WSL2 now and install NemoClaw? (Recommended)"
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
if (shouldSetup) {
|
|
234
|
+
console.log("\n 📦 Setting up Ubuntu in WSL2...\n");
|
|
235
|
+
console.log(" This will install Ubuntu and then install NemoClaw inside it.");
|
|
236
|
+
console.log(" You may be prompted to create a Linux username and password.\n");
|
|
237
|
+
try {
|
|
238
|
+
// Modern syntax (Win11/Win10 modern): wsl --install Ubuntu
|
|
239
|
+
// On older Win10 builds, -d flag is required: wsl --install --distribution Ubuntu
|
|
240
|
+
execSync("wsl --install Ubuntu", { stdio: "inherit" });
|
|
241
|
+
execSync("wsl --set-default-version 2", { stdio: "inherit" });
|
|
242
|
+
console.log("\n ✔ Ubuntu installed in WSL2.\n");
|
|
243
|
+
console.log(" 📦 Installing NemoClaw inside WSL2...\n");
|
|
244
|
+
execSync(
|
|
245
|
+
"wsl bash -c \"curl -fsSL https://nvidia.com/nemoclaw.sh | bash\"",
|
|
246
|
+
{ stdio: "inherit" }
|
|
247
|
+
);
|
|
248
|
+
console.log("\n ✔ NemoClaw installed in WSL2.\n");
|
|
249
|
+
console.log(" ℹ️ If onboard fails on Ubuntu 24.04: run inside WSL2: nemoclaw setup-spark\n");
|
|
250
|
+
} catch {
|
|
251
|
+
console.error("\n ❌ WSL2 setup failed. Try manually:");
|
|
252
|
+
console.error(" 1. wsl --install Ubuntu (or: wsl --install --distribution Ubuntu on older Win10)");
|
|
253
|
+
console.error(" 2. wsl bash -c \"curl -fsSL https://nvidia.com/nemoclaw.sh | bash\"\n");
|
|
254
|
+
console.error(" Falling back to OpenClaw for Windows...\n");
|
|
255
|
+
try {
|
|
256
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
257
|
+
console.log(" ✔ OpenClaw installed as fallback.\n");
|
|
258
|
+
} catch {
|
|
259
|
+
process.exit(1);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
} else {
|
|
263
|
+
console.log("\n 📦 Installing OpenClaw for Windows...\n");
|
|
264
|
+
try {
|
|
265
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
266
|
+
console.log("\n ✔ OpenClaw installed.\n");
|
|
267
|
+
console.log(" 💡 Tip: Run \"wsl --install Ubuntu\" later, then re-run this installer");
|
|
268
|
+
console.log(" to get NemoClaw with full sandbox support.\n");
|
|
269
|
+
} catch {
|
|
270
|
+
console.error("\n ❌ Failed to install OpenClaw:");
|
|
271
|
+
console.error(" npm install -g openclaw\n");
|
|
272
|
+
process.exit(1);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
console.log(" WSL2 is not installed on this machine.\n");
|
|
278
|
+
|
|
279
|
+
let shouldInstallWSL;
|
|
280
|
+
if (auto) {
|
|
281
|
+
shouldInstallWSL = false;
|
|
282
|
+
} else {
|
|
283
|
+
shouldInstallWSL = await confirm(
|
|
284
|
+
" Install WSL2 + Ubuntu now for full NemoClaw support? (Recommended)"
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (shouldInstallWSL) {
|
|
289
|
+
console.log("\n 📦 Installing WSL2 and Ubuntu...\n");
|
|
290
|
+
console.log(" ⚠️ This requires a system restart after WSL2 installs.");
|
|
291
|
+
console.log(" After restarting, re-run: npx @robbiesrobotics/alice-agents\n");
|
|
292
|
+
try {
|
|
293
|
+
execSync("wsl --install", { stdio: "inherit" });
|
|
294
|
+
try { execSync("wsl --set-default-version 2", { stdio: "pipe" }); } catch {}
|
|
295
|
+
console.log("\n ✔ WSL2 installation initiated.");
|
|
296
|
+
console.log(" 🔁 Please restart your computer, then re-run the installer.\n");
|
|
297
|
+
process.exit(0);
|
|
298
|
+
} catch {
|
|
299
|
+
console.error("\n ❌ WSL2 install failed. Enable it manually:");
|
|
300
|
+
console.error(" 1. Open PowerShell as Administrator");
|
|
301
|
+
console.error(" 2. Run: wsl --install");
|
|
302
|
+
console.error(" 3. Restart your computer");
|
|
303
|
+
console.error(" 4. Re-run: npx @robbiesrobotics/alice-agents\n");
|
|
304
|
+
console.error(" Falling back to OpenClaw for Windows...\n");
|
|
305
|
+
try {
|
|
306
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
307
|
+
console.log(" ✔ OpenClaw installed as fallback.\n");
|
|
308
|
+
} catch {
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
} else {
|
|
313
|
+
console.log("\n 📦 Installing OpenClaw for Windows...\n");
|
|
314
|
+
console.log(" A.L.I.C.E. will run without the NemoClaw sandbox.\n");
|
|
315
|
+
try {
|
|
316
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
317
|
+
console.log("\n ✔ OpenClaw installed.\n");
|
|
318
|
+
console.log(" 💡 To enable NemoClaw later:");
|
|
319
|
+
console.log(" 1. Open PowerShell as Administrator: wsl --install");
|
|
320
|
+
console.log(" 2. Restart, then re-run: npx @robbiesrobotics/alice-agents\n");
|
|
321
|
+
} catch {
|
|
322
|
+
console.error("\n ❌ Failed to install OpenClaw:");
|
|
323
|
+
console.error(" npm install -g openclaw\n");
|
|
324
|
+
process.exit(1);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
try {
|
|
330
|
+
execSync("openclaw configure", { stdio: "inherit" });
|
|
331
|
+
} catch {
|
|
332
|
+
console.error("\n ⚠️ Configuration incomplete. Run manually: openclaw configure\n");
|
|
333
|
+
process.exit(1);
|
|
334
|
+
}
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// macOS
|
|
339
|
+
if (plat === "darwin") {
|
|
340
|
+
console.log(" A.L.I.C.E. requires a compatible runtime. NemoClaw requires Linux");
|
|
341
|
+
console.log(" (OpenShell uses Linux kernel primitives: Landlock, seccomp, netns).\n");
|
|
342
|
+
console.log(" On macOS, OpenClaw will be installed. For NemoClaw sandbox mode,");
|
|
343
|
+
console.log(" use a Linux VM or deploy remotely with: nemoclaw deploy <brev-instance>\n");
|
|
344
|
+
|
|
345
|
+
console.log(" 📦 Installing OpenClaw...\n");
|
|
346
|
+
try {
|
|
347
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
348
|
+
console.log("\n ✔ OpenClaw installed.\n");
|
|
349
|
+
} catch {
|
|
350
|
+
console.error("\n ❌ Failed to install OpenClaw:");
|
|
351
|
+
console.error(" npm install -g openclaw\n");
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
try {
|
|
356
|
+
execSync("openclaw configure", { stdio: "inherit" });
|
|
357
|
+
console.log("\n ✓ OpenClaw configured\n");
|
|
358
|
+
} catch {
|
|
359
|
+
console.error("\n ⚠️ Configuration incomplete. Run manually: openclaw configure\n");
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Linux / WSL2
|
|
366
|
+
console.log(" A.L.I.C.E. requires a compatible runtime. We recommend NemoClaw —");
|
|
367
|
+
console.log(" NVIDIA\u2019s secure, open-source distribution that includes OpenClaw");
|
|
368
|
+
console.log(" plus enterprise-grade security (OpenShell sandbox, local AI models).\n");
|
|
369
|
+
|
|
370
|
+
if (isWSL) {
|
|
371
|
+
console.log(" ℹ️ WSL2 environment detected.");
|
|
372
|
+
console.log(" If NemoClaw onboard fails, run: nemoclaw setup-spark");
|
|
373
|
+
console.log(" (applies the required cgroup v2 Docker fix for WSL2)\n");
|
|
374
|
+
}
|
|
147
375
|
|
|
148
376
|
let choice;
|
|
149
377
|
if (auto) {
|
|
150
|
-
choice =
|
|
378
|
+
choice = "nemoclaw";
|
|
151
379
|
} else {
|
|
152
|
-
choice = await choose(
|
|
153
|
-
{ label:
|
|
154
|
-
{ label:
|
|
380
|
+
choice = await choose(" Which would you like to install?", [
|
|
381
|
+
{ label: "NemoClaw (Recommended)", value: "nemoclaw" },
|
|
382
|
+
{ label: "OpenClaw only", value: "openclaw" },
|
|
155
383
|
]);
|
|
156
384
|
}
|
|
157
385
|
|
|
158
|
-
if (choice ===
|
|
159
|
-
console.log(
|
|
386
|
+
if (choice === "nemoclaw") {
|
|
387
|
+
console.log(" 📦 Installing NemoClaw...\n");
|
|
160
388
|
try {
|
|
161
|
-
execSync(
|
|
162
|
-
console.log(
|
|
163
|
-
} catch
|
|
164
|
-
console.error(
|
|
165
|
-
console.error(
|
|
389
|
+
execSync("curl -fsSL https://nvidia.com/nemoclaw.sh | bash", { stdio: "inherit" });
|
|
390
|
+
console.log("\n ✔ NemoClaw installed — agents will run in OpenShell sandbox\n");
|
|
391
|
+
} catch {
|
|
392
|
+
console.error("\n ❌ Failed to install NemoClaw. Try manually:");
|
|
393
|
+
console.error(" curl -fsSL https://nvidia.com/nemoclaw.sh | bash\n");
|
|
166
394
|
process.exit(1);
|
|
167
395
|
}
|
|
168
396
|
} else {
|
|
169
|
-
console.log(
|
|
397
|
+
console.log(" 📦 Installing OpenClaw...\n");
|
|
170
398
|
try {
|
|
171
|
-
execSync(
|
|
172
|
-
console.log(
|
|
173
|
-
} catch
|
|
174
|
-
console.error(
|
|
175
|
-
console.error(
|
|
399
|
+
execSync("npm install -g openclaw", { stdio: "inherit" });
|
|
400
|
+
console.log("\n ✔ OpenClaw installed\n");
|
|
401
|
+
} catch {
|
|
402
|
+
console.error("\n ❌ Failed to install OpenClaw:");
|
|
403
|
+
console.error(" npm install -g openclaw\n");
|
|
176
404
|
process.exit(1);
|
|
177
405
|
}
|
|
178
406
|
}
|
|
179
407
|
|
|
180
|
-
// Run openclaw configure
|
|
181
408
|
try {
|
|
182
|
-
execSync(
|
|
183
|
-
console.log(
|
|
409
|
+
execSync("openclaw configure", { stdio: "inherit" });
|
|
410
|
+
console.log("\n ✓ OpenClaw configured\n");
|
|
184
411
|
} catch {
|
|
185
|
-
console.error(
|
|
186
|
-
console.error(
|
|
187
|
-
console.error(
|
|
412
|
+
console.error("\n ⚠️ Configuration incomplete. Run manually:");
|
|
413
|
+
console.error(" openclaw configure");
|
|
414
|
+
console.error(" Then: npx @robbiesrobotics/alice-agents\n");
|
|
188
415
|
process.exit(1);
|
|
189
416
|
}
|
|
190
417
|
}
|
|
@@ -197,39 +424,43 @@ function loadAgentRegistry() {
|
|
|
197
424
|
}
|
|
198
425
|
|
|
199
426
|
function printBanner() {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
console.log('
|
|
203
|
-
console.log(
|
|
204
|
-
console.log(
|
|
205
|
-
console.log('
|
|
206
|
-
console.log('
|
|
207
|
-
console.log(
|
|
208
|
-
console.log(
|
|
209
|
-
console.log();
|
|
427
|
+
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url)));
|
|
428
|
+
const version = pkg.version || '';
|
|
429
|
+
console.log('');
|
|
430
|
+
console.log(` ${dim('╭──────────────────────────────────────────────╮')}`);
|
|
431
|
+
console.log(` ${dim('│')} ${dim('│')}`);
|
|
432
|
+
console.log(` ${dim('│')} ${greenBold('A . L . I . C . E .')} ${dim('│')}`);
|
|
433
|
+
console.log(` ${dim('│')} ${dim('Adaptive Learning & Intelligent Coordination')} ${dim('│')}`);
|
|
434
|
+
console.log(` ${dim('│')} ${dim('Engine — Multi-Agent Orchestration')} ${dim('│')}`);
|
|
435
|
+
console.log(` ${dim('│')} ${dim('│')}`);
|
|
436
|
+
console.log(` ${dim('│')} ${dim('v' + version)} ${green('●')} ${dim('10 starter agents, one team')} ${dim('│')}`);
|
|
437
|
+
console.log(` ${dim('│')} ${dim('│')}`);
|
|
438
|
+
console.log(` ${dim('╰──────────────────────────────────────────────╯')}`);
|
|
439
|
+
console.log('');
|
|
210
440
|
}
|
|
211
441
|
|
|
212
442
|
function printSummary(mode, tier, agents, preset, userInfo, detectedModels) {
|
|
213
443
|
const modelLabel =
|
|
214
444
|
preset === 'detected'
|
|
215
|
-
? `${detectedModels?.primary || 'your configured model'} (detected)`
|
|
216
|
-
: preset === 'custom'
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
445
|
+
? `${detectedModels?.primary || 'your configured model'} ${dim('(detected)')}`
|
|
446
|
+
: preset === 'custom' ? 'custom' : preset;
|
|
447
|
+
|
|
448
|
+
printSection('Install Summary');
|
|
449
|
+
console.log('');
|
|
450
|
+
|
|
451
|
+
const lines = [
|
|
452
|
+
`${dim('Mode:')} ${green(mode)}`,
|
|
453
|
+
`${dim('Tier:')} ${green(tier)} ${dim('(' + agents.length + ' agents)')}`,
|
|
454
|
+
`${dim('Model:')} ${green(modelLabel)}`,
|
|
455
|
+
`${dim('User:')} ${green(userInfo.name)}`,
|
|
456
|
+
`${dim('Timezone:')} ${green(userInfo.timezone)}`,
|
|
457
|
+
'',
|
|
458
|
+
`${dim('Agents:')}`,
|
|
459
|
+
...agents.map(a => ` ${icons.bullet} ${green(a.emoji)} ${bold(a.name.padEnd(10))} ${dim('─')} ${a.domain}`),
|
|
460
|
+
];
|
|
461
|
+
|
|
462
|
+
printBox(lines, { title: 'Ready to install', padding: 2 });
|
|
463
|
+
console.log('');
|
|
233
464
|
}
|
|
234
465
|
|
|
235
466
|
export async function runInstall(options = {}) {
|
|
@@ -237,7 +468,7 @@ export async function runInstall(options = {}) {
|
|
|
237
468
|
|
|
238
469
|
// Check health flag first (before banner)
|
|
239
470
|
if (process.argv.includes('--health')) {
|
|
240
|
-
const healthPath = join(
|
|
471
|
+
const healthPath = join(homedir(), '.openclaw', '.alice-health-alert.json');
|
|
241
472
|
if (existsSync(healthPath)) {
|
|
242
473
|
const alerts = JSON.parse(readFileSync(healthPath, 'utf8'));
|
|
243
474
|
console.log('\n⚠️ A.L.I.C.E. Health Report\n');
|
|
@@ -263,7 +494,8 @@ export async function runInstall(options = {}) {
|
|
|
263
494
|
|
|
264
495
|
// Final check
|
|
265
496
|
if (!configExists()) {
|
|
266
|
-
|
|
497
|
+
printStepFail('OpenClaw config not found', 'Run: openclaw configure');
|
|
498
|
+
console.log('');
|
|
267
499
|
process.exit(1);
|
|
268
500
|
}
|
|
269
501
|
|
|
@@ -272,23 +504,27 @@ export async function runInstall(options = {}) {
|
|
|
272
504
|
|
|
273
505
|
const runtime = await detectRuntime();
|
|
274
506
|
if (runtime === 'nemoclaw') {
|
|
275
|
-
console.log('
|
|
507
|
+
console.log(` ${icons.ok} ${greenBold('NemoClaw detected')} ${dim('─')} agents run in OpenShell sandbox\n`);
|
|
276
508
|
} else {
|
|
277
|
-
console.log('
|
|
278
|
-
|
|
509
|
+
console.log(` ${icons.ok} ${green('OpenClaw detected')}\n`);
|
|
510
|
+
if (process.platform === "linux" || process.env.WSL_DISTRO_NAME || process.env.WSLENV) {
|
|
511
|
+
console.log(` ${icons.info} ${dim('Tip:')} Upgrade to NemoClaw for enterprise security: https://nvidia.com/nemoclaw\n`);
|
|
512
|
+
} else if (process.platform === "darwin") {
|
|
513
|
+
console.log(` ${icons.info} ${dim('Tip:')} NemoClaw requires Linux. For sandbox mode, use a Linux VM or Brev remote deploy.\n`);
|
|
514
|
+
}
|
|
279
515
|
}
|
|
280
516
|
|
|
281
517
|
// Detect what models the user already has configured
|
|
282
518
|
const detectedModels = detectAvailableModels();
|
|
283
519
|
if (detectedModels?.hasModel) {
|
|
284
|
-
console.log(`
|
|
520
|
+
console.log(` ${icons.ok} ${green('Detected configured model:')} ${detectedModels.primary}`);
|
|
285
521
|
if (detectedModels.providers.length > 0) {
|
|
286
522
|
console.log(` Providers: ${detectedModels.providers.join(', ')}\n`);
|
|
287
523
|
} else {
|
|
288
524
|
console.log();
|
|
289
525
|
}
|
|
290
526
|
} else {
|
|
291
|
-
console.log('
|
|
527
|
+
console.log(` ${icons.info} ${dim('No model configured yet — you\'ll be prompted to choose one.')}\n`);
|
|
292
528
|
}
|
|
293
529
|
|
|
294
530
|
const allAgents = loadAgentRegistry();
|
|
@@ -307,7 +543,7 @@ export async function runInstall(options = {}) {
|
|
|
307
543
|
if (mode === 'upgrade') {
|
|
308
544
|
const manifest = readManifest();
|
|
309
545
|
if (!manifest) {
|
|
310
|
-
console.log('
|
|
546
|
+
console.log(` ${icons.warn} ${yellow('No previous install found. Switching to fresh install.')}\n`);
|
|
311
547
|
mode = 'fresh';
|
|
312
548
|
}
|
|
313
549
|
}
|
|
@@ -326,7 +562,8 @@ export async function runInstall(options = {}) {
|
|
|
326
562
|
if (auto) {
|
|
327
563
|
userInfo = { name: detectUserName(), timezone: detectTimezone(), notes: '' };
|
|
328
564
|
} else {
|
|
329
|
-
|
|
565
|
+
printSection('About You');
|
|
566
|
+
console.log('');
|
|
330
567
|
userInfo = await promptUserInfo();
|
|
331
568
|
}
|
|
332
569
|
|
|
@@ -358,14 +595,14 @@ export async function runInstall(options = {}) {
|
|
|
358
595
|
const existing = await checkProLicense();
|
|
359
596
|
|
|
360
597
|
if (existing.licensed) {
|
|
361
|
-
|
|
598
|
+
printStepDone(`Pro license found (${existing.key.slice(0, 12)}...)`);
|
|
362
599
|
} else if (auto) {
|
|
363
600
|
// --yes flag: skip interactive prompt, fallback to Starter if no stored license
|
|
364
601
|
console.log('');
|
|
365
|
-
console.log('
|
|
366
|
-
console.log('
|
|
367
|
-
console.log('
|
|
368
|
-
console.log('
|
|
602
|
+
console.log(` ${icons.info} ${dim('Pro tier requires a license key.')}`);
|
|
603
|
+
console.log(` ${dim('Run without --yes to enter your license key.')}`);
|
|
604
|
+
console.log(` ${dim('Falling back to Starter tier.')}`);
|
|
605
|
+
console.log(` ${dim('Purchase a license at:')} ${cyan('https://getalice.av3.ai/pricing')}`);
|
|
369
606
|
tier = 'starter';
|
|
370
607
|
} else {
|
|
371
608
|
// No stored license — prompt for key
|
|
@@ -376,7 +613,7 @@ export async function runInstall(options = {}) {
|
|
|
376
613
|
key = await promptLicenseKey();
|
|
377
614
|
|
|
378
615
|
if (!isValidFormat(key)) {
|
|
379
|
-
|
|
616
|
+
printStepFail('Invalid format. Key must be ALICE-XXXX-XXXX-XXXX');
|
|
380
617
|
attempts++;
|
|
381
618
|
continue;
|
|
382
619
|
}
|
|
@@ -387,13 +624,13 @@ export async function runInstall(options = {}) {
|
|
|
387
624
|
if (result.valid) {
|
|
388
625
|
storeLicense(key);
|
|
389
626
|
if (result.message === 'offline') {
|
|
390
|
-
|
|
627
|
+
printStepDone('Key stored', 'offline — will validate on next run');
|
|
391
628
|
} else {
|
|
392
|
-
|
|
629
|
+
printStepDone('License verified! Welcome to A.L.I.C.E. Pro.');
|
|
393
630
|
}
|
|
394
631
|
break;
|
|
395
632
|
} else {
|
|
396
|
-
|
|
633
|
+
printStepFail(`Invalid key: ${result.message ?? 'Not recognized'}`);
|
|
397
634
|
attempts++;
|
|
398
635
|
|
|
399
636
|
if (attempts >= 3) {
|
|
@@ -424,16 +661,20 @@ export async function runInstall(options = {}) {
|
|
|
424
661
|
closePrompt();
|
|
425
662
|
|
|
426
663
|
// Execute
|
|
427
|
-
|
|
664
|
+
printSection('Installing');
|
|
665
|
+
console.log('');
|
|
428
666
|
|
|
429
667
|
// Merge config
|
|
430
|
-
const { backupPath, agentCount } = mergeConfig({
|
|
668
|
+
const { backupPath, agentCount, effectivePreset, warning } = mergeConfig({
|
|
431
669
|
agents,
|
|
432
670
|
mode,
|
|
433
671
|
preset,
|
|
434
672
|
customModels,
|
|
435
673
|
});
|
|
436
|
-
|
|
674
|
+
printStepDone('Config updated', `backup: ${backupPath}`);
|
|
675
|
+
if (warning) {
|
|
676
|
+
console.log(` ${icons.warn} ${yellow(warning)}`);
|
|
677
|
+
}
|
|
437
678
|
|
|
438
679
|
// Scaffold workspaces
|
|
439
680
|
const results = scaffoldAll(agents, userInfo);
|
|
@@ -446,7 +687,15 @@ export async function runInstall(options = {}) {
|
|
|
446
687
|
updatedWorkspaces++;
|
|
447
688
|
}
|
|
448
689
|
}
|
|
449
|
-
|
|
690
|
+
printStepDone('Workspaces', `${newWorkspaces} created, ${updatedWorkspaces} updated`);
|
|
691
|
+
|
|
692
|
+
// Skills installation step
|
|
693
|
+
const finalRuntimeForSkills = await detectRuntime();
|
|
694
|
+
const skillsInstalled = await runSkillsWizardStep({
|
|
695
|
+
auto,
|
|
696
|
+
nemoclaw: finalRuntimeForSkills === 'nemoclaw',
|
|
697
|
+
sandboxName: 'my-assistant',
|
|
698
|
+
});
|
|
450
699
|
|
|
451
700
|
// Write manifest
|
|
452
701
|
const existing = readManifest();
|
|
@@ -456,16 +705,28 @@ export async function runInstall(options = {}) {
|
|
|
456
705
|
agents: agents.map((a) => a.id),
|
|
457
706
|
userName: userInfo.name,
|
|
458
707
|
userTimezone: userInfo.timezone,
|
|
459
|
-
modelPreset:
|
|
708
|
+
modelPreset: effectivePreset,
|
|
460
709
|
});
|
|
461
|
-
|
|
710
|
+
printStepDone('Manifest written');
|
|
462
711
|
|
|
463
|
-
console.log(
|
|
712
|
+
console.log('');
|
|
713
|
+
printSeparator();
|
|
714
|
+
console.log('');
|
|
715
|
+
console.log(` ${icons.ok} ${greenBold('A.L.I.C.E. installed!')} ${dim(agentCount + ' agents ready.')}`);
|
|
716
|
+
console.log('');
|
|
464
717
|
const finalRuntime = await detectRuntime();
|
|
465
718
|
if (finalRuntime === 'nemoclaw') {
|
|
466
|
-
console.log(
|
|
719
|
+
console.log(` ${icons.ok} ${green('Secure mode')} ${dim('─')} OpenShell sandbox active`);
|
|
720
|
+
} else {
|
|
721
|
+
console.log(` ${icons.info} ${dim('Runtime: OpenClaw')}`);
|
|
467
722
|
}
|
|
468
|
-
console.log('
|
|
723
|
+
console.log('');
|
|
724
|
+
console.log(` ${dim('Manage skills:')} ${cyan('npx @robbiesrobotics/alice-agents --skills')}`);
|
|
725
|
+
console.log(` ${dim('Health check:')} ${cyan('npx @robbiesrobotics/alice-agents --doctor')}`);
|
|
726
|
+
console.log(` ${dim('Restart runtime:')} ${cyan('openclaw gateway restart')}`);
|
|
727
|
+
console.log('');
|
|
728
|
+
printSeparator();
|
|
729
|
+
console.log('');
|
|
469
730
|
}
|
|
470
731
|
|
|
471
732
|
export async function runUninstall(options = {}) {
|