@essentialai/cogent-bridge-bundled 3.21.9 → 3.22.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.
- package/cogent-bridge.mjs +190 -58
- 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.
|
|
26393
|
-
return "3.
|
|
26392
|
+
if ("3.22.0") {
|
|
26393
|
+
return "3.22.0";
|
|
26394
26394
|
}
|
|
26395
26395
|
try {
|
|
26396
26396
|
const require2 = createRequire(import.meta.url);
|
|
@@ -27747,8 +27747,13 @@ async function getRelayVersion(http, nowFn = Date.now) {
|
|
|
27747
27747
|
if (cached2 !== null && now - cached2.fetchedAt < TTL_MS) {
|
|
27748
27748
|
return cached2.version;
|
|
27749
27749
|
}
|
|
27750
|
+
return (await _refresh(http, now))?.version ?? null;
|
|
27751
|
+
}
|
|
27752
|
+
async function _refresh(http, now) {
|
|
27750
27753
|
try {
|
|
27751
|
-
const resp = await http.get(
|
|
27754
|
+
const resp = await http.get(
|
|
27755
|
+
"/api/health"
|
|
27756
|
+
);
|
|
27752
27757
|
const version2 = resp?.version;
|
|
27753
27758
|
if (typeof version2 !== "string" || version2.length === 0) {
|
|
27754
27759
|
logger.debug(
|
|
@@ -27756,14 +27761,26 @@ async function getRelayVersion(http, nowFn = Date.now) {
|
|
|
27756
27761
|
);
|
|
27757
27762
|
return null;
|
|
27758
27763
|
}
|
|
27759
|
-
|
|
27760
|
-
|
|
27764
|
+
const raw = resp?.capabilities;
|
|
27765
|
+
const capabilities = Array.isArray(raw) ? raw.filter((c2) => typeof c2 === "string") : [];
|
|
27766
|
+
cached2 = { version: version2, capabilities, fetchedAt: now };
|
|
27767
|
+
return cached2;
|
|
27761
27768
|
} catch (err) {
|
|
27762
27769
|
const msg = err instanceof Error ? err.message : String(err);
|
|
27763
27770
|
logger.debug(`relay-version-cache: /api/health fetch failed: ${msg}`);
|
|
27764
27771
|
return null;
|
|
27765
27772
|
}
|
|
27766
27773
|
}
|
|
27774
|
+
async function getRelayCapabilities(http, nowFn = Date.now) {
|
|
27775
|
+
const now = nowFn();
|
|
27776
|
+
if (cached2 !== null && now - cached2.fetchedAt < TTL_MS) {
|
|
27777
|
+
return cached2.capabilities;
|
|
27778
|
+
}
|
|
27779
|
+
return (await _refresh(http, now))?.capabilities ?? null;
|
|
27780
|
+
}
|
|
27781
|
+
async function relaySupports(http, capability, nowFn = Date.now) {
|
|
27782
|
+
return (await getRelayCapabilities(http, nowFn))?.includes(capability) ?? false;
|
|
27783
|
+
}
|
|
27767
27784
|
var TTL_MS, cached2;
|
|
27768
27785
|
var init_relay_version_cache = __esm({
|
|
27769
27786
|
"src/backend/relay-version-cache.ts"() {
|
|
@@ -27779,6 +27796,8 @@ var MAILBOX_DEPROVISIONED_HEADER, PATHS, HttpBackend;
|
|
|
27779
27796
|
var init_http_backend = __esm({
|
|
27780
27797
|
"src/backend/http-backend.ts"() {
|
|
27781
27798
|
"use strict";
|
|
27799
|
+
init_relay_version_cache();
|
|
27800
|
+
init_errors4();
|
|
27782
27801
|
init_health_check();
|
|
27783
27802
|
init_constants();
|
|
27784
27803
|
init_config();
|
|
@@ -27806,7 +27825,7 @@ var init_http_backend = __esm({
|
|
|
27806
27825
|
* The sessionId parameter from StorageBackend is the local CC sessionId;
|
|
27807
27826
|
* in cloud mode we ignore it and use this.sessionId (the cloud session).
|
|
27808
27827
|
*/
|
|
27809
|
-
async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId) {
|
|
27828
|
+
async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId, peerSecret) {
|
|
27810
27829
|
const path20 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27811
27830
|
const body = {
|
|
27812
27831
|
peerId,
|
|
@@ -27835,6 +27854,9 @@ var init_http_backend = __esm({
|
|
|
27835
27854
|
body.role = roleCap.slice("role:".length);
|
|
27836
27855
|
}
|
|
27837
27856
|
}
|
|
27857
|
+
if (peerSecret !== void 0 && await relaySupports(this.http, "peer-ownership")) {
|
|
27858
|
+
body.peerSecret = peerSecret;
|
|
27859
|
+
}
|
|
27838
27860
|
return this.http.post(path20, body);
|
|
27839
27861
|
}
|
|
27840
27862
|
/**
|
|
@@ -27852,8 +27874,11 @@ var init_http_backend = __esm({
|
|
|
27852
27874
|
const headers = await this.http.delete(path20, {});
|
|
27853
27875
|
const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
|
|
27854
27876
|
return { removed: true, mailboxDeprovisioned };
|
|
27855
|
-
} catch {
|
|
27856
|
-
|
|
27877
|
+
} catch (err) {
|
|
27878
|
+
if (err instanceof BridgeError && err.code === "PEER_NOT_FOUND" /* PEER_NOT_FOUND */) {
|
|
27879
|
+
return { removed: false, mailboxDeprovisioned: false };
|
|
27880
|
+
}
|
|
27881
|
+
throw err;
|
|
27857
27882
|
}
|
|
27858
27883
|
}
|
|
27859
27884
|
/**
|
|
@@ -27900,6 +27925,17 @@ var init_http_backend = __esm({
|
|
|
27900
27925
|
if (record2.isRelayEcho === true) {
|
|
27901
27926
|
body.isRelayEcho = true;
|
|
27902
27927
|
}
|
|
27928
|
+
if (await relaySupports(this.http, "message-delivery-fields")) {
|
|
27929
|
+
if (record2.success === false) {
|
|
27930
|
+
body.success = false;
|
|
27931
|
+
}
|
|
27932
|
+
if (record2.error != null) {
|
|
27933
|
+
body.error = record2.error;
|
|
27934
|
+
}
|
|
27935
|
+
if (record2.durationMs != null) {
|
|
27936
|
+
body.durationMs = record2.durationMs;
|
|
27937
|
+
}
|
|
27938
|
+
}
|
|
27903
27939
|
if (record2.attachments && record2.attachments.length > 0) {
|
|
27904
27940
|
body.attachments = record2.attachments;
|
|
27905
27941
|
}
|
|
@@ -33350,7 +33386,7 @@ function truncate(s) {
|
|
|
33350
33386
|
const flat = s.replace(/\s+/g, " ").trim();
|
|
33351
33387
|
return flat.length > DIAGNOSTIC_MAX ? `${flat.slice(0, DIAGNOSTIC_MAX - 1)}\u2026` : flat;
|
|
33352
33388
|
}
|
|
33353
|
-
var RELAY_STATUS, STATUS_MARKER_RE, DIAGNOSTIC_MAX, AutoRelayService, autoRelay;
|
|
33389
|
+
var RELAY_STATUS, STATUS_MARKER_RE, DIAGNOSTIC_MAX, EARLY_ACK_TTL_MS, EARLY_ACK_MAX, AutoRelayService, autoRelay;
|
|
33354
33390
|
var init_auto_relay = __esm({
|
|
33355
33391
|
"src/services/auto-relay.ts"() {
|
|
33356
33392
|
"use strict";
|
|
@@ -33371,6 +33407,8 @@ var init_auto_relay = __esm({
|
|
|
33371
33407
|
};
|
|
33372
33408
|
STATUS_MARKER_RE = /^\[cogent:(queued|processing|delivered|needs-manual|failed)\]/;
|
|
33373
33409
|
DIAGNOSTIC_MAX = 220;
|
|
33410
|
+
EARLY_ACK_TTL_MS = 12e4;
|
|
33411
|
+
EARLY_ACK_MAX = 256;
|
|
33374
33412
|
AutoRelayService = class {
|
|
33375
33413
|
localPeerId = null;
|
|
33376
33414
|
localSessionId = null;
|
|
@@ -33417,7 +33455,24 @@ var init_auto_relay = __esm({
|
|
|
33417
33455
|
// so the first send-message tool call returned literal "Superseded by
|
|
33418
33456
|
// newer send_message call" instead of the actual peer response.
|
|
33419
33457
|
responseWaiters = /* @__PURE__ */ new Map();
|
|
33458
|
+
/**
|
|
33459
|
+
* Pending delivery-ack waiters, keyed by MESSAGE ID.
|
|
33460
|
+
*
|
|
33461
|
+
* 🔴 AUD-002. This used to be keyed by PEER ID, so a peer could have only one outstanding
|
|
33462
|
+
* waiter and a second concurrent send displaced the first — resolving it, so the first send
|
|
33463
|
+
* reported "delivered" with no acknowledgment from anyone. Delivery acknowledgment is the one
|
|
33464
|
+
* claim this system must never fabricate.
|
|
33465
|
+
*/
|
|
33420
33466
|
deliveryAckWaiters = /* @__PURE__ */ new Map();
|
|
33467
|
+
/**
|
|
33468
|
+
* Acks that arrived before their waiter existed, keyed by message id.
|
|
33469
|
+
*
|
|
33470
|
+
* The recipient acknowledges over WS as soon as it receives the message, which can beat our own
|
|
33471
|
+
* POST response. Waiters used to be registered BEFORE the send to dodge that race, which is what
|
|
33472
|
+
* forced peer-keying. Buffering the early ack instead lets registration happen after the message
|
|
33473
|
+
* id is known, so correlation stays exact. Entries are consumed once and expire.
|
|
33474
|
+
*/
|
|
33475
|
+
recentAcks = /* @__PURE__ */ new Map();
|
|
33421
33476
|
sendDeliveryAckFn = null;
|
|
33422
33477
|
/**
|
|
33423
33478
|
* Set the local peer info. Called from register-peer tool after
|
|
@@ -33586,12 +33641,6 @@ var init_auto_relay = __esm({
|
|
|
33586
33641
|
cancelResponseWaiter(fromPeerId) {
|
|
33587
33642
|
this._cancelWaiter(fromPeerId);
|
|
33588
33643
|
}
|
|
33589
|
-
/**
|
|
33590
|
-
* Cancel only the active delivery ack waiter for a peer.
|
|
33591
|
-
*/
|
|
33592
|
-
cancelDeliveryAckWaiter(fromPeerId) {
|
|
33593
|
-
this._cancelDeliveryAckWaiter(fromPeerId);
|
|
33594
|
-
}
|
|
33595
33644
|
/**
|
|
33596
33645
|
* Cancel ALL pending response waiters for a peer by rejecting them with
|
|
33597
33646
|
* a clear error. Used by clearExpectation()/cancelResponseWaiter() to
|
|
@@ -33614,39 +33663,73 @@ var init_auto_relay = __esm({
|
|
|
33614
33663
|
* resolves when the target peer's MCP sends a delivery_ack frame, or
|
|
33615
33664
|
* rejects on timeout (recipient likely offline).
|
|
33616
33665
|
*/
|
|
33617
|
-
waitForDeliveryAck(fromPeerId, timeoutMs) {
|
|
33666
|
+
waitForDeliveryAck(fromPeerId, messageId, timeoutMs) {
|
|
33667
|
+
if (this.recentAcks.delete(messageId)) {
|
|
33668
|
+
logger.debug(`Auto-relay: delivery ack for ${messageId} was already buffered`);
|
|
33669
|
+
return Promise.resolve();
|
|
33670
|
+
}
|
|
33618
33671
|
return new Promise((resolve, reject) => {
|
|
33619
|
-
this._cancelDeliveryAckWaiter(fromPeerId);
|
|
33620
33672
|
const timer = setTimeout(() => {
|
|
33621
|
-
this.deliveryAckWaiters.delete(
|
|
33622
|
-
reject(
|
|
33673
|
+
this.deliveryAckWaiters.delete(messageId);
|
|
33674
|
+
reject(
|
|
33675
|
+
new Error(
|
|
33676
|
+
`Delivery ack timeout from ${fromPeerId} for ${messageId} after ${timeoutMs}ms`
|
|
33677
|
+
)
|
|
33678
|
+
);
|
|
33623
33679
|
}, timeoutMs);
|
|
33624
|
-
this.deliveryAckWaiters.set(
|
|
33680
|
+
this.deliveryAckWaiters.set(messageId, { peerId: fromPeerId, resolve, reject, timer });
|
|
33625
33681
|
});
|
|
33626
33682
|
}
|
|
33627
33683
|
/**
|
|
33628
|
-
*
|
|
33629
|
-
*
|
|
33684
|
+
* Settle the waiter for exactly this message.
|
|
33685
|
+
*
|
|
33686
|
+
* 🔴 Correlation is by MESSAGE ID, and the acknowledging peer must match the peer we sent to.
|
|
33687
|
+
* The frame has carried `messageId` all along (src/cloud/ws-client.ts:52); startup.ts used to
|
|
33688
|
+
* drop it and resolve by peer, so any ack settled any outstanding send to that peer — and an ack
|
|
33689
|
+
* naming a peer the sender never messaged could settle a waiter outright (AUD-003).
|
|
33690
|
+
*
|
|
33691
|
+
* An ack with no matching waiter is BUFFERED rather than discarded: the recipient can legitimately
|
|
33692
|
+
* acknowledge before our POST response returns.
|
|
33630
33693
|
*/
|
|
33631
|
-
resolveDeliveryAck(fromPeerId) {
|
|
33632
|
-
const waiter = this.deliveryAckWaiters.get(
|
|
33694
|
+
resolveDeliveryAck(fromPeerId, messageId) {
|
|
33695
|
+
const waiter = this.deliveryAckWaiters.get(messageId);
|
|
33633
33696
|
if (waiter) {
|
|
33697
|
+
if (waiter.peerId !== fromPeerId) {
|
|
33698
|
+
logger.warn(
|
|
33699
|
+
`Auto-relay: IGNORED delivery ack for ${messageId} \u2014 claimed by '${fromPeerId}' but that message was sent to '${waiter.peerId}'`
|
|
33700
|
+
);
|
|
33701
|
+
return;
|
|
33702
|
+
}
|
|
33634
33703
|
clearTimeout(waiter.timer);
|
|
33635
|
-
this.deliveryAckWaiters.delete(
|
|
33704
|
+
this.deliveryAckWaiters.delete(messageId);
|
|
33636
33705
|
waiter.resolve();
|
|
33637
|
-
logger.debug(`Auto-relay: delivery ack received from ${fromPeerId}`);
|
|
33706
|
+
logger.debug(`Auto-relay: delivery ack received from ${fromPeerId} for ${messageId}`);
|
|
33707
|
+
return;
|
|
33638
33708
|
}
|
|
33709
|
+
this._bufferEarlyAck(messageId);
|
|
33710
|
+
}
|
|
33711
|
+
/** Remember an ack whose waiter does not exist yet, with bounded retention. */
|
|
33712
|
+
_bufferEarlyAck(messageId) {
|
|
33713
|
+
const now = Date.now();
|
|
33714
|
+
for (const [id, at] of this.recentAcks) {
|
|
33715
|
+
if (now - at > EARLY_ACK_TTL_MS) this.recentAcks.delete(id);
|
|
33716
|
+
}
|
|
33717
|
+
while (this.recentAcks.size >= EARLY_ACK_MAX) {
|
|
33718
|
+
const oldest = this.recentAcks.keys().next().value;
|
|
33719
|
+
if (oldest === void 0) break;
|
|
33720
|
+
this.recentAcks.delete(oldest);
|
|
33721
|
+
}
|
|
33722
|
+
this.recentAcks.set(messageId, now);
|
|
33723
|
+
logger.debug(`Auto-relay: buffered early delivery ack for ${messageId}`);
|
|
33639
33724
|
}
|
|
33640
|
-
/**
|
|
33641
|
-
* Cancel a pending delivery ack waiter for a peer.
|
|
33642
|
-
* Resolves the old promise so callers awaiting it don't hang forever.
|
|
33643
|
-
*/
|
|
33644
33725
|
_cancelDeliveryAckWaiter(fromPeerId) {
|
|
33645
|
-
const
|
|
33646
|
-
|
|
33647
|
-
clearTimeout(
|
|
33648
|
-
this.deliveryAckWaiters.delete(
|
|
33649
|
-
|
|
33726
|
+
for (const [messageId, waiter] of this.deliveryAckWaiters) {
|
|
33727
|
+
if (waiter.peerId !== fromPeerId) continue;
|
|
33728
|
+
clearTimeout(waiter.timer);
|
|
33729
|
+
this.deliveryAckWaiters.delete(messageId);
|
|
33730
|
+
waiter.reject(
|
|
33731
|
+
new Error(`Delivery ack wait for ${messageId} cancelled (${fromPeerId})`)
|
|
33732
|
+
);
|
|
33650
33733
|
}
|
|
33651
33734
|
}
|
|
33652
33735
|
/**
|
|
@@ -34149,15 +34232,18 @@ var init_auto_relay = __esm({
|
|
|
34149
34232
|
for (const [, queue] of this.responseWaiters) {
|
|
34150
34233
|
for (const waiter of queue) {
|
|
34151
34234
|
clearTimeout(waiter.timer);
|
|
34152
|
-
waiter.
|
|
34235
|
+
waiter.reject(new Error("Auto-relay shut down while waiting for a response"));
|
|
34153
34236
|
}
|
|
34154
34237
|
}
|
|
34155
34238
|
this.responseWaiters.clear();
|
|
34156
|
-
for (const [, waiter] of this.deliveryAckWaiters) {
|
|
34239
|
+
for (const [messageId, waiter] of this.deliveryAckWaiters) {
|
|
34157
34240
|
clearTimeout(waiter.timer);
|
|
34158
|
-
waiter.
|
|
34241
|
+
waiter.reject(
|
|
34242
|
+
new Error(`Auto-relay shut down while waiting for delivery ack (${messageId})`)
|
|
34243
|
+
);
|
|
34159
34244
|
}
|
|
34160
34245
|
this.deliveryAckWaiters.clear();
|
|
34246
|
+
this.recentAcks.clear();
|
|
34161
34247
|
this.queue = [];
|
|
34162
34248
|
this.awarenessOnly.clear();
|
|
34163
34249
|
this.localPeerId = null;
|
|
@@ -34580,7 +34666,7 @@ function createCloudWsClient(endpoint, sessionId, token, http, inbox, pollInterv
|
|
|
34580
34666
|
logger.warn(`WebSocket error frame: ${err.code}: ${err.message}`);
|
|
34581
34667
|
},
|
|
34582
34668
|
onDeliveryAck: (payload) => {
|
|
34583
|
-
autoRelay.resolveDeliveryAck(payload.peerId);
|
|
34669
|
+
autoRelay.resolveDeliveryAck(payload.peerId, payload.messageId);
|
|
34584
34670
|
},
|
|
34585
34671
|
onPeerEvicted: () => {
|
|
34586
34672
|
triggerReRegistration().catch((err) => {
|
|
@@ -34872,6 +34958,10 @@ var init_mail_credential_store = __esm({
|
|
|
34872
34958
|
|
|
34873
34959
|
// src/tools/register-peer.ts
|
|
34874
34960
|
import crypto6 from "node:crypto";
|
|
34961
|
+
function unresolvedSessionReason(r) {
|
|
34962
|
+
if (r.sessionId) return null;
|
|
34963
|
+
return r.candidateCount === 0 ? "no-candidates" : "ambiguous";
|
|
34964
|
+
}
|
|
34875
34965
|
function registerRegisterPeerTool(server) {
|
|
34876
34966
|
server.registerTool(
|
|
34877
34967
|
"cogent_register_peer",
|
|
@@ -34883,6 +34973,9 @@ function registerRegisterPeerTool(server) {
|
|
|
34883
34973
|
sessionId: import_zod3.z.string().describe("Claude Code session ID (used with --resume)"),
|
|
34884
34974
|
cwd: import_zod3.z.string().describe("Absolute path to the project working directory"),
|
|
34885
34975
|
label: import_zod3.z.string().describe("Human-readable label, e.g. 'Cogent_Backend' or 'Cogent_Frontend'"),
|
|
34976
|
+
peerSecret: import_zod3.z.string().optional().describe(
|
|
34977
|
+
"AUD-003 ownership proof. Only needed to RECLAIM a peerId whose registration was made from a different connection \u2014 e.g. this agent re-joined the channel and was issued a new token. Normally omitted: the stored credential is replayed automatically."
|
|
34978
|
+
),
|
|
34886
34979
|
mode: import_zod3.z.enum(["observer", "agent"]).optional().default("agent").describe(
|
|
34887
34980
|
'Peer participation mode. "agent" (default) auto-responds via execClaude on inbound directed messages. "observer" registers a passive watcher that receives WS frames and remains targetable but never spawns a subprocess. Useful for operators using their MCP client to monitor a channel without polluting transcript with phantom replies.'
|
|
34888
34981
|
),
|
|
@@ -34897,7 +34990,7 @@ function registerRegisterPeerTool(server) {
|
|
|
34897
34990
|
openWorldHint: false
|
|
34898
34991
|
}
|
|
34899
34992
|
},
|
|
34900
|
-
async ({ peerId, sessionId, cwd, label, mode, role }) => {
|
|
34993
|
+
async ({ peerId, sessionId, cwd, label, mode, role, peerSecret: argPeerSecret }) => {
|
|
34901
34994
|
try {
|
|
34902
34995
|
const config2 = getConfig();
|
|
34903
34996
|
const hasExplicitCloudSession = !!config2.COGENT_SESSION_ID || process.env.COGENT_TRUST_PERSISTED_CREDENTIALS === "1";
|
|
@@ -34990,6 +35083,14 @@ function registerRegisterPeerTool(server) {
|
|
|
34990
35083
|
}
|
|
34991
35084
|
const workspaceId = deriveWorkspaceId(cwd);
|
|
34992
35085
|
const threadId = sessionId;
|
|
35086
|
+
let storedPeerSecret = argPeerSecret;
|
|
35087
|
+
if (storedPeerSecret === void 0 && isCloudMode()) {
|
|
35088
|
+
try {
|
|
35089
|
+
storedPeerSecret = (await loadCredentials())?.peerSecret;
|
|
35090
|
+
} catch {
|
|
35091
|
+
storedPeerSecret = void 0;
|
|
35092
|
+
}
|
|
35093
|
+
}
|
|
34993
35094
|
const peer = await backend.registerPeer(
|
|
34994
35095
|
peerId,
|
|
34995
35096
|
sessionId,
|
|
@@ -35000,15 +35101,18 @@ function registerRegisterPeerTool(server) {
|
|
|
35000
35101
|
channelSessionId,
|
|
35001
35102
|
capabilities,
|
|
35002
35103
|
workspaceId,
|
|
35003
|
-
threadId
|
|
35104
|
+
threadId,
|
|
35105
|
+
storedPeerSecret
|
|
35004
35106
|
);
|
|
35005
35107
|
if (isCloudMode()) {
|
|
35006
35108
|
try {
|
|
35007
35109
|
const creds = await loadCredentials();
|
|
35008
|
-
|
|
35110
|
+
const issuedSecret = peer?.peerSecret;
|
|
35111
|
+
if (creds && (creds.peerId !== peerId || issuedSecret && creds.peerSecret !== issuedSecret)) {
|
|
35009
35112
|
await saveCredentials({
|
|
35010
35113
|
...creds,
|
|
35011
35114
|
peerId,
|
|
35115
|
+
...issuedSecret ? { peerSecret: issuedSecret } : {},
|
|
35012
35116
|
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
35013
35117
|
});
|
|
35014
35118
|
}
|
|
@@ -35036,16 +35140,17 @@ function registerRegisterPeerTool(server) {
|
|
|
35036
35140
|
logger.info(
|
|
35037
35141
|
`Register: session resolved ${resolution.decision}/${resolution.confidence} (${resolution.candidateCount} candidate[s]) -> ${localSessionId}`
|
|
35038
35142
|
);
|
|
35039
|
-
const
|
|
35040
|
-
if (
|
|
35143
|
+
const unresolved = unresolvedSessionReason(resolution);
|
|
35144
|
+
if (unresolved) {
|
|
35041
35145
|
try {
|
|
35042
35146
|
const base = getConfig().COGENT_PLATFORM === "cc" ? await transcriptBaseSummary() : "(codex: scans CODEX_HOME/sessions)";
|
|
35147
|
+
const cause = unresolved === "ambiguous" ? `${resolution.candidateCount} candidate sessions matched and NONE could be chosen, so the id you supplied was pinned UNCHECKED \u2014 if that is a channel UUID rather than a local session id, every wake will fail in ~2s` : `NO local ${getConfig().COGENT_PLATFORM} session was found for this cwd`;
|
|
35043
35148
|
logger.warn(
|
|
35044
|
-
`Register:
|
|
35149
|
+
`Register: ${cause} \u2014 auto-wake WILL be refused. cwd=${cwd}; scanned ${(resolution.probedPaths ?? []).join(", ") || "(unknown)"}; base ${base}. If the base is missing or empty, this agent's config dir is elsewhere \u2014 set CLAUDE_CONFIG_DIR / CODEX_HOME so the BRIDGE process sees it too. If the base has project dirs but none match, the registered cwd is not where this agent runs.`
|
|
35045
35150
|
);
|
|
35046
35151
|
} catch (err) {
|
|
35047
35152
|
logger.warn(
|
|
35048
|
-
`Register:
|
|
35153
|
+
`Register: unresolved session (${unresolved}) for cwd=${cwd} (auto-wake WILL be refused); could not describe the transcript base: ${err.message}`
|
|
35049
35154
|
);
|
|
35050
35155
|
}
|
|
35051
35156
|
}
|
|
@@ -35059,8 +35164,8 @@ function registerRegisterPeerTool(server) {
|
|
|
35059
35164
|
confidence: resolution.confidence,
|
|
35060
35165
|
candidateCount: resolution.candidateCount,
|
|
35061
35166
|
// Only on the broken path — keeps the happy-path result terse.
|
|
35062
|
-
...
|
|
35063
|
-
warning: "No local session transcript found for this cwd \u2014 auto-wake will be REFUSED. Verify the cwd is where this agent actually runs and that CLAUDE_CONFIG_DIR / CODEX_HOME are visible to the bridge process.",
|
|
35167
|
+
...unresolved ? {
|
|
35168
|
+
warning: (unresolved === "ambiguous" ? `${resolution.candidateCount} local session transcripts matched this cwd and none could be chosen, so the sessionId you supplied was pinned UNCHECKED \u2014 if it is a channel UUID rather than a local session id, auto-wake will be REFUSED. ` : "No local session transcript found for this cwd \u2014 auto-wake will be REFUSED. ") + "Verify the cwd is where this agent actually runs and that CLAUDE_CONFIG_DIR / CODEX_HOME are visible to the bridge process.",
|
|
35064
35169
|
scannedPaths: resolution.probedPaths ?? []
|
|
35065
35170
|
} : {}
|
|
35066
35171
|
}
|
|
@@ -35276,8 +35381,9 @@ function registerSendMessageTool(server) {
|
|
|
35276
35381
|
if (isCloud && success2) {
|
|
35277
35382
|
const effectiveAckTimeout = Math.min(ACK_TIMEOUT_MS, config2.COGENT_TIMEOUT_MS);
|
|
35278
35383
|
const fastPathMs = Math.min(config2.COGENT_FASTPATH_MS, config2.COGENT_TIMEOUT_MS);
|
|
35279
|
-
const ackPromise = autoRelay.waitForDeliveryAck(toPeerId, effectiveAckTimeout);
|
|
35280
35384
|
const responsePromise = autoRelay.waitForResponse(toPeerId, fastPathMs);
|
|
35385
|
+
responsePromise.catch(() => {
|
|
35386
|
+
});
|
|
35281
35387
|
let outboundRecord;
|
|
35282
35388
|
try {
|
|
35283
35389
|
outboundRecord = await backend.recordMessage({
|
|
@@ -35293,6 +35399,11 @@ function registerSendMessageTool(server) {
|
|
|
35293
35399
|
autoRelay.clearExpectation(toPeerId);
|
|
35294
35400
|
throw recordErr;
|
|
35295
35401
|
}
|
|
35402
|
+
const ackPromise = autoRelay.waitForDeliveryAck(
|
|
35403
|
+
toPeerId,
|
|
35404
|
+
outboundRecord.id,
|
|
35405
|
+
effectiveAckTimeout
|
|
35406
|
+
);
|
|
35296
35407
|
let ackReceived = false;
|
|
35297
35408
|
try {
|
|
35298
35409
|
await ackPromise;
|
|
@@ -35473,6 +35584,7 @@ var init_message = __esm({
|
|
|
35473
35584
|
timestamp: import_zod6.z.string().datetime().describe("ISO 8601 message timestamp"),
|
|
35474
35585
|
durationMs: import_zod6.z.number().nullable().describe("Round-trip duration in ms"),
|
|
35475
35586
|
success: import_zod6.z.boolean().describe("Whether delivery succeeded"),
|
|
35587
|
+
pending: import_zod6.z.boolean().optional().describe("Delivered+acked; the reply is still expected"),
|
|
35476
35588
|
error: import_zod6.z.string().nullable().describe("Error message if delivery failed"),
|
|
35477
35589
|
originPlatform: import_zod6.z.enum(["cc", "codex", "slack", "gchat", "web", "gemini", "whatsapp", "telegram", "discord"]).optional().describe("Platform that originated this message"),
|
|
35478
35590
|
attachments: import_zod6.z.array(AttachmentSchema).optional().describe("Cogent Mail M2.5 \u2014 file references (byte transport = email)")
|
|
@@ -35562,15 +35674,31 @@ var init_errors5 = __esm({
|
|
|
35562
35674
|
});
|
|
35563
35675
|
|
|
35564
35676
|
// cogent/dist/schemas/api-requests.js
|
|
35565
|
-
var import_zod10, CreateSessionRequestSchema, JoinSessionRequestSchema, ResolveSessionRequestSchema, RegisterPeerRequestSchema, DeregisterPeerRequestSchema, SendMessageRequestSchema, GetHistoryQuerySchema, PollQuerySchema;
|
|
35677
|
+
var import_zod10, FIELD_LIMITS, CreateSessionRequestSchema, JoinSessionRequestSchema, ResolveSessionRequestSchema, RegisterPeerRequestSchema, DeregisterPeerRequestSchema, SendMessageRequestSchema, GetHistoryQuerySchema, PollQuerySchema;
|
|
35566
35678
|
var init_api_requests = __esm({
|
|
35567
35679
|
"cogent/dist/schemas/api-requests.js"() {
|
|
35568
35680
|
"use strict";
|
|
35569
35681
|
import_zod10 = __toESM(require_zod(), 1);
|
|
35682
|
+
FIELD_LIMITS = {
|
|
35683
|
+
/** A shared channel secret. Long passphrases are fine; novels are not. */
|
|
35684
|
+
SECRET_MAX: 1024,
|
|
35685
|
+
/** Org_ID. */
|
|
35686
|
+
ORG_ID_MAX: 256,
|
|
35687
|
+
/** Peer identifier. */
|
|
35688
|
+
PEER_ID_MAX: 128,
|
|
35689
|
+
/** Human-readable peer label. */
|
|
35690
|
+
PEER_LABEL_MAX: 256,
|
|
35691
|
+
/** Working directory — comfortably above PATH_MAX (4096) on every platform we support. */
|
|
35692
|
+
CWD_MAX: 8192,
|
|
35693
|
+
/** A single message body. */
|
|
35694
|
+
MESSAGE_MAX: 1048576,
|
|
35695
|
+
/** One platform-identity value (e.g. a Slack user id). */
|
|
35696
|
+
PLATFORM_IDENTITY_VALUE_MAX: 512
|
|
35697
|
+
};
|
|
35570
35698
|
CreateSessionRequestSchema = import_zod10.z.object({
|
|
35571
35699
|
label: import_zod10.z.string().regex(/^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$/).optional().describe("Optional human-readable session label (3-32 lowercase alphanumeric + hyphens)"),
|
|
35572
|
-
secret: import_zod10.z.string().min(8).describe("Shared secret for joining the session (min 8 chars)"),
|
|
35573
|
-
orgId: import_zod10.z.string().min(1).optional().describe("Optional Org_ID -- gates the channel to Business Edition orgs (multi-tenant relay only)")
|
|
35700
|
+
secret: import_zod10.z.string().min(8).max(FIELD_LIMITS.SECRET_MAX).describe("Shared secret for joining the session (min 8 chars)"),
|
|
35701
|
+
orgId: import_zod10.z.string().min(1).max(FIELD_LIMITS.ORG_ID_MAX).optional().describe("Optional Org_ID -- gates the channel to Business Edition orgs (multi-tenant relay only)")
|
|
35574
35702
|
}).strict();
|
|
35575
35703
|
JoinSessionRequestSchema = import_zod10.z.object({
|
|
35576
35704
|
secret: import_zod10.z.string().min(1).describe("Shared secret for the session"),
|
|
@@ -35581,13 +35709,14 @@ var init_api_requests = __esm({
|
|
|
35581
35709
|
orgId: import_zod10.z.string().min(1).optional().describe("Optional Org_ID -- required to resolve an Org_ID-gated business channel")
|
|
35582
35710
|
}).strict();
|
|
35583
35711
|
RegisterPeerRequestSchema = import_zod10.z.object({
|
|
35584
|
-
peerId: import_zod10.z.string().min(1).describe("Unique peer identifier"),
|
|
35585
|
-
|
|
35586
|
-
|
|
35712
|
+
peerId: import_zod10.z.string().min(1).max(FIELD_LIMITS.PEER_ID_MAX).describe("Unique peer identifier"),
|
|
35713
|
+
peerSecret: import_zod10.z.string().min(1).max(256).optional().describe("AUD-003: proof of ownership when reclaiming a peer from a different token"),
|
|
35714
|
+
cwd: import_zod10.z.string().max(FIELD_LIMITS.CWD_MAX).describe("Peer working directory path"),
|
|
35715
|
+
label: import_zod10.z.string().max(FIELD_LIMITS.PEER_LABEL_MAX).describe("Human-readable peer label"),
|
|
35587
35716
|
platform: import_zod10.z.enum(["cc", "codex", "slack", "gchat", "web", "gemini"]).optional().describe("Platform this peer belongs to"),
|
|
35588
35717
|
type: import_zod10.z.enum(["agent", "human"]).optional().describe("Peer type"),
|
|
35589
35718
|
transport: import_zod10.z.enum(["ws", "slack-bot", "gchat-bot", "websocket"]).optional().describe("Transport mechanism"),
|
|
35590
|
-
platformIdentity: import_zod10.z.record(import_zod10.z.string(), import_zod10.z.string()).optional().describe("Platform-specific identity fields"),
|
|
35719
|
+
platformIdentity: import_zod10.z.record(import_zod10.z.string().max(64), import_zod10.z.string().max(FIELD_LIMITS.PLATFORM_IDENTITY_VALUE_MAX)).optional().describe("Platform-specific identity fields"),
|
|
35591
35720
|
role: import_zod10.z.string().max(64).optional().describe("A2A role advertised by this peer (Agent Card)"),
|
|
35592
35721
|
capabilities: import_zod10.z.array(import_zod10.z.string().max(64)).max(16).optional().describe("Capability strings \u2192 A2A Agent Card skills[]")
|
|
35593
35722
|
}).strict();
|
|
@@ -35595,8 +35724,11 @@ var init_api_requests = __esm({
|
|
|
35595
35724
|
SendMessageRequestSchema = import_zod10.z.object({
|
|
35596
35725
|
fromPeerId: import_zod10.z.string().min(1).describe("Sender peer ID"),
|
|
35597
35726
|
toPeerId: import_zod10.z.string().min(1).describe("Recipient peer ID (use '*' for broadcast)"),
|
|
35598
|
-
message: import_zod10.z.string().min(1).describe("Message content"),
|
|
35599
|
-
originPlatform: import_zod10.z.enum(["cc", "codex", "slack", "gchat", "web", "gemini"]).optional().describe("Platform originating this message")
|
|
35727
|
+
message: import_zod10.z.string().min(1).max(FIELD_LIMITS.MESSAGE_MAX).describe("Message content"),
|
|
35728
|
+
originPlatform: import_zod10.z.enum(["cc", "codex", "slack", "gchat", "web", "gemini"]).optional().describe("Platform originating this message"),
|
|
35729
|
+
success: import_zod10.z.boolean().optional().describe("Delivery outcome as reported by the sender"),
|
|
35730
|
+
error: import_zod10.z.string().nullable().optional().describe("Failure code as reported by the sender"),
|
|
35731
|
+
durationMs: import_zod10.z.number().int().nonnegative().nullable().optional().describe("Sender-measured duration")
|
|
35600
35732
|
}).strict();
|
|
35601
35733
|
GetHistoryQuerySchema = import_zod10.z.object({
|
|
35602
35734
|
peerId: import_zod10.z.string().optional().describe("Filter messages by peer ID"),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essentialai/cogent-bridge-bundled",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.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": {
|