@essentialai/cogent-bridge-bundled 3.23.8 → 3.24.0

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 (2) hide show
  1. package/cogent-bridge.mjs +244 -7
  2. package/package.json +1 -1
package/cogent-bridge.mjs CHANGED
@@ -26389,8 +26389,8 @@ var init_stdio2 = __esm({
26389
26389
  // src/constants.ts
26390
26390
  import { createRequire } from "node:module";
26391
26391
  function resolveVersion() {
26392
- if ("3.23.8") {
26393
- return "3.23.8";
26392
+ if ("3.24.0") {
26393
+ return "3.24.0";
26394
26394
  }
26395
26395
  try {
26396
26396
  const require2 = createRequire(import.meta.url);
@@ -32141,6 +32141,15 @@ var init_ws_client = __esm({
32141
32141
  backoff;
32142
32142
  reconnectTimer = null;
32143
32143
  pollTimer = null;
32144
+ /**
32145
+ * DELIVERY-PATH EVIDENCE. Before 3.23.9 a poll failure was caught and only logger.warn'd, so the
32146
+ * bridge had no idea whether its FALLBACK delivery path worked — and `healthy` could not be
32147
+ * computed honestly because the data did not exist. Captured evidence that nothing reads is the
32148
+ * defect shape this codebase keeps hitting.
32149
+ */
32150
+ lastPollOkAt = null;
32151
+ lastPollError = null;
32152
+ lastWsErrorSticky = null;
32144
32153
  pingTimer = null;
32145
32154
  lastMessageId = null;
32146
32155
  /**
@@ -32219,6 +32228,7 @@ var init_ws_client = __esm({
32219
32228
  this.ws = ws;
32220
32229
  ws.on("open", () => {
32221
32230
  if (generation !== this.connectionGeneration || this.ws !== ws) return;
32231
+ this.lastWsErrorSticky = null;
32222
32232
  this.setState("connected");
32223
32233
  this.backoff.reset();
32224
32234
  this.stopPolling();
@@ -32275,6 +32285,7 @@ var init_ws_client = __esm({
32275
32285
  ws.on("error", (err) => {
32276
32286
  if (generation !== this.connectionGeneration || this.ws !== ws) return;
32277
32287
  this.lastWsError = err.message;
32288
+ this.lastWsErrorSticky = err.message;
32278
32289
  logger.error(`CloudWsClient: WebSocket error: ${err.message}`);
32279
32290
  });
32280
32291
  }
@@ -32338,6 +32349,18 @@ var init_ws_client = __esm({
32338
32349
  * ISO string. Survives reconnects, same as `getLastFrameAt()`.
32339
32350
  * Audit L2.
32340
32351
  */
32352
+ /**
32353
+ * What this bridge's DELIVERY situation actually is — the input `healthy` needs in order to
32354
+ * describe THIS BRIDGE rather than the relay's uptime.
32355
+ */
32356
+ getDeliveryDiagnostics() {
32357
+ return {
32358
+ pollActive: this.pollTimer !== null,
32359
+ lastPollOkAt: this.lastPollOkAt,
32360
+ lastPollError: this.lastPollError,
32361
+ lastWsError: this.lastWsErrorSticky
32362
+ };
32363
+ }
32341
32364
  getLastFrameAtMs() {
32342
32365
  return this.lastFrameAt;
32343
32366
  }
@@ -32474,10 +32497,11 @@ var init_ws_client = __esm({
32474
32497
  this.opts.onMessages(result.messages);
32475
32498
  this.advanceCursor(result.messages[result.messages.length - 1].id);
32476
32499
  }
32500
+ this.lastPollOkAt = Date.now();
32501
+ this.lastPollError = null;
32477
32502
  } catch (err) {
32478
- logger.warn(
32479
- `CloudWsClient: Poll failed: ${err instanceof Error ? err.message : String(err)}`
32480
- );
32503
+ this.lastPollError = err instanceof Error ? err.message : String(err);
32504
+ logger.warn(`CloudWsClient: Poll failed: ${this.lastPollError}`);
32481
32505
  }
32482
32506
  };
32483
32507
  void poll();
@@ -35098,6 +35122,113 @@ var init_auto_relay = __esm({
35098
35122
  }
35099
35123
  });
35100
35124
 
35125
+ // src/services/peer-presence.ts
35126
+ function autoPresenceEnabled(env = process.env) {
35127
+ const v = env.COGENT_AUTO_PRESENCE;
35128
+ if (v === void 0 || v === "") return true;
35129
+ return !/^(0|false|no|off)$/i.test(v.trim());
35130
+ }
35131
+ async function restorePresence(deps) {
35132
+ try {
35133
+ if (!deps.isCloudConfigured()) {
35134
+ return { state: "local", restored: false, detail: "local mode \u2014 presence does not apply" };
35135
+ }
35136
+ if (deps.alreadyRegisteredInProcess()) {
35137
+ return { state: "online", restored: false, detail: "registered by this process" };
35138
+ }
35139
+ const creds = await deps.loadCredentials();
35140
+ if (!creds || !creds.endpoint || !creds.sessionId || !creds.token) {
35141
+ return {
35142
+ state: "deferred",
35143
+ restored: false,
35144
+ detail: "no stored channel credentials for this working directory \u2014 join a channel first"
35145
+ };
35146
+ }
35147
+ if (!creds.peerId) {
35148
+ return {
35149
+ state: "deferred",
35150
+ restored: false,
35151
+ detail: "channel credentials exist but name no peer \u2014 nothing was registered here"
35152
+ };
35153
+ }
35154
+ const peerId = creds.peerId;
35155
+ if (deps.peerAlreadyServed(peerId)) {
35156
+ return {
35157
+ state: "online",
35158
+ restored: false,
35159
+ detail: `peer '${peerId}' is already served by a live bridge for this working directory`
35160
+ };
35161
+ }
35162
+ if (!autoPresenceEnabled(deps.env ?? process.env)) {
35163
+ return {
35164
+ state: "offline",
35165
+ restored: false,
35166
+ detail: `peer '${peerId}' is not registered and COGENT_AUTO_PRESENCE is off \u2014 this agent is absent from its channel`
35167
+ };
35168
+ }
35169
+ await deps.goOnline({
35170
+ peerId,
35171
+ endpoint: creds.endpoint,
35172
+ sessionId: creds.sessionId,
35173
+ token: creds.token,
35174
+ cwd: deps.cwd(),
35175
+ // 🔴 THE PEER'S DISPLAY LABEL IS NOT PERSISTED ANYWHERE — only the CHANNEL's is,
35176
+ // in credentials.label (create-session.ts writes `label: data.label`; join-session
35177
+ // writes the resolved channel label). Using that would label the agent after the
35178
+ // channel: a restore once put "paymentorchestrator" beside a sibling called "POFE".
35179
+ // peerId is the one identifier we hold that genuinely names this agent. The
35180
+ // operator's chosen label returns on the next cogent_register_peer, which carries it.
35181
+ label: peerId,
35182
+ // 🔴 WITHOUT THIS THE RESTORE CANNOT RECLAIM ITS OWN PEER. A re-join issues a NEW
35183
+ // token, and AUD-003 ownership is proven by the token that CREATED the peer or by
35184
+ // the secret issued with it. Omitting it means an entry owned by an earlier token
35185
+ // answers PEER_NOT_YOURS and the agent stays offline — precisely the state this
35186
+ // module exists to leave. The secret is in the credential file; send it.
35187
+ peerSecret: creds.peerSecret
35188
+ });
35189
+ return {
35190
+ state: "online",
35191
+ restored: true,
35192
+ peerId,
35193
+ // Says what THIS process did. Whether the relay now lists the peer is the relay's
35194
+ // state, and asserting it from here would be a success nobody measured.
35195
+ detail: `re-registered peer '${peerId}' from stored credentials`
35196
+ };
35197
+ } catch (err) {
35198
+ const reason = err instanceof Error ? err.message : String(err);
35199
+ return {
35200
+ state: "offline",
35201
+ restored: false,
35202
+ detail: `presence restore failed: ${reason}`
35203
+ };
35204
+ }
35205
+ }
35206
+ function setPresence(outcome) {
35207
+ lastPresence = outcome;
35208
+ }
35209
+ function getPresence() {
35210
+ return lastPresence;
35211
+ }
35212
+ function logPresence(outcome) {
35213
+ if (outcome.state === "online" && outcome.restored) {
35214
+ logger.info(
35215
+ `Presence: offline -> online \u2014 ${outcome.detail}. This agent is addressable on its channel again, and leftover bridges for this checkout are now reapable.`
35216
+ );
35217
+ } else if (outcome.state === "offline") {
35218
+ logger.warn(`Presence: OFFLINE \u2014 ${outcome.detail}.`);
35219
+ } else {
35220
+ logger.debug(`Presence: ${outcome.state} \u2014 ${outcome.detail}.`);
35221
+ }
35222
+ }
35223
+ var lastPresence;
35224
+ var init_peer_presence = __esm({
35225
+ "src/services/peer-presence.ts"() {
35226
+ "use strict";
35227
+ init_logger();
35228
+ lastPresence = null;
35229
+ }
35230
+ });
35231
+
35101
35232
  // src/services/heartbeat.ts
35102
35233
  var HeartbeatService, heartbeat;
35103
35234
  var init_heartbeat = __esm({
@@ -35329,8 +35460,10 @@ __export(startup_exports, {
35329
35460
  cloudWsClient: () => cloudWsClient,
35330
35461
  hasPendingLabelResolve: () => hasPendingLabelResolve,
35331
35462
  isCloudMode: () => isCloudMode2,
35463
+ presenceRegisterArgs: () => presenceRegisterArgs,
35332
35464
  reinitCloudBackend: () => reinitCloudBackend,
35333
35465
  resolvePendingLabel: () => resolvePendingLabel,
35466
+ restorePeerPresence: () => restorePeerPresence,
35334
35467
  runPreflights: () => runPreflights,
35335
35468
  runStartup: () => runStartup,
35336
35469
  setInboxNotifier: () => setInboxNotifier,
@@ -35461,6 +35594,58 @@ async function triggerReRegistration() {
35461
35594
  reRegistrationInProgress = false;
35462
35595
  }
35463
35596
  }
35597
+ function presenceRegisterArgs(p) {
35598
+ return [
35599
+ p.peerId,
35600
+ p.sessionId,
35601
+ p.cwd,
35602
+ p.label,
35603
+ CLIENT_VERSION,
35604
+ "agent",
35605
+ void 0,
35606
+ // channelSessionId — not tracked on a presence restore
35607
+ void 0,
35608
+ // capabilities — likewise
35609
+ deriveWorkspaceId(p.cwd),
35610
+ p.sessionId,
35611
+ // threadId
35612
+ p.peerSecret
35613
+ // AUD-003 ownership proof — reclaims a peer owned by an earlier token
35614
+ ];
35615
+ }
35616
+ async function restorePeerPresence() {
35617
+ const outcome = await restorePresence({
35618
+ // The endpoint being a relay URL is what makes presence meaningful. We deliberately do
35619
+ // NOT gate on the active backend being the cloud one: at startup it is still the
35620
+ // deferred FileBackend placeholder, and gating on it made this whole path inert
35621
+ // (measured: "skipped: not-cloud-mode" with valid credentials on disk).
35622
+ isCloudConfigured: () => {
35623
+ const ep = getConfig().COGENT_ENDPOINT;
35624
+ return !!ep && isCloudEndpoint(ep);
35625
+ },
35626
+ alreadyRegisteredInProcess: () => autoRelay.getDiagnostics().registered,
35627
+ peerAlreadyServed: (peerId) => {
35628
+ try {
35629
+ return listLiveBridges(process.cwd(), peerId).some((b) => b.pid !== process.pid);
35630
+ } catch {
35631
+ return false;
35632
+ }
35633
+ },
35634
+ loadCredentials: () => loadCredentials(),
35635
+ cwd: () => process.cwd(),
35636
+ goOnline: async ({ peerId, endpoint, sessionId, token, cwd, label, peerSecret }) => {
35637
+ await reinitCloudBackend(endpoint, sessionId, token);
35638
+ const backend = getBackend();
35639
+ await backend.registerPeer(...presenceRegisterArgs({ peerId, sessionId, cwd, label, peerSecret }));
35640
+ autoRelay.setLocalPeer(peerId, sessionId, cwd, "agent", label, sessionId);
35641
+ if (cloudWsClient) cloudWsClient.setPeerId(peerId);
35642
+ heartbeat.restart();
35643
+ }
35644
+ });
35645
+ setPresence(outcome);
35646
+ logPresence(outcome);
35647
+ return outcome;
35648
+ }
35464
35649
  function createCloudWsClient(endpoint, sessionId, token, http, inbox, pollIntervalMs) {
35465
35650
  const client = new CloudWsClient({
35466
35651
  endpoint,
@@ -35712,6 +35897,8 @@ var init_startup = __esm({
35712
35897
  init_cloud();
35713
35898
  init_http_client();
35714
35899
  init_auto_relay();
35900
+ init_peer_presence();
35901
+ init_wake_ownership();
35715
35902
  init_heartbeat();
35716
35903
  init_codex_preflight();
35717
35904
  init_codex_cli();
@@ -37089,6 +37276,18 @@ function registerDeregisterPeerTool(server) {
37089
37276
  logger.warn("failed to clear local mail credentials after deprovision", { error: err });
37090
37277
  }
37091
37278
  }
37279
+ if (removed) {
37280
+ try {
37281
+ const creds = await loadCredentials();
37282
+ if (creds?.peerId === peerId) {
37283
+ const { peerId: _dropped, peerSecret: _secret, ...rest } = creds;
37284
+ await saveCredentials({ ...rest, savedAt: (/* @__PURE__ */ new Date()).toISOString() });
37285
+ logger.info("cleared stored peerId after deregister", { peerId });
37286
+ }
37287
+ } catch (err) {
37288
+ logger.warn("failed to clear stored peerId after deregister", { error: err });
37289
+ }
37290
+ }
37092
37291
  return successResult({
37093
37292
  success: removed,
37094
37293
  message: removed ? `Peer '${peerId}' deregistered` : `Peer '${peerId}' was not registered`
@@ -37111,6 +37310,7 @@ var init_deregister_peer = __esm({
37111
37310
  init_logger();
37112
37311
  init_heartbeat();
37113
37312
  init_mail_credential_store();
37313
+ init_credential_store();
37114
37314
  }
37115
37315
  });
37116
37316
 
@@ -37134,12 +37334,14 @@ function registerHealthCheckTool(server) {
37134
37334
  const backend = getBackend();
37135
37335
  const result = await backend.checkHealth();
37136
37336
  let wsConnected = false;
37337
+ let delivery = null;
37137
37338
  let wsLastFrameAt = null;
37138
37339
  let wsLastFrameAtMs = null;
37139
37340
  try {
37140
37341
  const startup = await Promise.resolve().then(() => (init_startup(), startup_exports));
37141
37342
  if (startup.cloudWsClient) {
37142
37343
  wsConnected = startup.cloudWsClient.isConnected();
37344
+ delivery = startup.cloudWsClient.getDeliveryDiagnostics?.() ?? null;
37143
37345
  wsLastFrameAt = startup.cloudWsClient.getLastFrameAt();
37144
37346
  wsLastFrameAtMs = startup.cloudWsClient.getLastFrameAtMs();
37145
37347
  }
@@ -37177,8 +37379,20 @@ function registerHealthCheckTool(server) {
37177
37379
  }
37178
37380
  }
37179
37381
  const updateAvailable = getLastNudge();
37382
+ const relayHealthy = result.healthy !== false;
37383
+ let deliveryPath = "unknown";
37384
+ if (cloud && delivery) {
37385
+ deliveryPath = wsConnected ? "websocket" : delivery.pollActive && !delivery.lastPollError ? "poll" : "none";
37386
+ } else if (cloud && wsConnected) {
37387
+ deliveryPath = "websocket";
37388
+ }
37389
+ const registered = autoRelay.getDiagnostics().registered;
37390
+ const deliveryBroken = cloud && registered && deliveryPath === "none";
37391
+ 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"}) \u2014 messages addressed to this peer cannot reach it` : null;
37180
37392
  const enriched = {
37181
37393
  ...JSON.parse(JSON.stringify(result)),
37394
+ healthy: relayHealthy && !deliveryBroken,
37395
+ ...unhealthyReason ? { unhealthyReason } : {},
37182
37396
  clientVersion: SERVER_VERSION,
37183
37397
  ...updateAvailable ? { updateAvailable } : {},
37184
37398
  runtimeMode: cloud ? "cloud" : "local",
@@ -37198,9 +37412,26 @@ function registerHealthCheckTool(server) {
37198
37412
  // on HttpBackend; null when the /api/health fetch fails. Keep the
37199
37413
  // key cloud-gated for shape consistency with wsHealth (local mode
37200
37414
  // never has an upstream relay version to report).
37201
- ...cloud ? { wsHealth, relayVersion } : {}
37415
+ ...cloud ? { wsHealth, relayVersion, deliveryPath, lastWsError: delivery?.lastWsError ?? null } : {}
37202
37416
  },
37203
- autoRelay: autoRelay.getDiagnostics()
37417
+ autoRelay: autoRelay.getDiagnostics(),
37418
+ // PRESENCE — the agent's own view of whether it is IN its channel, so it can
37419
+ // answer "am I reachable?" without inferring it from transport internals.
37420
+ // "online" registered · "offline" owns a peer but is not registered (nobody can
37421
+ // reach it) · "deferred" never joined · "local" no relay.
37422
+ // services/peer-presence.ts carries the vocabulary and how each state arises.
37423
+ presence: (() => {
37424
+ const p = getPresence();
37425
+ if (!p) {
37426
+ return { state: "unknown", detail: "presence has not been evaluated yet" };
37427
+ }
37428
+ return {
37429
+ state: p.state,
37430
+ restored: p.restored,
37431
+ detail: p.detail,
37432
+ ..."peerId" in p ? { peerId: p.peerId } : {}
37433
+ };
37434
+ })()
37204
37435
  };
37205
37436
  return successResult(enriched);
37206
37437
  } catch (err) {
@@ -37220,6 +37451,7 @@ var init_health_check2 = __esm({
37220
37451
  init_errors4();
37221
37452
  init_logger();
37222
37453
  init_auto_relay();
37454
+ init_peer_presence();
37223
37455
  }
37224
37456
  });
37225
37457
 
@@ -93981,6 +94213,11 @@ async function main() {
93981
94213
  `Preflight error (non-fatal): ${err instanceof Error ? err.message : String(err)}`
93982
94214
  );
93983
94215
  });
94216
+ void restorePeerPresence().catch((err) => {
94217
+ logger.warn(
94218
+ `Presence restore error (non-fatal): ${err instanceof Error ? err.message : String(err)}`
94219
+ );
94220
+ });
93984
94221
  startUpdateCheckLoop(SERVER_VERSION);
93985
94222
  logger.info(
93986
94223
  "Server ready. Tools: cogent_register_peer, cogent_deregister_peer, cogent_send_message, cogent_list_peers, cogent_get_history, cogent_health_check, cogent_create_session, cogent_join_session"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@essentialai/cogent-bridge-bundled",
3
- "version": "3.23.8",
3
+ "version": "3.24.0",
4
4
  "description": "Zero-dependency, pre-bundled Cogent MCP bridge — a single self-contained file for fast cold `npx` startup (used by the Codex plugin, whose MCP startup window is short). Functionally identical to @essentialai/cogent-bridge; carries no npm dependencies so `npx` skips dependency install.",
5
5
  "type": "module",
6
6
  "bin": {