@yemi33/minions 0.1.1825 → 0.1.1826
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 +5 -0
- package/bin/minions.js +81 -11
- package/engine/copilot-models.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/bin/minions.js
CHANGED
|
@@ -86,6 +86,43 @@ function hasRecentDashboardBrowserTab(minionsHome, now = Date.now()) {
|
|
|
86
86
|
} catch { return false; }
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
// Clear the browser-presence cache. Pre-restart beacons can outlive the
|
|
90
|
+
// browser window that produced them (closed Edge, locked-screen RDP session,
|
|
91
|
+
// stale heuristic timer) and falsely tell `restart` to skip the auto-open. We
|
|
92
|
+
// wipe it during restart so the post-restart probe only counts beacons that
|
|
93
|
+
// arrive AFTER the new dashboard is up — i.e. from a still-living tab.
|
|
94
|
+
function _clearDashboardBrowserState(minionsHome) {
|
|
95
|
+
try {
|
|
96
|
+
const fp = path.join(minionsHome, 'engine', 'dashboard-browser.json');
|
|
97
|
+
fs.writeFileSync(fp, JSON.stringify({ tabs: {}, updatedAt: new Date().toISOString() }));
|
|
98
|
+
} catch {}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function _waitForBrowserReconnect(minionsHome, { afterMs, timeoutMs = 5000, pollMs = 500 } = {}) {
|
|
102
|
+
const start = Date.now();
|
|
103
|
+
while (Date.now() - start < timeoutMs) {
|
|
104
|
+
try {
|
|
105
|
+
const fp = path.join(minionsHome, 'engine', 'dashboard-browser.json');
|
|
106
|
+
const state = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
|
107
|
+
const tabs = state && state.tabs ? Object.values(state.tabs) : [];
|
|
108
|
+
if (tabs.some(t => Number(t && t.lastSeen) > afterMs)) return true;
|
|
109
|
+
} catch { /* file may be temporarily missing during write */ }
|
|
110
|
+
await new Promise(r => setTimeout(r, pollMs));
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function _openInBrowser(url) {
|
|
116
|
+
try {
|
|
117
|
+
if (process.platform === 'win32') execSync(`start "" "${url}"`, { stdio: 'ignore', windowsHide: true });
|
|
118
|
+
else if (process.platform === 'darwin') execSync(`open "${url}"`, { stdio: 'ignore' });
|
|
119
|
+
else execSync(`xdg-open "${url}"`, { stdio: 'ignore' });
|
|
120
|
+
} catch (e) {
|
|
121
|
+
console.log(` Could not auto-open browser: ${e.message}`);
|
|
122
|
+
console.log(` Please open ${url} manually.`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
89
126
|
/**
|
|
90
127
|
* Read the engine's recorded PID from engine/control.json. Returns null if
|
|
91
128
|
* the file is missing/corrupt or the PID isn't a positive integer.
|
|
@@ -411,12 +448,12 @@ function init() {
|
|
|
411
448
|
if (isUpgrade && skipStart) return;
|
|
412
449
|
|
|
413
450
|
// Auto-start on fresh install; direct force-upgrade restarts automatically.
|
|
414
|
-
// Probe before kill so we suppress browser auto-open only when a browser tab
|
|
415
|
-
// was recently polling the dashboard. A bare/orphan dashboard process on the
|
|
416
|
-
// port is not enough; cold starts should still open the UI.
|
|
417
451
|
const dashWasUp = isPortListening(DASH_PORT);
|
|
418
|
-
const
|
|
452
|
+
const restartStartMs = Date.now();
|
|
419
453
|
if (isUpgrade) {
|
|
454
|
+
// Clear stale beacons so the post-restart probe only counts tabs that
|
|
455
|
+
// reconnect to the NEW dashboard.
|
|
456
|
+
_clearDashboardBrowserState(MINIONS_HOME);
|
|
420
457
|
try { execSync(`node "${path.join(MINIONS_HOME, 'engine.js')}" stop`, { stdio: 'ignore', cwd: MINIONS_HOME, timeout: 10000, windowsHide: true }); } catch {}
|
|
421
458
|
// Free the dashboard port too — without this the new dashboard EADDRINUSE-dies
|
|
422
459
|
// silently and the user keeps running stale code from the old dashboard process.
|
|
@@ -431,10 +468,28 @@ function init() {
|
|
|
431
468
|
engineProc.unref();
|
|
432
469
|
console.log(` Engine started (PID: ${engineProc.pid})`);
|
|
433
470
|
|
|
434
|
-
|
|
471
|
+
// Always suppress dashboard's self-open — we decide here after the health
|
|
472
|
+
// check based on whether an existing browser tab actually reconnects.
|
|
473
|
+
const dashProc = spawnDashboard(true);
|
|
435
474
|
console.log(` Dashboard started (PID: ${dashProc.pid})`);
|
|
436
475
|
console.log(` Dashboard: http://localhost:${DASH_PORT}`);
|
|
437
476
|
|
|
477
|
+
void (async () => {
|
|
478
|
+
let shouldOpen = forceOpen || !dashWasUp;
|
|
479
|
+
if (!shouldOpen) {
|
|
480
|
+
// Hot upgrade: give an existing browser tab up to 5s to reconnect via
|
|
481
|
+
// its 4s auto-refresh poll. If nothing beacons, the tab is gone — open.
|
|
482
|
+
const reconnected = await _waitForBrowserReconnect(MINIONS_HOME, {
|
|
483
|
+
afterMs: restartStartMs, timeoutMs: 5000,
|
|
484
|
+
});
|
|
485
|
+
shouldOpen = !reconnected;
|
|
486
|
+
}
|
|
487
|
+
if (shouldOpen) {
|
|
488
|
+
console.log(` Opening dashboard in browser...`);
|
|
489
|
+
_openInBrowser(`http://localhost:${DASH_PORT}`);
|
|
490
|
+
}
|
|
491
|
+
})();
|
|
492
|
+
|
|
438
493
|
// Next steps guidance
|
|
439
494
|
console.log(`
|
|
440
495
|
Next steps:
|
|
@@ -689,11 +744,11 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
|
689
744
|
// `--cli` / `--model` flags forward to `engine.js start` so the runtime
|
|
690
745
|
// fleet flips before the daemon spawns (P-6b3f9c2e AC: works on restart).
|
|
691
746
|
ensureInstalled();
|
|
692
|
-
// Probe before kill so we suppress browser auto-open only when a browser tab
|
|
693
|
-
// was recently polling the dashboard. A bare/orphan dashboard process on the
|
|
694
|
-
// port is not enough; cold starts should still open the UI.
|
|
695
747
|
const dashWasUp = isPortListening(DASH_PORT);
|
|
696
|
-
|
|
748
|
+
// Mark the restart boundary so post-restart beacon timestamps are unambiguous,
|
|
749
|
+
// and clear stale beacons (browsers that closed without notifying).
|
|
750
|
+
const restartStartMs = Date.now();
|
|
751
|
+
_clearDashboardBrowserState(MINIONS_HOME);
|
|
697
752
|
// Layered kill — each step is best-effort, layered so the next still runs if
|
|
698
753
|
// one fails. Goal: the old engine is gone before we spawn a new one, even if
|
|
699
754
|
// PowerShell is unavailable, the engine is hung, or its cmdline doesn't match.
|
|
@@ -712,7 +767,9 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
|
712
767
|
});
|
|
713
768
|
engineProc.unref();
|
|
714
769
|
console.log(`\n Engine started (PID: ${engineProc.pid})`);
|
|
715
|
-
|
|
770
|
+
// Always tell the dashboard to skip its own auto-open — we'll decide here
|
|
771
|
+
// after observing whether an existing browser tab reconnects.
|
|
772
|
+
const dashProc = spawnDashboard(true);
|
|
716
773
|
console.log(` Dashboard started (PID: ${dashProc.pid})`);
|
|
717
774
|
console.log(` Dashboard: http://localhost:${DASH_PORT}`);
|
|
718
775
|
console.log(' Verifying restart health...');
|
|
@@ -725,7 +782,20 @@ if (!cmd || cmd === 'help' || cmd === '--help' || cmd === '-h') {
|
|
|
725
782
|
console.error(formatRestartHealthError(result));
|
|
726
783
|
process.exit(1);
|
|
727
784
|
}
|
|
728
|
-
console.log(` Restart verified: engine PID ${result.engine.pid}; dashboard healthy
|
|
785
|
+
console.log(` Restart verified: engine PID ${result.engine.pid}; dashboard healthy.`);
|
|
786
|
+
|
|
787
|
+
let shouldOpen = forceOpen || !dashWasUp;
|
|
788
|
+
if (!shouldOpen) {
|
|
789
|
+
const reconnected = await _waitForBrowserReconnect(MINIONS_HOME, {
|
|
790
|
+
afterMs: restartStartMs, timeoutMs: 5000,
|
|
791
|
+
});
|
|
792
|
+
shouldOpen = !reconnected;
|
|
793
|
+
}
|
|
794
|
+
if (shouldOpen) {
|
|
795
|
+
console.log(` Opening dashboard in browser...`);
|
|
796
|
+
_openInBrowser(`http://localhost:${DASH_PORT}`);
|
|
797
|
+
}
|
|
798
|
+
console.log('');
|
|
729
799
|
})().catch(err => {
|
|
730
800
|
console.error(`\n ERROR: Restart verification failed: ${err.message}\n`);
|
|
731
801
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1826",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|