@axiomatic-labs/claudeflow 2.13.66 → 2.13.67
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/lib/panel.js +36 -11
- package/package.json +1 -1
package/lib/panel.js
CHANGED
|
@@ -331,11 +331,18 @@ function getObserverInfo(cwd) {
|
|
|
331
331
|
const unresolvedIncidents = summary && Array.isArray(summary.unresolved_incidents)
|
|
332
332
|
? summary.unresolved_incidents
|
|
333
333
|
: [];
|
|
334
|
-
const
|
|
334
|
+
const allInState = state && state.incidents && typeof state.incidents === 'object'
|
|
335
335
|
? Object.values(state.incidents)
|
|
336
336
|
.sort((a, b) => String(b.last_seen_at || '').localeCompare(String(a.last_seen_at || '')))
|
|
337
337
|
.slice(0, 50)
|
|
338
338
|
: [];
|
|
339
|
+
// Default surface to UI: ACTIVE only. "Clear observer state" resolves all
|
|
340
|
+
// active incidents, so after clear the active list is empty (which matches
|
|
341
|
+
// the user's expectation that "Clear" empties the feed). Resolved incidents
|
|
342
|
+
// are kept in state.incidents for audit and can be surfaced via the
|
|
343
|
+
// "Show resolved" filter pill.
|
|
344
|
+
const activeIncidents = allInState.filter((inc) => !inc.resolved_at && inc.active !== false);
|
|
345
|
+
const resolvedIncidents = allInState.filter((inc) => inc.resolved_at || inc.active === false);
|
|
339
346
|
|
|
340
347
|
return {
|
|
341
348
|
daemon,
|
|
@@ -347,7 +354,10 @@ function getObserverInfo(cwd) {
|
|
|
347
354
|
servers,
|
|
348
355
|
browser,
|
|
349
356
|
unresolved_incidents: unresolvedIncidents,
|
|
350
|
-
|
|
357
|
+
active_incidents: activeIncidents,
|
|
358
|
+
resolved_incidents: resolvedIncidents,
|
|
359
|
+
// Kept for backwards compat with older render code — same as active_incidents.
|
|
360
|
+
recent_incidents: activeIncidents,
|
|
351
361
|
totals: summary ? {
|
|
352
362
|
unresolved: summary.unresolved_incidents_total || 0,
|
|
353
363
|
browser: summary.browser_incidents_total || 0,
|
|
@@ -848,6 +858,7 @@ const SECTIONS = [
|
|
|
848
858
|
let state = null;
|
|
849
859
|
let active = 'overview';
|
|
850
860
|
let observerFilter = 'all';
|
|
861
|
+
let observerShowResolved = false;
|
|
851
862
|
let timer = null;
|
|
852
863
|
|
|
853
864
|
// Preserve which <details> were open across re-renders (auto-refresh would
|
|
@@ -1457,10 +1468,13 @@ function renderObserver() {
|
|
|
1457
1468
|
</div>\`
|
|
1458
1469
|
: '<p class="muted">No browser snapshots received yet. (The observer collects when the agent navigates with mcp__claude-in-chrome__*.)</p>';
|
|
1459
1470
|
|
|
1460
|
-
//
|
|
1461
|
-
//
|
|
1462
|
-
//
|
|
1463
|
-
|
|
1471
|
+
// Active vs resolved toggle (client-side state observerShowResolved).
|
|
1472
|
+
// After "Clear observer state", all active incidents are marked resolved;
|
|
1473
|
+
// by default the UI shows only active. Toggle the pill to see history.
|
|
1474
|
+
const showResolved = (typeof observerShowResolved !== 'undefined') && observerShowResolved;
|
|
1475
|
+
const sourceList = showResolved ? o.resolved_incidents : o.active_incidents;
|
|
1476
|
+
|
|
1477
|
+
// Build the filter index ON THE CURRENT VIEW (active or resolved).
|
|
1464
1478
|
const serverByOrigin = {};
|
|
1465
1479
|
o.servers.forEach((srv) => {
|
|
1466
1480
|
if (srv.port) serverByOrigin[\`localhost:\${srv.port}\`] = srv.label;
|
|
@@ -1479,7 +1493,7 @@ function renderObserver() {
|
|
|
1479
1493
|
return inc.source || 'other';
|
|
1480
1494
|
}
|
|
1481
1495
|
const buckets = {};
|
|
1482
|
-
|
|
1496
|
+
sourceList.forEach((inc) => {
|
|
1483
1497
|
const b = incidentBucket(inc);
|
|
1484
1498
|
if (!buckets[b]) buckets[b] = [];
|
|
1485
1499
|
buckets[b].push(inc);
|
|
@@ -1487,7 +1501,7 @@ function renderObserver() {
|
|
|
1487
1501
|
const surfacesInUse = Object.keys(buckets).sort();
|
|
1488
1502
|
// Apply observerFilter client-side state. Default 'all' (no filter).
|
|
1489
1503
|
const filteredIncidents = (typeof observerFilter === 'undefined' || observerFilter === 'all')
|
|
1490
|
-
?
|
|
1504
|
+
? sourceList
|
|
1491
1505
|
: (buckets[observerFilter] || []);
|
|
1492
1506
|
|
|
1493
1507
|
const filterPill = (label, value, count) => {
|
|
@@ -1495,9 +1509,13 @@ function renderObserver() {
|
|
|
1495
1509
|
const cls = active ? 'observer-filter active' : 'observer-filter';
|
|
1496
1510
|
return \`<button class="\${cls}" data-observer-filter="\${escapeHtml(value)}">\${escapeHtml(label)}<span class="muted" style="margin-left:6px;font-size:11px;">\${count}</span></button>\`;
|
|
1497
1511
|
};
|
|
1498
|
-
|
|
1499
|
-
|
|
1512
|
+
// Show resolved toggle pill — separate from surface filters.
|
|
1513
|
+
const showResolvedClass = showResolved ? 'observer-filter active' : 'observer-filter';
|
|
1514
|
+
const showResolvedPill = \`<button class="\${showResolvedClass}" data-observer-show-resolved="toggle" style="margin-left:auto;">\${showResolved ? 'Showing resolved' : 'Show resolved'}<span class="muted" style="margin-left:6px;font-size:11px;">\${o.resolved_incidents.length}</span></button>\`;
|
|
1515
|
+
const filterPills = '<div class="observer-filters" style="display:flex;gap:6px;flex-wrap:wrap;align-items:center;margin:8px 0;">' +
|
|
1516
|
+
filterPill('All', 'all', sourceList.length) +
|
|
1500
1517
|
surfacesInUse.map((surface) => filterPill(surface, surface, buckets[surface].length)).join('') +
|
|
1518
|
+
showResolvedPill +
|
|
1501
1519
|
'</div>';
|
|
1502
1520
|
|
|
1503
1521
|
// Incidents feed
|
|
@@ -1542,7 +1560,7 @@ function renderObserver() {
|
|
|
1542
1560
|
<div class="card" style="padding:0;">\${serversTable}</div>
|
|
1543
1561
|
<h3 style="margin-top:18px;font-size:14px;">Browser channel</h3>
|
|
1544
1562
|
\${browserBlock}
|
|
1545
|
-
<h3 style="margin-top:18px;font-size:14px;"
|
|
1563
|
+
<h3 style="margin-top:18px;font-size:14px;">\${showResolved ? 'Resolved incidents (' + o.resolved_incidents.length + ')' : 'Active incidents (' + o.active_incidents.length + ')'}</h3>
|
|
1546
1564
|
\${filterPills}
|
|
1547
1565
|
<div class="card" style="padding:0;">\${incidentsBlock}</div>\`;
|
|
1548
1566
|
}
|
|
@@ -1699,6 +1717,13 @@ document.addEventListener('click', (e) => {
|
|
|
1699
1717
|
renderContent();
|
|
1700
1718
|
return;
|
|
1701
1719
|
}
|
|
1720
|
+
if (t.dataset && t.dataset.observerShowResolved) {
|
|
1721
|
+
observerShowResolved = !observerShowResolved;
|
|
1722
|
+
// Reset surface filter when toggling, since counts change.
|
|
1723
|
+
observerFilter = 'all';
|
|
1724
|
+
renderContent();
|
|
1725
|
+
return;
|
|
1726
|
+
}
|
|
1702
1727
|
});
|
|
1703
1728
|
|
|
1704
1729
|
async function clearObserverAction(btn) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiomatic-labs/claudeflow",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.67",
|
|
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"
|