clementine-agent 1.18.145 → 1.18.147
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/dashboard.js +22 -0
- package/dist/cli/index.js +87 -17
- package/package.json +1 -1
package/dist/cli/dashboard.js
CHANGED
|
@@ -1754,6 +1754,28 @@ export async function cmdDashboard(opts) {
|
|
|
1754
1754
|
}
|
|
1755
1755
|
catch { /* ignore */ }
|
|
1756
1756
|
};
|
|
1757
|
+
// 1.18.147 — Auto-open the dashboard URL in the user's default
|
|
1758
|
+
// browser once the child has had a chance to bind + write the
|
|
1759
|
+
// token file. Direct `clementine dashboard` invocations now match
|
|
1760
|
+
// the restart/update flow so the user never has to copy-paste a
|
|
1761
|
+
// token by hand. Honors NO_BROWSER=1 for headless / CI runs.
|
|
1762
|
+
if (process.env.NO_BROWSER !== '1') {
|
|
1763
|
+
setTimeout(() => {
|
|
1764
|
+
try {
|
|
1765
|
+
const tokenPath = path.join(BASE_DIR, '.dashboard-token');
|
|
1766
|
+
const token = existsSync(tokenPath) ? readFileSync(tokenPath, 'utf-8').trim() : '';
|
|
1767
|
+
if (!token)
|
|
1768
|
+
return;
|
|
1769
|
+
const url = `http://localhost:${childPort}/?token=${token}`;
|
|
1770
|
+
const platform = process.platform;
|
|
1771
|
+
const cmd = platform === 'darwin' ? 'open'
|
|
1772
|
+
: platform === 'win32' ? 'start'
|
|
1773
|
+
: 'xdg-open';
|
|
1774
|
+
spawn(cmd, [url], { detached: true, stdio: 'ignore' }).unref();
|
|
1775
|
+
}
|
|
1776
|
+
catch { /* best effort */ }
|
|
1777
|
+
}, 1500);
|
|
1778
|
+
}
|
|
1757
1779
|
// Forward signals to child
|
|
1758
1780
|
process.on('SIGINT', () => { child.kill('SIGINT'); cleanup(); process.exit(0); });
|
|
1759
1781
|
process.on('SIGTERM', () => { child.kill('SIGTERM'); cleanup(); process.exit(0); });
|
package/dist/cli/index.js
CHANGED
|
@@ -463,31 +463,90 @@ 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
|
+
/**
|
|
476
|
+
* 1.18.147 — Open the dashboard URL in the user's default browser.
|
|
477
|
+
*
|
|
478
|
+
* Invoked after the dashboard child binds. Best-effort cross-platform:
|
|
479
|
+
* macOS uses `open`, Windows uses `start`, Linux falls back to
|
|
480
|
+
* `xdg-open`. Failures are swallowed (no native browser, headless
|
|
481
|
+
* SSH session, etc.) — the printed URL is still the source of truth
|
|
482
|
+
* the user can copy by hand.
|
|
483
|
+
*
|
|
484
|
+
* Honors NO_BROWSER=1 env var so CI / scripted runs don't get a
|
|
485
|
+
* spurious browser tab.
|
|
486
|
+
*/
|
|
487
|
+
function openInBrowser(url) {
|
|
488
|
+
if (process.env.NO_BROWSER === '1')
|
|
489
|
+
return;
|
|
490
|
+
const platform = process.platform;
|
|
491
|
+
const cmd = platform === 'darwin' ? 'open'
|
|
492
|
+
: platform === 'win32' ? 'start'
|
|
493
|
+
: 'xdg-open';
|
|
494
|
+
try {
|
|
495
|
+
const { spawn: spawnProc } = require('node:child_process');
|
|
496
|
+
spawnProc(cmd, [url], { detached: true, stdio: 'ignore' }).unref();
|
|
497
|
+
}
|
|
498
|
+
catch { /* no browser available; URL was already printed */ }
|
|
499
|
+
}
|
|
500
|
+
async function relaunchDashboardDetached(opts = {}) {
|
|
501
|
+
try {
|
|
502
|
+
const { spawn: spawnProc } = await import('node:child_process');
|
|
503
|
+
const child = spawnProc('node', [path.join(PACKAGE_ROOT, 'dist/cli/index.js'), 'dashboard'], { detached: true, stdio: 'ignore' });
|
|
504
|
+
child.unref();
|
|
505
|
+
// Brief liveness wait — give the child ~3s to bind before we
|
|
506
|
+
// print the URL. If it never binds, the URL still prints (user
|
|
507
|
+
// can retry) but we surface the failure in logs.
|
|
508
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
509
|
+
let token = '';
|
|
510
|
+
try {
|
|
511
|
+
const tokenPath = path.join(BASE_DIR, '.dashboard-token');
|
|
512
|
+
if (existsSync(tokenPath))
|
|
513
|
+
token = readFileSync(tokenPath, 'utf-8').trim();
|
|
514
|
+
}
|
|
515
|
+
catch { /* token may not be ready yet */ }
|
|
516
|
+
if (token) {
|
|
517
|
+
const url = `http://localhost:3030/?token=${token}`;
|
|
518
|
+
console.log(` Dashboard relaunched: ${url}`);
|
|
519
|
+
// 1.18.147 — auto-open the browser by default. Restart/update
|
|
520
|
+
// already imply user wants the dashboard back; making them copy a
|
|
521
|
+
// URL was a UX papercut.
|
|
522
|
+
if (opts.open !== false)
|
|
523
|
+
openInBrowser(url);
|
|
524
|
+
}
|
|
525
|
+
else {
|
|
526
|
+
console.log(' Dashboard relaunched (token not ready — check `clementine status`).');
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
catch {
|
|
530
|
+
console.log(' Could not relaunch dashboard — run: clementine dashboard');
|
|
531
|
+
}
|
|
532
|
+
}
|
|
466
533
|
async function cmdRestart(options) {
|
|
467
534
|
cmdStop();
|
|
468
|
-
// Kill ALL dashboard processes (not just PID file — catches orphans)
|
|
469
|
-
|
|
535
|
+
// Kill ALL dashboard processes (not just PID file — catches orphans).
|
|
536
|
+
// Restart implies "I want a fresh dashboard too" — always respawn,
|
|
537
|
+
// not just when the kill check found one. Closes the race where the
|
|
538
|
+
// dashboard had crashed (or been killed by an earlier `clementine
|
|
539
|
+
// update`) before restart ran, leaving the user with no dashboard.
|
|
470
540
|
try {
|
|
471
541
|
const { killExistingDashboards } = await import('./dashboard.js');
|
|
472
542
|
const killed = killExistingDashboards();
|
|
473
543
|
if (killed > 0) {
|
|
474
|
-
dashboardWasRunning = true;
|
|
475
544
|
console.log(` Stopped ${killed} dashboard process(es).`);
|
|
476
545
|
}
|
|
477
546
|
}
|
|
478
547
|
catch { /* dashboard module may not be available */ }
|
|
479
548
|
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
|
-
}
|
|
549
|
+
await relaunchDashboardDetached();
|
|
491
550
|
}
|
|
492
551
|
function cmdStatus() {
|
|
493
552
|
const DIM = '\x1b[0;90m';
|
|
@@ -4262,10 +4321,13 @@ async function cmdUpdate(options) {
|
|
|
4262
4321
|
}
|
|
4263
4322
|
}
|
|
4264
4323
|
catch { /* no dashboard running */ }
|
|
4265
|
-
//
|
|
4266
|
-
//
|
|
4324
|
+
// 1.18.146 — `dashboardWasRunning` was previously dropped on the
|
|
4325
|
+
// floor here (the comment said "the daemon restart below will handle
|
|
4326
|
+
// it" — but cmdRestart's own dashboard detection runs after this kill
|
|
4327
|
+
// so it sees zero and never respawns). Now we explicitly remember to
|
|
4328
|
+
// respawn at the end of update if the user had a dashboard up before.
|
|
4267
4329
|
if (dashboardWasRunning) {
|
|
4268
|
-
console.log(`
|
|
4330
|
+
console.log(` ${GREEN}OK${RESET} Dashboard will relaunch after daemon restart.`);
|
|
4269
4331
|
}
|
|
4270
4332
|
// 12. Write update sentinel so the daemon can report what happened
|
|
4271
4333
|
let commitHash = '';
|
|
@@ -4399,6 +4461,14 @@ async function cmdUpdate(options) {
|
|
|
4399
4461
|
}
|
|
4400
4462
|
catch { /* .env read failed */ }
|
|
4401
4463
|
}
|
|
4464
|
+
// 13.5. Respawn dashboard if it was running before the update.
|
|
4465
|
+
// 1.18.146 — closes the bug where `clementine update restart` left
|
|
4466
|
+
// users with no dashboard because the kill at step 11 above robbed
|
|
4467
|
+
// cmdRestart of its respawn signal. Now we own the respawn here
|
|
4468
|
+
// when we own the kill.
|
|
4469
|
+
if (dashboardWasRunning) {
|
|
4470
|
+
await relaunchDashboardDetached();
|
|
4471
|
+
}
|
|
4402
4472
|
// 14. Show current version
|
|
4403
4473
|
console.log();
|
|
4404
4474
|
if (previousVersion !== 'unknown' && newVersion !== 'unknown' && previousVersion !== newVersion) {
|