@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.
Files changed (3) hide show
  1. package/dashboard.html +39 -6
  2. package/logs.html +1018 -480
  3. 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.textContent = "5s";
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
- }, 5000);
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(8000) });
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, "&amp;")
2332
2364
  .replace(/</g, "&lt;")
2333
2365
  .replace(/>/g, "&gt;")
2334
- .replace(/"/g, "&quot;");
2366
+ .replace(/"/g, "&quot;")
2367
+ .replace(/'/g, "&#39;");
2335
2368
  }
2336
2369
  function fmtUptime(ms) {
2337
2370
  const s = Math.floor(ms / 1000);