@silicaclaw/cli 1.0.0-beta.16 → 1.0.0-beta.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silicaclaw/cli",
3
- "version": "1.0.0-beta.16",
3
+ "version": "1.0.0-beta.18",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -37,6 +37,19 @@ function runCapture(cmd, args, extra = {}) {
37
37
  return result;
38
38
  }
39
39
 
40
+ function runInherit(cmd, args, extra = {}) {
41
+ const result = spawnSync(cmd, args, {
42
+ cwd: ROOT_DIR,
43
+ stdio: "inherit",
44
+ env: process.env,
45
+ ...extra,
46
+ });
47
+ if (result.error) {
48
+ throw result.error;
49
+ }
50
+ return result;
51
+ }
52
+
40
53
  function readVersion() {
41
54
  const versionFile = resolve(ROOT_DIR, "VERSION");
42
55
  if (!existsSync(versionFile)) return "unknown";
@@ -112,6 +125,49 @@ function showUpdateGuide(current, latest, beta) {
112
125
  }
113
126
  }
114
127
 
128
+ function getGatewayStatus() {
129
+ try {
130
+ const result = runCapture("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "status"], {
131
+ cwd: process.cwd(),
132
+ });
133
+ if ((result.status ?? 1) !== 0) return null;
134
+ const text = String(result.stdout || "").trim();
135
+ return text ? JSON.parse(text) : null;
136
+ } catch {
137
+ return null;
138
+ }
139
+ }
140
+
141
+ function restartGatewayIfRunning() {
142
+ const status = getGatewayStatus();
143
+ const localRunning = Boolean(status?.local_console?.running);
144
+ const signalingRunning = Boolean(status?.signaling?.running);
145
+ if (!localRunning && !signalingRunning) {
146
+ console.log("Gateway not running: no restart needed.");
147
+ return;
148
+ }
149
+
150
+ const mode = String(status?.mode || "local");
151
+ const args = [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), "restart", `--mode=${mode}`];
152
+ if (mode === "global-preview" && status?.signaling?.url) {
153
+ args.push(`--signaling-url=${status.signaling.url}`);
154
+ }
155
+ if (mode === "global-preview" && status?.signaling?.room) {
156
+ args.push(`--room=${status.signaling.room}`);
157
+ }
158
+
159
+ console.log("Refreshing gateway services...");
160
+ runInherit("node", args, { cwd: process.cwd() });
161
+ }
162
+
163
+ function tryGlobalUpgrade(beta) {
164
+ const writableGlobal = canWriteGlobalPrefix();
165
+ if (!writableGlobal) return false;
166
+ console.log(`Installing @silicaclaw/cli@${beta} globally...`);
167
+ const result = runInherit("npm", ["i", "-g", `@silicaclaw/cli@${beta}`]);
168
+ return (result.status ?? 1) === 0;
169
+ }
170
+
115
171
  function update() {
116
172
  const current = readPackageVersion();
117
173
  try {
@@ -126,6 +182,20 @@ function update() {
126
182
  const latest = tags.latest ? String(tags.latest) : "";
127
183
  const beta = tags.beta ? String(tags.beta) : "";
128
184
  showUpdateGuide(current, latest, beta);
185
+ const hasNewBeta = Boolean(beta) && beta !== current;
186
+ const npxRuntime = isNpxRun();
187
+
188
+ if (hasNewBeta) {
189
+ if (npxRuntime) {
190
+ console.log(`New beta detected (${beta}). npx will use latest on next run.`);
191
+ } else if (tryGlobalUpgrade(beta)) {
192
+ console.log(`Global upgrade completed: ${beta}`);
193
+ } else {
194
+ console.log("Skipped global upgrade (no write permission or upgrade failed).");
195
+ }
196
+ }
197
+
198
+ restartGatewayIfRunning();
129
199
  process.exit(0);
130
200
  } catch (error) {
131
201
  console.error(`Update check failed: ${error.message}`);
@@ -143,6 +213,11 @@ Usage:
143
213
  silicaclaw onboard
144
214
  silicaclaw connect
145
215
  silicaclaw update
216
+ silicaclaw start [--mode=local|lan|global-preview]
217
+ silicaclaw stop
218
+ silicaclaw restart [--mode=local|lan|global-preview]
219
+ silicaclaw status
220
+ silicaclaw logs [local-console|signaling]
146
221
  silicaclaw gateway <start|stop|restart|status|logs>
147
222
  silicaclaw local-console
148
223
  silicaclaw explorer
@@ -155,6 +230,11 @@ Commands:
155
230
  onboard Interactive step-by-step onboarding (recommended)
156
231
  connect Cross-network connect wizard (global-preview first)
157
232
  update Check latest npm version and show upgrade commands
233
+ start Start gateway-managed background services
234
+ stop Stop gateway-managed background services
235
+ restart Restart gateway-managed background services
236
+ status Show gateway-managed service status
237
+ logs Show gateway-managed service logs
158
238
  gateway Manage background services (start/stop/restart/status/logs)
159
239
  local-console Start local console (http://localhost:4310)
160
240
  explorer Start public explorer (http://localhost:4311)
@@ -188,6 +268,15 @@ switch (cmd) {
188
268
  cwd: process.cwd(),
189
269
  });
190
270
  break;
271
+ case "start":
272
+ case "stop":
273
+ case "restart":
274
+ case "status":
275
+ case "logs":
276
+ run("node", [resolve(ROOT_DIR, "scripts", "silicaclaw-gateway.mjs"), cmd, ...process.argv.slice(3)], {
277
+ cwd: process.cwd(),
278
+ });
279
+ break;
191
280
  case "local-console":
192
281
  case "console":
193
282
  run("npm", ["run", "local-console"]);
@@ -13,6 +13,25 @@ const ROOT_DIR = resolve(__dirname, "..");
13
13
  const argv = process.argv.slice(2);
14
14
  const cmd = String(argv[0] || "help").toLowerCase();
15
15
 
16
+ function readJson(file) {
17
+ try {
18
+ return JSON.parse(String(readFileSync(file, "utf8")));
19
+ } catch {
20
+ return null;
21
+ }
22
+ }
23
+
24
+ function isSilicaClawDir(dir) {
25
+ const pkgPath = join(dir, "package.json");
26
+ if (!existsSync(pkgPath)) return false;
27
+ const pkg = readJson(pkgPath);
28
+ if (!pkg || typeof pkg !== "object") return false;
29
+ const name = String(pkg.name || "");
30
+ if (name === "@silicaclaw/cli" || name === "silicaclaw") return true;
31
+ const scripts = pkg.scripts && typeof pkg.scripts === "object" ? pkg.scripts : {};
32
+ return Boolean(scripts.gateway || scripts["local-console"] || scripts["public-explorer"]);
33
+ }
34
+
16
35
  function parseFlag(name, fallback = "") {
17
36
  const prefix = `--${name}=`;
18
37
  for (const item of argv) {
@@ -27,17 +46,17 @@ function hasFlag(name) {
27
46
 
28
47
  function detectAppDir() {
29
48
  const envDir = process.env.SILICACLAW_APP_DIR;
30
- if (envDir && existsSync(join(envDir, "package.json"))) {
49
+ if (envDir && isSilicaClawDir(envDir)) {
31
50
  return resolve(envDir);
32
51
  }
33
52
 
34
53
  const cwd = process.cwd();
35
- if (existsSync(join(cwd, "package.json"))) {
54
+ if (isSilicaClawDir(cwd)) {
36
55
  return resolve(cwd);
37
56
  }
38
57
 
39
58
  const homeCandidate = join(homedir(), "silicaclaw");
40
- if (existsSync(join(homeCandidate, "package.json"))) {
59
+ if (isSilicaClawDir(homeCandidate)) {
41
60
  return resolve(homeCandidate);
42
61
  }
43
62
 
@@ -209,9 +228,9 @@ function printConnectionSummary(status) {
209
228
  console.log(`- signaling: ${signalingUrl} (room=${room})`);
210
229
  }
211
230
  console.log(`- local-console log: ${status?.local_console?.log_file || CONSOLE_LOG_FILE}`);
212
- console.log(`- status: cd "${APP_DIR}" && npm run gateway -- status`);
213
- console.log(`- logs: cd "${APP_DIR}" && npm run gateway -- logs local-console`);
214
- console.log(`- stop: cd "${APP_DIR}" && npm run gateway -- stop`);
231
+ console.log(`- status: silicaclaw gateway status`);
232
+ console.log(`- logs: silicaclaw gateway logs local-console`);
233
+ console.log(`- stop: silicaclaw gateway stop`);
215
234
  }
216
235
 
217
236
  function listeningProcessOnPort(port) {
@@ -260,7 +279,7 @@ function printStopSummary() {
260
279
  console.log(` inspect: lsof -nP -iTCP:4510 -sTCP:LISTEN`);
261
280
  console.log(` stop it: kill ${signalingListener.pid}`);
262
281
  }
263
- console.log(`- check status: cd "${APP_DIR}" && npm run gateway -- status`);
282
+ console.log(`- check status: silicaclaw gateway status`);
264
283
  }
265
284
 
266
285
  function tailFile(file, lines = 80) {