@codemem/opencode-plugin 0.22.0-alpha.0 → 0.22.0-alpha.2

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.
@@ -621,6 +621,14 @@ export const OpencodeMemPlugin = async ({
621
621
  let fallbackFailureNoted = false;
622
622
  let lastStatusCheckAt = 0;
623
623
  let lastStatusAvailable = true;
624
+
625
+ // Viewer health-check state
626
+ const HEALTH_CHECK_INTERVAL_MS = 60_000;
627
+ const HEALTH_CONSECUTIVE_FAILURES_BEFORE_RESTART = 3;
628
+ const HEALTH_RESTART_COOLDOWN_MS = 5 * 60_000;
629
+ let healthCheckTimer = null;
630
+ let healthConsecutiveFailures = 0;
631
+ let healthLastRestartAttempt = 0;
624
632
  const nextEventId = () => {
625
633
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
626
634
  return crypto.randomUUID();
@@ -1081,6 +1089,7 @@ export const OpencodeMemPlugin = async ({
1081
1089
  } catch (err) {
1082
1090
  logLine(`viewer spawn failed: ${err}`).catch(() => {});
1083
1091
  }
1092
+ startHealthCheck();
1084
1093
  };
1085
1094
 
1086
1095
  const runCommand = async (cmd, options = {}) => {
@@ -1399,10 +1408,68 @@ export const OpencodeMemPlugin = async ({
1399
1408
  return;
1400
1409
  }
1401
1410
  viewerStarted = false;
1411
+ stopHealthCheck();
1402
1412
  await logLine("viewer stop requested");
1403
1413
  await runCli(["serve", "stop"]);
1404
1414
  };
1405
1415
 
1416
+ const checkViewerHealth = async () => {
1417
+ if (!viewerStarted || !viewerEnabled) return;
1418
+ try {
1419
+ const resp = await fetch(rawEventsStatusUrl, {
1420
+ method: "GET",
1421
+ signal: AbortSignal.timeout(5000),
1422
+ });
1423
+ if (resp.ok) {
1424
+ if (healthConsecutiveFailures > 0) {
1425
+ await logLine(`viewer.health recovered after ${healthConsecutiveFailures} failure(s)`);
1426
+ }
1427
+ healthConsecutiveFailures = 0;
1428
+ return;
1429
+ }
1430
+ healthConsecutiveFailures++;
1431
+ await logLine(`viewer.health check failed (status=${resp.status}, consecutive=${healthConsecutiveFailures})`);
1432
+ } catch (err) {
1433
+ healthConsecutiveFailures++;
1434
+ await logLine(`viewer.health check error (consecutive=${healthConsecutiveFailures}): ${String(err).slice(0, 200)}`);
1435
+ }
1436
+
1437
+ if (
1438
+ healthConsecutiveFailures >= HEALTH_CONSECUTIVE_FAILURES_BEFORE_RESTART &&
1439
+ Date.now() - healthLastRestartAttempt >= HEALTH_RESTART_COOLDOWN_MS
1440
+ ) {
1441
+ healthLastRestartAttempt = Date.now();
1442
+ await logLine(`viewer.health restarting viewer after ${healthConsecutiveFailures} consecutive failures`);
1443
+ try {
1444
+ const result = await runCli(["serve", "restart"]);
1445
+ const ok = result?.exitCode === 0;
1446
+ await logLine(`viewer.health restart ${ok ? "succeeded" : "failed"} (exit=${result?.exitCode ?? "unknown"})`);
1447
+ if (ok) {
1448
+ healthConsecutiveFailures = 0;
1449
+ }
1450
+ } catch (restartErr) {
1451
+ await logLine(`viewer.health restart error: ${String(restartErr).slice(0, 200)}`);
1452
+ }
1453
+ }
1454
+ };
1455
+
1456
+ const startHealthCheck = () => {
1457
+ if (healthCheckTimer) return;
1458
+ healthConsecutiveFailures = 0;
1459
+ healthCheckTimer = setInterval(() => {
1460
+ checkViewerHealth().catch(() => {});
1461
+ }, HEALTH_CHECK_INTERVAL_MS);
1462
+ if (healthCheckTimer.unref) healthCheckTimer.unref();
1463
+ };
1464
+
1465
+ const stopHealthCheck = () => {
1466
+ if (healthCheckTimer) {
1467
+ clearInterval(healthCheckTimer);
1468
+ healthCheckTimer = null;
1469
+ }
1470
+ healthConsecutiveFailures = 0;
1471
+ };
1472
+
1406
1473
  // Get version info (commit hash) for debugging
1407
1474
  let version = "unknown";
1408
1475
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codemem/opencode-plugin",
3
- "version": "0.22.0-alpha.0",
3
+ "version": "0.22.0-alpha.2",
4
4
  "description": "CodeMem plugin for OpenCode",
5
5
  "type": "module",
6
6
  "main": "./index.js",