@axiomatic-labs/claudeflow 2.13.64 → 2.13.65
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 +56 -3
- package/package.json +1 -1
package/lib/panel.js
CHANGED
|
@@ -734,6 +734,9 @@ details[open] summary { padding-bottom: 8px; border-bottom: 1px solid var(--bord
|
|
|
734
734
|
.logs-controls { display: flex; gap: 12px; align-items: center; margin-bottom: 14px; }
|
|
735
735
|
.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; }
|
|
736
736
|
.logs-controls button:hover { border-color: var(--accent); cursor: pointer; }
|
|
737
|
+
.observer-filter { background: var(--panel); border: 1px solid var(--border); color: var(--fg); padding: 4px 10px; border-radius: 999px; cursor: pointer; font-size: 12px; font: inherit; }
|
|
738
|
+
.observer-filter:hover { border-color: var(--accent, #6cf); }
|
|
739
|
+
.observer-filter.active { background: rgba(108,170,255,0.12); border-color: var(--accent, #6cf); color: var(--accent, #6cf); }
|
|
737
740
|
.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; }
|
|
738
741
|
.btn-warn:hover { border-color: var(--warn, #f5c234); background: rgba(245,194,52,0.08); }
|
|
739
742
|
.btn-warn:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
@@ -829,6 +832,7 @@ const SECTIONS = [
|
|
|
829
832
|
|
|
830
833
|
let state = null;
|
|
831
834
|
let active = 'overview';
|
|
835
|
+
let observerFilter = 'all';
|
|
832
836
|
let timer = null;
|
|
833
837
|
|
|
834
838
|
// Preserve which <details> were open across re-renders (auto-refresh would
|
|
@@ -1424,11 +1428,54 @@ function renderObserver() {
|
|
|
1424
1428
|
</div>\`
|
|
1425
1429
|
: '<p class="muted">No browser snapshots received yet. (The observer collects when the agent navigates with mcp__claude-in-chrome__*.)</p>';
|
|
1426
1430
|
|
|
1431
|
+
// Build the filter index: for each surface (server label), find which
|
|
1432
|
+
// incidents belong to it. browser incidents are matched by origin URL
|
|
1433
|
+
// against each server's :PORT. Browser-other = browser incidents whose
|
|
1434
|
+
// origin doesn't match any configured server (e.g. external URL).
|
|
1435
|
+
const serverByOrigin = {};
|
|
1436
|
+
o.servers.forEach((srv) => {
|
|
1437
|
+
if (srv.port) serverByOrigin[\`localhost:\${srv.port}\`] = srv.label;
|
|
1438
|
+
if (srv.port) serverByOrigin[\`127.0.0.1:\${srv.port}\`] = srv.label;
|
|
1439
|
+
});
|
|
1440
|
+
function incidentBucket(inc) {
|
|
1441
|
+
if (inc.source === 'server') {
|
|
1442
|
+
return (inc.metadata && inc.metadata.label) || inc.surface || 'server-unknown';
|
|
1443
|
+
}
|
|
1444
|
+
if (inc.source === 'browser') {
|
|
1445
|
+
const url = (inc.metadata && (inc.metadata.url || inc.metadata.origin)) || '';
|
|
1446
|
+
const m = url.match(/^https?:\\/\\/([^/]+)/);
|
|
1447
|
+
if (m && serverByOrigin[m[1]]) return serverByOrigin[m[1]];
|
|
1448
|
+
return 'browser-other';
|
|
1449
|
+
}
|
|
1450
|
+
return inc.source || 'other';
|
|
1451
|
+
}
|
|
1452
|
+
const buckets = {};
|
|
1453
|
+
o.recent_incidents.forEach((inc) => {
|
|
1454
|
+
const b = incidentBucket(inc);
|
|
1455
|
+
if (!buckets[b]) buckets[b] = [];
|
|
1456
|
+
buckets[b].push(inc);
|
|
1457
|
+
});
|
|
1458
|
+
const surfacesInUse = Object.keys(buckets).sort();
|
|
1459
|
+
// Apply observerFilter client-side state. Default 'all' (no filter).
|
|
1460
|
+
const filteredIncidents = (typeof observerFilter === 'undefined' || observerFilter === 'all')
|
|
1461
|
+
? o.recent_incidents
|
|
1462
|
+
: (buckets[observerFilter] || []);
|
|
1463
|
+
|
|
1464
|
+
const filterPill = (label, value, count) => {
|
|
1465
|
+
const active = (typeof observerFilter === 'undefined' && value === 'all') || observerFilter === value;
|
|
1466
|
+
const cls = active ? 'observer-filter active' : 'observer-filter';
|
|
1467
|
+
return \`<button class="\${cls}" data-observer-filter="\${escapeHtml(value)}">\${escapeHtml(label)}<span class="muted" style="margin-left:6px;font-size:11px;">\${count}</span></button>\`;
|
|
1468
|
+
};
|
|
1469
|
+
const filterPills = '<div class="observer-filters" style="display:flex;gap:6px;flex-wrap:wrap;margin:8px 0;">' +
|
|
1470
|
+
filterPill('All', 'all', o.recent_incidents.length) +
|
|
1471
|
+
surfacesInUse.map((surface) => filterPill(surface, surface, buckets[surface].length)).join('') +
|
|
1472
|
+
'</div>';
|
|
1473
|
+
|
|
1427
1474
|
// Incidents feed
|
|
1428
|
-
const incidentsBlock =
|
|
1429
|
-
? '<p class="muted">No incidents
|
|
1475
|
+
const incidentsBlock = filteredIncidents.length === 0
|
|
1476
|
+
? '<p class="muted">No incidents in this filter.</p>'
|
|
1430
1477
|
: '<div class="incidents-feed">' +
|
|
1431
|
-
|
|
1478
|
+
filteredIncidents.map((inc) => {
|
|
1432
1479
|
const sevClass = inc.severity === 'error' || inc.severity === 'critical' ? 'err' : (inc.severity === 'warning' ? 'warn' : 'info');
|
|
1433
1480
|
const resolvedBadge = inc.resolved_at
|
|
1434
1481
|
? '<span class="badge ok" style="margin-left:6px;">resolved</span>'
|
|
@@ -1467,6 +1514,7 @@ function renderObserver() {
|
|
|
1467
1514
|
<h3 style="margin-top:18px;font-size:14px;">Browser channel</h3>
|
|
1468
1515
|
\${browserBlock}
|
|
1469
1516
|
<h3 style="margin-top:18px;font-size:14px;">Incidents (most recent \${o.recent_incidents.length})</h3>
|
|
1517
|
+
\${filterPills}
|
|
1470
1518
|
<div class="card" style="padding:0;">\${incidentsBlock}</div>\`;
|
|
1471
1519
|
}
|
|
1472
1520
|
|
|
@@ -1617,6 +1665,11 @@ document.addEventListener('click', (e) => {
|
|
|
1617
1665
|
if (t.id === 'clear-observer') {
|
|
1618
1666
|
return clearObserverAction(t);
|
|
1619
1667
|
}
|
|
1668
|
+
if (t.dataset && t.dataset.observerFilter) {
|
|
1669
|
+
observerFilter = t.dataset.observerFilter;
|
|
1670
|
+
renderContent();
|
|
1671
|
+
return;
|
|
1672
|
+
}
|
|
1620
1673
|
});
|
|
1621
1674
|
|
|
1622
1675
|
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.65",
|
|
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"
|