@yemi33/squad 0.1.15 → 0.1.16

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.
Files changed (2) hide show
  1. package/dashboard.js +48 -0
  2. package/package.json +1 -1
package/dashboard.js CHANGED
@@ -1394,6 +1394,54 @@ server.listen(PORT, '127.0.0.1', () => {
1394
1394
  console.log(` Could not auto-open browser: ${e.message}`);
1395
1395
  console.log(` Please open http://localhost:${PORT} manually.`);
1396
1396
  }
1397
+
1398
+ // ─── Engine Watchdog ─────────────────────────────────────────────────────
1399
+ // Every 30s, check if engine PID is alive. If dead but control.json says
1400
+ // running, auto-restart it. Prevents silent engine death.
1401
+ const { execSync, spawn: cpSpawn } = require('child_process');
1402
+ setInterval(() => {
1403
+ try {
1404
+ const control = getEngineState();
1405
+ if (control.state !== 'running' || !control.pid) return;
1406
+
1407
+ // Check if PID is alive
1408
+ let alive = false;
1409
+ try {
1410
+ if (process.platform === 'win32') {
1411
+ const out = execSync(`tasklist /FI "PID eq ${control.pid}" /NH`, { encoding: 'utf8', timeout: 3000 });
1412
+ alive = out.includes(String(control.pid));
1413
+ } else {
1414
+ process.kill(control.pid, 0); // signal 0 = check existence
1415
+ alive = true;
1416
+ }
1417
+ } catch { alive = false; }
1418
+
1419
+ if (!alive) {
1420
+ console.log(`[watchdog] Engine PID ${control.pid} is dead — auto-restarting...`);
1421
+
1422
+ // Set state to stopped first
1423
+ const controlPath = path.join(SQUAD_DIR, 'engine', 'control.json');
1424
+ safeWrite(controlPath, { state: 'stopped', pid: null, crashed_at: new Date().toISOString() });
1425
+
1426
+ // Restart engine
1427
+ const childEnv = { ...process.env };
1428
+ for (const key of Object.keys(childEnv)) {
1429
+ if (key === 'CLAUDECODE' || key.startsWith('CLAUDE_CODE') || key.startsWith('CLAUDECODE_')) delete childEnv[key];
1430
+ }
1431
+ const engineProc = cpSpawn(process.execPath, [path.join(SQUAD_DIR, 'engine.js'), 'start'], {
1432
+ cwd: SQUAD_DIR,
1433
+ stdio: 'ignore',
1434
+ detached: true,
1435
+ env: childEnv,
1436
+ });
1437
+ engineProc.unref();
1438
+ console.log(`[watchdog] Engine restarted (new PID: ${engineProc.pid})`);
1439
+ }
1440
+ } catch (e) {
1441
+ console.error(`[watchdog] Error: ${e.message}`);
1442
+ }
1443
+ }, 30000);
1444
+ console.log(` Engine watchdog: active (checks every 30s)`);
1397
1445
  });
1398
1446
 
1399
1447
  server.on('error', e => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/squad",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "Multi-agent AI dev team that runs from ~/.squad/ — five autonomous agents share a single engine, dashboard, and knowledge base",
5
5
  "bin": {
6
6
  "squad": "bin/squad.js"