@axiomatic-labs/claudeflow 2.13.63 → 2.13.64

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 +69 -1
  2. package/package.json +1 -1
package/lib/panel.js CHANGED
@@ -1452,8 +1452,15 @@ function renderObserver() {
1452
1452
  }).join('') +
1453
1453
  '</div>';
1454
1454
 
1455
+ // Clear button — only meaningful when the daemon is running AND there's
1456
+ // either at least one unresolved incident or some browser snapshots to wipe.
1457
+ const clearable = daemonAlive && (totals.unresolved > 0 || (o.browser && o.browser.snapshots_received > 0) || o.recent_incidents.length > 0);
1458
+ const clearBtn = clearable
1459
+ ? '<button id="clear-observer" class="logs-clear-btn" style="margin-left:14px;" title="Resolves all active incidents, clears per-server recent_log buffers, and resets browser snapshot counter. The state file keeps incident history (marked resolved). Future events repopulate as usual.">Clear observer state</button>'
1460
+ : '';
1461
+
1455
1462
  return \`<h2>Observer</h2>
1456
- <p class="sub">Daemon: \${statusBadge}\${restartBtn}</p>
1463
+ <p class="sub">Daemon: \${statusBadge}\${restartBtn}\${clearBtn}</p>
1457
1464
  <p class="sub">Incidents: \${totalsBadge} \${summaryStatus}</p>
1458
1465
  <h3 style="margin-top:18px;font-size:14px;">Servers (\${o.servers.length})</h3>
1459
1466
  <div class="card" style="padding:0;">\${serversTable}</div>
@@ -1607,8 +1614,33 @@ document.addEventListener('click', (e) => {
1607
1614
  if (t.id === 'fix-cdp-port') {
1608
1615
  return fixCdpPortAction(t);
1609
1616
  }
1617
+ if (t.id === 'clear-observer') {
1618
+ return clearObserverAction(t);
1619
+ }
1610
1620
  });
1611
1621
 
1622
+ async function clearObserverAction(btn) {
1623
+ if (!confirm('Resolve all active observer incidents and clear server logs?\\n\\nIncident history is preserved in state.incidents (marked resolved). Future events repopulate normally. This cannot be undone.')) return;
1624
+ const originalLabel = btn.textContent;
1625
+ btn.disabled = true;
1626
+ btn.textContent = 'Clearing…';
1627
+ try {
1628
+ const r = await fetch('/api/observer/clear', { method: 'POST' });
1629
+ const result = await r.json();
1630
+ if (r.ok && result.ok) {
1631
+ showToast('Observer state cleared at ' + (result.reset_at || 'now'), 'ok');
1632
+ } else {
1633
+ showToast('Clear failed: ' + (result.error || 'unknown'), 'err');
1634
+ }
1635
+ } catch (e) {
1636
+ showToast('Network error: ' + e.message, 'err');
1637
+ } finally {
1638
+ btn.disabled = false;
1639
+ btn.textContent = originalLabel;
1640
+ await refresh();
1641
+ }
1642
+ }
1643
+
1612
1644
  async function fixCdpPortAction(btn) {
1613
1645
  const originalLabel = btn.textContent;
1614
1646
  btn.disabled = true;
@@ -1936,6 +1968,42 @@ function handler(cwd) {
1936
1968
  }), 'application/json');
1937
1969
  }
1938
1970
 
1971
+ if (req.method === 'POST' && route === '/api/observer/clear') {
1972
+ // Forwards to the observer daemon's /reset-session endpoint, which
1973
+ // resolves all active browser + server incidents, clears the per-server
1974
+ // recent_log buffers, and resets the browser snapshot counter. The
1975
+ // history is preserved in state.incidents (marked resolved), so this
1976
+ // is a soft clear: future polls won't see the old incidents as active.
1977
+ const observer = readObserverState(cwd);
1978
+ if (!observer.running) {
1979
+ return send(409, JSON.stringify({ ok: false, error: 'observer is not running — start it first, then clear.' }), 'application/json');
1980
+ }
1981
+ const { request: httpRequest } = require('node:http');
1982
+ const result = await new Promise((resolve) => {
1983
+ const req2 = httpRequest({
1984
+ hostname: '127.0.0.1',
1985
+ port: observer.port,
1986
+ path: '/reset-session',
1987
+ method: 'POST',
1988
+ headers: { 'Content-Type': 'application/json', 'Content-Length': 2 },
1989
+ }, (r) => {
1990
+ let body = '';
1991
+ r.on('data', (c) => { body += c; });
1992
+ r.on('end', () => {
1993
+ try { resolve({ status: r.statusCode, body: JSON.parse(body) }); }
1994
+ catch { resolve({ status: r.statusCode, body: { raw: body } }); }
1995
+ });
1996
+ });
1997
+ req2.on('error', (err) => resolve({ status: 0, body: { error: err.message } }));
1998
+ req2.write('{}');
1999
+ req2.end();
2000
+ });
2001
+ if (result.status === 200 && result.body && result.body.ok) {
2002
+ return send(200, JSON.stringify({ ok: true, reset_at: result.body.reset_at }), 'application/json');
2003
+ }
2004
+ return send(502, JSON.stringify({ ok: false, error: 'observer returned ' + result.status, daemon_response: result.body }), 'application/json');
2005
+ }
2006
+
1939
2007
  if (req.method === 'POST' && route === '/api/observer/restart') {
1940
2008
  // Re-run the SessionStart/browser-error-daemon.js hook script
1941
2009
  // synchronously. The script calls ensureObserver() which spawns
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiomatic-labs/claudeflow",
3
- "version": "2.13.63",
3
+ "version": "2.13.64",
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"