@axiomatic-labs/claudeflow 2.13.56 → 2.13.57

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/lib/panel.js +54 -0
  2. package/package.json +1 -1
package/lib/panel.js CHANGED
@@ -658,6 +658,9 @@ details[open] summary { padding-bottom: 8px; border-bottom: 1px solid var(--bord
658
658
  .logs-controls { display: flex; gap: 12px; align-items: center; margin-bottom: 14px; }
659
659
  .logs-controls select, .logs-controls button { background: var(--panel); border: 1px solid var(--border); color: var(--fg); padding: 6px 10px; border-radius: 6px; font: inherit; }
660
660
  .logs-controls button:hover { border-color: var(--accent); cursor: pointer; }
661
+ .btn-warn { background: var(--panel); border: 1px solid rgba(245,194,52,0.5); color: var(--warn, #f5c234); padding: 6px 12px; border-radius: 6px; cursor: pointer; font: inherit; }
662
+ .btn-warn:hover { border-color: var(--warn, #f5c234); background: rgba(245,194,52,0.08); }
663
+ .btn-warn:disabled { opacity: 0.4; cursor: not-allowed; }
661
664
  .logs-clear-btn { margin-left: auto; color: var(--err); border-color: rgba(248,81,73,0.4); }
662
665
  .logs-clear-btn:hover { border-color: var(--err); background: rgba(248,81,73,0.08); }
663
666
  .logs-clear-btn:disabled { opacity: 0.4; cursor: not-allowed; color: var(--muted); border-color: var(--border); }
@@ -1300,6 +1303,7 @@ function renderMcp() {
1300
1303
  \${row('Computed port (from path)', String(m.playwright.computed))}
1301
1304
  \${row('Match', m.playwright.match ? 'YES' : 'NO', { kind: m.playwright.match ? 'ok' : 'err', text: m.playwright.match ? '✓' : '✗' })}
1302
1305
  \${row('Observer', m.observer.running ? 'running (pid '+m.observer.pid+')' : 'STOPPED — browser errors NOT being collected', { kind: m.observer.running ? 'ok' : (m.playwright.match ? 'warn' : 'info'), text: m.observer.running ? '✓' : (m.playwright.match ? '⚠' : '·') })}
1306
+ \${!m.observer.running && m.playwright.match ? '<div style="padding:10px 14px;border-top:1px solid var(--border);"><button id="restart-observer" class="btn-warn">Restart observer</button> <span class="muted" style="margin-left:10px;font-size:12px;">Re-runs SessionStart/browser-error-daemon.js — spawns Chrome with --cdp-endpoint and registers the daemon pidfile.</span></div>' : ''}
1303
1307
  </div>
1304
1308
  <h2 style="margin-top:18px">Stale lockfiles</h2>
1305
1309
  \${lockfiles}\`;
@@ -1409,8 +1413,32 @@ document.addEventListener('click', (e) => {
1409
1413
  if (!confirm('Delete ' + total + ' captured log event(s) and truncate .claude/tmp/hooks.log?\\n\\nThis cannot be undone. (Future events will be captured normally.)')) return;
1410
1414
  return clearLogsAction();
1411
1415
  }
1416
+ if (t.id === 'restart-observer') {
1417
+ return restartObserverAction(t);
1418
+ }
1412
1419
  });
1413
1420
 
1421
+ async function restartObserverAction(btn) {
1422
+ const originalLabel = btn.textContent;
1423
+ btn.disabled = true;
1424
+ btn.textContent = 'Restarting…';
1425
+ try {
1426
+ const r = await fetch('/api/observer/restart', { method: 'POST' });
1427
+ const result = await r.json();
1428
+ if (r.ok && result.ok) {
1429
+ showToast('Observer restarted — pid ' + (result.observer && result.observer.pid) + '. Refreshing…', 'ok');
1430
+ } else {
1431
+ showToast('Restart failed: ' + (result.error || result.script_stderr || 'unknown'), 'err');
1432
+ }
1433
+ } catch (e) {
1434
+ showToast('Network error: ' + e.message, 'err');
1435
+ } finally {
1436
+ btn.disabled = false;
1437
+ btn.textContent = originalLabel;
1438
+ await refresh();
1439
+ }
1440
+ }
1441
+
1414
1442
  async function clearLogsAction() {
1415
1443
  try {
1416
1444
  const r = await fetch('/api/logs', { method: 'DELETE' });
@@ -1661,6 +1689,32 @@ function handler(cwd) {
1661
1689
  return send(status, JSON.stringify(result), 'application/json');
1662
1690
  }
1663
1691
 
1692
+ if (req.method === 'POST' && route === '/api/observer/restart') {
1693
+ // Re-run the SessionStart/browser-error-daemon.js hook script
1694
+ // synchronously. The script calls ensureObserver() which spawns
1695
+ // Chrome with --cdp-endpoint as a detached process. Once the
1696
+ // script exits, the daemon is up (or the script logged the failure).
1697
+ const daemonScript = path.join(cwd, '.claude', 'hooks', 'SessionStart', 'browser-error-daemon.js');
1698
+ if (!fs.existsSync(daemonScript)) {
1699
+ return send(404, JSON.stringify({ ok: false, error: 'daemon script not found at .claude/hooks/SessionStart/browser-error-daemon.js' }), 'application/json');
1700
+ }
1701
+ const { spawnSync } = require('child_process');
1702
+ const r = spawnSync(process.execPath, [daemonScript], {
1703
+ cwd,
1704
+ env: { ...process.env, CLAUDE_PROJECT_DIR: cwd },
1705
+ encoding: 'utf8',
1706
+ timeout: 15000,
1707
+ });
1708
+ const observerState = readObserverState(cwd, deriveCdpPort(cwd));
1709
+ const ok = observerState.running;
1710
+ return send(ok ? 200 : 500, JSON.stringify({
1711
+ ok,
1712
+ observer: observerState,
1713
+ script_exit: r.status,
1714
+ script_stderr: (r.stderr || '').slice(0, 500),
1715
+ }), 'application/json');
1716
+ }
1717
+
1664
1718
  if (req.method === 'POST' && route === '/api/reminders/toggle') {
1665
1719
  const raw = await readRequestBody(req);
1666
1720
  let payload;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiomatic-labs/claudeflow",
3
- "version": "2.13.56",
3
+ "version": "2.13.57",
4
4
  "description": "Claudeflow — AI-powered development toolkit for Claude Code. Skills, agents, hooks, and quality gates that ship production apps.",
5
5
  "bin": {
6
6
  "claudeflow": "./bin/cli.js"