@essentialai/cogent-bridge-bundled 3.24.2 → 3.25.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 +61 -14
  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.24.2") {
26393
- return "3.24.2";
26392
+ if ("3.25.0") {
26393
+ return "3.25.0";
26394
26394
  }
26395
26395
  try {
26396
26396
  const require2 = createRequire(import.meta.url);
@@ -27710,7 +27710,7 @@ var init_file_backend = __esm({
27710
27710
  threadId
27711
27711
  );
27712
27712
  }
27713
- async deregisterPeer(peerId) {
27713
+ async deregisterPeer(peerId, _peerSecret) {
27714
27714
  return { removed: await deregisterPeer(peerId), mailboxDeprovisioned: false };
27715
27715
  }
27716
27716
  getPeer(peerId) {
@@ -27871,10 +27871,10 @@ var init_http_backend = __esm({
27871
27871
  * confirmed the Team mailbox was reaped, so the deregister-peer tool can clear the now-dead
27872
27872
  * local mail creds. A 404 (peer not found) resolves to `{ removed: false, ... }`, not a throw.
27873
27873
  */
27874
- async deregisterPeer(peerId) {
27874
+ async deregisterPeer(peerId, peerSecret) {
27875
27875
  const path26 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
27876
27876
  try {
27877
- const headers = await this.http.delete(path26, {});
27877
+ const headers = await this.http.delete(path26, peerSecret ? { peerSecret } : {});
27878
27878
  const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
27879
27879
  return { removed: true, mailboxDeprovisioned };
27880
27880
  } catch (err) {
@@ -27942,6 +27942,9 @@ var init_http_backend = __esm({
27942
27942
  if (record2.attachments && record2.attachments.length > 0) {
27943
27943
  body.attachments = record2.attachments;
27944
27944
  }
27945
+ if (record2.replyExpected === false && await relaySupports(this.http, "terminal-messages")) {
27946
+ body.replyExpected = false;
27947
+ }
27945
27948
  const resp = await this.http.post(path26, body);
27946
27949
  return {
27947
27950
  ...record2,
@@ -28125,6 +28128,38 @@ var init_http_client = __esm({
28125
28128
  clearTimeout(timer);
28126
28129
  }
28127
28130
  }
28131
+ /**
28132
+ * Parse a SUCCESS body, turning an unparseable one into a BridgeError.
28133
+ *
28134
+ * 🔴 WHY THIS EXISTS. `throwMappedError` has always guarded the NON-2xx path, so an nginx 502 or
28135
+ * 413 HTML page arrives as a clean BridgeError. The 2xx path did not: `return resp.json()` let a
28136
+ * truncated or empty success body escape as a raw `SyntaxError` carrying no code, no suggestion,
28137
+ * and nothing in the signature to warn a caller it could happen — callers at
28138
+ * http-backend.ts (list peers / get history / health check) simply propagated it.
28139
+ *
28140
+ * That is the worst corner of the trade-off the vault describes (how much information a failure
28141
+ * carries vs how strictly consumers must handle it —
28142
+ * memory/typescript-master-vault/concepts/Error_Handling.md), in a codebase whose own
28143
+ * BridgeError(code, message, suggestion) is the answer to it.
28144
+ *
28145
+ * A 2xx with an unreadable body is REAL: @hono/node-server can answer with a null body or append
28146
+ * `Error: …` to an already-streaming response (handleResponseError), and any proxy may truncate a
28147
+ * long /poll body. STARTUP_FAILED is deliberately the same code throwMappedError falls back to
28148
+ * for a non-JSON error body, so both directions of "the relay said something we cannot read"
28149
+ * report identically rather than inventing a second vocabulary.
28150
+ */
28151
+ async parseJson(resp, method, url) {
28152
+ try {
28153
+ return await resp.json();
28154
+ } catch (e) {
28155
+ const detail = e instanceof Error ? e.message : String(e);
28156
+ throw new BridgeError(
28157
+ "STARTUP_FAILED" /* STARTUP_FAILED */,
28158
+ `Relay returned HTTP ${resp.status} with an unreadable body for ${method} ${url.pathname}: ${detail}`,
28159
+ "The response was not valid JSON \u2014 usually a proxy error page or a truncated body. Retry; if it persists, check the relay and any proxy in front of it."
28160
+ );
28161
+ }
28162
+ }
28128
28163
  /**
28129
28164
  * Perform an authenticated GET request.
28130
28165
  * Appends query parameters to the URL if provided.
@@ -28140,7 +28175,7 @@ var init_http_client = __esm({
28140
28175
  if (!resp.ok) {
28141
28176
  await this.throwMappedError(resp);
28142
28177
  }
28143
- return resp.json();
28178
+ return this.parseJson(resp, "GET", url);
28144
28179
  }
28145
28180
  /**
28146
28181
  * Perform an authenticated POST request with a JSON body.
@@ -28158,7 +28193,7 @@ var init_http_client = __esm({
28158
28193
  if (resp.status === 204 || resp.headers?.get("content-length") === "0") {
28159
28194
  return void 0;
28160
28195
  }
28161
- return resp.json();
28196
+ return this.parseJson(resp, "POST", url);
28162
28197
  }
28163
28198
  /**
28164
28199
  * Perform an authenticated PATCH request with a JSON body.
@@ -28177,7 +28212,7 @@ var init_http_client = __esm({
28177
28212
  if (resp.status === 204 || resp.headers?.get("content-length") === "0") {
28178
28213
  return void 0;
28179
28214
  }
28180
- return resp.json();
28215
+ return this.parseJson(resp, "PATCH", url);
28181
28216
  }
28182
28217
  /**
28183
28218
  * Perform an authenticated DELETE request.
@@ -36370,7 +36405,10 @@ function registerSendMessageTool(server) {
36370
36405
  inputSchema: {
36371
36406
  fromPeerId: import_zod4.z.string().describe("Peer ID of the sender, e.g. 'backend'"),
36372
36407
  toPeerId: import_zod4.z.string().describe("Peer ID of the recipient, e.g. 'frontend'. Use '*' or 'broadcast' to send to all peers."),
36373
- message: import_zod4.z.string().describe("The message content to send to the target peer")
36408
+ message: import_zod4.z.string().describe("The message content to send to the target peer"),
36409
+ replyExpected: import_zod4.z.boolean().optional().describe(
36410
+ "Set false for a TERMINAL message \u2014 an acknowledgement, confirmation or FYI that conveys information and needs no answer. The recipient's check-on-stop hook then never counts it as owing a reply. Omit (or true) for anything that asks a question or expects a response. Without this, two agents acknowledging each other never terminate: every ACK is itself a directed message demanding an ACK."
36411
+ )
36374
36412
  },
36375
36413
  annotations: {
36376
36414
  readOnlyHint: false,
@@ -36379,7 +36417,7 @@ function registerSendMessageTool(server) {
36379
36417
  openWorldHint: true
36380
36418
  }
36381
36419
  },
36382
- async ({ fromPeerId, toPeerId, message }) => {
36420
+ async ({ fromPeerId, toPeerId, message, replyExpected }) => {
36383
36421
  try {
36384
36422
  if (isCloudDeferred(getConfig().COGENT_ENDPOINT)) {
36385
36423
  return successResult({
@@ -36421,7 +36459,8 @@ function registerSendMessageTool(server) {
36421
36459
  response: null,
36422
36460
  durationMs: Date.now() - startMs2,
36423
36461
  success: true,
36424
- error: null
36462
+ error: null,
36463
+ ...replyExpected === false ? { replyExpected: false } : {}
36425
36464
  });
36426
36465
  return successResult({
36427
36466
  success: true,
@@ -36484,7 +36523,8 @@ function registerSendMessageTool(server) {
36484
36523
  response: null,
36485
36524
  durationMs,
36486
36525
  success: true,
36487
- error: null
36526
+ error: null,
36527
+ ...replyExpected === false ? { replyExpected: false } : {}
36488
36528
  });
36489
36529
  } catch (recordErr) {
36490
36530
  autoRelay.clearExpectation(toPeerId);
@@ -36579,7 +36619,8 @@ function registerSendMessageTool(server) {
36579
36619
  response: success2 ? result.stdout : null,
36580
36620
  durationMs,
36581
36621
  success: success2,
36582
- error: success2 ? null : result.stderr
36622
+ error: success2 ? null : result.stderr,
36623
+ ...replyExpected === false ? { replyExpected: false } : {}
36583
36624
  });
36584
36625
  return successResult({
36585
36626
  success: success2,
@@ -36676,6 +36717,7 @@ var init_message = __esm({
36676
36717
  durationMs: import_zod6.z.number().nullable().describe("Round-trip duration in ms"),
36677
36718
  success: import_zod6.z.boolean().describe("Whether delivery succeeded"),
36678
36719
  pending: import_zod6.z.boolean().optional().describe("Delivered+acked; the reply is still expected"),
36720
+ replyExpected: import_zod6.z.boolean().optional().describe("Sender declares the message terminal \u2014 no reply expected. Absent/true = a reply is expected."),
36679
36721
  error: import_zod6.z.string().nullable().describe("Error message if delivery failed"),
36680
36722
  originPlatform: import_zod6.z.enum(["cc", "codex", "slack", "gchat", "web", "gemini", "whatsapp", "telegram", "discord"]).optional().describe("Platform that originated this message"),
36681
36723
  attachments: import_zod6.z.array(AttachmentSchema).optional().describe("Cogent Mail M2.5 \u2014 file references (byte transport = email)")
@@ -37285,7 +37327,12 @@ function registerDeregisterPeerTool(server) {
37285
37327
  });
37286
37328
  }
37287
37329
  const backend = getBackend();
37288
- const { removed, mailboxDeprovisioned } = await backend.deregisterPeer(peerId);
37330
+ let ownershipProof;
37331
+ try {
37332
+ ownershipProof = (await loadCredentials())?.peerSecret;
37333
+ } catch {
37334
+ }
37335
+ const { removed, mailboxDeprovisioned } = await backend.deregisterPeer(peerId, ownershipProof);
37289
37336
  if (removed) heartbeat.stop();
37290
37337
  if (mailboxDeprovisioned) {
37291
37338
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@essentialai/cogent-bridge-bundled",
3
- "version": "3.24.2",
3
+ "version": "3.25.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": {