@silicaclaw/cli 1.0.0-beta.3 → 1.0.0-beta.30
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 +93 -0
- package/INSTALL.md +41 -4
- package/README.md +80 -6
- package/apps/local-console/public/index.html +1283 -251
- package/apps/local-console/src/server.ts +108 -31
- package/docs/CLOUDFLARE_RELAY.md +61 -0
- package/docs/NEW_USER_INSTALL.md +166 -0
- package/docs/NEW_USER_OPERATIONS.md +265 -0
- package/package.json +6 -1
- package/packages/core/dist/crypto.d.ts +6 -0
- package/packages/core/dist/crypto.js +50 -0
- package/packages/core/dist/directory.d.ts +17 -0
- package/packages/core/dist/directory.js +145 -0
- package/packages/core/dist/identity.d.ts +2 -0
- package/packages/core/dist/identity.js +18 -0
- package/packages/core/dist/index.d.ts +11 -0
- package/packages/core/dist/index.js +27 -0
- package/packages/core/dist/indexing.d.ts +6 -0
- package/packages/core/dist/indexing.js +43 -0
- package/packages/core/dist/presence.d.ts +4 -0
- package/packages/core/dist/presence.js +23 -0
- package/packages/core/dist/profile.d.ts +4 -0
- package/packages/core/dist/profile.js +39 -0
- package/packages/core/dist/publicProfileSummary.d.ts +70 -0
- package/packages/core/dist/publicProfileSummary.js +103 -0
- package/packages/core/dist/socialConfig.d.ts +99 -0
- package/packages/core/dist/socialConfig.js +288 -0
- package/packages/core/dist/socialResolver.d.ts +46 -0
- package/packages/core/dist/socialResolver.js +237 -0
- package/packages/core/dist/socialTemplate.d.ts +2 -0
- package/packages/core/dist/socialTemplate.js +88 -0
- package/packages/core/dist/types.d.ts +37 -0
- package/packages/core/dist/types.js +2 -0
- package/packages/core/src/socialConfig.ts +8 -7
- package/packages/core/src/socialResolver.ts +17 -5
- package/packages/network/dist/abstractions/messageEnvelope.d.ts +28 -0
- package/packages/network/dist/abstractions/messageEnvelope.js +36 -0
- package/packages/network/dist/abstractions/peerDiscovery.d.ts +43 -0
- package/packages/network/dist/abstractions/peerDiscovery.js +2 -0
- package/packages/network/dist/abstractions/topicCodec.d.ts +4 -0
- package/packages/network/dist/abstractions/topicCodec.js +2 -0
- package/packages/network/dist/abstractions/transport.d.ts +36 -0
- package/packages/network/dist/abstractions/transport.js +2 -0
- package/packages/network/dist/codec/jsonMessageEnvelopeCodec.d.ts +5 -0
- package/packages/network/dist/codec/jsonMessageEnvelopeCodec.js +24 -0
- package/packages/network/dist/codec/jsonTopicCodec.d.ts +5 -0
- package/packages/network/dist/codec/jsonTopicCodec.js +12 -0
- package/packages/network/dist/discovery/heartbeatPeerDiscovery.d.ts +28 -0
- package/packages/network/dist/discovery/heartbeatPeerDiscovery.js +144 -0
- package/packages/network/dist/index.d.ts +14 -0
- package/packages/network/dist/index.js +30 -0
- package/packages/network/dist/localEventBus.d.ts +9 -0
- package/packages/network/dist/localEventBus.js +47 -0
- package/packages/network/dist/mock.d.ts +8 -0
- package/packages/network/dist/mock.js +24 -0
- package/packages/network/dist/realPreview.d.ts +105 -0
- package/packages/network/dist/realPreview.js +327 -0
- package/packages/network/dist/relayPreview.d.ts +166 -0
- package/packages/network/dist/relayPreview.js +430 -0
- package/packages/network/dist/transport/udpLanBroadcastTransport.d.ts +23 -0
- package/packages/network/dist/transport/udpLanBroadcastTransport.js +153 -0
- package/packages/network/dist/types.d.ts +6 -0
- package/packages/network/dist/types.js +2 -0
- package/packages/network/dist/webrtcPreview.d.ts +163 -0
- package/packages/network/dist/webrtcPreview.js +844 -0
- package/packages/network/src/index.ts +1 -0
- package/packages/network/src/relayPreview.ts +552 -0
- package/packages/storage/dist/index.d.ts +3 -0
- package/packages/storage/dist/index.js +19 -0
- package/packages/storage/dist/jsonRepo.d.ts +7 -0
- package/packages/storage/dist/jsonRepo.js +29 -0
- package/packages/storage/dist/repos.d.ts +21 -0
- package/packages/storage/dist/repos.js +41 -0
- package/packages/storage/dist/socialRuntimeRepo.d.ts +5 -0
- package/packages/storage/dist/socialRuntimeRepo.js +52 -0
- package/packages/storage/src/socialRuntimeRepo.ts +4 -4
- package/packages/storage/tsconfig.json +6 -1
- package/scripts/quickstart.sh +314 -36
- package/scripts/silicaclaw-cli.mjs +466 -24
- package/scripts/silicaclaw-gateway.mjs +475 -0
- package/scripts/webrtc-signaling-server.mjs +89 -5
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { accessSync, constants, cpSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { homedir } from "node:os";
|
|
5
6
|
import { dirname, resolve } from "node:path";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
8
|
|
|
@@ -9,6 +10,37 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
9
10
|
const __dirname = dirname(__filename);
|
|
10
11
|
const ROOT_DIR = resolve(__dirname, "..");
|
|
11
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(readPackageVersion(), 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
|
+
|
|
12
44
|
function run(cmd, args, extra = {}) {
|
|
13
45
|
const result = spawnSync(cmd, args, {
|
|
14
46
|
cwd: ROOT_DIR,
|
|
@@ -17,48 +49,454 @@ function run(cmd, args, extra = {}) {
|
|
|
17
49
|
...extra,
|
|
18
50
|
});
|
|
19
51
|
if (result.error) {
|
|
20
|
-
|
|
52
|
+
headline();
|
|
53
|
+
console.log("");
|
|
54
|
+
console.error(`${paint("Command failed", COLOR.bold, COLOR.yellow)} ${cmd}`);
|
|
55
|
+
console.error(result.error.message);
|
|
21
56
|
process.exit(1);
|
|
22
57
|
}
|
|
23
58
|
process.exit(result.status ?? 0);
|
|
24
59
|
}
|
|
25
60
|
|
|
61
|
+
function runCapture(cmd, args, extra = {}) {
|
|
62
|
+
const result = spawnSync(cmd, args, {
|
|
63
|
+
cwd: ROOT_DIR,
|
|
64
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
65
|
+
encoding: "utf8",
|
|
66
|
+
env: process.env,
|
|
67
|
+
...extra,
|
|
68
|
+
});
|
|
69
|
+
if (result.error) {
|
|
70
|
+
throw result.error;
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function runInherit(cmd, args, extra = {}) {
|
|
76
|
+
const result = spawnSync(cmd, args, {
|
|
77
|
+
cwd: ROOT_DIR,
|
|
78
|
+
stdio: "inherit",
|
|
79
|
+
env: process.env,
|
|
80
|
+
...extra,
|
|
81
|
+
});
|
|
82
|
+
if (result.error) {
|
|
83
|
+
throw result.error;
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
|
|
26
88
|
function readVersion() {
|
|
27
89
|
const versionFile = resolve(ROOT_DIR, "VERSION");
|
|
28
90
|
if (!existsSync(versionFile)) return "unknown";
|
|
29
91
|
return readFileSync(versionFile, "utf8").trim() || "unknown";
|
|
30
92
|
}
|
|
31
93
|
|
|
94
|
+
function readPackageVersion() {
|
|
95
|
+
const pkgFile = resolve(ROOT_DIR, "package.json");
|
|
96
|
+
if (!existsSync(pkgFile)) return "unknown";
|
|
97
|
+
try {
|
|
98
|
+
const pkg = JSON.parse(readFileSync(pkgFile, "utf8"));
|
|
99
|
+
return String(pkg.version || "unknown");
|
|
100
|
+
} catch {
|
|
101
|
+
return "unknown";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function preferredShellRcFile() {
|
|
106
|
+
const shell = String(process.env.SHELL || "");
|
|
107
|
+
if (shell.endsWith("/zsh")) return resolve(homedir(), ".zshrc");
|
|
108
|
+
if (shell.endsWith("/bash")) return resolve(homedir(), ".bashrc");
|
|
109
|
+
if (process.env.ZSH_VERSION) return resolve(homedir(), ".zshrc");
|
|
110
|
+
return resolve(homedir(), ".bashrc");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function userShimDir() {
|
|
114
|
+
return resolve(homedir(), ".silicaclaw", "bin");
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function userShimPath() {
|
|
118
|
+
return resolve(userShimDir(), "silicaclaw");
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function userEnvFile() {
|
|
122
|
+
return resolve(homedir(), ".silicaclaw", "env.sh");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function ensureLineInFile(filePath, block) {
|
|
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) };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function describeFileOwner(filePath) {
|
|
141
|
+
try {
|
|
142
|
+
if (!existsSync(filePath)) return null;
|
|
143
|
+
const stat = statSync(filePath);
|
|
144
|
+
return String(stat.uid);
|
|
145
|
+
} catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function currentUid() {
|
|
151
|
+
try {
|
|
152
|
+
return typeof process.getuid === "function" ? String(process.getuid()) : null;
|
|
153
|
+
} catch {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function shellInitTargets() {
|
|
159
|
+
const home = homedir();
|
|
160
|
+
const shell = String(process.env.SHELL || "");
|
|
161
|
+
const targets = [];
|
|
162
|
+
const add = (filePath) => {
|
|
163
|
+
if (!targets.includes(filePath)) {
|
|
164
|
+
targets.push(filePath);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
if (shell.endsWith("/zsh") || process.env.ZSH_VERSION || existsSync(resolve(home, ".zshrc"))) {
|
|
169
|
+
add(resolve(home, ".zshrc"));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Bash login shells on macOS often read .bash_profile instead of .bashrc.
|
|
173
|
+
if (
|
|
174
|
+
shell.endsWith("/bash") ||
|
|
175
|
+
process.env.BASH_VERSION ||
|
|
176
|
+
existsSync(resolve(home, ".bashrc")) ||
|
|
177
|
+
existsSync(resolve(home, ".bash_profile"))
|
|
178
|
+
) {
|
|
179
|
+
add(resolve(home, ".bashrc"));
|
|
180
|
+
add(resolve(home, ".bash_profile"));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (targets.length === 0) {
|
|
184
|
+
add(preferredShellRcFile());
|
|
185
|
+
}
|
|
186
|
+
return targets;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function installPersistentCommand() {
|
|
190
|
+
const binDir = userShimDir();
|
|
191
|
+
const shimPath = userShimPath();
|
|
192
|
+
const envFile = userEnvFile();
|
|
193
|
+
const envBlock = [
|
|
194
|
+
"#!/usr/bin/env bash",
|
|
195
|
+
'export PATH="$HOME/.silicaclaw/bin:$PATH"',
|
|
196
|
+
"",
|
|
197
|
+
].join("\n");
|
|
198
|
+
const rcBlock = [
|
|
199
|
+
"# >>> silicaclaw >>>",
|
|
200
|
+
'[ -f "$HOME/.silicaclaw/env.sh" ] && . "$HOME/.silicaclaw/env.sh"',
|
|
201
|
+
"# <<< silicaclaw <<<",
|
|
202
|
+
].join("\n");
|
|
203
|
+
|
|
204
|
+
mkdirSync(binDir, { recursive: true });
|
|
205
|
+
writeFileSync(envFile, envBlock, { encoding: "utf8", mode: 0o755 });
|
|
206
|
+
writeFileSync(
|
|
207
|
+
shimPath,
|
|
208
|
+
[
|
|
209
|
+
"#!/usr/bin/env bash",
|
|
210
|
+
"set -euo pipefail",
|
|
211
|
+
'exec npx -y @silicaclaw/cli@beta "$@"',
|
|
212
|
+
"",
|
|
213
|
+
].join("\n"),
|
|
214
|
+
{ encoding: "utf8", mode: 0o755 }
|
|
215
|
+
);
|
|
216
|
+
const rcFiles = shellInitTargets();
|
|
217
|
+
const updatedFiles = [];
|
|
218
|
+
const configuredFiles = [];
|
|
219
|
+
const failedFiles = [];
|
|
220
|
+
for (const filePath of rcFiles) {
|
|
221
|
+
const result = ensureLineInFile(filePath, rcBlock);
|
|
222
|
+
if (result.changed) {
|
|
223
|
+
updatedFiles.push(filePath);
|
|
224
|
+
configuredFiles.push(filePath);
|
|
225
|
+
} else if (!result.error) {
|
|
226
|
+
configuredFiles.push(filePath);
|
|
227
|
+
}
|
|
228
|
+
if (result.error) {
|
|
229
|
+
failedFiles.push({ filePath, error: result.error });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
headline();
|
|
234
|
+
console.log("");
|
|
235
|
+
console.log(`${paint("Installed", COLOR.bold)} \`silicaclaw\` command`);
|
|
236
|
+
kv("Command", "silicaclaw");
|
|
237
|
+
console.log("");
|
|
238
|
+
kv("Activate", `source "${envFile}"`);
|
|
239
|
+
if (configuredFiles.length > 0) {
|
|
240
|
+
kv("Startup", "configured");
|
|
241
|
+
} else {
|
|
242
|
+
kv("Startup", "manual setup required");
|
|
243
|
+
}
|
|
244
|
+
if (failedFiles.length > 0) {
|
|
245
|
+
console.log("");
|
|
246
|
+
console.log(paint("Shell files skipped", COLOR.bold, COLOR.yellow));
|
|
247
|
+
const uid = currentUid();
|
|
248
|
+
for (const item of failedFiles) {
|
|
249
|
+
const owner = describeFileOwner(item.filePath);
|
|
250
|
+
const reason =
|
|
251
|
+
owner && uid && owner !== uid
|
|
252
|
+
? `${item.error} (owned by another user)`
|
|
253
|
+
: item.error;
|
|
254
|
+
kv(item.filePath, reason);
|
|
255
|
+
}
|
|
256
|
+
console.log("");
|
|
257
|
+
kv("Manual", '[ -f "$HOME/.silicaclaw/env.sh" ] && . "$HOME/.silicaclaw/env.sh"');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function isNpxRun() {
|
|
262
|
+
return ROOT_DIR.includes("/.npm/_npx/");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function canWriteGlobalPrefix() {
|
|
266
|
+
try {
|
|
267
|
+
const prefixResult = runCapture("npm", ["prefix", "-g"]);
|
|
268
|
+
if ((prefixResult.status ?? 1) !== 0) return false;
|
|
269
|
+
const prefix = String(prefixResult.stdout || "").trim();
|
|
270
|
+
if (!prefix) return false;
|
|
271
|
+
const targetDir = resolve(prefix, "lib", "node_modules");
|
|
272
|
+
accessSync(targetDir, constants.W_OK);
|
|
273
|
+
return true;
|
|
274
|
+
} catch {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function showUpdateGuide(current, latest, beta) {
|
|
280
|
+
headline();
|
|
281
|
+
console.log("");
|
|
282
|
+
const upToDate = Boolean(beta) && current === beta;
|
|
283
|
+
if (upToDate) {
|
|
284
|
+
kv("Status", `up to date (${current})`);
|
|
285
|
+
} else {
|
|
286
|
+
kv("Status", `beta update available (${beta || "-"})`);
|
|
287
|
+
}
|
|
288
|
+
console.log("");
|
|
289
|
+
kv("Start", "silicaclaw start");
|
|
290
|
+
kv("Status", "silicaclaw status");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function getGatewayStatus() {
|
|
294
|
+
try {
|
|
295
|
+
const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status", "--json"], {
|
|
296
|
+
cwd: process.cwd(),
|
|
297
|
+
});
|
|
298
|
+
if ((result.status ?? 1) !== 0) return null;
|
|
299
|
+
const text = String(result.stdout || "").trim();
|
|
300
|
+
return text ? JSON.parse(text) : null;
|
|
301
|
+
} catch {
|
|
302
|
+
return null;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function isManagedAppDir(appDir) {
|
|
307
|
+
if (!appDir || !existsSync(resolve(appDir, "package.json"))) return false;
|
|
308
|
+
try {
|
|
309
|
+
const pkg = JSON.parse(readFileSync(resolve(appDir, "package.json"), "utf8"));
|
|
310
|
+
const name = String(pkg?.name || "");
|
|
311
|
+
return name === "@silicaclaw/cli" || name === "silicaclaw";
|
|
312
|
+
} catch {
|
|
313
|
+
return false;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function syncCurrentPackageToAppDir(appDir) {
|
|
318
|
+
if (!appDir || resolve(appDir) === ROOT_DIR) return false;
|
|
319
|
+
if (!isManagedAppDir(appDir)) return false;
|
|
320
|
+
|
|
321
|
+
const entries = [
|
|
322
|
+
"apps/local-console",
|
|
323
|
+
"apps/public-explorer",
|
|
324
|
+
"packages/core",
|
|
325
|
+
"packages/network",
|
|
326
|
+
"packages/storage",
|
|
327
|
+
"scripts",
|
|
328
|
+
"README.md",
|
|
329
|
+
"INSTALL.md",
|
|
330
|
+
"CHANGELOG.md",
|
|
331
|
+
"ARCHITECTURE.md",
|
|
332
|
+
"ROADMAP.md",
|
|
333
|
+
"SOCIAL_MD_SPEC.md",
|
|
334
|
+
"DEMO_GUIDE.md",
|
|
335
|
+
"RELEASE_NOTES_v1.0.md",
|
|
336
|
+
"social.md.example",
|
|
337
|
+
"openclaw.social.md.example",
|
|
338
|
+
"VERSION",
|
|
339
|
+
"package.json",
|
|
340
|
+
"package-lock.json",
|
|
341
|
+
];
|
|
342
|
+
|
|
343
|
+
for (const rel of entries) {
|
|
344
|
+
const src = resolve(ROOT_DIR, rel);
|
|
345
|
+
if (!existsSync(src)) continue;
|
|
346
|
+
const dst = resolve(appDir, rel);
|
|
347
|
+
cpSync(src, dst, { recursive: true, force: true });
|
|
348
|
+
}
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function restartGatewayIfRunning() {
|
|
353
|
+
const status = getGatewayStatus();
|
|
354
|
+
const appDir = status?.app_dir ? String(status.app_dir) : "";
|
|
355
|
+
syncCurrentPackageToAppDir(appDir);
|
|
356
|
+
|
|
357
|
+
const localRunning = Boolean(status?.local_console?.running);
|
|
358
|
+
const signalingRunning = Boolean(status?.signaling?.running);
|
|
359
|
+
if (!localRunning && !signalingRunning) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const mode = String(status?.mode || "local");
|
|
364
|
+
const args = [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "restart", `--mode=${mode}`];
|
|
365
|
+
if (mode === "global-preview" && status?.signaling?.url) {
|
|
366
|
+
args.push(`--signaling-url=${status.signaling.url}`);
|
|
367
|
+
}
|
|
368
|
+
if (mode === "global-preview" && status?.signaling?.room) {
|
|
369
|
+
args.push(`--room=${status.signaling.room}`);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
console.log("");
|
|
373
|
+
console.log(paint("Refreshing services", COLOR.bold));
|
|
374
|
+
runInherit("node", args, { cwd: process.cwd() });
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function tryGlobalUpgrade(beta) {
|
|
378
|
+
const writableGlobal = canWriteGlobalPrefix();
|
|
379
|
+
if (!writableGlobal) return false;
|
|
380
|
+
kv("Upgrade", `installing @silicaclaw/cli@${beta} globally`);
|
|
381
|
+
const result = runInherit("npm", ["i", "-g", `@silicaclaw/cli@${beta}`]);
|
|
382
|
+
return (result.status ?? 1) === 0;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function update() {
|
|
386
|
+
const current = readPackageVersion();
|
|
387
|
+
try {
|
|
388
|
+
const result = runCapture("npm", ["view", "@silicaclaw/cli", "dist-tags", "--json"]);
|
|
389
|
+
if ((result.status ?? 1) !== 0) {
|
|
390
|
+
headline();
|
|
391
|
+
console.log("");
|
|
392
|
+
console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
|
|
393
|
+
if (result.stderr) console.error(result.stderr.trim());
|
|
394
|
+
console.log("");
|
|
395
|
+
kv("Try", "npm view @silicaclaw/cli dist-tags --json");
|
|
396
|
+
process.exit(result.status ?? 1);
|
|
397
|
+
}
|
|
398
|
+
const text = String(result.stdout || "").trim();
|
|
399
|
+
const tags = text ? JSON.parse(text) : {};
|
|
400
|
+
const latest = tags.latest ? String(tags.latest) : "";
|
|
401
|
+
const beta = tags.beta ? String(tags.beta) : "";
|
|
402
|
+
showUpdateGuide(current, latest, beta);
|
|
403
|
+
const hasNewBeta = Boolean(beta) && beta !== current;
|
|
404
|
+
const npxRuntime = isNpxRun();
|
|
405
|
+
|
|
406
|
+
if (hasNewBeta) {
|
|
407
|
+
if (npxRuntime) {
|
|
408
|
+
kv("Update", `next run will use ${beta}`);
|
|
409
|
+
} else if (tryGlobalUpgrade(beta)) {
|
|
410
|
+
kv("Update", `installed ${beta}`);
|
|
411
|
+
} else {
|
|
412
|
+
kv("Update", `install ${beta} manually if needed`);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
restartGatewayIfRunning();
|
|
417
|
+
process.exit(0);
|
|
418
|
+
} catch (error) {
|
|
419
|
+
headline();
|
|
420
|
+
console.log("");
|
|
421
|
+
console.error(paint("Update check failed", COLOR.bold, COLOR.yellow));
|
|
422
|
+
console.error(error.message);
|
|
423
|
+
console.log("");
|
|
424
|
+
kv("Try", "npm view @silicaclaw/cli dist-tags --json");
|
|
425
|
+
process.exit(1);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
32
429
|
function help() {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
silicaclaw
|
|
38
|
-
silicaclaw
|
|
39
|
-
silicaclaw
|
|
40
|
-
silicaclaw
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
silicaclaw
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
430
|
+
headline();
|
|
431
|
+
console.log("");
|
|
432
|
+
section("Core commands");
|
|
433
|
+
kv("Install", "npx -y @silicaclaw/cli@beta install");
|
|
434
|
+
kv("Start", "silicaclaw start --mode=global-preview");
|
|
435
|
+
kv("Status", "silicaclaw status");
|
|
436
|
+
kv("Stop", "silicaclaw stop");
|
|
437
|
+
kv("Update", "silicaclaw update");
|
|
438
|
+
console.log("");
|
|
439
|
+
section("Setup and network");
|
|
440
|
+
kv("Onboard", "silicaclaw onboard");
|
|
441
|
+
kv("Connect", "silicaclaw connect");
|
|
442
|
+
kv("Gateway", "silicaclaw gateway <start|stop|restart|status|logs>");
|
|
443
|
+
kv("Signaling", "silicaclaw signaling");
|
|
444
|
+
console.log("");
|
|
445
|
+
section("Local apps");
|
|
446
|
+
kv("Console", "silicaclaw local-console");
|
|
447
|
+
kv("Explorer", "silicaclaw explorer");
|
|
448
|
+
kv("Doctor", "silicaclaw doctor");
|
|
449
|
+
kv("Version", "silicaclaw version");
|
|
450
|
+
kv("Help", "silicaclaw help");
|
|
54
451
|
}
|
|
55
452
|
|
|
56
453
|
const cmd = String(process.argv[2] || "help").trim().toLowerCase();
|
|
57
454
|
|
|
58
455
|
switch (cmd) {
|
|
59
456
|
case "onboard":
|
|
457
|
+
headline();
|
|
458
|
+
console.log("");
|
|
459
|
+
section("Opening onboarding");
|
|
460
|
+
kv("Mode", "interactive setup");
|
|
461
|
+
kv("Focus", "install command, profile, internet relay");
|
|
462
|
+
console.log("");
|
|
60
463
|
run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")]);
|
|
61
464
|
break;
|
|
465
|
+
case "connect":
|
|
466
|
+
headline();
|
|
467
|
+
console.log("");
|
|
468
|
+
section("Opening connect wizard");
|
|
469
|
+
kv("Mode", "global-preview first");
|
|
470
|
+
kv("Relay", "https://relay.silicaclaw.com");
|
|
471
|
+
console.log("");
|
|
472
|
+
run("bash", [resolve(ROOT_DIR, "scripts", "quickstart.sh")], {
|
|
473
|
+
env: {
|
|
474
|
+
...process.env,
|
|
475
|
+
QUICKSTART_DEFAULT_MODE: "3",
|
|
476
|
+
QUICKSTART_CONNECT_MODE: "1",
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
break;
|
|
480
|
+
case "update":
|
|
481
|
+
update();
|
|
482
|
+
break;
|
|
483
|
+
case "install":
|
|
484
|
+
installPersistentCommand();
|
|
485
|
+
break;
|
|
486
|
+
case "gateway":
|
|
487
|
+
run("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), ...process.argv.slice(3)], {
|
|
488
|
+
cwd: process.cwd(),
|
|
489
|
+
});
|
|
490
|
+
break;
|
|
491
|
+
case "start":
|
|
492
|
+
case "stop":
|
|
493
|
+
case "restart":
|
|
494
|
+
case "status":
|
|
495
|
+
case "logs":
|
|
496
|
+
run("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), cmd, ...process.argv.slice(3)], {
|
|
497
|
+
cwd: process.cwd(),
|
|
498
|
+
});
|
|
499
|
+
break;
|
|
62
500
|
case "local-console":
|
|
63
501
|
case "console":
|
|
64
502
|
run("npm", ["run", "local-console"]);
|
|
@@ -72,12 +510,16 @@ switch (cmd) {
|
|
|
72
510
|
run("npm", ["run", "webrtc-signaling"]);
|
|
73
511
|
break;
|
|
74
512
|
case "doctor":
|
|
513
|
+
headline();
|
|
514
|
+
console.log("");
|
|
515
|
+
section("Running health checks");
|
|
516
|
+
console.log("");
|
|
75
517
|
run("npm", ["run", "health"]);
|
|
76
518
|
break;
|
|
77
519
|
case "version":
|
|
78
520
|
case "-v":
|
|
79
521
|
case "--version":
|
|
80
|
-
|
|
522
|
+
headline();
|
|
81
523
|
break;
|
|
82
524
|
case "help":
|
|
83
525
|
case "-h":
|