@nockdev/hsa 1.2.1 → 1.2.3
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/dashboard.html +39 -6
- package/logs.html +1018 -480
- package/package.json +1 -1
package/dashboard.html
CHANGED
|
@@ -1490,6 +1490,10 @@
|
|
|
1490
1490
|
let selectedSessionId = "";
|
|
1491
1491
|
let selectedIde = "";
|
|
1492
1492
|
let selectedProject = "";
|
|
1493
|
+
let sessionSSERetryMs = 1000;
|
|
1494
|
+
let fetchErrorCount = 0;
|
|
1495
|
+
const BASE_REFRESH_MS = 5000;
|
|
1496
|
+
const MAX_REFRESH_MS = 30000;
|
|
1493
1497
|
|
|
1494
1498
|
document.getElementById("endpointInput").value = endpoint;
|
|
1495
1499
|
|
|
@@ -1502,6 +1506,7 @@
|
|
|
1502
1506
|
.value.replace(/\/$/, "");
|
|
1503
1507
|
localStorage.setItem("hsa_endpoint", endpoint);
|
|
1504
1508
|
setStatus("connecting");
|
|
1509
|
+
fetchErrorCount = 0; // Reset error counter on manual connect
|
|
1505
1510
|
fetchDashboard();
|
|
1506
1511
|
fetchSessions();
|
|
1507
1512
|
}
|
|
@@ -1517,7 +1522,7 @@
|
|
|
1517
1522
|
const badge = document.getElementById("refreshBadge");
|
|
1518
1523
|
if (autoRefresh) {
|
|
1519
1524
|
btn.classList.add("active");
|
|
1520
|
-
badge
|
|
1525
|
+
updateRefreshBadge(badge);
|
|
1521
1526
|
startRefresh();
|
|
1522
1527
|
} else {
|
|
1523
1528
|
btn.classList.remove("active");
|
|
@@ -1527,10 +1532,14 @@
|
|
|
1527
1532
|
}
|
|
1528
1533
|
function startRefresh() {
|
|
1529
1534
|
stopRefresh();
|
|
1535
|
+
const interval = Math.min(
|
|
1536
|
+
BASE_REFRESH_MS * Math.pow(2, fetchErrorCount),
|
|
1537
|
+
MAX_REFRESH_MS,
|
|
1538
|
+
);
|
|
1530
1539
|
refreshInterval = setInterval(() => {
|
|
1531
1540
|
fetchDashboard();
|
|
1532
1541
|
fetchSessions();
|
|
1533
|
-
},
|
|
1542
|
+
}, interval);
|
|
1534
1543
|
}
|
|
1535
1544
|
function stopRefresh() {
|
|
1536
1545
|
if (refreshInterval) {
|
|
@@ -1538,6 +1547,15 @@
|
|
|
1538
1547
|
refreshInterval = null;
|
|
1539
1548
|
}
|
|
1540
1549
|
}
|
|
1550
|
+
function adjustRefreshInterval() {
|
|
1551
|
+
if (!autoRefresh) return;
|
|
1552
|
+
updateRefreshBadge(document.getElementById("refreshBadge"));
|
|
1553
|
+
startRefresh();
|
|
1554
|
+
}
|
|
1555
|
+
function updateRefreshBadge(badge) {
|
|
1556
|
+
const ms = Math.min(BASE_REFRESH_MS * Math.pow(2, fetchErrorCount), MAX_REFRESH_MS);
|
|
1557
|
+
badge.textContent = ms >= 1000 ? (ms / 1000) + "s" : ms + "ms";
|
|
1558
|
+
}
|
|
1541
1559
|
|
|
1542
1560
|
/* ================================================================
|
|
1543
1561
|
CONTEXT SELECTORS
|
|
@@ -1598,13 +1616,19 @@
|
|
|
1598
1616
|
try {
|
|
1599
1617
|
let url = endpoint + "/api/dashboard";
|
|
1600
1618
|
// Note: /api/dashboard doesn't support session filtering yet, handled client-side
|
|
1601
|
-
const res = await fetch(url, { signal: AbortSignal.timeout(
|
|
1619
|
+
const res = await fetch(url, { signal: AbortSignal.timeout(15000) });
|
|
1602
1620
|
if (!res.ok) throw new Error("HTTP " + res.status);
|
|
1603
1621
|
const data = await res.json();
|
|
1604
1622
|
setStatus("connected");
|
|
1623
|
+
if (fetchErrorCount > 0) {
|
|
1624
|
+
fetchErrorCount = 0;
|
|
1625
|
+
adjustRefreshInterval();
|
|
1626
|
+
}
|
|
1605
1627
|
render(data);
|
|
1606
1628
|
} catch (err) {
|
|
1607
1629
|
setStatus("error");
|
|
1630
|
+
fetchErrorCount++;
|
|
1631
|
+
adjustRefreshInterval();
|
|
1608
1632
|
console.warn("HSA fetch error:", err.message);
|
|
1609
1633
|
}
|
|
1610
1634
|
}
|
|
@@ -2127,8 +2151,8 @@
|
|
|
2127
2151
|
const deltas = [];
|
|
2128
2152
|
for (let i = 1; i < cacheHistory.length; i++) {
|
|
2129
2153
|
deltas.push({
|
|
2130
|
-
hits: cacheHistory[i].hits - cacheHistory[i - 1].hits,
|
|
2131
|
-
misses: cacheHistory[i].misses - cacheHistory[i - 1].misses,
|
|
2154
|
+
hits: Math.max(0, cacheHistory[i].hits - cacheHistory[i - 1].hits),
|
|
2155
|
+
misses: Math.max(0, cacheHistory[i].misses - cacheHistory[i - 1].misses),
|
|
2132
2156
|
});
|
|
2133
2157
|
}
|
|
2134
2158
|
const maxVal = Math.max(
|
|
@@ -2229,9 +2253,17 @@
|
|
|
2229
2253
|
}
|
|
2230
2254
|
} catch {}
|
|
2231
2255
|
};
|
|
2256
|
+
// FE-02: Auto-reconnect with exponential backoff
|
|
2232
2257
|
sessionSSE.onerror = () => {
|
|
2233
2258
|
sessionSSE.close();
|
|
2234
2259
|
sessionSSE = null;
|
|
2260
|
+
setTimeout(() => {
|
|
2261
|
+
connectSessionSSE();
|
|
2262
|
+
sessionSSERetryMs = Math.min(sessionSSERetryMs * 2, 30000);
|
|
2263
|
+
}, sessionSSERetryMs);
|
|
2264
|
+
};
|
|
2265
|
+
sessionSSE.onopen = () => {
|
|
2266
|
+
sessionSSERetryMs = 1000;
|
|
2235
2267
|
};
|
|
2236
2268
|
} catch {}
|
|
2237
2269
|
}
|
|
@@ -2331,7 +2363,8 @@
|
|
|
2331
2363
|
.replace(/&/g, "&")
|
|
2332
2364
|
.replace(/</g, "<")
|
|
2333
2365
|
.replace(/>/g, ">")
|
|
2334
|
-
.replace(/"/g, """)
|
|
2366
|
+
.replace(/"/g, """)
|
|
2367
|
+
.replace(/'/g, "'");
|
|
2335
2368
|
}
|
|
2336
2369
|
function fmtUptime(ms) {
|
|
2337
2370
|
const s = Math.floor(ms / 1000);
|