@essentialai/cogent-bridge
Version:
Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.
195 lines • 11.3 kB
JavaScript
import { getBackend, isCloudMode } from "../backend/index.js";
import { getConfig } from "../config.js";
import { SERVER_VERSION } from "../constants.js";
import { getLastNudge } from "../backend/npm-update-check.js";
import { successResult, errorResult } from "../errors.js";
import { logger } from "../logger.js";
import { autoRelay } from "../services/auto-relay.js";
import { getPresence } from "../services/peer-presence.js";
export function registerHealthCheckTool(server) {
server.registerTool("cogent_health_check", {
title: "Health Check",
description: "Diagnose the bridge's operational status. Checks state file accessibility, " +
"lock mechanism, and Claude CLI availability. Returns per-check pass/fail with details.",
inputSchema: {},
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: false,
},
}, async () => {
try {
const backend = getBackend();
const result = await backend.checkHealth();
// Read live WS transport state from the startup-time singleton.
// Dynamic import avoids a circular dep with startup.ts (which itself
// imports backend code transitively). In local mode or when startup
// hasn't run, defaults are wsConnected=false / wsLastFrameAt=null --
// the field is always present so consumers don't need a mode switch.
let wsConnected = false;
let delivery = null;
let wsLastFrameAt = null;
let wsLastFrameAtMs = null;
try {
const startup = await import("../startup.js");
if (startup.cloudWsClient) {
wsConnected = startup.cloudWsClient.isConnected();
delivery = startup.cloudWsClient.getDeliveryDiagnostics?.() ?? null;
wsLastFrameAt = startup.cloudWsClient.getLastFrameAt();
wsLastFrameAtMs = startup.cloudWsClient.getLastFrameAtMs();
}
}
catch (err) {
// Test harness or local-only mode -- defaults are correct. Log at
// debug so a future regression (syntax error in startup.ts, circular
// dep, torn singleton) is observable when COGENT_LOG_LEVEL=debug.
// Audit L1.
logger.debug(`health-check: startup module unavailable: ${err instanceof Error ? err.message : String(err)}`);
}
const cloud = isCloudMode();
// wsHealth: cloud-only enum derived from wsConnected + wsAgeMs vs COGENT_WS_STALE_MS.
// Four states (3.2.2): "fresh" (connected, recent frame), "stale" (connected, no
// frame within threshold — see 3.1.10 keepalive-pong refresh), "reconnecting"
// (socket momentarily down but last frame was recent, i.e. an in-progress
// auto-reconnect cycle — bridge keepalive cycles every ~5-20min on idle channels
// and each cycle takes 1-4s; pre-3.2.2 reported these as "disconnected" which
// alarmed operators on a healthy idle channel), and "disconnected" (socket down
// and last frame older than threshold, i.e. extended outage). Null age while
// connected => "fresh" (just-connected grace).
let wsHealth = "fresh";
if (cloud) {
const threshold = getConfig().COGENT_WS_STALE_MS;
const ageMs = wsLastFrameAtMs === null ? null : Date.now() - wsLastFrameAtMs;
if (!wsConnected) {
// Socket-down + recent frame = transient reconnect, not a real outage.
// Same threshold as fresh/stale boundary so the metric stays internally
// consistent (no second tunable env var).
if (ageMs !== null && ageMs <= threshold) {
wsHealth = "reconnecting";
}
else {
wsHealth = "disconnected";
}
}
else if (ageMs !== null && ageMs > threshold) {
wsHealth = "stale";
}
else {
wsHealth = "fresh";
}
}
// VER-02: lazy lookup of the upstream relay version. Cloud-only —
// HttpBackend implements getRelayVersion (delegates to the 60s TTL
// cache); FileBackend omits it. On fetch failure the cache returns
// null and we keep null here; the rest of the health response stays
// intact. Optional-chained so a backend without the method (e.g.,
// FileBackend) cannot break the tool.
let relayVersion = null;
if (cloud && typeof backend.getRelayVersion === "function") {
try {
relayVersion = (await backend.getRelayVersion()) ?? null;
}
catch (err) {
// Defense in depth — the cache module already swallows fetch
// errors and returns null, but if a future backend impl throws
// we still want health-check to succeed.
logger.debug(`health-check: getRelayVersion threw: ${err instanceof Error ? err.message : String(err)}`);
relayVersion = null;
}
}
// Surface the running client version and, if the startup npm check found a
// newer release, the same update nudge — so the agent shows the user they're
// on a stale build (the recurring "/cogent map is out of date" pain). The nudge
// is computed once at startup (best-effort, never blocks); null when current.
const updateAvailable = getLastNudge();
/**
* 🔴 `healthy` USED TO MEAN "THE RELAY IS UP" (http-backend: `resp.status === "ok"`).
* It never described THIS BRIDGE, so an agent with no delivery path at all still answered
* `healthy: true`, was listed in the roster and looked live. Reported by marvin-mobile on
* 2026-09-06 after losing a day to it.
*
* `wsConnected: false` alone is NOT unreachable — the poll fallback delivers, and that is
* how the reporter's own messages were arriving. Marking a working degraded mode "broken"
* would fire on every ordinary reconnect. The condition is: is ANY path delivering?
*/
const relayHealthy = result.healthy !== false;
let deliveryPath = "unknown";
if (cloud && delivery) {
deliveryPath = wsConnected
? "websocket"
// A poll that has not completed a cycle yet is UNKNOWN, not failed — do not alarm on it.
: delivery.pollActive && !delivery.lastPollError
? "poll"
: "none";
}
else if (cloud && wsConnected) {
deliveryPath = "websocket";
}
const registered = autoRelay.getDiagnostics().registered;
// Only a REGISTERED cloud peer has anything addressed to it; an unregistered bridge with no
// socket is idle, not broken.
const deliveryBroken = cloud && registered && deliveryPath === "none";
const unhealthyReason = deliveryBroken
? `registered as a cloud peer but NO delivery path is working (websocket down${delivery?.lastWsError ? `: ${delivery.lastWsError}` : ""}; poll ${delivery?.lastPollError ? `failing: ${delivery.lastPollError}` : "inactive"}) — ` +
`messages addressed to this peer cannot reach it`
: null;
const enriched = {
...JSON.parse(JSON.stringify(result)),
healthy: relayHealthy && !deliveryBroken,
...(unhealthyReason ? { unhealthyReason } : {}),
clientVersion: SERVER_VERSION,
...(updateAvailable ? { updateAvailable } : {}),
runtimeMode: cloud ? "cloud" : "local",
// Field placement: mode -> transport -> autoRelay reads sensibly
// in JSON output (operational layers from outermost to innermost).
transport: {
// wsApplicable first so consumers see the gate before the gated
// values; existing two fields keep their relative order; wsAgeMs
// last (newest, least likely to be relied on by existing
// consumers). Audit L5 + L2.
wsApplicable: cloud,
wsConnected,
wsLastFrameAt,
wsAgeMs: wsLastFrameAtMs === null
? null
: Date.now() - wsLastFrameAtMs,
// wsHealth: cloud-only by design — local backends have no WS to assess.
// relayVersion: cloud-only (VER-02). Populated from a 60s TTL cache
// on HttpBackend; null when the /api/health fetch fails. Keep the
// key cloud-gated for shape consistency with wsHealth (local mode
// never has an upstream relay version to report).
...(cloud ? { wsHealth, relayVersion, deliveryPath, lastWsError: delivery?.lastWsError ?? null } : {}),
},
autoRelay: autoRelay.getDiagnostics(),
// PRESENCE — the agent's own view of whether it is IN its channel, so it can
// answer "am I reachable?" without inferring it from transport internals.
// "online" registered · "offline" owns a peer but is not registered (nobody can
// reach it) · "standby" another live bridge serves this peer, so THIS process is not
// registered (servedBy names it) · "deferred" never joined · "local" no relay.
// services/peer-presence.ts carries the vocabulary and how each state arises.
presence: (() => {
const p = getPresence();
if (!p) {
// Evaluated once at startup, fire-and-forget. Null means that has not
// completed — report the uncertainty rather than guessing a state.
return { state: "unknown", detail: "presence has not been evaluated yet" };
}
return {
state: p.state,
restored: p.restored,
detail: p.detail,
...("peerId" in p ? { peerId: p.peerId } : {}),
...("servedBy" in p ? { servedBy: p.servedBy } : {}),
};
})(),
};
return successResult(enriched);
}
catch (err) {
logger.error("health-check failed", { error: err });
return errorResult(err);
}
});
}
//# sourceMappingURL=health-check.js.map