clementine-agent 1.18.145 → 1.18.146
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/dist/cli/index.js +56 -17
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -463,31 +463,59 @@ function cmdStop() {
|
|
|
463
463
|
catch { /* ignore */ }
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* 1.18.146 — Spawn the dashboard child detached + briefly verify it's
|
|
468
|
+
* listening on :3030. Used by both `restart` and `update` so the
|
|
469
|
+
* dashboard reliably comes back after a daemon refresh.
|
|
470
|
+
*
|
|
471
|
+
* The dashboard token rotates on each spawn — print the fresh URL so
|
|
472
|
+
* the user's old browser tab (which would silently 401 on the stale
|
|
473
|
+
* token) doesn't waste their time.
|
|
474
|
+
*/
|
|
475
|
+
async function relaunchDashboardDetached() {
|
|
476
|
+
try {
|
|
477
|
+
const { spawn: spawnProc } = await import('node:child_process');
|
|
478
|
+
const child = spawnProc('node', [path.join(PACKAGE_ROOT, 'dist/cli/index.js'), 'dashboard'], { detached: true, stdio: 'ignore' });
|
|
479
|
+
child.unref();
|
|
480
|
+
// Brief liveness wait — give the child ~3s to bind before we
|
|
481
|
+
// print the URL. If it never binds, the URL still prints (user
|
|
482
|
+
// can retry) but we surface the failure in logs.
|
|
483
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
484
|
+
let token = '';
|
|
485
|
+
try {
|
|
486
|
+
const tokenPath = path.join(BASE_DIR, '.dashboard-token');
|
|
487
|
+
if (existsSync(tokenPath))
|
|
488
|
+
token = readFileSync(tokenPath, 'utf-8').trim();
|
|
489
|
+
}
|
|
490
|
+
catch { /* token may not be ready yet */ }
|
|
491
|
+
if (token) {
|
|
492
|
+
console.log(` Dashboard relaunched: http://localhost:3030/?token=${token}`);
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
console.log(' Dashboard relaunched (token not ready — check `clementine status`).');
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
catch {
|
|
499
|
+
console.log(' Could not relaunch dashboard — run: clementine dashboard');
|
|
500
|
+
}
|
|
501
|
+
}
|
|
466
502
|
async function cmdRestart(options) {
|
|
467
503
|
cmdStop();
|
|
468
|
-
// Kill ALL dashboard processes (not just PID file — catches orphans)
|
|
469
|
-
|
|
504
|
+
// Kill ALL dashboard processes (not just PID file — catches orphans).
|
|
505
|
+
// Restart implies "I want a fresh dashboard too" — always respawn,
|
|
506
|
+
// not just when the kill check found one. Closes the race where the
|
|
507
|
+
// dashboard had crashed (or been killed by an earlier `clementine
|
|
508
|
+
// update`) before restart ran, leaving the user with no dashboard.
|
|
470
509
|
try {
|
|
471
510
|
const { killExistingDashboards } = await import('./dashboard.js');
|
|
472
511
|
const killed = killExistingDashboards();
|
|
473
512
|
if (killed > 0) {
|
|
474
|
-
dashboardWasRunning = true;
|
|
475
513
|
console.log(` Stopped ${killed} dashboard process(es).`);
|
|
476
514
|
}
|
|
477
515
|
}
|
|
478
516
|
catch { /* dashboard module may not be available */ }
|
|
479
517
|
await cmdLaunch({ foreground: options.foreground });
|
|
480
|
-
|
|
481
|
-
try {
|
|
482
|
-
const { spawn: spawnProc } = await import('node:child_process');
|
|
483
|
-
const child = spawnProc('node', [path.join(PACKAGE_ROOT, 'dist/cli/index.js'), 'dashboard'], { detached: true, stdio: 'ignore' });
|
|
484
|
-
child.unref();
|
|
485
|
-
console.log(' Dashboard relaunched.');
|
|
486
|
-
}
|
|
487
|
-
catch {
|
|
488
|
-
console.log(' Could not relaunch dashboard — run: clementine dashboard');
|
|
489
|
-
}
|
|
490
|
-
}
|
|
518
|
+
await relaunchDashboardDetached();
|
|
491
519
|
}
|
|
492
520
|
function cmdStatus() {
|
|
493
521
|
const DIM = '\x1b[0;90m';
|
|
@@ -4262,10 +4290,13 @@ async function cmdUpdate(options) {
|
|
|
4262
4290
|
}
|
|
4263
4291
|
}
|
|
4264
4292
|
catch { /* no dashboard running */ }
|
|
4265
|
-
//
|
|
4266
|
-
//
|
|
4293
|
+
// 1.18.146 — `dashboardWasRunning` was previously dropped on the
|
|
4294
|
+
// floor here (the comment said "the daemon restart below will handle
|
|
4295
|
+
// it" — but cmdRestart's own dashboard detection runs after this kill
|
|
4296
|
+
// so it sees zero and never respawns). Now we explicitly remember to
|
|
4297
|
+
// respawn at the end of update if the user had a dashboard up before.
|
|
4267
4298
|
if (dashboardWasRunning) {
|
|
4268
|
-
console.log(`
|
|
4299
|
+
console.log(` ${GREEN}OK${RESET} Dashboard will relaunch after daemon restart.`);
|
|
4269
4300
|
}
|
|
4270
4301
|
// 12. Write update sentinel so the daemon can report what happened
|
|
4271
4302
|
let commitHash = '';
|
|
@@ -4399,6 +4430,14 @@ async function cmdUpdate(options) {
|
|
|
4399
4430
|
}
|
|
4400
4431
|
catch { /* .env read failed */ }
|
|
4401
4432
|
}
|
|
4433
|
+
// 13.5. Respawn dashboard if it was running before the update.
|
|
4434
|
+
// 1.18.146 — closes the bug where `clementine update restart` left
|
|
4435
|
+
// users with no dashboard because the kill at step 11 above robbed
|
|
4436
|
+
// cmdRestart of its respawn signal. Now we own the respawn here
|
|
4437
|
+
// when we own the kill.
|
|
4438
|
+
if (dashboardWasRunning) {
|
|
4439
|
+
await relaunchDashboardDetached();
|
|
4440
|
+
}
|
|
4402
4441
|
// 14. Show current version
|
|
4403
4442
|
console.log();
|
|
4404
4443
|
if (previousVersion !== 'unknown' && newVersion !== 'unknown' && previousVersion !== newVersion) {
|