@silicaclaw/cli 2026.3.18-2 → 2026.3.18-3

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 CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## v1.0 beta - 2026-03-18
4
4
 
5
+ ### 2026.3.18-3
6
+
7
+ - local-console sidebar + gateway stop reliability:
8
+ - left sidebar bottom version is now rendered as a single stable version label so it no longer disappears
9
+ - `silicaclaw stop` now also stops leftover SilicaClaw-owned listeners on ports `4310` and `4510`
10
+ - users no longer need to manually kill the local-console process after `stop`
11
+
5
12
  ### Beta 28
6
13
 
7
14
  - local-console version visibility:
package/VERSION CHANGED
@@ -1 +1 @@
1
- v2026.3.18.02
1
+ v2026.3.18-3
@@ -270,7 +270,6 @@
270
270
  .app.nav-collapsed .brand h1,
271
271
  .app.nav-collapsed .brand p,
272
272
  .app.nav-collapsed .sidebar-foot,
273
- .app.nav-collapsed .sidebar-version__label,
274
273
  .app.nav-collapsed .sidebar-nav__label {
275
274
  display: none;
276
275
  }
@@ -332,9 +331,6 @@
332
331
  justify-content: center;
333
332
  border-radius: 16px;
334
333
  }
335
- .app.nav-collapsed .sidebar-version__text {
336
- display: none;
337
- }
338
334
 
339
335
  .nav {
340
336
  display: grid;
@@ -463,8 +459,7 @@
463
459
  margin-top: 10px;
464
460
  display: flex;
465
461
  align-items: center;
466
- justify-content: space-between;
467
- gap: 10px;
462
+ justify-content: center;
468
463
  min-height: 40px;
469
464
  padding: 0 12px;
470
465
  border-radius: 14px;
@@ -472,41 +467,20 @@
472
467
  border: 1px solid color-mix(in srgb, var(--border) 72%, transparent);
473
468
  box-shadow: none;
474
469
  }
475
- .sidebar-version__label {
476
- display: inline-flex;
477
- align-items: center;
478
- gap: 6px;
479
- font-size: 11px;
480
- font-weight: 600;
481
- color: var(--muted);
482
- text-transform: uppercase;
483
- letter-spacing: 0.06em;
484
- }
485
470
  .sidebar-version__text {
486
471
  font-size: 12px;
487
472
  color: var(--text);
488
473
  font-weight: 600;
489
- }
490
- .sidebar-version__status {
491
- width: 8px;
492
- height: 8px;
493
- border-radius: 999px;
494
- flex-shrink: 0;
495
- margin-left: auto;
496
- background: var(--danger);
497
- box-shadow: 0 0 0 4px color-mix(in srgb, var(--danger) 14%, transparent);
498
- }
499
- .sidebar-version__status.online {
500
- background: var(--ok);
501
- box-shadow: 0 0 0 4px color-mix(in srgb, var(--ok) 14%, transparent);
474
+ line-height: 1.2;
475
+ white-space: nowrap;
476
+ overflow: hidden;
477
+ text-overflow: ellipsis;
478
+ text-align: center;
502
479
  }
503
480
  .app.nav-collapsed .sidebar-version {
504
481
  justify-content: center;
505
482
  padding: 0;
506
483
  }
507
- .app.nav-collapsed .sidebar-version__status {
508
- margin-left: 0;
509
- }
510
484
 
511
485
  .main {
512
486
  display: flex;
@@ -1273,9 +1247,7 @@
1273
1247
  </div>
1274
1248
  <div class="sidebar-shell__footer">
1275
1249
  <div class="sidebar-version" title="Current version">
1276
- <span class="sidebar-version__label"><span class="version-dot"></span>Version</span>
1277
1250
  <span class="sidebar-version__text" id="brandVersion">-</span>
1278
- <span class="sidebar-version__status" id="brandStatusDot" aria-hidden="true"></span>
1279
1251
  </div>
1280
1252
  </div>
1281
1253
  </div>
@@ -2245,7 +2217,6 @@
2245
2217
  document.getElementById('sidebarToggleBtn').title = t('labels.collapseSidebar');
2246
2218
  document.getElementById('sidebarToggleBtn').setAttribute('aria-label', t('labels.collapseSidebar'));
2247
2219
  document.querySelector('.sidebar-version').title = t('common.version');
2248
- setText('.sidebar-version__label', t('common.version'));
2249
2220
  setText('.dashboard-header__breadcrumb-current', t('pageMeta.overview.title'));
2250
2221
  document.getElementById('topbarTitle').textContent = t('common.localConsole');
2251
2222
  document.getElementById('topbarSubtitle').textContent = t('common.subtitle');
@@ -2867,7 +2838,6 @@
2867
2838
  mode,
2868
2839
  public: status.public_enabled ? t('common.on') : t('common.off'),
2869
2840
  });
2870
- document.getElementById('brandStatusDot').classList.toggle('online', !!status.connected_to_silicaclaw);
2871
2841
  const reasons = [];
2872
2842
  if (!status.configured && status.configured_reason) reasons.push(t('social.configuredReason', { reason: status.configured_reason }));
2873
2843
  if (!status.running && status.running_reason) reasons.push(t('social.runningReason', { reason: status.running_reason }));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silicaclaw/cli",
3
- "version": "2026.3.18-2",
3
+ "version": "2026.3.18-3",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -314,6 +314,38 @@ function listeningProcessOnPort(port) {
314
314
  }
315
315
  }
316
316
 
317
+ function normalizePathForMatch(value) {
318
+ return String(value || "").replace(/\\/g, "/");
319
+ }
320
+
321
+ function isOwnedListener(listener, kind) {
322
+ if (!listener?.command) return false;
323
+ const command = normalizePathForMatch(listener.command).toLowerCase();
324
+ const appDir = normalizePathForMatch(APP_DIR).toLowerCase();
325
+ const rootDir = normalizePathForMatch(ROOT_DIR).toLowerCase();
326
+ const inWorkspace = command.includes(appDir) || command.includes(rootDir);
327
+ if (!inWorkspace) return false;
328
+ if (kind === "local-console") {
329
+ return (
330
+ command.includes("@silicaclaw/local-console") ||
331
+ command.includes("/apps/local-console/") ||
332
+ command.includes("src/server.ts") ||
333
+ command.includes("dist/server.js")
334
+ );
335
+ }
336
+ if (kind === "signaling") {
337
+ return command.includes("webrtc-signaling-server.mjs") || command.includes("npm run webrtc-signaling");
338
+ }
339
+ return false;
340
+ }
341
+
342
+ async function stopOwnedListener(port, kind) {
343
+ const listener = listeningProcessOnPort(port);
344
+ if (!listener || !isOwnedListener(listener, kind)) return false;
345
+ await stopPid(Number(listener.pid), kind);
346
+ return true;
347
+ }
348
+
317
349
  function printStopSummary() {
318
350
  const localListener = listeningProcessOnPort(4310);
319
351
  const signalingListener = listeningProcessOnPort(4510);
@@ -357,6 +389,8 @@ async function stopAll() {
357
389
  const sigPid = readPid(SIGNALING_PID_FILE);
358
390
  await stopPid(localPid, "local-console");
359
391
  await stopPid(sigPid, "signaling");
392
+ await stopOwnedListener(4310, "local-console");
393
+ await stopOwnedListener(4510, "signaling");
360
394
  removeFileIfExists(CONSOLE_PID_FILE);
361
395
  removeFileIfExists(SIGNALING_PID_FILE);
362
396
  writeState({