@silicaclaw/cli 1.0.0-beta.25 → 1.0.0-beta.29
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/CHANGELOG.md +27 -0
- package/INSTALL.md +19 -16
- package/README.md +9 -8
- package/apps/local-console/public/index.html +1055 -261
- package/apps/local-console/src/server.ts +21 -0
- package/package.json +1 -1
- package/scripts/quickstart.sh +89 -45
- package/scripts/silicaclaw-cli.mjs +147 -88
- package/scripts/silicaclaw-gateway.mjs +134 -62
|
@@ -10,6 +10,37 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
10
10
|
const __dirname = dirname(__filename);
|
|
11
11
|
const ROOT_DIR = resolve(__dirname, "..");
|
|
12
12
|
|
|
13
|
+
const COLOR = {
|
|
14
|
+
reset: "\x1b[0m",
|
|
15
|
+
bold: "\x1b[1m",
|
|
16
|
+
dim: "\x1b[2m",
|
|
17
|
+
orange: "\x1b[38;5;208m",
|
|
18
|
+
green: "\x1b[32m",
|
|
19
|
+
yellow: "\x1b[33m",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function useColor() {
|
|
23
|
+
return Boolean(process.stdout.isTTY && !process.env.NO_COLOR);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function paint(text, ...styles) {
|
|
27
|
+
if (!useColor() || styles.length === 0) return text;
|
|
28
|
+
return `${styles.join("")}${text}${COLOR.reset}`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function headline() {
|
|
32
|
+
console.log(`${paint("SilicaClaw", COLOR.bold, COLOR.orange)} ${paint(readVersion(), COLOR.dim)}`);
|
|
33
|
+
console.log(paint("Public identity and discovery for OpenClaw agents.", COLOR.dim));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function kv(label, value) {
|
|
37
|
+
console.log(`${paint(label.padEnd(14), COLOR.dim)} ${value}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function section(title) {
|
|
41
|
+
console.log(paint(title, COLOR.bold));
|
|
42
|
+
}
|
|
43
|
+
|
|
13
44
|
function run(cmd, args, extra = {}) {
|
|
14
45
|
const result = spawnSync(cmd, args, {
|
|
15
46
|
cwd: ROOT_DIR,
|
|
@@ -18,7 +49,10 @@ function run(cmd, args, extra = {}) {
|
|
|
18
49
|
...extra,
|
|
19
50
|
});
|
|
20
51
|
if (result.error) {
|
|
21
|
-
|
|
52
|
+
headline();
|
|
53
|
+
console.log("");
|
|
54
|
+
console.error(`${paint("Command failed", COLOR.bold, COLOR.yellow)} ${cmd}`);
|
|
55
|
+
console.error(result.error.message);
|
|
22
56
|
process.exit(1);
|
|
23
57
|
}
|
|
24
58
|
process.exit(result.status ?? 0);
|
|
@@ -89,14 +123,18 @@ function userEnvFile() {
|
|
|
89
123
|
}
|
|
90
124
|
|
|
91
125
|
function ensureLineInFile(filePath, block) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
126
|
+
try {
|
|
127
|
+
const current = existsSync(filePath) ? readFileSync(filePath, "utf8") : "";
|
|
128
|
+
if (current.includes(block.trim())) {
|
|
129
|
+
return { changed: false, error: null };
|
|
130
|
+
}
|
|
131
|
+
const next = `${current.replace(/\s*$/, "")}\n\n${block}\n`;
|
|
132
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
133
|
+
writeFileSync(filePath, next, "utf8");
|
|
134
|
+
return { changed: true, error: null };
|
|
135
|
+
} catch (error) {
|
|
136
|
+
return { changed: false, error: error instanceof Error ? error.message : String(error) };
|
|
95
137
|
}
|
|
96
|
-
const next = `${current.replace(/\s*$/, "")}\n\n${block}\n`;
|
|
97
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
98
|
-
writeFileSync(filePath, next, "utf8");
|
|
99
|
-
return true;
|
|
100
138
|
}
|
|
101
139
|
|
|
102
140
|
function shellInitTargets() {
|
|
@@ -159,21 +197,37 @@ function installPersistentCommand() {
|
|
|
159
197
|
);
|
|
160
198
|
const rcFiles = shellInitTargets();
|
|
161
199
|
const updatedFiles = [];
|
|
200
|
+
const failedFiles = [];
|
|
162
201
|
for (const filePath of rcFiles) {
|
|
163
|
-
|
|
202
|
+
const result = ensureLineInFile(filePath, rcBlock);
|
|
203
|
+
if (result.changed) {
|
|
164
204
|
updatedFiles.push(filePath);
|
|
165
205
|
}
|
|
206
|
+
if (result.error) {
|
|
207
|
+
failedFiles.push({ filePath, error: result.error });
|
|
208
|
+
}
|
|
166
209
|
}
|
|
167
210
|
|
|
168
|
-
|
|
169
|
-
console.log(
|
|
170
|
-
console.log(
|
|
171
|
-
|
|
211
|
+
headline();
|
|
212
|
+
console.log("");
|
|
213
|
+
console.log(`${paint("Installed", COLOR.bold)} persistent command`);
|
|
214
|
+
kv("Command", "silicaclaw");
|
|
215
|
+
kv("Shim", shimPath);
|
|
216
|
+
kv("Env", envFile);
|
|
217
|
+
kv("Shell init", rcFiles.join(", "));
|
|
172
218
|
console.log("");
|
|
173
|
-
|
|
174
|
-
console.log(`source "${envFile}"`);
|
|
219
|
+
kv("Activate", `source "${envFile}"`);
|
|
175
220
|
if (updatedFiles.length === 0) {
|
|
176
|
-
|
|
221
|
+
kv("Startup", "shell files already configured");
|
|
222
|
+
}
|
|
223
|
+
if (failedFiles.length > 0) {
|
|
224
|
+
console.log("");
|
|
225
|
+
console.log(paint("Shell files not updated automatically", COLOR.bold, COLOR.yellow));
|
|
226
|
+
for (const item of failedFiles) {
|
|
227
|
+
kv(item.filePath, item.error);
|
|
228
|
+
}
|
|
229
|
+
console.log("");
|
|
230
|
+
kv("Manual line", '[ -f "$HOME/.silicaclaw/env.sh" ] && . "$HOME/.silicaclaw/env.sh"');
|
|
177
231
|
}
|
|
178
232
|
}
|
|
179
233
|
|
|
@@ -197,49 +251,48 @@ function canWriteGlobalPrefix() {
|
|
|
197
251
|
|
|
198
252
|
function showUpdateGuide(current, latest, beta) {
|
|
199
253
|
const npxRuntime = isNpxRun();
|
|
200
|
-
|
|
201
|
-
console.log(
|
|
202
|
-
console.log(
|
|
203
|
-
|
|
254
|
+
headline();
|
|
255
|
+
console.log("");
|
|
256
|
+
console.log(paint("Update check", COLOR.bold));
|
|
257
|
+
kv("Current", current);
|
|
258
|
+
kv("Latest", latest || "-");
|
|
259
|
+
kv("Beta", beta || "-");
|
|
204
260
|
console.log("");
|
|
205
261
|
|
|
206
262
|
const upToDate = Boolean(beta) && current === beta;
|
|
207
263
|
if (upToDate) {
|
|
208
|
-
console.log("
|
|
264
|
+
console.log(`${paint("Ready", COLOR.bold)} you're already on the latest beta.`);
|
|
209
265
|
} else {
|
|
210
|
-
console.log("Update available.
|
|
266
|
+
console.log(`${paint("Update available", COLOR.bold, COLOR.yellow)} install the latest beta and refresh your services.`);
|
|
211
267
|
}
|
|
212
268
|
console.log("");
|
|
213
|
-
console.log("
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
console.log("3) Install persistent command (recommended once)");
|
|
219
|
-
console.log(" npx -y @silicaclaw/cli@beta install");
|
|
220
|
-
console.log("4) npx one-shot (no install)");
|
|
221
|
-
console.log(" npx -y @silicaclaw/cli@beta start --mode=global-preview");
|
|
269
|
+
console.log(paint("Next commands", COLOR.bold));
|
|
270
|
+
kv("Start", "silicaclaw start --mode=global-preview");
|
|
271
|
+
kv("Status", "silicaclaw status");
|
|
272
|
+
kv("Install", "npx -y @silicaclaw/cli@beta install");
|
|
273
|
+
kv("One-shot", "npx -y @silicaclaw/cli@beta start --mode=global-preview");
|
|
222
274
|
console.log("");
|
|
223
275
|
|
|
224
276
|
const writableGlobal = canWriteGlobalPrefix();
|
|
225
277
|
if (!npxRuntime && writableGlobal) {
|
|
226
|
-
console.log("Optional global install
|
|
227
|
-
|
|
228
|
-
|
|
278
|
+
console.log(paint("Optional global install", COLOR.bold));
|
|
279
|
+
kv("Install", "npm i -g @silicaclaw/cli@beta");
|
|
280
|
+
kv("Verify", "silicaclaw version");
|
|
229
281
|
console.log("");
|
|
230
282
|
} else if (!npxRuntime) {
|
|
231
|
-
console.log("Global install skipped
|
|
283
|
+
console.log(paint("Global install skipped", COLOR.bold, COLOR.yellow));
|
|
284
|
+
console.log("npm global directory is not writable on this machine.");
|
|
232
285
|
console.log("");
|
|
233
286
|
}
|
|
234
287
|
if (npxRuntime) {
|
|
235
|
-
console.log("Detected npx runtime.
|
|
288
|
+
console.log(paint("Detected npx runtime", COLOR.bold));
|
|
236
289
|
console.log("Run `npx -y @silicaclaw/cli@beta install` once to make `silicaclaw` available in new shells.");
|
|
237
290
|
}
|
|
238
291
|
}
|
|
239
292
|
|
|
240
293
|
function getGatewayStatus() {
|
|
241
294
|
try {
|
|
242
|
-
const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status"], {
|
|
295
|
+
const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status", "--json"], {
|
|
243
296
|
cwd: process.cwd(),
|
|
244
297
|
});
|
|
245
298
|
if ((result.status ?? 1) !== 0) return null;
|
|
@@ -301,13 +354,13 @@ function restartGatewayIfRunning() {
|
|
|
301
354
|
const appDir = status?.app_dir ? String(status.app_dir) : "";
|
|
302
355
|
const synced = syncCurrentPackageToAppDir(appDir);
|
|
303
356
|
if (synced) {
|
|
304
|
-
|
|
357
|
+
kv("Synced", appDir);
|
|
305
358
|
}
|
|
306
359
|
|
|
307
360
|
const localRunning = Boolean(status?.local_console?.running);
|
|
308
361
|
const signalingRunning = Boolean(status?.signaling?.running);
|
|
309
362
|
if (!localRunning && !signalingRunning) {
|
|
310
|
-
|
|
363
|
+
kv("Runtime", "gateway not running; no refresh needed");
|
|
311
364
|
return;
|
|
312
365
|
}
|
|
313
366
|
|
|
@@ -320,14 +373,15 @@ function restartGatewayIfRunning() {
|
|
|
320
373
|
args.push(`--room=${status.signaling.room}`);
|
|
321
374
|
}
|
|
322
375
|
|
|
323
|
-
console.log("
|
|
376
|
+
console.log("");
|
|
377
|
+
console.log(paint("Refreshing background services", COLOR.bold));
|
|
324
378
|
runInherit("node", args, { cwd: process.cwd() });
|
|
325
379
|
}
|
|
326
380
|
|
|
327
381
|
function tryGlobalUpgrade(beta) {
|
|
328
382
|
const writableGlobal = canWriteGlobalPrefix();
|
|
329
383
|
if (!writableGlobal) return false;
|
|
330
|
-
|
|
384
|
+
kv("Upgrade", `installing @silicaclaw/cli@${beta} globally`);
|
|
331
385
|
const result = runInherit("npm", ["i", "-g", `@silicaclaw/cli@${beta}`]);
|
|
332
386
|
return (result.status ?? 1) === 0;
|
|
333
387
|
}
|
|
@@ -337,8 +391,12 @@ function update() {
|
|
|
337
391
|
try {
|
|
338
392
|
const result = runCapture("npm", ["view", "@silicaclaw/cli", "dist-tags", "--json"]);
|
|
339
393
|
if ((result.status ?? 1) !== 0) {
|
|
340
|
-
|
|
394
|
+
headline();
|
|
395
|
+
console.log("");
|
|
396
|
+
console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
|
|
341
397
|
if (result.stderr) console.error(result.stderr.trim());
|
|
398
|
+
console.log("");
|
|
399
|
+
kv("Try", "npm view @silicaclaw/cli dist-tags --json");
|
|
342
400
|
process.exit(result.status ?? 1);
|
|
343
401
|
}
|
|
344
402
|
const text = String(result.stdout || "").trim();
|
|
@@ -351,73 +409,70 @@ function update() {
|
|
|
351
409
|
|
|
352
410
|
if (hasNewBeta) {
|
|
353
411
|
if (npxRuntime) {
|
|
354
|
-
|
|
412
|
+
kv("Update", `new beta detected (${beta}); npx will use it on the next run`);
|
|
355
413
|
} else if (tryGlobalUpgrade(beta)) {
|
|
356
|
-
|
|
414
|
+
kv("Upgrade", `global install updated to ${beta}`);
|
|
357
415
|
} else {
|
|
358
|
-
|
|
416
|
+
kv("Upgrade", "skipped global install");
|
|
359
417
|
}
|
|
360
418
|
}
|
|
361
419
|
|
|
362
420
|
restartGatewayIfRunning();
|
|
363
421
|
process.exit(0);
|
|
364
422
|
} catch (error) {
|
|
365
|
-
|
|
366
|
-
console.log("
|
|
367
|
-
console.
|
|
423
|
+
headline();
|
|
424
|
+
console.log("");
|
|
425
|
+
console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
|
|
426
|
+
console.error(error.message);
|
|
427
|
+
console.log("");
|
|
428
|
+
kv("Try", "npm view @silicaclaw/cli dist-tags --json");
|
|
368
429
|
process.exit(1);
|
|
369
430
|
}
|
|
370
431
|
}
|
|
371
432
|
|
|
372
433
|
function help() {
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
silicaclaw
|
|
378
|
-
silicaclaw
|
|
379
|
-
silicaclaw
|
|
380
|
-
silicaclaw
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
silicaclaw
|
|
384
|
-
silicaclaw
|
|
385
|
-
silicaclaw
|
|
386
|
-
silicaclaw
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
silicaclaw
|
|
390
|
-
silicaclaw
|
|
391
|
-
silicaclaw
|
|
392
|
-
silicaclaw
|
|
393
|
-
|
|
394
|
-
Commands:
|
|
395
|
-
onboard Interactive step-by-step onboarding (recommended)
|
|
396
|
-
connect Cross-network connect wizard (global-preview first)
|
|
397
|
-
update Check latest npm version and show upgrade commands
|
|
398
|
-
install Install persistent silicaclaw command for future shells
|
|
399
|
-
start Start gateway-managed background services
|
|
400
|
-
stop Stop gateway-managed background services
|
|
401
|
-
restart Restart gateway-managed background services
|
|
402
|
-
status Show gateway-managed service status
|
|
403
|
-
logs Show gateway-managed service logs
|
|
404
|
-
gateway Manage background services (start/stop/restart/status/logs)
|
|
405
|
-
local-console Start local console (http://localhost:4310)
|
|
406
|
-
explorer Start public explorer (http://localhost:4311)
|
|
407
|
-
signaling Start WebRTC signaling preview server
|
|
408
|
-
doctor Run project checks (npm run health)
|
|
409
|
-
version Print SilicaClaw version
|
|
410
|
-
help Show this help
|
|
411
|
-
`.trim());
|
|
434
|
+
headline();
|
|
435
|
+
console.log("");
|
|
436
|
+
section("Core commands");
|
|
437
|
+
kv("Install", "npx -y @silicaclaw/cli@beta install");
|
|
438
|
+
kv("Start", "silicaclaw start --mode=global-preview");
|
|
439
|
+
kv("Status", "silicaclaw status");
|
|
440
|
+
kv("Stop", "silicaclaw stop");
|
|
441
|
+
kv("Update", "silicaclaw update");
|
|
442
|
+
console.log("");
|
|
443
|
+
section("Setup and network");
|
|
444
|
+
kv("Onboard", "silicaclaw onboard");
|
|
445
|
+
kv("Connect", "silicaclaw connect");
|
|
446
|
+
kv("Gateway", "silicaclaw gateway <start|stop|restart|status|logs>");
|
|
447
|
+
kv("Signaling", "silicaclaw signaling");
|
|
448
|
+
console.log("");
|
|
449
|
+
section("Local apps");
|
|
450
|
+
kv("Console", "silicaclaw local-console");
|
|
451
|
+
kv("Explorer", "silicaclaw explorer");
|
|
452
|
+
kv("Doctor", "silicaclaw doctor");
|
|
453
|
+
kv("Version", "silicaclaw version");
|
|
454
|
+
kv("Help", "silicaclaw help");
|
|
412
455
|
}
|
|
413
456
|
|
|
414
457
|
const cmd = String(process.argv[2] || "help").trim().toLowerCase();
|
|
415
458
|
|
|
416
459
|
switch (cmd) {
|
|
417
460
|
case "onboard":
|
|
461
|
+
headline();
|
|
462
|
+
console.log("");
|
|
463
|
+
section("Opening onboarding");
|
|
464
|
+
kv("Mode", "interactive setup");
|
|
465
|
+
kv("Focus", "install command, profile, internet relay");
|
|
466
|
+
console.log("");
|
|
418
467
|
run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")]);
|
|
419
468
|
break;
|
|
420
469
|
case "connect":
|
|
470
|
+
headline();
|
|
471
|
+
console.log("");
|
|
472
|
+
section("Opening connect wizard");
|
|
473
|
+
kv("Mode", "global-preview first");
|
|
474
|
+
kv("Relay", "https://relay.silicaclaw.com");
|
|
475
|
+
console.log("");
|
|
421
476
|
run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")], {
|
|
422
477
|
env: {
|
|
423
478
|
...process.env,
|
|
@@ -459,12 +514,16 @@ switch (cmd) {
|
|
|
459
514
|
run("npm", ["run", "webrtc-signaling"]);
|
|
460
515
|
break;
|
|
461
516
|
case "doctor":
|
|
517
|
+
headline();
|
|
518
|
+
console.log("");
|
|
519
|
+
section("Running health checks");
|
|
520
|
+
console.log("");
|
|
462
521
|
run("npm", ["run", "health"]);
|
|
463
522
|
break;
|
|
464
523
|
case "version":
|
|
465
524
|
case "-v":
|
|
466
525
|
case "--version":
|
|
467
|
-
|
|
526
|
+
headline();
|
|
468
527
|
break;
|
|
469
528
|
case "help":
|
|
470
529
|
case "-h":
|