@essentialai/cogent-plugin 3.25.6 → 3.25.8
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/.claude-plugin/plugin.json +1 -1
- package/bridge/cogent-bridge.mjs +894 -379
- package/commands/register.md +43 -33
- package/package.json +1 -1
- package/skills/bridge-setup/SKILL.md +16 -7
package/bridge/cogent-bridge.mjs
CHANGED
|
@@ -1282,8 +1282,8 @@ var init_parseUtil = __esm({
|
|
|
1282
1282
|
init_errors();
|
|
1283
1283
|
init_en();
|
|
1284
1284
|
makeIssue = (params) => {
|
|
1285
|
-
const { data, path:
|
|
1286
|
-
const fullPath = [...
|
|
1285
|
+
const { data, path: path27, errorMaps, issueData } = params;
|
|
1286
|
+
const fullPath = [...path27, ...issueData.path || []];
|
|
1287
1287
|
const fullIssue = {
|
|
1288
1288
|
...issueData,
|
|
1289
1289
|
path: fullPath
|
|
@@ -1563,11 +1563,11 @@ var init_types = __esm({
|
|
|
1563
1563
|
init_parseUtil();
|
|
1564
1564
|
init_util();
|
|
1565
1565
|
ParseInputLazyPath = class {
|
|
1566
|
-
constructor(parent, value,
|
|
1566
|
+
constructor(parent, value, path27, key) {
|
|
1567
1567
|
this._cachedPath = [];
|
|
1568
1568
|
this.parent = parent;
|
|
1569
1569
|
this.data = value;
|
|
1570
|
-
this._path =
|
|
1570
|
+
this._path = path27;
|
|
1571
1571
|
this._key = key;
|
|
1572
1572
|
}
|
|
1573
1573
|
get path() {
|
|
@@ -5019,10 +5019,10 @@ function assignProp(target, prop, value) {
|
|
|
5019
5019
|
configurable: true
|
|
5020
5020
|
});
|
|
5021
5021
|
}
|
|
5022
|
-
function getElementAtPath(obj,
|
|
5023
|
-
if (!
|
|
5022
|
+
function getElementAtPath(obj, path27) {
|
|
5023
|
+
if (!path27)
|
|
5024
5024
|
return obj;
|
|
5025
|
-
return
|
|
5025
|
+
return path27.reduce((acc, key) => acc?.[key], obj);
|
|
5026
5026
|
}
|
|
5027
5027
|
function promiseAllObject(promisesObj) {
|
|
5028
5028
|
const keys = Object.keys(promisesObj);
|
|
@@ -5271,11 +5271,11 @@ function aborted(x, startIndex = 0) {
|
|
|
5271
5271
|
}
|
|
5272
5272
|
return false;
|
|
5273
5273
|
}
|
|
5274
|
-
function prefixIssues(
|
|
5274
|
+
function prefixIssues(path27, issues) {
|
|
5275
5275
|
return issues.map((iss) => {
|
|
5276
5276
|
var _a;
|
|
5277
5277
|
(_a = iss).path ?? (_a.path = []);
|
|
5278
|
-
iss.path.unshift(
|
|
5278
|
+
iss.path.unshift(path27);
|
|
5279
5279
|
return iss;
|
|
5280
5280
|
});
|
|
5281
5281
|
}
|
|
@@ -17081,8 +17081,8 @@ var require_utils = __commonJS({
|
|
|
17081
17081
|
}
|
|
17082
17082
|
return ind;
|
|
17083
17083
|
}
|
|
17084
|
-
function removeDotSegments(
|
|
17085
|
-
let input =
|
|
17084
|
+
function removeDotSegments(path27) {
|
|
17085
|
+
let input = path27;
|
|
17086
17086
|
const output = [];
|
|
17087
17087
|
let nextSlash = -1;
|
|
17088
17088
|
let len = 0;
|
|
@@ -17281,8 +17281,8 @@ var require_schemes = __commonJS({
|
|
|
17281
17281
|
wsComponent.secure = void 0;
|
|
17282
17282
|
}
|
|
17283
17283
|
if (wsComponent.resourceName) {
|
|
17284
|
-
const [
|
|
17285
|
-
wsComponent.path =
|
|
17284
|
+
const [path27, query] = wsComponent.resourceName.split("?");
|
|
17285
|
+
wsComponent.path = path27 && path27 !== "/" ? path27 : void 0;
|
|
17286
17286
|
wsComponent.query = query;
|
|
17287
17287
|
wsComponent.resourceName = void 0;
|
|
17288
17288
|
}
|
|
@@ -20635,12 +20635,12 @@ var require_dist = __commonJS({
|
|
|
20635
20635
|
throw new Error(`Unknown format "${name}"`);
|
|
20636
20636
|
return f;
|
|
20637
20637
|
};
|
|
20638
|
-
function addFormats(ajv, list,
|
|
20638
|
+
function addFormats(ajv, list, fs25, exportName) {
|
|
20639
20639
|
var _a;
|
|
20640
20640
|
var _b;
|
|
20641
20641
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
20642
20642
|
for (const f of list)
|
|
20643
|
-
ajv.addFormat(f,
|
|
20643
|
+
ajv.addFormat(f, fs25[f]);
|
|
20644
20644
|
}
|
|
20645
20645
|
module.exports = exports = formatsPlugin;
|
|
20646
20646
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -21752,8 +21752,8 @@ var require_parseUtil = __commonJS({
|
|
|
21752
21752
|
var errors_js_1 = require_errors2();
|
|
21753
21753
|
var en_js_1 = __importDefault(require_en());
|
|
21754
21754
|
var makeIssue2 = (params) => {
|
|
21755
|
-
const { data, path:
|
|
21756
|
-
const fullPath = [...
|
|
21755
|
+
const { data, path: path27, errorMaps, issueData } = params;
|
|
21756
|
+
const fullPath = [...path27, ...issueData.path || []];
|
|
21757
21757
|
const fullIssue = {
|
|
21758
21758
|
...issueData,
|
|
21759
21759
|
path: fullPath
|
|
@@ -21907,11 +21907,11 @@ var require_types2 = __commonJS({
|
|
|
21907
21907
|
var parseUtil_js_1 = require_parseUtil();
|
|
21908
21908
|
var util_js_1 = require_util2();
|
|
21909
21909
|
var ParseInputLazyPath2 = class {
|
|
21910
|
-
constructor(parent, value,
|
|
21910
|
+
constructor(parent, value, path27, key) {
|
|
21911
21911
|
this._cachedPath = [];
|
|
21912
21912
|
this.parent = parent;
|
|
21913
21913
|
this.data = value;
|
|
21914
|
-
this._path =
|
|
21914
|
+
this._path = path27;
|
|
21915
21915
|
this._key = key;
|
|
21916
21916
|
}
|
|
21917
21917
|
get path() {
|
|
@@ -26412,8 +26412,8 @@ var init_stdio2 = __esm({
|
|
|
26412
26412
|
// src/constants.ts
|
|
26413
26413
|
import { createRequire } from "node:module";
|
|
26414
26414
|
function resolveVersion() {
|
|
26415
|
-
if ("3.25.
|
|
26416
|
-
return "3.25.
|
|
26415
|
+
if ("3.25.8") {
|
|
26416
|
+
return "3.25.8";
|
|
26417
26417
|
}
|
|
26418
26418
|
try {
|
|
26419
26419
|
const require2 = createRequire(import.meta.url);
|
|
@@ -26432,6 +26432,34 @@ var init_constants = __esm({
|
|
|
26432
26432
|
}
|
|
26433
26433
|
});
|
|
26434
26434
|
|
|
26435
|
+
// src/instructions.ts
|
|
26436
|
+
var ENV_KEY_NAMES_COMMAND, SERVER_INSTRUCTIONS;
|
|
26437
|
+
var init_instructions = __esm({
|
|
26438
|
+
"src/instructions.ts"() {
|
|
26439
|
+
"use strict";
|
|
26440
|
+
ENV_KEY_NAMES_COMMAND = "grep -noE '^#COGENT[A-Za-z0-9_ -]*|^(CHANNEL|COG[A-Z]*NT)_(CHANNEL_)?(NAME|PASSWORD|ORG_ID|PEER_NAME|PEER_LABEL)=' .env";
|
|
26441
|
+
SERVER_INSTRUCTIONS = [
|
|
26442
|
+
"Cogent connects this agent to a shared channel with other agents and with people in Slack. Follow the steps below only when the user asks you to register, join or get online on Cogent; never read .env or register unprompted.",
|
|
26443
|
+
"To get online:",
|
|
26444
|
+
"1. cogent_join_session { channel, secret, orgId? }. channel is the channel NAME (3-32 characters: lowercase letters, digits, hyphens), never a UUID. If you were given an Org_ID (Team channel) pass it as orgId on every call and never retry without it.",
|
|
26445
|
+
"2. Only if step 1 answers CHANNEL_NOT_FOUND: cogent_create_session { label, secret, orgId? } with the SAME name, password and Org_ID. It creates the channel and joins you. Never change the name. Do not repeat step 1 first: five failed joins lock the name for 15 minutes.",
|
|
26446
|
+
"3. cogent_register_peer { peerId, sessionId, cwd, label }. peerId is the peer name you were given. sessionId is this agent session's own resumable id, not the channel id. Do not call this first.",
|
|
26447
|
+
"Values come from the user's message, else from the project .env: the keys ending in CHANNEL_NAME, CHANNEL_PASSWORD, ORG_ID, PEER_NAME and PEER_LABEL. To find them, list the key NAMES only:",
|
|
26448
|
+
ENV_KEY_NAMES_COMMAND,
|
|
26449
|
+
"Then pass the values straight into the tool call. Do not print them and do not write a script that prints them. A key with a misspelled prefix is still used: report its KEY NAME. If the channel name or peer name is missing, or appears more than once, ask. Never invent either.",
|
|
26450
|
+
"Errors:",
|
|
26451
|
+
"- CHANNEL_NOT_FOUND: do step 2 once. Exception: if you were given an Org_ID and left it out, do step 1 again WITH orgId and create nothing.",
|
|
26452
|
+
"- 'already in use' from create: the channel exists. Do step 1 again with the same name.",
|
|
26453
|
+
"- Invalid credentials or Invalid session secret (HTTP 401): the password or Org_ID is wrong. Stop and ask.",
|
|
26454
|
+
"- RATE_LIMITED or HTTP 429: wait the seconds it states, then repeat the same call once. Change nothing.",
|
|
26455
|
+
"- JOIN_NOT_CONFIRMED: step 1 or 2 has not succeeded in this session. Do it, then register.",
|
|
26456
|
+
"- PEER_NOT_YOURS: your own earlier session holds the name. Retry the SAME peerId when the error says. Never rename.",
|
|
26457
|
+
"- Anything else: report it and stop.",
|
|
26458
|
+
"Never print the channel password or the Org_ID. When online, report the peer name, the channel name, whether you created or joined it, and the Slack command from the tool result with its placeholders left as they are."
|
|
26459
|
+
].join("\n");
|
|
26460
|
+
}
|
|
26461
|
+
});
|
|
26462
|
+
|
|
26435
26463
|
// src/logger.ts
|
|
26436
26464
|
import fs5 from "node:fs";
|
|
26437
26465
|
import path5 from "node:path";
|
|
@@ -26803,7 +26831,9 @@ var init_errors4 = __esm({
|
|
|
26803
26831
|
BridgeErrorCode2["DIR_NOT_WRITABLE"] = "DIR_NOT_WRITABLE";
|
|
26804
26832
|
BridgeErrorCode2["NETWORK_TIMEOUT"] = "NETWORK_TIMEOUT";
|
|
26805
26833
|
BridgeErrorCode2["JOIN_NOT_CONFIRMED"] = "JOIN_NOT_CONFIRMED";
|
|
26834
|
+
BridgeErrorCode2["CHANNEL_NOT_FOUND"] = "CHANNEL_NOT_FOUND";
|
|
26806
26835
|
BridgeErrorCode2["PEER_NOT_YOURS"] = "PEER_NOT_YOURS";
|
|
26836
|
+
BridgeErrorCode2["PEER_HELD_IN_FOLDER"] = "PEER_HELD_IN_FOLDER";
|
|
26807
26837
|
return BridgeErrorCode2;
|
|
26808
26838
|
})(BridgeErrorCode || {});
|
|
26809
26839
|
BridgeError = class extends Error {
|
|
@@ -27857,7 +27887,7 @@ var init_http_backend = __esm({
|
|
|
27857
27887
|
* in cloud mode we ignore it and use this.sessionId (the cloud session).
|
|
27858
27888
|
*/
|
|
27859
27889
|
async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId, peerSecret) {
|
|
27860
|
-
const
|
|
27890
|
+
const path27 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27861
27891
|
const body = {
|
|
27862
27892
|
peerId,
|
|
27863
27893
|
cwd,
|
|
@@ -27888,7 +27918,7 @@ var init_http_backend = __esm({
|
|
|
27888
27918
|
if (peerSecret !== void 0 && await relaySupports(this.http, "peer-ownership")) {
|
|
27889
27919
|
body.peerSecret = peerSecret;
|
|
27890
27920
|
}
|
|
27891
|
-
const peer = await this.http.post(
|
|
27921
|
+
const peer = await this.http.post(path27, body);
|
|
27892
27922
|
const issued = peer?.peerSecret;
|
|
27893
27923
|
if (issued) {
|
|
27894
27924
|
try {
|
|
@@ -27908,9 +27938,9 @@ var init_http_backend = __esm({
|
|
|
27908
27938
|
* local mail creds. A 404 (peer not found) resolves to `{ removed: false, ... }`, not a throw.
|
|
27909
27939
|
*/
|
|
27910
27940
|
async deregisterPeer(peerId, peerSecret) {
|
|
27911
|
-
const
|
|
27941
|
+
const path27 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
|
|
27912
27942
|
try {
|
|
27913
|
-
const headers = await this.http.delete(
|
|
27943
|
+
const headers = await this.http.delete(path27, peerSecret ? { peerSecret } : {});
|
|
27914
27944
|
const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
|
|
27915
27945
|
return { removed: true, mailboxDeprovisioned };
|
|
27916
27946
|
} catch (err) {
|
|
@@ -27934,8 +27964,8 @@ var init_http_backend = __esm({
|
|
|
27934
27964
|
* GET /api/sessions/:sessionId/peers
|
|
27935
27965
|
*/
|
|
27936
27966
|
async listPeers() {
|
|
27937
|
-
const
|
|
27938
|
-
const result = await this.http.get(
|
|
27967
|
+
const path27 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27968
|
+
const result = await this.http.get(path27);
|
|
27939
27969
|
return result.peers;
|
|
27940
27970
|
}
|
|
27941
27971
|
/**
|
|
@@ -27943,8 +27973,8 @@ var init_http_backend = __esm({
|
|
|
27943
27973
|
* Calls the lightweight heartbeat endpoint on the cloud relay server.
|
|
27944
27974
|
*/
|
|
27945
27975
|
async updateLastSeen(peerId) {
|
|
27946
|
-
const
|
|
27947
|
-
await this.http.post(
|
|
27976
|
+
const path27 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
|
|
27977
|
+
await this.http.post(path27, { peerId });
|
|
27948
27978
|
}
|
|
27949
27979
|
/**
|
|
27950
27980
|
* Record a message in the cloud session.
|
|
@@ -27955,7 +27985,7 @@ var init_http_backend = __esm({
|
|
|
27955
27985
|
* the input record to construct a full MessageRecord.
|
|
27956
27986
|
*/
|
|
27957
27987
|
async recordMessage(record2) {
|
|
27958
|
-
const
|
|
27988
|
+
const path27 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27959
27989
|
const body = {
|
|
27960
27990
|
fromPeerId: record2.fromPeerId,
|
|
27961
27991
|
toPeerId: record2.toPeerId,
|
|
@@ -27981,7 +28011,7 @@ var init_http_backend = __esm({
|
|
|
27981
28011
|
if (record2.replyExpected === false && await relaySupports(this.http, "terminal-messages")) {
|
|
27982
28012
|
body.replyExpected = false;
|
|
27983
28013
|
}
|
|
27984
|
-
const resp = await this.http.post(
|
|
28014
|
+
const resp = await this.http.post(path27, body);
|
|
27985
28015
|
return {
|
|
27986
28016
|
...record2,
|
|
27987
28017
|
id: resp.id,
|
|
@@ -27995,7 +28025,7 @@ var init_http_backend = __esm({
|
|
|
27995
28025
|
* Supports optional peerId filter and limit (default 300).
|
|
27996
28026
|
*/
|
|
27997
28027
|
async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
|
|
27998
|
-
const
|
|
28028
|
+
const path27 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27999
28029
|
const query = {};
|
|
28000
28030
|
if (peerId) {
|
|
28001
28031
|
query.peerId = peerId;
|
|
@@ -28010,7 +28040,7 @@ var init_http_backend = __esm({
|
|
|
28010
28040
|
if (dedupInferredEchoes) {
|
|
28011
28041
|
query.dedupInferredEchoes = "true";
|
|
28012
28042
|
}
|
|
28013
|
-
const result = await this.http.get(
|
|
28043
|
+
const result = await this.http.get(path27, query);
|
|
28014
28044
|
return result.messages;
|
|
28015
28045
|
}
|
|
28016
28046
|
/**
|
|
@@ -28021,12 +28051,12 @@ var init_http_backend = __esm({
|
|
|
28021
28051
|
* so that get-history shows the actual response (not null).
|
|
28022
28052
|
*/
|
|
28023
28053
|
async updateMessageResponse(messageId, response, durationMs, pending) {
|
|
28024
|
-
const
|
|
28054
|
+
const path27 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
|
|
28025
28055
|
const body = { response, durationMs };
|
|
28026
28056
|
if (pending === true) {
|
|
28027
28057
|
body.pending = true;
|
|
28028
28058
|
}
|
|
28029
|
-
await this.http.patch(
|
|
28059
|
+
await this.http.patch(path27, body);
|
|
28030
28060
|
}
|
|
28031
28061
|
/**
|
|
28032
28062
|
* Validate a session.
|
|
@@ -28200,8 +28230,8 @@ var init_http_client = __esm({
|
|
|
28200
28230
|
* Perform an authenticated GET request.
|
|
28201
28231
|
* Appends query parameters to the URL if provided.
|
|
28202
28232
|
*/
|
|
28203
|
-
async get(
|
|
28204
|
-
const url = new URL(
|
|
28233
|
+
async get(path27, query) {
|
|
28234
|
+
const url = new URL(path27, this.baseUrl);
|
|
28205
28235
|
if (query) {
|
|
28206
28236
|
for (const [k, v] of Object.entries(query)) {
|
|
28207
28237
|
url.searchParams.set(k, v);
|
|
@@ -28216,8 +28246,8 @@ var init_http_client = __esm({
|
|
|
28216
28246
|
/**
|
|
28217
28247
|
* Perform an authenticated POST request with a JSON body.
|
|
28218
28248
|
*/
|
|
28219
|
-
async post(
|
|
28220
|
-
const url = new URL(
|
|
28249
|
+
async post(path27, body) {
|
|
28250
|
+
const url = new URL(path27, this.baseUrl);
|
|
28221
28251
|
const resp = await this.fetchWithTimeout(url, {
|
|
28222
28252
|
method: "POST",
|
|
28223
28253
|
headers: this.headers(),
|
|
@@ -28235,8 +28265,8 @@ var init_http_client = __esm({
|
|
|
28235
28265
|
* Perform an authenticated PATCH request with a JSON body.
|
|
28236
28266
|
* Used to update existing resources (e.g., message response fields).
|
|
28237
28267
|
*/
|
|
28238
|
-
async patch(
|
|
28239
|
-
const url = new URL(
|
|
28268
|
+
async patch(path27, body) {
|
|
28269
|
+
const url = new URL(path27, this.baseUrl);
|
|
28240
28270
|
const resp = await this.fetchWithTimeout(url, {
|
|
28241
28271
|
method: "PATCH",
|
|
28242
28272
|
headers: this.headers(),
|
|
@@ -28261,8 +28291,8 @@ var init_http_client = __esm({
|
|
|
28261
28291
|
* "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
|
|
28262
28292
|
* any client (including third-party tools) DELETEd a peer without a body.
|
|
28263
28293
|
*/
|
|
28264
|
-
async delete(
|
|
28265
|
-
const url = new URL(
|
|
28294
|
+
async delete(path27, body) {
|
|
28295
|
+
const url = new URL(path27, this.baseUrl);
|
|
28266
28296
|
const headers = {
|
|
28267
28297
|
"Authorization": `Bearer ${this.token}`
|
|
28268
28298
|
};
|
|
@@ -32563,14 +32593,14 @@ var init_ws_client = __esm({
|
|
|
32563
32593
|
this.restoreCursor();
|
|
32564
32594
|
const poll = async () => {
|
|
32565
32595
|
try {
|
|
32566
|
-
const
|
|
32596
|
+
const path27 = `/api/sessions/${this.opts.sessionId}/poll`;
|
|
32567
32597
|
const query = {
|
|
32568
32598
|
peerId: this.opts.peerId
|
|
32569
32599
|
};
|
|
32570
32600
|
if (this.lastMessageId) {
|
|
32571
32601
|
query.lastMessageId = this.lastMessageId;
|
|
32572
32602
|
}
|
|
32573
|
-
const result = await this.opts.http.get(
|
|
32603
|
+
const result = await this.opts.http.get(path27, query);
|
|
32574
32604
|
if (result.messages && result.messages.length > 0) {
|
|
32575
32605
|
this.opts.onMessages(result.messages);
|
|
32576
32606
|
this.advanceCursor(result.messages[result.messages.length - 1].id);
|
|
@@ -33487,6 +33517,10 @@ import crypto5 from "node:crypto";
|
|
|
33487
33517
|
import fs15 from "node:fs";
|
|
33488
33518
|
import os11 from "node:os";
|
|
33489
33519
|
import path16 from "node:path";
|
|
33520
|
+
function drainCapMs(timeoutMs) {
|
|
33521
|
+
const t = Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 3e5;
|
|
33522
|
+
return Math.min(INFLIGHT_TIMEOUT_FACTOR * t, INFLIGHT_MAX_MS);
|
|
33523
|
+
}
|
|
33490
33524
|
function hashCwd3(cwd) {
|
|
33491
33525
|
return crypto5.createHash("sha256").update(path16.resolve(cwd)).digest("hex").slice(0, 16);
|
|
33492
33526
|
}
|
|
@@ -33813,12 +33847,36 @@ import crypto8 from "node:crypto";
|
|
|
33813
33847
|
import fs18 from "node:fs";
|
|
33814
33848
|
import os14 from "node:os";
|
|
33815
33849
|
import path19 from "node:path";
|
|
33850
|
+
function agentSessionId(env = process.env) {
|
|
33851
|
+
if (env.COGENT_PLATFORM && env.COGENT_PLATFORM !== "cc") return void 0;
|
|
33852
|
+
const id = env.CLAUDE_CODE_SESSION_ID?.trim();
|
|
33853
|
+
return id && id.length <= 128 ? id : void 0;
|
|
33854
|
+
}
|
|
33855
|
+
function startedWithoutClient() {
|
|
33856
|
+
if (withoutClient === void 0) {
|
|
33857
|
+
try {
|
|
33858
|
+
withoutClient = fs18.fstatSync(0).isCharacterDevice();
|
|
33859
|
+
} catch {
|
|
33860
|
+
withoutClient = false;
|
|
33861
|
+
}
|
|
33862
|
+
}
|
|
33863
|
+
return withoutClient;
|
|
33864
|
+
}
|
|
33816
33865
|
function hashCwd6(cwd) {
|
|
33817
33866
|
return crypto8.createHash("sha256").update(path19.resolve(cwd)).digest("hex").slice(0, 16);
|
|
33818
33867
|
}
|
|
33819
33868
|
function bridgeDirFor(cwd, peerId) {
|
|
33820
33869
|
return path19.join(os14.homedir(), ".cogent", "bridges", `${hashCwd6(cwd)}.${safe4(peerId)}`);
|
|
33821
33870
|
}
|
|
33871
|
+
function isReservedPeerName(peerId) {
|
|
33872
|
+
return safe4(peerId).toLowerCase() === safe4(PROCESS_MARK).toLowerCase();
|
|
33873
|
+
}
|
|
33874
|
+
function registryText(value) {
|
|
33875
|
+
return String(value ?? "").replace(/[^A-Za-z0-9._-]/g, "").slice(0, 64) || "unreadable";
|
|
33876
|
+
}
|
|
33877
|
+
function registryOwnerLabel(o) {
|
|
33878
|
+
return `pid ${registryText(o.pid)} (v${registryText(o.version)}, ${JSON.stringify(String(o.endpoint ?? "").slice(0, 200))})`;
|
|
33879
|
+
}
|
|
33822
33880
|
function pidAlive(pid) {
|
|
33823
33881
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) return false;
|
|
33824
33882
|
if (pid === process.pid) return true;
|
|
@@ -33829,7 +33887,7 @@ function pidAlive(pid) {
|
|
|
33829
33887
|
return err?.code === "EPERM";
|
|
33830
33888
|
}
|
|
33831
33889
|
}
|
|
33832
|
-
function announceBridge(cwd, peerId, version2, endpoint) {
|
|
33890
|
+
function announceBridge(cwd, peerId, version2, endpoint, sessionId = agentSessionId()) {
|
|
33833
33891
|
const dir = bridgeDirFor(cwd, peerId);
|
|
33834
33892
|
try {
|
|
33835
33893
|
fs18.mkdirSync(dir, { recursive: true });
|
|
@@ -33839,13 +33897,30 @@ function announceBridge(cwd, peerId, version2, endpoint) {
|
|
|
33839
33897
|
version: version2,
|
|
33840
33898
|
peerId,
|
|
33841
33899
|
endpoint,
|
|
33842
|
-
cwd: path19.resolve(cwd)
|
|
33900
|
+
cwd: path19.resolve(cwd),
|
|
33901
|
+
parentPid: process.ppid,
|
|
33902
|
+
...sessionId ? { sessionId } : {},
|
|
33903
|
+
// 🔴 A headless bridge never had a client to lose (review r7 FIX2-2, SEC2-2): when its launching
|
|
33904
|
+
// shell exited, the changed parent read as "client gone" and any bridge that started took its name.
|
|
33905
|
+
...startedWithoutClient() ? { noClient: true } : {}
|
|
33843
33906
|
};
|
|
33844
33907
|
fs18.writeFileSync(path19.join(dir, `${process.pid}.json`), JSON.stringify(entry));
|
|
33845
33908
|
} catch (err) {
|
|
33846
33909
|
logger.debug(`wake-ownership: could not announce this bridge (${err.message})`);
|
|
33847
33910
|
}
|
|
33848
33911
|
}
|
|
33912
|
+
function markBridgeDraining(cwd, peerId) {
|
|
33913
|
+
const file = path19.join(bridgeDirFor(cwd, peerId), `${process.pid}.json`);
|
|
33914
|
+
try {
|
|
33915
|
+
const entry = JSON.parse(fs18.readFileSync(file, "utf-8"));
|
|
33916
|
+
fs18.writeFileSync(file, JSON.stringify({ ...entry, draining: true }));
|
|
33917
|
+
} catch {
|
|
33918
|
+
}
|
|
33919
|
+
}
|
|
33920
|
+
function markBridgeProcess(cwd, version2) {
|
|
33921
|
+
listLiveBridges(cwd, PROCESS_MARK);
|
|
33922
|
+
announceBridge(cwd, PROCESS_MARK, version2, "");
|
|
33923
|
+
}
|
|
33849
33924
|
function withdrawBridge(cwd, peerId) {
|
|
33850
33925
|
try {
|
|
33851
33926
|
fs18.unlinkSync(path19.join(bridgeDirFor(cwd, peerId), `${process.pid}.json`));
|
|
@@ -33882,6 +33957,16 @@ function listLiveBridges(cwd, peerId) {
|
|
|
33882
33957
|
live.sort((a, b) => b.startedAt - a.startedAt || b.pid - a.pid);
|
|
33883
33958
|
return live;
|
|
33884
33959
|
}
|
|
33960
|
+
function listLiveBridgesInFolder(cwd) {
|
|
33961
|
+
const prefix = `${hashCwd6(cwd)}.`;
|
|
33962
|
+
let dirs;
|
|
33963
|
+
try {
|
|
33964
|
+
dirs = fs18.readdirSync(path19.join(os14.homedir(), ".cogent", "bridges"));
|
|
33965
|
+
} catch {
|
|
33966
|
+
return [];
|
|
33967
|
+
}
|
|
33968
|
+
return dirs.filter((d) => d.startsWith(prefix)).flatMap((d) => listLiveBridges(cwd, d.slice(prefix.length)));
|
|
33969
|
+
}
|
|
33885
33970
|
function checkWakeOwnership(cwd, peerId) {
|
|
33886
33971
|
let live;
|
|
33887
33972
|
try {
|
|
@@ -33902,13 +33987,14 @@ function checkWakeOwnership(cwd, peerId) {
|
|
|
33902
33987
|
}
|
|
33903
33988
|
return { isOwner: true, liveCount: live.length + 1 };
|
|
33904
33989
|
}
|
|
33905
|
-
var PROCESS_STARTED_AT, safe4;
|
|
33990
|
+
var PROCESS_STARTED_AT, withoutClient, safe4, PROCESS_MARK;
|
|
33906
33991
|
var init_wake_ownership = __esm({
|
|
33907
33992
|
"src/services/wake-ownership.ts"() {
|
|
33908
33993
|
"use strict";
|
|
33909
33994
|
init_logger();
|
|
33910
33995
|
PROCESS_STARTED_AT = Date.now() - Math.floor(process.uptime() * 1e3);
|
|
33911
33996
|
safe4 = (s) => String(s).replace(/[^A-Za-z0-9._-]/g, "_");
|
|
33997
|
+
PROCESS_MARK = ".process";
|
|
33912
33998
|
}
|
|
33913
33999
|
});
|
|
33914
34000
|
|
|
@@ -33927,6 +34013,39 @@ function versionFromArgv(argv) {
|
|
|
33927
34013
|
const m = argv.match(/\/cogent\/(\d+\.\d+\.\d+)\//);
|
|
33928
34014
|
return m ? m[1] : null;
|
|
33929
34015
|
}
|
|
34016
|
+
function versionAtLeast(a, b) {
|
|
34017
|
+
const pa = a.split(/[-+]/)[0].split(".").map(Number);
|
|
34018
|
+
const pb = b.split(/[-+]/)[0].split(".").map(Number);
|
|
34019
|
+
for (let i = 0; i < 3; i++) {
|
|
34020
|
+
const x = pa[i] ?? 0;
|
|
34021
|
+
const y = pb[i] ?? 0;
|
|
34022
|
+
if (x !== y) return x > y;
|
|
34023
|
+
}
|
|
34024
|
+
return true;
|
|
34025
|
+
}
|
|
34026
|
+
function bridgeVersion(argv, readFile = (p) => fs19.readFileSync(p, "utf-8")) {
|
|
34027
|
+
const fromPath = versionFromArgv(argv);
|
|
34028
|
+
if (fromPath) return fromPath;
|
|
34029
|
+
const candidates = [];
|
|
34030
|
+
const pkg = argv.match(/(\S*\/@essentialai\/cogent-bridge(?:-bundled)?)\/dist\/(?:cli|index)\.js(?:\s|$)/);
|
|
34031
|
+
if (pkg) candidates.push(path20.join(pkg[1], "package.json"));
|
|
34032
|
+
const bin = argv.match(/(\S*\/node_modules)\/\.bin\/cogent-bridge(?:\s|$)/);
|
|
34033
|
+
if (bin) {
|
|
34034
|
+
for (const name of ["cogent-bridge", "cogent-bridge-bundled"]) {
|
|
34035
|
+
candidates.push(path20.join(bin[1], "@essentialai", name, "package.json"));
|
|
34036
|
+
}
|
|
34037
|
+
}
|
|
34038
|
+
for (const file of candidates) {
|
|
34039
|
+
try {
|
|
34040
|
+
const pj = JSON.parse(readFile(file));
|
|
34041
|
+
if (typeof pj.name === "string" && pj.name.startsWith("@essentialai/cogent-bridge") && typeof pj.version === "string" && /^\d+\.\d+\.\d+/.test(pj.version)) {
|
|
34042
|
+
return pj.version;
|
|
34043
|
+
}
|
|
34044
|
+
} catch {
|
|
34045
|
+
}
|
|
34046
|
+
}
|
|
34047
|
+
return null;
|
|
34048
|
+
}
|
|
33930
34049
|
function listProcesses() {
|
|
33931
34050
|
let out;
|
|
33932
34051
|
try {
|
|
@@ -33988,25 +34107,13 @@ function ancestorsOf(pid, procs) {
|
|
|
33988
34107
|
}
|
|
33989
34108
|
return seen;
|
|
33990
34109
|
}
|
|
33991
|
-
function announcedPidsFor(cwd) {
|
|
33992
|
-
const pids = /* @__PURE__ */ new Set();
|
|
33993
|
-
try {
|
|
33994
|
-
const base = path20.dirname(bridgeDirFor(cwd, "x"));
|
|
33995
|
-
const prefix = path20.basename(bridgeDirFor(cwd, "x")).split(".")[0];
|
|
33996
|
-
for (const dir of fs19.readdirSync(base)) {
|
|
33997
|
-
if (!dir.startsWith(`${prefix}.`)) continue;
|
|
33998
|
-
const peerId = dir.slice(prefix.length + 1);
|
|
33999
|
-
for (const e of listLiveBridges(cwd, peerId)) pids.add(e.pid);
|
|
34000
|
-
}
|
|
34001
|
-
} catch {
|
|
34002
|
-
}
|
|
34003
|
-
return pids;
|
|
34004
|
-
}
|
|
34005
34110
|
function findStaleBridges(cwd, procs = listProcesses(), opts = {}) {
|
|
34111
|
+
const versionOf = opts.versionOf ?? ((argv) => bridgeVersion(argv));
|
|
34006
34112
|
const selfPid = opts.selfPid ?? process.pid;
|
|
34007
|
-
const selfStartedAt = opts.selfStartedAt ??
|
|
34113
|
+
const selfStartedAt = opts.selfStartedAt ?? procs.find((p) => p.pid === selfPid)?.startedAt ?? NaN;
|
|
34114
|
+
if (!Number.isFinite(selfStartedAt)) return [];
|
|
34008
34115
|
const cwdOf = opts.cwdOf ?? processCwd;
|
|
34009
|
-
const announced = opts.announced ??
|
|
34116
|
+
const announced = opts.announced ?? new Set(listLiveBridgesInFolder(cwd).map((e) => e.pid));
|
|
34010
34117
|
const target = canonicalPath(cwd);
|
|
34011
34118
|
const ancestors = ancestorsOf(selfPid, procs);
|
|
34012
34119
|
const out = [];
|
|
@@ -34018,10 +34125,11 @@ function findStaleBridges(cwd, procs = listProcesses(), opts = {}) {
|
|
|
34018
34125
|
if (!Number.isFinite(p.startedAt) || p.startedAt >= selfStartedAt) continue;
|
|
34019
34126
|
const theirCwd = cwdOf(p.pid);
|
|
34020
34127
|
if (!theirCwd || canonicalPath(theirCwd) !== target) continue;
|
|
34021
|
-
const ver =
|
|
34128
|
+
const ver = versionOf(p.argv);
|
|
34129
|
+
if (!ver || versionAtLeast(ver, SELF_SUPERSESSION_VERSION)) continue;
|
|
34022
34130
|
out.push({
|
|
34023
34131
|
proc: p,
|
|
34024
|
-
reason: `pid ${p.pid}
|
|
34132
|
+
reason: `pid ${p.pid} (version ${ver}) is a cogent bridge in this exact checkout, started ${new Date(p.startedAt).toISOString()} \u2014 before this process \u2014 and is not in the bridge registry; version ${ver} predates ${SELF_SUPERSESSION_VERSION} self-supersession and would keep waking this session forever`
|
|
34025
34133
|
});
|
|
34026
34134
|
}
|
|
34027
34135
|
return out;
|
|
@@ -34055,21 +34163,25 @@ function reapStaleBridges(cwd, opts = {}) {
|
|
|
34055
34163
|
}
|
|
34056
34164
|
if (reaped.length) {
|
|
34057
34165
|
logger.warn(
|
|
34058
|
-
`Cogent: reaped ${reaped.length} stale bridge process(es)
|
|
34166
|
+
`Cogent: reaped ${reaped.length} stale bridge process(es) for this checkout, each at a version before ${SELF_SUPERSESSION_VERSION}: they could not stand down on their own.`
|
|
34059
34167
|
);
|
|
34060
34168
|
}
|
|
34061
34169
|
return reaped;
|
|
34062
34170
|
}
|
|
34171
|
+
var SELF_SUPERSESSION_VERSION;
|
|
34063
34172
|
var init_stale_bridge_reaper = __esm({
|
|
34064
34173
|
"src/services/stale-bridge-reaper.ts"() {
|
|
34065
34174
|
"use strict";
|
|
34066
34175
|
init_logger();
|
|
34067
34176
|
init_wake_ownership();
|
|
34177
|
+
SELF_SUPERSESSION_VERSION = "3.23.4";
|
|
34068
34178
|
}
|
|
34069
34179
|
});
|
|
34070
34180
|
|
|
34071
34181
|
// src/services/auto-relay.ts
|
|
34072
34182
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
34183
|
+
import fs20 from "node:fs";
|
|
34184
|
+
import path21 from "node:path";
|
|
34073
34185
|
function buildStatusNotice(status, peerId, traceId) {
|
|
34074
34186
|
const tail = traceId ? ` (trace ${traceId})` : "";
|
|
34075
34187
|
if (status === RELAY_STATUS.QUEUED) {
|
|
@@ -34196,6 +34308,21 @@ function truncate(s) {
|
|
|
34196
34308
|
const flat = s.replace(/\s+/g, " ").trim();
|
|
34197
34309
|
return flat.length > DIAGNOSTIC_MAX ? `${flat.slice(0, DIAGNOSTIC_MAX - 1)}\u2026` : flat;
|
|
34198
34310
|
}
|
|
34311
|
+
function isInsideOwnFolder(dir) {
|
|
34312
|
+
try {
|
|
34313
|
+
const real = fs20.realpathSync.native(dir);
|
|
34314
|
+
return real === process.cwd() || real.startsWith(process.cwd() + path21.sep);
|
|
34315
|
+
} catch {
|
|
34316
|
+
return false;
|
|
34317
|
+
}
|
|
34318
|
+
}
|
|
34319
|
+
function isOwnFolder(dir) {
|
|
34320
|
+
try {
|
|
34321
|
+
return fs20.realpathSync.native(dir) === fs20.realpathSync.native(process.cwd());
|
|
34322
|
+
} catch {
|
|
34323
|
+
return false;
|
|
34324
|
+
}
|
|
34325
|
+
}
|
|
34199
34326
|
var RELAY_STATUS, STATUS_MARKER_RE, DIAGNOSTIC_MAX, EARLY_ACK_TTL_MS, EARLY_ACK_MAX, AutoRelayService, autoRelay;
|
|
34200
34327
|
var init_auto_relay = __esm({
|
|
34201
34328
|
"src/services/auto-relay.ts"() {
|
|
@@ -34236,6 +34363,8 @@ var init_auto_relay = __esm({
|
|
|
34236
34363
|
*/
|
|
34237
34364
|
pinnedSessionId = null;
|
|
34238
34365
|
localCwd = null;
|
|
34366
|
+
/** Every folder this process announced the current peer name under — what a drain or a stop must cover. */
|
|
34367
|
+
announcedCwds = /* @__PURE__ */ new Set();
|
|
34239
34368
|
/**
|
|
34240
34369
|
* Peer participation mode (3.2.0, Phase 17 OBS-03).
|
|
34241
34370
|
* - "agent" (default): full auto-relay — inbound directed messages run
|
|
@@ -34299,6 +34428,7 @@ var init_auto_relay = __esm({
|
|
|
34299
34428
|
* successful registration so we know which session to inject into.
|
|
34300
34429
|
*/
|
|
34301
34430
|
setLocalPeer(peerId, sessionId, cwd, mode, label, pinnedSessionId) {
|
|
34431
|
+
if (this.localPeerId && this.localPeerId !== peerId) this.withdrawAnnouncement();
|
|
34302
34432
|
this.localPeerId = peerId;
|
|
34303
34433
|
this.localSessionId = sessionId;
|
|
34304
34434
|
this.pinnedSessionId = pinnedSessionId ?? sessionId;
|
|
@@ -34308,7 +34438,12 @@ var init_auto_relay = __esm({
|
|
|
34308
34438
|
logger.info(
|
|
34309
34439
|
`Auto-relay configured for peer ${peerId} (session: ${sessionId}, pinned: ${this.pinnedSessionId}, mode: ${this.localMode}, label: ${this.localLabel})`
|
|
34310
34440
|
);
|
|
34311
|
-
|
|
34441
|
+
const dirs = /* @__PURE__ */ new Set([path21.resolve(cwd)]);
|
|
34442
|
+
if (isInsideOwnFolder(path21.resolve(cwd))) dirs.add(process.cwd());
|
|
34443
|
+
for (const dir of dirs) {
|
|
34444
|
+
this.announcedCwds.add(dir);
|
|
34445
|
+
announceBridge(dir, peerId, CLIENT_VERSION, getConfig().COGENT_ENDPOINT ?? "local");
|
|
34446
|
+
}
|
|
34312
34447
|
this.supersededNotified.clear();
|
|
34313
34448
|
if (!this.reapedStaleBridges) {
|
|
34314
34449
|
this.reapedStaleBridges = true;
|
|
@@ -34683,10 +34818,13 @@ var init_auto_relay = __esm({
|
|
|
34683
34818
|
}
|
|
34684
34819
|
}
|
|
34685
34820
|
if (this.localPeerId && this.localCwd) {
|
|
34686
|
-
const
|
|
34687
|
-
|
|
34688
|
-
|
|
34689
|
-
|
|
34821
|
+
const dirs = /* @__PURE__ */ new Set([path21.resolve(this.localCwd), ...isOwnFolder(this.localCwd) ? [process.cwd()] : []]);
|
|
34822
|
+
for (const dir of dirs) {
|
|
34823
|
+
const own = checkWakeOwnership(dir, this.localPeerId);
|
|
34824
|
+
if (!own.isOwner) {
|
|
34825
|
+
await this._reportSuperseded(msg, own.owner);
|
|
34826
|
+
return;
|
|
34827
|
+
}
|
|
34690
34828
|
}
|
|
34691
34829
|
}
|
|
34692
34830
|
if (this.localPeerId && !this.awarenessOnly.has(msg.id)) {
|
|
@@ -34731,7 +34869,7 @@ var init_auto_relay = __esm({
|
|
|
34731
34869
|
* notice generator.
|
|
34732
34870
|
*/
|
|
34733
34871
|
async _reportSuperseded(msg, owner) {
|
|
34734
|
-
const who = owner ?
|
|
34872
|
+
const who = owner ? registryOwnerLabel(owner) : "a newer bridge";
|
|
34735
34873
|
logger.warn(
|
|
34736
34874
|
`Auto-relay: NOT waking for ${msg.fromPeerId} \u2014 this bridge (pid ${process.pid}, v${CLIENT_VERSION}) has been superseded for peer "${this.localPeerId}" in this checkout by ${who}. It is a leftover process; the newer bridge is answering. Standing down.`
|
|
34737
34875
|
);
|
|
@@ -35162,6 +35300,24 @@ var init_auto_relay = __esm({
|
|
|
35162
35300
|
activeDeliveryAckWaiters: Array.from(this.deliveryAckWaiters.keys())
|
|
35163
35301
|
};
|
|
35164
35302
|
}
|
|
35303
|
+
/**
|
|
35304
|
+
* Stop claiming this peer's name for this checkout, WITHOUT stopping work already in flight.
|
|
35305
|
+
* Called the moment the MCP client is gone: a draining bridge serves no agent, and while it
|
|
35306
|
+
* counted as the peer's holder, the restarted agent's new bridge stood by behind it (review r2
|
|
35307
|
+
* NEW-1). The announcement is MARKED, not removed — see markBridgeDraining (R3-2). Idempotent.
|
|
35308
|
+
* 🔴 EVERY announcement, not only the last registered cwd's (review r7 SEC2-1, ABC2-2, FIX2-5):
|
|
35309
|
+
* after a register with another spelling of the folder, the one for the bridge's own folder stayed
|
|
35310
|
+
* unmarked, and the restarted agent waited out the drain or stood by for good.
|
|
35311
|
+
*/
|
|
35312
|
+
announceDraining() {
|
|
35313
|
+
if (!this.localPeerId) return;
|
|
35314
|
+
for (const dir of this.announcedCwds) markBridgeDraining(dir, this.localPeerId);
|
|
35315
|
+
}
|
|
35316
|
+
/** Remove this bridge's ownership announcements (graceful shutdown, a rename). Idempotent. */
|
|
35317
|
+
withdrawAnnouncement() {
|
|
35318
|
+
if (this.localPeerId) for (const dir of this.announcedCwds) withdrawBridge(dir, this.localPeerId);
|
|
35319
|
+
this.announcedCwds.clear();
|
|
35320
|
+
}
|
|
35165
35321
|
/**
|
|
35166
35322
|
* Stop the auto-relay service: clear queue and reset state.
|
|
35167
35323
|
*/
|
|
@@ -35181,7 +35337,7 @@ var init_auto_relay = __esm({
|
|
|
35181
35337
|
}
|
|
35182
35338
|
this.deliveryAckWaiters.clear();
|
|
35183
35339
|
this.recentAcks.clear();
|
|
35184
|
-
|
|
35340
|
+
this.withdrawAnnouncement();
|
|
35185
35341
|
this.queue = [];
|
|
35186
35342
|
this.awarenessOnly.clear();
|
|
35187
35343
|
this.supersededNotified.clear();
|
|
@@ -35201,6 +35357,76 @@ var init_auto_relay = __esm({
|
|
|
35201
35357
|
});
|
|
35202
35358
|
|
|
35203
35359
|
// src/services/peer-presence.ts
|
|
35360
|
+
function holderRelation(holderSession, ownSession) {
|
|
35361
|
+
if (holderSession && ownSession) return holderSession === ownSession ? "same-session" : "other-session";
|
|
35362
|
+
return holderSession || ownSession ? "unknown" : "no-session";
|
|
35363
|
+
}
|
|
35364
|
+
function holderClientGone(holder, procs) {
|
|
35365
|
+
if (holder.noClient === true) return false;
|
|
35366
|
+
const byPid = new Map(procs.map((p) => [p.pid, p]));
|
|
35367
|
+
let cur = byPid.get(holder.pid);
|
|
35368
|
+
if (!cur) return false;
|
|
35369
|
+
if (typeof holder.parentPid === "number") return cur.ppid !== holder.parentPid;
|
|
35370
|
+
for (let hops = 0; hops < 3; hops++) {
|
|
35371
|
+
if (cur.ppid === 1) return true;
|
|
35372
|
+
const parent = byPid.get(cur.ppid);
|
|
35373
|
+
if (!parent) return false;
|
|
35374
|
+
const exe = parent.argv.trim().split(/\s+/)[0] ?? "";
|
|
35375
|
+
if (ORPHAN_PARENT_RE.test(exe.split("/").pop() ?? "")) return true;
|
|
35376
|
+
if (!NPX_WRAPPER_RE.test(parent.argv.trim())) return false;
|
|
35377
|
+
cur = parent;
|
|
35378
|
+
}
|
|
35379
|
+
return false;
|
|
35380
|
+
}
|
|
35381
|
+
function insideCodexWakeTurn(selfPid, procs) {
|
|
35382
|
+
const byPid = new Map(procs.map((p) => [p.pid, p]));
|
|
35383
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35384
|
+
let cur = byPid.get(selfPid)?.ppid;
|
|
35385
|
+
while (cur && cur > 1 && !seen.has(cur)) {
|
|
35386
|
+
seen.add(cur);
|
|
35387
|
+
const p = byPid.get(cur);
|
|
35388
|
+
if (!p) break;
|
|
35389
|
+
if (/(^|[\s/])codex(\.js)?\s+exec\s+resume(\s|$)/.test(p.argv)) return true;
|
|
35390
|
+
cur = p.ppid;
|
|
35391
|
+
}
|
|
35392
|
+
return false;
|
|
35393
|
+
}
|
|
35394
|
+
function otherBridgesInFolder(entries, self, listProcs) {
|
|
35395
|
+
let procs = null;
|
|
35396
|
+
return entries.filter(
|
|
35397
|
+
(e) => e.peerId !== PROCESS_MARK && e.pid !== self.pid && !e.draining && holderRelation(e.sessionId, self.sessionId) !== "same-session" && !holderClientGone(e, procs ??= listProcs())
|
|
35398
|
+
);
|
|
35399
|
+
}
|
|
35400
|
+
function heldInFolder(others, peerId, ownSession) {
|
|
35401
|
+
return others.find((o) => o.peerId === peerId && !mayBeOwnPreSessionBridge(o, ownSession));
|
|
35402
|
+
}
|
|
35403
|
+
function mayBeOwnPreSessionBridge(holder, ownSession) {
|
|
35404
|
+
if (holder.sessionId || !ownSession) return false;
|
|
35405
|
+
const v = /^(\d+)\.(\d+)\.(\d+)$/.exec(String(holder.version ?? ""));
|
|
35406
|
+
if (!v) return false;
|
|
35407
|
+
const [maj, min, pat] = [Number(v[1]), Number(v[2]), Number(v[3])];
|
|
35408
|
+
return maj < 3 || maj === 3 && (min < 25 || min === 25 && pat < 7);
|
|
35409
|
+
}
|
|
35410
|
+
function heldNameAdvice(peerId) {
|
|
35411
|
+
return `If this agent was just restarted, its previous connection closes within ${HOLDER_LINGER_SECONDS} seconds: wait ${HOLDER_LINGER_SECONDS}+ seconds, then run /cogent:register again with the SAME peer name '${peerId}'. If '${peerId}' is still held after that, another live connection is using it \u2014 another agent, or an old window of this one still open. Do not take the name and do not rename: ask the user`;
|
|
35412
|
+
}
|
|
35413
|
+
function anotherAgentSessionAmong(others, ownSession) {
|
|
35414
|
+
return others.some((o) => holderRelation(o.sessionId, ownSession) === "other-session");
|
|
35415
|
+
}
|
|
35416
|
+
function otherBridgeNotice(others, peerId, verdict, ownSession) {
|
|
35417
|
+
const lines = others.map((o) => {
|
|
35418
|
+
const version2 = registryText(o.version);
|
|
35419
|
+
const who = holderRelation(o.sessionId, ownSession) === "other-session" ? `Another live agent session in this folder (bridge pid ${o.pid}, version ${version2}, agent session ${registryText(o.sessionId)})` : `Another live bridge in this folder (pid ${o.pid}, version ${version2}; its agent session cannot be compared with this one, so it may be this agent's own previous or second bridge)`;
|
|
35420
|
+
if (o.peerId !== peerId) {
|
|
35421
|
+
return `${who} is still registered as '${registryText(o.peerId)}'. It keeps that name while it runs, but the folder's saved identity now points at this bridge ('${peerId}'): after a restart that bridge's agent comes back as '${peerId}' only if this bridge is no longer running then; otherwise it stays out of the channel until it registers again.`;
|
|
35422
|
+
}
|
|
35423
|
+
if (verdict.isOwner) {
|
|
35424
|
+
return `${who} was registered as '${peerId}'. It is now superseded: this bridge holds '${peerId}' and that bridge has stopped answering for it.`;
|
|
35425
|
+
}
|
|
35426
|
+
return `${who} is registered as '${peerId}' too. NOBODY answers for '${peerId}' in this channel now: the bridge that started last (pid ${verdict.owner?.pid ?? "unknown"}) is the one that wakes its agent, but in this channel the relay registration now belongs to this bridge, so the relay refuses that bridge's replies here and this bridge does not wake. It stays that way until that bridge is closed or its agent registers again. If that bridge is registered in another channel, it still answers there.`;
|
|
35427
|
+
});
|
|
35428
|
+
return lines.join(" ") + (anotherAgentSessionAmong(others, ownSession) ? ` Two agents in one folder are not supported yet: each agent needs its own peer name and, for now, its own folder.` : "");
|
|
35429
|
+
}
|
|
35204
35430
|
function autoPresenceEnabled(env = process.env) {
|
|
35205
35431
|
const v = env.COGENT_AUTO_PRESENCE;
|
|
35206
35432
|
if (v === void 0 || v === "") return true;
|
|
@@ -35230,11 +35456,42 @@ async function restorePresence(deps) {
|
|
|
35230
35456
|
};
|
|
35231
35457
|
}
|
|
35232
35458
|
const peerId = creds.peerId;
|
|
35233
|
-
if (deps.
|
|
35459
|
+
if (deps.startedByWakeTurn?.()) {
|
|
35460
|
+
return {
|
|
35461
|
+
state: "deferred",
|
|
35462
|
+
restored: false,
|
|
35463
|
+
detail: `this bridge runs inside a codex wake turn ('codex exec resume'); peer '${peerId}' belongs to the agent's own bridge, which started this turn \u2014 nothing to restore here`
|
|
35464
|
+
};
|
|
35465
|
+
}
|
|
35466
|
+
const served = deps.peerAlreadyServed(peerId);
|
|
35467
|
+
if (served) {
|
|
35468
|
+
const session = deps.agentSessionId?.();
|
|
35469
|
+
const holder = holderRelation(served.sessionId, session);
|
|
35470
|
+
const servedBy = {
|
|
35471
|
+
...served,
|
|
35472
|
+
...served.version === void 0 ? {} : { version: registryText(served.version) },
|
|
35473
|
+
...served.sessionId === void 0 ? {} : { sessionId: registryText(served.sessionId) }
|
|
35474
|
+
};
|
|
35475
|
+
const started = Number.isFinite(servedBy.startedAt) ? new Date(servedBy.startedAt).toISOString() : "unknown";
|
|
35476
|
+
const recheck = holder === "same-session";
|
|
35477
|
+
const every = deps.recheckSeconds ? ` (re-checked every ${deps.recheckSeconds}s)` : "";
|
|
35478
|
+
const take = heldNameAdvice(peerId);
|
|
35479
|
+
const why = {
|
|
35480
|
+
"same-session": `That bridge serves this same agent session (${session})`,
|
|
35481
|
+
"no-session": `Neither bridge records an agent session (codex, gemini), so it cannot be told whether that bridge is this agent's previous one or another agent's. ${take}`,
|
|
35482
|
+
"other-session": `That bridge serves another agent session (${servedBy.sessionId}; ours: ${session}). Two agents in one folder are not supported yet: a second agent needs its own folder and peer name. ${take}`,
|
|
35483
|
+
unknown: `Its agent session cannot be compared with this one (that bridge: ${servedBy.sessionId ?? "not recorded"}; this bridge: ${session ?? "not known"}): it may be this agent's own other bridge of an older version, or another agent's. ${take}`
|
|
35484
|
+
};
|
|
35234
35485
|
return {
|
|
35235
|
-
state: "
|
|
35486
|
+
state: "standby",
|
|
35236
35487
|
restored: false,
|
|
35237
|
-
|
|
35488
|
+
peerId,
|
|
35489
|
+
servedBy,
|
|
35490
|
+
holder,
|
|
35491
|
+
recheck,
|
|
35492
|
+
// A final standby is evaluated once, so it says "when this bridge started": the health
|
|
35493
|
+
// check keeps showing this text after that bridge is gone.
|
|
35494
|
+
detail: `peer '${peerId}' ${recheck ? "is already served" : "was already served when this bridge started"} by a live bridge for this working directory (pid ${servedBy.pid}, version ${servedBy.version ?? "unknown"}, started ${started}); this bridge has NOT registered and ` + (recheck ? `restores '${peerId}' by itself once that bridge is gone${every}. ` : `does NOT take '${peerId}' by itself, also after that bridge is gone. `) + why[holder]
|
|
35238
35495
|
};
|
|
35239
35496
|
}
|
|
35240
35497
|
if (!autoPresenceEnabled(deps.env ?? process.env)) {
|
|
@@ -35294,15 +35551,23 @@ function logPresence(outcome) {
|
|
|
35294
35551
|
);
|
|
35295
35552
|
} else if (outcome.state === "offline") {
|
|
35296
35553
|
logger.warn(`Presence: OFFLINE \u2014 ${outcome.detail}.`);
|
|
35554
|
+
} else if (outcome.state === "standby" && outcome.holder === "other-session") {
|
|
35555
|
+
logger.warn(`Presence: STANDBY \u2014 ${outcome.detail}.`);
|
|
35556
|
+
} else if (outcome.state === "standby" || outcome.state === "deferred") {
|
|
35557
|
+
logger.info(`Presence: ${outcome.state.toUpperCase()} \u2014 ${outcome.detail}.`);
|
|
35297
35558
|
} else {
|
|
35298
35559
|
logger.debug(`Presence: ${outcome.state} \u2014 ${outcome.detail}.`);
|
|
35299
35560
|
}
|
|
35300
35561
|
}
|
|
35301
|
-
var lastPresence;
|
|
35562
|
+
var ORPHAN_PARENT_RE, NPX_WRAPPER_RE, HOLDER_LINGER_SECONDS, lastPresence;
|
|
35302
35563
|
var init_peer_presence = __esm({
|
|
35303
35564
|
"src/services/peer-presence.ts"() {
|
|
35304
35565
|
"use strict";
|
|
35305
35566
|
init_logger();
|
|
35567
|
+
init_wake_ownership();
|
|
35568
|
+
ORPHAN_PARENT_RE = /^(init|launchd|systemd)$/;
|
|
35569
|
+
NPX_WRAPPER_RE = /^(?:\S*\/)?(?:sh|bash|dash) -c cogent-bridge\b|^npm exec @essentialai\/cogent-bridge/;
|
|
35570
|
+
HOLDER_LINGER_SECONDS = 60;
|
|
35306
35571
|
lastPresence = null;
|
|
35307
35572
|
}
|
|
35308
35573
|
});
|
|
@@ -35550,8 +35815,8 @@ __export(startup_exports, {
|
|
|
35550
35815
|
triggerReRegistration: () => triggerReRegistration
|
|
35551
35816
|
});
|
|
35552
35817
|
import os15 from "node:os";
|
|
35553
|
-
import
|
|
35554
|
-
import
|
|
35818
|
+
import path22 from "node:path";
|
|
35819
|
+
import fs21 from "node:fs/promises";
|
|
35555
35820
|
import readline2 from "node:readline";
|
|
35556
35821
|
import { execFile as execFile5 } from "node:child_process";
|
|
35557
35822
|
import { promisify as promisify4 } from "node:util";
|
|
@@ -35569,7 +35834,7 @@ function bindInboxNotifier() {
|
|
|
35569
35834
|
}
|
|
35570
35835
|
async function loadPersistedConfig() {
|
|
35571
35836
|
try {
|
|
35572
|
-
const raw = await
|
|
35837
|
+
const raw = await fs21.readFile(PERSIST_PATH, "utf-8");
|
|
35573
35838
|
return JSON.parse(raw);
|
|
35574
35839
|
} catch {
|
|
35575
35840
|
return {};
|
|
@@ -35577,7 +35842,7 @@ async function loadPersistedConfig() {
|
|
|
35577
35842
|
}
|
|
35578
35843
|
async function savePersistedConfig(config2) {
|
|
35579
35844
|
try {
|
|
35580
|
-
await
|
|
35845
|
+
await fs21.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
35581
35846
|
} catch (err) {
|
|
35582
35847
|
const msg = err instanceof Error ? err.message : String(err);
|
|
35583
35848
|
logger.warn(`Could not save config to ${PERSIST_PATH}: ${msg}`);
|
|
@@ -35612,11 +35877,11 @@ First run detected. Where should cogent-bridge store its data?
|
|
|
35612
35877
|
});
|
|
35613
35878
|
}
|
|
35614
35879
|
async function validateStateDir(statePath) {
|
|
35615
|
-
await
|
|
35616
|
-
const testFile =
|
|
35880
|
+
await fs21.mkdir(statePath, { recursive: true });
|
|
35881
|
+
const testFile = path22.join(statePath, ".write-test");
|
|
35617
35882
|
try {
|
|
35618
|
-
await
|
|
35619
|
-
await
|
|
35883
|
+
await fs21.writeFile(testFile, "test", "utf-8");
|
|
35884
|
+
await fs21.unlink(testFile);
|
|
35620
35885
|
} catch {
|
|
35621
35886
|
throw new BridgeError(
|
|
35622
35887
|
"STARTUP_FAILED" /* STARTUP_FAILED */,
|
|
@@ -35700,9 +35965,15 @@ function cancelPresenceRetry() {
|
|
|
35700
35965
|
if (presenceRetry) clearTimeout(presenceRetry);
|
|
35701
35966
|
presenceRetry = null;
|
|
35702
35967
|
}
|
|
35703
|
-
function
|
|
35968
|
+
function presenceRetryBaseMs() {
|
|
35704
35969
|
const base = Number(process.env.COGENT_PRESENCE_RETRY_MS);
|
|
35705
|
-
return
|
|
35970
|
+
return Number.isFinite(base) && base > 0 ? base : 3e4;
|
|
35971
|
+
}
|
|
35972
|
+
function presenceRetryDelayMs(attempt) {
|
|
35973
|
+
return Math.min(presenceRetryBaseMs() * 2 ** attempt, 3e5);
|
|
35974
|
+
}
|
|
35975
|
+
function standbyRecheckMs() {
|
|
35976
|
+
return Math.max(250, Math.min(presenceRetryBaseMs(), 15e3));
|
|
35706
35977
|
}
|
|
35707
35978
|
async function restorePeerPresence(attempt = 0) {
|
|
35708
35979
|
if (!presenceSupersedeBound) {
|
|
@@ -35716,6 +35987,8 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35716
35987
|
}
|
|
35717
35988
|
const generation = getCloudAttemptGeneration();
|
|
35718
35989
|
const stillCurrent = () => getCloudAttemptGeneration() === generation;
|
|
35990
|
+
let procs = null;
|
|
35991
|
+
const ps = () => procs ??= listProcesses();
|
|
35719
35992
|
const outcome = await restorePresence({
|
|
35720
35993
|
// The endpoint being a relay URL is what makes presence meaningful. We deliberately do
|
|
35721
35994
|
// NOT gate on the active backend being the cloud one: at startup it is still the
|
|
@@ -35728,13 +36001,27 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35728
36001
|
alreadyRegisteredInProcess: () => autoRelay.getDiagnostics().registered,
|
|
35729
36002
|
peerAlreadyServed: (peerId) => {
|
|
35730
36003
|
try {
|
|
35731
|
-
|
|
36004
|
+
const holders = listLiveBridges(process.cwd(), peerId).filter((b) => b.pid !== process.pid && !b.draining);
|
|
36005
|
+
const other = holders.find((b) => {
|
|
36006
|
+
if (!holderClientGone(b, ps())) return true;
|
|
36007
|
+
if (!ignoredHolders.has(b.pid)) {
|
|
36008
|
+
ignoredHolders.add(b.pid);
|
|
36009
|
+
logger.info(
|
|
36010
|
+
`Presence: ignoring bridge pid ${b.pid} (${registryText(b.version)}) announced for '${peerId}' \u2014 its MCP client is gone (parent then: ${b.parentPid === void 0 ? "not recorded" : registryText(b.parentPid)}), so it serves no agent`
|
|
36011
|
+
);
|
|
36012
|
+
}
|
|
36013
|
+
return false;
|
|
36014
|
+
});
|
|
36015
|
+
return other ? { pid: other.pid, version: other.version, startedAt: other.startedAt, sessionId: other.sessionId } : null;
|
|
35732
36016
|
} catch {
|
|
35733
|
-
return
|
|
36017
|
+
return null;
|
|
35734
36018
|
}
|
|
35735
36019
|
},
|
|
36020
|
+
agentSessionId: () => agentSessionId(),
|
|
36021
|
+
startedByWakeTurn: () => insideCodexWakeTurn(process.pid, ps()),
|
|
35736
36022
|
loadCredentials: () => loadCredentials(),
|
|
35737
36023
|
cwd: () => process.cwd(),
|
|
36024
|
+
recheckSeconds: Math.round(standbyRecheckMs() / 1e3),
|
|
35738
36025
|
goOnline: async ({ peerId, endpoint, sessionId, token, cwd, label, peerSecret }) => {
|
|
35739
36026
|
if (!stillCurrent()) throw new Error(PRESENCE_SUPERSEDED);
|
|
35740
36027
|
await reinitCloudBackend(endpoint, sessionId, token);
|
|
@@ -35754,18 +36041,25 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35754
36041
|
logPresence(superseded);
|
|
35755
36042
|
return superseded;
|
|
35756
36043
|
}
|
|
36044
|
+
const prev = getPresence();
|
|
35757
36045
|
setPresence(outcome);
|
|
35758
|
-
|
|
35759
|
-
|
|
35760
|
-
|
|
36046
|
+
if (outcome.state === "standby" && prev?.state === "standby" && prev.servedBy.pid === outcome.servedBy.pid) {
|
|
36047
|
+
logger.debug(`Presence: STANDBY (unchanged) \u2014 ${outcome.detail}.`);
|
|
36048
|
+
} else {
|
|
36049
|
+
logPresence(outcome);
|
|
36050
|
+
}
|
|
36051
|
+
const failed = outcome.state === "offline" && outcome.detail.startsWith("presence restore failed");
|
|
36052
|
+
const standby = outcome.state === "standby" && outcome.recheck;
|
|
36053
|
+
if (failed || standby) {
|
|
36054
|
+
const delay = standby ? standbyRecheckMs() : presenceRetryDelayMs(attempt);
|
|
35761
36055
|
cancelPresenceRetry();
|
|
35762
36056
|
presenceRetry = setTimeout(() => {
|
|
35763
36057
|
presenceRetry = null;
|
|
35764
|
-
void restorePeerPresence(attempt + 1).catch(() => {
|
|
36058
|
+
void restorePeerPresence(standby ? 0 : attempt + 1).catch(() => {
|
|
35765
36059
|
});
|
|
35766
36060
|
}, delay);
|
|
35767
36061
|
presenceRetry.unref?.();
|
|
35768
|
-
logger.warn(`presence: restore failed \u2014 retrying in ${Math.round(delay / 1e3)}s`);
|
|
36062
|
+
if (failed) logger.warn(`presence: restore failed \u2014 retrying in ${Math.round(delay / 1e3)}s`);
|
|
35769
36063
|
}
|
|
35770
36064
|
return outcome;
|
|
35771
36065
|
}
|
|
@@ -35899,10 +36193,10 @@ async function runStartup() {
|
|
|
35899
36193
|
if (envStatePath) {
|
|
35900
36194
|
statePath = envStatePath;
|
|
35901
36195
|
} else {
|
|
35902
|
-
const defaultPath =
|
|
36196
|
+
const defaultPath = path22.join(os15.homedir(), ".cogent");
|
|
35903
36197
|
statePath = await firstRunPrompt(defaultPath);
|
|
35904
36198
|
}
|
|
35905
|
-
if (!envStatePath && statePath !==
|
|
36199
|
+
if (!envStatePath && statePath !== path22.join(os15.homedir(), ".cogent")) {
|
|
35906
36200
|
process.env.COGENT_STATE_PATH = statePath;
|
|
35907
36201
|
} else if (!envStatePath) {
|
|
35908
36202
|
process.env.COGENT_STATE_PATH = statePath;
|
|
@@ -35966,7 +36260,7 @@ async function runStartup() {
|
|
|
35966
36260
|
}
|
|
35967
36261
|
initLogger(
|
|
35968
36262
|
config2.COGENT_LOG_LEVEL,
|
|
35969
|
-
|
|
36263
|
+
path22.join(config2.COGENT_STATE_PATH, "logs")
|
|
35970
36264
|
);
|
|
35971
36265
|
if (isCloud && effectiveSessionId && effectiveToken) {
|
|
35972
36266
|
cloudInbox = new MessageInbox();
|
|
@@ -36006,7 +36300,7 @@ async function runPreflights() {
|
|
|
36006
36300
|
await preflightClaude(config2.COGENT_CLAUDE_PATH);
|
|
36007
36301
|
}
|
|
36008
36302
|
}
|
|
36009
|
-
var UUID_V4_RE, execFileAsync3, PERSIST_PATH, legacyWarnEmitted, cloudWsClient, cloudInbox, cloudHttpClient, cloudModeActive, inboxNotifier, notifierBoundTo, reRegistrationInProgress, presenceRetry, presenceSupersedeBound, PRESENCE_SUPERSEDED, pendingLabelResolve;
|
|
36303
|
+
var UUID_V4_RE, execFileAsync3, PERSIST_PATH, legacyWarnEmitted, cloudWsClient, cloudInbox, cloudHttpClient, cloudModeActive, inboxNotifier, notifierBoundTo, reRegistrationInProgress, presenceRetry, ignoredHolders, presenceSupersedeBound, PRESENCE_SUPERSEDED, pendingLabelResolve;
|
|
36010
36304
|
var init_startup = __esm({
|
|
36011
36305
|
"src/startup.ts"() {
|
|
36012
36306
|
"use strict";
|
|
@@ -36022,6 +36316,7 @@ var init_startup = __esm({
|
|
|
36022
36316
|
init_auto_relay();
|
|
36023
36317
|
init_peer_presence();
|
|
36024
36318
|
init_wake_ownership();
|
|
36319
|
+
init_stale_bridge_reaper();
|
|
36025
36320
|
init_heartbeat();
|
|
36026
36321
|
init_codex_preflight();
|
|
36027
36322
|
init_codex_cli();
|
|
@@ -36030,7 +36325,7 @@ var init_startup = __esm({
|
|
|
36030
36325
|
init_auto_relay();
|
|
36031
36326
|
UUID_V4_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
36032
36327
|
execFileAsync3 = promisify4(execFile5);
|
|
36033
|
-
PERSIST_PATH =
|
|
36328
|
+
PERSIST_PATH = path22.join(os15.homedir(), ".cogent-config.json");
|
|
36034
36329
|
legacyWarnEmitted = false;
|
|
36035
36330
|
cloudWsClient = null;
|
|
36036
36331
|
cloudInbox = null;
|
|
@@ -36040,6 +36335,7 @@ var init_startup = __esm({
|
|
|
36040
36335
|
notifierBoundTo = null;
|
|
36041
36336
|
reRegistrationInProgress = false;
|
|
36042
36337
|
presenceRetry = null;
|
|
36338
|
+
ignoredHolders = /* @__PURE__ */ new Set();
|
|
36043
36339
|
presenceSupersedeBound = false;
|
|
36044
36340
|
PRESENCE_SUPERSEDED = "presence restore superseded: an explicit cogent_join_session/cogent_create_session ran in this process and owns the channel choice";
|
|
36045
36341
|
pendingLabelResolve = null;
|
|
@@ -36048,12 +36344,12 @@ var init_startup = __esm({
|
|
|
36048
36344
|
|
|
36049
36345
|
// src/cloud/mail-credential-store.ts
|
|
36050
36346
|
import crypto9 from "node:crypto";
|
|
36051
|
-
import
|
|
36052
|
-
import
|
|
36347
|
+
import fs22 from "node:fs/promises";
|
|
36348
|
+
import path23 from "node:path";
|
|
36053
36349
|
import os16 from "node:os";
|
|
36054
36350
|
function defaultMailCredentialPath(cwd = process.cwd()) {
|
|
36055
|
-
const hash = crypto9.createHash("sha256").update(
|
|
36056
|
-
return
|
|
36351
|
+
const hash = crypto9.createHash("sha256").update(path23.resolve(cwd)).digest("hex").slice(0, 16);
|
|
36352
|
+
return path23.join(os16.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
|
|
36057
36353
|
}
|
|
36058
36354
|
function resolveMailCredentialPath(credentialPath) {
|
|
36059
36355
|
if (credentialPath) return credentialPath;
|
|
@@ -36064,16 +36360,16 @@ function resolveMailCredentialPath(credentialPath) {
|
|
|
36064
36360
|
async function loadMailCredentials(credentialPath) {
|
|
36065
36361
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36066
36362
|
try {
|
|
36067
|
-
return JSON.parse(await
|
|
36363
|
+
return JSON.parse(await fs22.readFile(filePath, "utf-8"));
|
|
36068
36364
|
} catch {
|
|
36069
36365
|
return null;
|
|
36070
36366
|
}
|
|
36071
36367
|
}
|
|
36072
36368
|
async function saveMailCredentials(creds, credentialPath) {
|
|
36073
36369
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36074
|
-
await
|
|
36075
|
-
await
|
|
36076
|
-
await
|
|
36370
|
+
await fs22.mkdir(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
36371
|
+
await fs22.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
36372
|
+
await fs22.chmod(filePath, 384);
|
|
36077
36373
|
}
|
|
36078
36374
|
async function persistProvisionedMailbox(mailbox, credentialPath) {
|
|
36079
36375
|
if (!mailbox?.address || !mailbox.password) return false;
|
|
@@ -36094,7 +36390,7 @@ async function persistProvisionedMailbox(mailbox, credentialPath) {
|
|
|
36094
36390
|
async function clearMailCredentials(credentialPath) {
|
|
36095
36391
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36096
36392
|
try {
|
|
36097
|
-
await
|
|
36393
|
+
await fs22.unlink(filePath);
|
|
36098
36394
|
} catch (err) {
|
|
36099
36395
|
if (err.code !== "ENOENT") throw err;
|
|
36100
36396
|
}
|
|
@@ -36143,10 +36439,10 @@ function registerRegisterPeerTool(server) {
|
|
|
36143
36439
|
"cogent_register_peer",
|
|
36144
36440
|
{
|
|
36145
36441
|
title: "Register Peer",
|
|
36146
|
-
description: "
|
|
36442
|
+
description: "Step 3: put this agent online in the channel joined or created in this session. peerId = the peer name you were given (never invent or suffix one); sessionId = this agent session's own resumable id (Claude Code or Codex), not the channel id. Also needs the working directory (cwd) and a human-readable label.",
|
|
36147
36443
|
inputSchema: {
|
|
36148
|
-
peerId: import_zod3.z.string().describe("
|
|
36149
|
-
sessionId: import_zod3.z.string().describe("
|
|
36444
|
+
peerId: import_zod3.z.string().describe("The peer name you were given, e.g. 'backend' or 'frontend'. Never invent or suffix one."),
|
|
36445
|
+
sessionId: import_zod3.z.string().describe("This agent session's own resumable id (Claude Code or Codex) \u2014 NOT the channel id"),
|
|
36150
36446
|
cwd: import_zod3.z.string().describe("Absolute path to the project working directory"),
|
|
36151
36447
|
label: import_zod3.z.string().describe("Human-readable label, e.g. 'Cogent_Backend' or 'Cogent_Frontend'"),
|
|
36152
36448
|
peerSecret: import_zod3.z.string().optional().describe(
|
|
@@ -36169,16 +36465,43 @@ function registerRegisterPeerTool(server) {
|
|
|
36169
36465
|
async ({ peerId, sessionId, cwd, label, mode, role, peerSecret: argPeerSecret }) => {
|
|
36170
36466
|
try {
|
|
36171
36467
|
const config2 = getConfig();
|
|
36468
|
+
if (isReservedPeerName(peerId)) {
|
|
36469
|
+
return errorResult(
|
|
36470
|
+
new BridgeError(
|
|
36471
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
36472
|
+
`peerId '${PROCESS_MARK}' is reserved by the bridge`,
|
|
36473
|
+
"Register under another peerId"
|
|
36474
|
+
)
|
|
36475
|
+
);
|
|
36476
|
+
}
|
|
36172
36477
|
const hasExplicitCloudSession = !!config2.COGENT_SESSION_ID || process.env.COGENT_TRUST_PERSISTED_CREDENTIALS === "1";
|
|
36173
36478
|
if (!hasExplicitCloudSession && hasCloudAttemptInProcess() && !hasJoinedInProcess()) {
|
|
36174
36479
|
return errorResult(
|
|
36175
36480
|
new BridgeError(
|
|
36176
36481
|
"JOIN_NOT_CONFIRMED" /* JOIN_NOT_CONFIRMED */,
|
|
36177
36482
|
"A cogent_join_session/cogent_create_session call was attempted this session but did not succeed, so cogent_register_peer will not fall back to local mode or auto-create a new channel (that would silently put you on the WRONG channel while reporting success)",
|
|
36178
|
-
"Re-run cogent_join_session with the correct channel name + secret (+ Org_ID for Team channels) and confirm it returns success before calling cogent_register_peer"
|
|
36483
|
+
"Re-run cogent_join_session with the correct channel name + secret (+ Org_ID for Team channels) and confirm it returns success before calling cogent_register_peer; or, if the join answered CHANNEL_NOT_FOUND, cogent_create_session with the same name, secret and Org_ID"
|
|
36179
36484
|
)
|
|
36180
36485
|
);
|
|
36181
36486
|
}
|
|
36487
|
+
if (config2.COGENT_ENDPOINT) try {
|
|
36488
|
+
const own = agentSessionId();
|
|
36489
|
+
const seen = /* @__PURE__ */ new Set();
|
|
36490
|
+
const entries = [...listLiveBridgesInFolder(cwd), ...listLiveBridgesInFolder(process.cwd())].filter((e) => !seen.has(`${e.pid}:${e.peerId}`) && seen.add(`${e.pid}:${e.peerId}`));
|
|
36491
|
+
const holder = heldInFolder(otherBridgesInFolder(entries, { pid: process.pid, sessionId: own }, listProcesses), peerId, own);
|
|
36492
|
+
if (holder) {
|
|
36493
|
+
logger.info(`Register: refused '${peerId}' \u2014 held in this folder by bridge pid ${holder.pid}`);
|
|
36494
|
+
return errorResult(
|
|
36495
|
+
new BridgeError(
|
|
36496
|
+
"PEER_HELD_IN_FOLDER" /* PEER_HELD_IN_FOLDER */,
|
|
36497
|
+
`'${peerId}' is held by another live connection in this folder (bridge pid ${holder.pid}, version ${registryText(holder.version)}); this bridge has NOT registered`,
|
|
36498
|
+
heldNameAdvice(peerId)
|
|
36499
|
+
)
|
|
36500
|
+
);
|
|
36501
|
+
}
|
|
36502
|
+
} catch (err) {
|
|
36503
|
+
logger.debug(`Register: could not check this folder for a holder of '${peerId}': ${err.message}`);
|
|
36504
|
+
}
|
|
36182
36505
|
const hasCloudEndpointConfig = config2.COGENT_ENDPOINT && isCloudEndpoint(config2.COGENT_ENDPOINT);
|
|
36183
36506
|
let sessionCreated = false;
|
|
36184
36507
|
let cloudSessionId;
|
|
@@ -36273,7 +36596,7 @@ function registerRegisterPeerTool(server) {
|
|
|
36273
36596
|
new BridgeError(
|
|
36274
36597
|
"JOIN_NOT_CONFIRMED" /* JOIN_NOT_CONFIRMED */,
|
|
36275
36598
|
"Cloud endpoint + COGENT_SESSION_ID are configured but this bridge has not joined the channel (no session token \u2014 the relay was unreachable or the session label did not resolve at startup). cogent_register_peer will NOT register against local state (that would leave you on no channel while other local agents' data sits on this host).",
|
|
36276
|
-
"Call cogent_join_session with the channel name + secret (+ Org_ID for Team channels) and confirm it returns success, then retry cogent_register_peer."
|
|
36599
|
+
"Call cogent_join_session with the channel name + secret (+ Org_ID for Team channels) and confirm it returns success (or, if the join answered CHANNEL_NOT_FOUND, cogent_create_session with the same name, secret and Org_ID), then retry cogent_register_peer."
|
|
36277
36600
|
)
|
|
36278
36601
|
);
|
|
36279
36602
|
}
|
|
@@ -36422,9 +36745,25 @@ function registerRegisterPeerTool(server) {
|
|
|
36422
36745
|
}
|
|
36423
36746
|
}
|
|
36424
36747
|
autoRelay.setLocalPeer(peerId, localSessionId, cwd, mode, label, localSessionId);
|
|
36748
|
+
if (isCloudMode()) {
|
|
36749
|
+
setPresence({ state: "online", restored: false, detail: `registered as '${peerId}' by cogent_register_peer` });
|
|
36750
|
+
}
|
|
36751
|
+
let otherBridges;
|
|
36752
|
+
try {
|
|
36753
|
+
const own = agentSessionId();
|
|
36754
|
+
const others = otherBridgesInFolder(listLiveBridgesInFolder(cwd), { pid: process.pid, sessionId: own }, listProcesses);
|
|
36755
|
+
if (others.length) {
|
|
36756
|
+
otherBridges = otherBridgeNotice(others, peerId, checkWakeOwnership(cwd, peerId), own);
|
|
36757
|
+
if (anotherAgentSessionAmong(others, own)) logger.warn(`Register: ${otherBridges}`);
|
|
36758
|
+
else logger.info(`Register: ${otherBridges}`);
|
|
36759
|
+
}
|
|
36760
|
+
} catch (err) {
|
|
36761
|
+
logger.debug(`Register: could not look for other bridges in this folder: ${err.message}`);
|
|
36762
|
+
}
|
|
36425
36763
|
const result = {
|
|
36426
36764
|
success: true,
|
|
36427
36765
|
action: existing ? "updated" : "registered",
|
|
36766
|
+
...otherBridges ? { otherBridgeInThisFolder: otherBridges } : {},
|
|
36428
36767
|
peer,
|
|
36429
36768
|
sessionResolution: {
|
|
36430
36769
|
decision: resolution.decision,
|
|
@@ -36503,6 +36842,9 @@ var init_register_peer = __esm({
|
|
|
36503
36842
|
init_logger();
|
|
36504
36843
|
init_heartbeat();
|
|
36505
36844
|
init_auto_relay();
|
|
36845
|
+
init_wake_ownership();
|
|
36846
|
+
init_peer_presence();
|
|
36847
|
+
init_stale_bridge_reaper();
|
|
36506
36848
|
init_session_resolver();
|
|
36507
36849
|
init_cc_cli();
|
|
36508
36850
|
init_durable_identity();
|
|
@@ -37172,9 +37514,14 @@ var init_ids = __esm({
|
|
|
37172
37514
|
});
|
|
37173
37515
|
|
|
37174
37516
|
// cogent/dist/helpers/validation.js
|
|
37517
|
+
function isValidSessionLabel(value) {
|
|
37518
|
+
return SESSION_LABEL_REGEX.test(value);
|
|
37519
|
+
}
|
|
37520
|
+
var SESSION_LABEL_REGEX;
|
|
37175
37521
|
var init_validation = __esm({
|
|
37176
37522
|
"cogent/dist/helpers/validation.js"() {
|
|
37177
37523
|
"use strict";
|
|
37524
|
+
SESSION_LABEL_REGEX = /^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$/;
|
|
37178
37525
|
}
|
|
37179
37526
|
});
|
|
37180
37527
|
|
|
@@ -37627,7 +37974,8 @@ function registerHealthCheckTool(server) {
|
|
|
37627
37974
|
// PRESENCE — the agent's own view of whether it is IN its channel, so it can
|
|
37628
37975
|
// answer "am I reachable?" without inferring it from transport internals.
|
|
37629
37976
|
// "online" registered · "offline" owns a peer but is not registered (nobody can
|
|
37630
|
-
// reach it) · "
|
|
37977
|
+
// reach it) · "standby" another live bridge serves this peer, so THIS process is not
|
|
37978
|
+
// registered (servedBy names it) · "deferred" never joined · "local" no relay.
|
|
37631
37979
|
// services/peer-presence.ts carries the vocabulary and how each state arises.
|
|
37632
37980
|
presence: (() => {
|
|
37633
37981
|
const p = getPresence();
|
|
@@ -37638,7 +37986,8 @@ function registerHealthCheckTool(server) {
|
|
|
37638
37986
|
state: p.state,
|
|
37639
37987
|
restored: p.restored,
|
|
37640
37988
|
detail: p.detail,
|
|
37641
|
-
..."peerId" in p ? { peerId: p.peerId } : {}
|
|
37989
|
+
..."peerId" in p ? { peerId: p.peerId } : {},
|
|
37990
|
+
..."servedBy" in p ? { servedBy: p.servedBy } : {}
|
|
37642
37991
|
};
|
|
37643
37992
|
})()
|
|
37644
37993
|
};
|
|
@@ -37725,18 +38074,43 @@ var init_wake_log2 = __esm({
|
|
|
37725
38074
|
}
|
|
37726
38075
|
});
|
|
37727
38076
|
|
|
38077
|
+
// src/tools/channel-text.ts
|
|
38078
|
+
function invalidChannelName(name) {
|
|
38079
|
+
if (isValidSessionLabel(name)) return null;
|
|
38080
|
+
return new BridgeError(
|
|
38081
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
38082
|
+
`Channel names are 3-32 characters: lowercase letters, digits and hyphens. '${name}' is not valid`,
|
|
38083
|
+
"If it differs only by capital letters, retry with it in lowercase; otherwise ask the user."
|
|
38084
|
+
);
|
|
38085
|
+
}
|
|
38086
|
+
function slackMapCommand(o) {
|
|
38087
|
+
return o.team ? `/cogent map ${o.label} <password> <org-id>` : `/cogent map ${o.sessionId} <password>`;
|
|
38088
|
+
}
|
|
38089
|
+
var init_channel_text = __esm({
|
|
38090
|
+
"src/tools/channel-text.ts"() {
|
|
38091
|
+
"use strict";
|
|
38092
|
+
init_dist();
|
|
38093
|
+
init_errors4();
|
|
38094
|
+
}
|
|
38095
|
+
});
|
|
38096
|
+
|
|
37728
38097
|
// src/tools/create-session.ts
|
|
37729
38098
|
import crypto11 from "node:crypto";
|
|
37730
38099
|
function registerCreateSessionTool(server) {
|
|
37731
38100
|
server.registerTool(
|
|
37732
38101
|
"cogent_create_session",
|
|
37733
38102
|
{
|
|
37734
|
-
title: "Create Cloud
|
|
37735
|
-
description: "
|
|
38103
|
+
title: "Create Cloud Channel",
|
|
38104
|
+
description: "Step 2: create a Cogent channel and join it. Call this ONLY after cogent_join_session answered CHANNEL_NOT_FOUND, with the SAME channel name, secret and (Team channel) orgId. Never choose a different name. Next call: cogent_register_peer.",
|
|
37736
38105
|
inputSchema: {
|
|
37737
|
-
label: import_zod15.z.string().optional().describe(
|
|
38106
|
+
label: import_zod15.z.string().optional().describe(
|
|
38107
|
+
"The channel name (3-32 characters: lowercase letters, digits, hyphens) \u2014 the same name the join was given. Auto-generated if omitted."
|
|
38108
|
+
),
|
|
37738
38109
|
secret: import_zod15.z.string().min(8).optional().describe(
|
|
37739
|
-
"Shared secret for
|
|
38110
|
+
"Shared secret / password for the channel (min 8 chars). Auto-generated if omitted."
|
|
38111
|
+
),
|
|
38112
|
+
orgId: import_zod15.z.string().min(1).optional().describe(
|
|
38113
|
+
"Org_ID \u2014 the 3rd credential for a Team (business) channel. Provide it to create a Team channel; omit for a free channel."
|
|
37740
38114
|
)
|
|
37741
38115
|
},
|
|
37742
38116
|
annotations: {
|
|
@@ -37746,28 +38120,57 @@ function registerCreateSessionTool(server) {
|
|
|
37746
38120
|
openWorldHint: true
|
|
37747
38121
|
}
|
|
37748
38122
|
},
|
|
37749
|
-
async ({ label, secret }) => {
|
|
38123
|
+
async ({ label, secret, orgId }) => {
|
|
37750
38124
|
try {
|
|
37751
38125
|
markCloudAttemptInProcess();
|
|
38126
|
+
if (label !== void 0 && label.trim() === "") {
|
|
38127
|
+
return errorResult(invalidChannelName(label) ?? new Error("label is empty"));
|
|
38128
|
+
}
|
|
38129
|
+
if (secret !== void 0 && secret.trim() === "") {
|
|
38130
|
+
return errorResult(
|
|
38131
|
+
new BridgeError(
|
|
38132
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
38133
|
+
"The channel password is empty",
|
|
38134
|
+
"Pass the password you were given, or omit `secret` to have one generated."
|
|
38135
|
+
)
|
|
38136
|
+
);
|
|
38137
|
+
}
|
|
38138
|
+
label = label?.trim() || void 0;
|
|
38139
|
+
secret = secret?.trim() || void 0;
|
|
38140
|
+
orgId = orgId?.trim() || void 0;
|
|
37752
38141
|
const config2 = getConfig();
|
|
37753
|
-
|
|
38142
|
+
const endpoint = orgId ? config2.COGENT_TEAM_ENDPOINT : config2.COGENT_ENDPOINT;
|
|
38143
|
+
if (!endpoint) {
|
|
37754
38144
|
return errorResult(
|
|
37755
38145
|
new Error(
|
|
37756
|
-
"COGENT_ENDPOINT not configured. Set it to use cloud mode."
|
|
38146
|
+
orgId ? "COGENT_TEAM_ENDPOINT not configured. Set it to create Team (Org_ID) channels." : "COGENT_ENDPOINT not configured. Set it to use cloud mode."
|
|
37757
38147
|
)
|
|
37758
38148
|
);
|
|
37759
38149
|
}
|
|
38150
|
+
if (label !== void 0) {
|
|
38151
|
+
const invalid = invalidChannelName(label);
|
|
38152
|
+
if (invalid) return errorResult(invalid);
|
|
38153
|
+
}
|
|
38154
|
+
const secretWasGenerated = secret === void 0;
|
|
37760
38155
|
const sessionSecret = secret ?? crypto11.randomBytes(16).toString("hex");
|
|
38156
|
+
const createBody = orgId ? { secret: sessionSecret, label, orgId } : { secret: sessionSecret, label };
|
|
37761
38157
|
const resp = await fetch(
|
|
37762
|
-
`${
|
|
38158
|
+
`${endpoint}/api/sessions`,
|
|
37763
38159
|
{
|
|
37764
38160
|
method: "POST",
|
|
37765
38161
|
headers: { "Content-Type": "application/json" },
|
|
37766
|
-
body: JSON.stringify(
|
|
38162
|
+
body: JSON.stringify(createBody)
|
|
37767
38163
|
}
|
|
37768
38164
|
);
|
|
37769
38165
|
if (!resp.ok) {
|
|
37770
38166
|
const body = await resp.text().catch(() => "");
|
|
38167
|
+
if (resp.status === 400 && body.includes("already in use")) {
|
|
38168
|
+
return errorResult(
|
|
38169
|
+
new Error(
|
|
38170
|
+
`Channel '${label}' already exists (already in use). Call cogent_join_session with the same name, secret${orgId ? " and Org_ID" : ""}. Do not choose another name.`
|
|
38171
|
+
)
|
|
38172
|
+
);
|
|
38173
|
+
}
|
|
37771
38174
|
return errorResult(
|
|
37772
38175
|
new Error(
|
|
37773
38176
|
`Failed to create session: HTTP ${resp.status}${body ? ` - ${body}` : ""}`
|
|
@@ -37776,7 +38179,7 @@ function registerCreateSessionTool(server) {
|
|
|
37776
38179
|
}
|
|
37777
38180
|
const data = await resp.json();
|
|
37778
38181
|
await saveCredentials({
|
|
37779
|
-
endpoint
|
|
38182
|
+
endpoint,
|
|
37780
38183
|
sessionId: data.sessionId,
|
|
37781
38184
|
token: data.token,
|
|
37782
38185
|
label: data.label,
|
|
@@ -37786,7 +38189,7 @@ function registerCreateSessionTool(server) {
|
|
|
37786
38189
|
try {
|
|
37787
38190
|
const startupModule = await Promise.resolve().then(() => (init_startup(), startup_exports));
|
|
37788
38191
|
if (typeof startupModule.reinitCloudBackend === "function") {
|
|
37789
|
-
await startupModule.reinitCloudBackend(
|
|
38192
|
+
await startupModule.reinitCloudBackend(endpoint, data.sessionId, data.token);
|
|
37790
38193
|
logger.info(
|
|
37791
38194
|
"Cloud backend reinitialized with new session credentials"
|
|
37792
38195
|
);
|
|
@@ -37794,32 +38197,40 @@ function registerCreateSessionTool(server) {
|
|
|
37794
38197
|
} catch (err) {
|
|
37795
38198
|
logger.debug(`Backend reinit not available: ${err}`);
|
|
37796
38199
|
}
|
|
38200
|
+
const channelName = data.label ?? data.sessionId;
|
|
37797
38201
|
return successResult({
|
|
37798
38202
|
success: true,
|
|
38203
|
+
created: true,
|
|
37799
38204
|
sessionId: data.sessionId,
|
|
37800
38205
|
label: data.label,
|
|
37801
|
-
secret: sessionSecret,
|
|
37802
38206
|
token: data.token,
|
|
37803
38207
|
createdAt: data.createdAt,
|
|
37804
|
-
|
|
37805
|
-
|
|
37806
|
-
|
|
38208
|
+
slackMapCommand: slackMapCommand({ team: !!orgId, label: channelName, sessionId: data.sessionId }),
|
|
38209
|
+
// A secret the CALLER supplied is never echoed back: the caller already has it, and a
|
|
38210
|
+
// tool result can be quoted into a channel by an auto-reply. Only a secret this tool
|
|
38211
|
+
// generated is returned — nothing else knows it.
|
|
38212
|
+
...secretWasGenerated ? {
|
|
38213
|
+
secret: sessionSecret,
|
|
38214
|
+
config_snippet: {
|
|
38215
|
+
env_vars: `COGENT_ENDPOINT=${endpoint}
|
|
38216
|
+
COGENT_SESSION_ID=${channelName}
|
|
37807
38217
|
COGENT_SECRET=${sessionSecret}
|
|
37808
38218
|
COGENT_PLATFORM=${config2.COGENT_PLATFORM}`,
|
|
37809
|
-
|
|
37810
|
-
|
|
37811
|
-
|
|
37812
|
-
|
|
37813
|
-
|
|
37814
|
-
|
|
37815
|
-
|
|
37816
|
-
|
|
37817
|
-
|
|
38219
|
+
mcp_config: {
|
|
38220
|
+
"cogent": {
|
|
38221
|
+
command: "npx",
|
|
38222
|
+
args: ["-y", "@essentialai/cogent-bridge"],
|
|
38223
|
+
env: {
|
|
38224
|
+
COGENT_ENDPOINT: endpoint,
|
|
38225
|
+
COGENT_SESSION_ID: channelName,
|
|
38226
|
+
COGENT_SECRET: sessionSecret,
|
|
38227
|
+
COGENT_PLATFORM: config2.COGENT_PLATFORM
|
|
38228
|
+
}
|
|
37818
38229
|
}
|
|
37819
38230
|
}
|
|
37820
38231
|
}
|
|
37821
|
-
},
|
|
37822
|
-
note:
|
|
38232
|
+
} : {},
|
|
38233
|
+
note: `${orgId ? "Team channel" : "Channel"} "${channelName}" was created by this call and you are joined to it. Credentials saved locally. Cloud backend updated. Next: cogent_register_peer.`
|
|
37823
38234
|
});
|
|
37824
38235
|
} catch (err) {
|
|
37825
38236
|
logger.error("create-session failed", { error: err });
|
|
@@ -37837,6 +38248,7 @@ var init_create_session = __esm({
|
|
|
37837
38248
|
init_errors4();
|
|
37838
38249
|
init_credential_store();
|
|
37839
38250
|
init_logger();
|
|
38251
|
+
init_channel_text();
|
|
37840
38252
|
}
|
|
37841
38253
|
});
|
|
37842
38254
|
|
|
@@ -37846,14 +38258,14 @@ function registerJoinSessionTool(server) {
|
|
|
37846
38258
|
"cogent_join_session",
|
|
37847
38259
|
{
|
|
37848
38260
|
title: "Join Cloud Channel",
|
|
37849
|
-
description: '
|
|
38261
|
+
description: 'Step 1: join an existing Cogent channel by its channel name (e.g. "mt-space") and shared secret (plus orgId for a Team channel). The channel name is the human-readable label provided by the user, NOT a UUID. Do NOT pass an agent session ID here \u2014 use the channel/space name the user gave you. Next call: cogent_register_peer. If this answers CHANNEL_NOT_FOUND, the next call is cogent_create_session with the same name, secret and orgId.',
|
|
37850
38262
|
inputSchema: {
|
|
37851
38263
|
channel: import_zod16.z.string().describe(
|
|
37852
|
-
'The channel name to join (e.g. "mt-space"). This is the human-readable name the user provided, NOT a UUID. Do NOT use
|
|
38264
|
+
'The channel name to join (e.g. "mt-space"). This is the human-readable name the user provided, NOT a UUID. Do NOT use an agent session ID here.'
|
|
37853
38265
|
),
|
|
37854
38266
|
secret: import_zod16.z.string().min(1).describe("The shared secret / password for the channel"),
|
|
37855
38267
|
orgId: import_zod16.z.string().min(1).optional().describe(
|
|
37856
|
-
"Org_ID \u2014 the 3rd credential for a Team (business) channel. Provide it for team channels; omit for free channels."
|
|
38268
|
+
"Org_ID \u2014 the 3rd credential for a Team (business) channel. Provide it for team channels; omit for free channels. If you were given one, never retry without it."
|
|
37857
38269
|
)
|
|
37858
38270
|
},
|
|
37859
38271
|
annotations: {
|
|
@@ -37881,10 +38293,12 @@ function registerJoinSessionTool(server) {
|
|
|
37881
38293
|
if (UUID_V4_RE2.test(channel)) {
|
|
37882
38294
|
return errorResult(
|
|
37883
38295
|
new Error(
|
|
37884
|
-
`The "channel" parameter ("${channel}") looks like a UUID. You should pass the human-readable channel name (e.g. "mt-space") that the user provided, NOT
|
|
38296
|
+
`The "channel" parameter ("${channel}") looks like a UUID. You should pass the human-readable channel name (e.g. "mt-space") that the user provided, NOT an agent session ID or any UUID. Please retry with the correct channel name.`
|
|
37885
38297
|
)
|
|
37886
38298
|
);
|
|
37887
38299
|
}
|
|
38300
|
+
const invalid = invalidChannelName(channel);
|
|
38301
|
+
if (invalid) return errorResult(invalid);
|
|
37888
38302
|
let resolvedSessionId;
|
|
37889
38303
|
let resolvedLabel;
|
|
37890
38304
|
if (orgId) {
|
|
@@ -37896,6 +38310,13 @@ function registerJoinSessionTool(server) {
|
|
|
37896
38310
|
body: JSON.stringify({ label: channel, orgId })
|
|
37897
38311
|
}
|
|
37898
38312
|
);
|
|
38313
|
+
if (resolveResp.status === 404) {
|
|
38314
|
+
return errorResult(new BridgeError(
|
|
38315
|
+
"CHANNEL_NOT_FOUND" /* CHANNEL_NOT_FOUND */,
|
|
38316
|
+
`Team channel '${channel}' was not found on ${endpoint} for this Org_ID (HTTP 404)`,
|
|
38317
|
+
`If the name and Org_ID are exactly as given, the channel does not exist yet: call cogent_create_session with label '${channel}', the same secret and the same orgId, then cogent_register_peer. Do not call cogent_join_session again first, and never without orgId.`
|
|
38318
|
+
));
|
|
38319
|
+
}
|
|
37899
38320
|
if (!resolveResp.ok) {
|
|
37900
38321
|
const body = await resolveResp.text().catch(() => "");
|
|
37901
38322
|
return errorResult(new Error(
|
|
@@ -37909,6 +38330,13 @@ function registerJoinSessionTool(server) {
|
|
|
37909
38330
|
const resolveResp = await fetch(
|
|
37910
38331
|
`${endpoint}/api/sessions/resolve/${encodeURIComponent(channel)}`
|
|
37911
38332
|
);
|
|
38333
|
+
if (resolveResp.status === 404) {
|
|
38334
|
+
return errorResult(new BridgeError(
|
|
38335
|
+
"CHANNEL_NOT_FOUND" /* CHANNEL_NOT_FOUND */,
|
|
38336
|
+
`Channel '${channel}' was not found on ${endpoint} (HTTP 404)`,
|
|
38337
|
+
`If you were given an Org_ID you left it out: call cogent_join_session again WITH orgId and do not create anything. Otherwise call cogent_create_session with label '${channel}' and the same secret.`
|
|
38338
|
+
));
|
|
38339
|
+
}
|
|
37912
38340
|
if (!resolveResp.ok) {
|
|
37913
38341
|
const body = await resolveResp.text().catch(() => "");
|
|
37914
38342
|
return errorResult(new Error(`Failed to resolve channel name "${channel}": HTTP ${resolveResp.status}${body ? ` - ${body}` : ""}`));
|
|
@@ -37928,9 +38356,10 @@ function registerJoinSessionTool(server) {
|
|
|
37928
38356
|
);
|
|
37929
38357
|
if (!resp.ok) {
|
|
37930
38358
|
const body = await resp.text().catch(() => "");
|
|
38359
|
+
const wrong = resp.status === 401 ? `. The password${orgId ? " or Org_ID" : ""} is wrong. Do not retry with guesses - ask the user.` : "";
|
|
37931
38360
|
return errorResult(
|
|
37932
38361
|
new Error(
|
|
37933
|
-
`Failed to join session: HTTP ${resp.status}${body ? ` - ${body}` : ""}`
|
|
38362
|
+
`Failed to join session: HTTP ${resp.status}${body ? ` - ${body}` : ""}${wrong}`
|
|
37934
38363
|
)
|
|
37935
38364
|
);
|
|
37936
38365
|
}
|
|
@@ -37979,6 +38408,11 @@ function registerJoinSessionTool(server) {
|
|
|
37979
38408
|
token: data.token,
|
|
37980
38409
|
label: resolvedLabel ?? data.label ?? channel,
|
|
37981
38410
|
peerCount: data.peerCount,
|
|
38411
|
+
slackMapCommand: slackMapCommand({
|
|
38412
|
+
team: !!orgId,
|
|
38413
|
+
label: resolvedLabel ?? data.label ?? channel,
|
|
38414
|
+
sessionId: data.sessionId
|
|
38415
|
+
}),
|
|
37982
38416
|
note: "Successfully joined session. Credentials saved locally. Cloud backend updated. You can now use cogent_register_peer.",
|
|
37983
38417
|
...updateNudge ? { updateAvailable: updateNudge } : {}
|
|
37984
38418
|
});
|
|
@@ -37999,6 +38433,7 @@ var init_join_session = __esm({
|
|
|
37999
38433
|
init_credential_store();
|
|
38000
38434
|
init_logger();
|
|
38001
38435
|
init_npm_update_check();
|
|
38436
|
+
init_channel_text();
|
|
38002
38437
|
UUID_V4_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
38003
38438
|
}
|
|
38004
38439
|
});
|
|
@@ -38233,8 +38668,8 @@ var require_cookies = __commonJS({
|
|
|
38233
38668
|
if (urlparts.hostname !== cookie.domain && (cookie.domain.charAt(0) !== "." || ("." + urlparts.hostname).substr(-cookie.domain.length) !== cookie.domain)) {
|
|
38234
38669
|
return false;
|
|
38235
38670
|
}
|
|
38236
|
-
let
|
|
38237
|
-
if (
|
|
38671
|
+
let path27 = this.getPath(urlparts.pathname);
|
|
38672
|
+
if (path27.substr(0, cookie.path.length) !== cookie.path) {
|
|
38238
38673
|
return false;
|
|
38239
38674
|
}
|
|
38240
38675
|
if (cookie.secure && urlparts.protocol !== "https:") {
|
|
@@ -38294,16 +38729,16 @@ var require_cookies = __commonJS({
|
|
|
38294
38729
|
* @returns {String} Normalized path
|
|
38295
38730
|
*/
|
|
38296
38731
|
getPath(pathname) {
|
|
38297
|
-
let
|
|
38298
|
-
|
|
38299
|
-
|
|
38300
|
-
if (
|
|
38301
|
-
|
|
38732
|
+
let path27 = (pathname || "/").split("/");
|
|
38733
|
+
path27.pop();
|
|
38734
|
+
path27 = path27.join("/").trim();
|
|
38735
|
+
if (path27.charAt(0) !== "/") {
|
|
38736
|
+
path27 = "/" + path27;
|
|
38302
38737
|
}
|
|
38303
|
-
if (
|
|
38304
|
-
|
|
38738
|
+
if (path27.substr(-1) !== "/") {
|
|
38739
|
+
path27 += "/";
|
|
38305
38740
|
}
|
|
38306
|
-
return
|
|
38741
|
+
return path27;
|
|
38307
38742
|
}
|
|
38308
38743
|
};
|
|
38309
38744
|
module.exports = Cookies;
|
|
@@ -38604,7 +39039,7 @@ var require_shared = __commonJS({
|
|
|
38604
39039
|
"use strict";
|
|
38605
39040
|
var urllib = __require("url");
|
|
38606
39041
|
var util2 = __require("util");
|
|
38607
|
-
var
|
|
39042
|
+
var fs25 = __require("fs");
|
|
38608
39043
|
var nmfetch = require_fetch();
|
|
38609
39044
|
var dns = __require("dns");
|
|
38610
39045
|
var net = __require("net");
|
|
@@ -38990,7 +39425,7 @@ var require_shared = __commonJS({
|
|
|
38990
39425
|
}
|
|
38991
39426
|
return callback(null, parsedDataUri.data);
|
|
38992
39427
|
} else if (content.path) {
|
|
38993
|
-
return resolveStream(
|
|
39428
|
+
return resolveStream(fs25.createReadStream(content.path), callback);
|
|
38994
39429
|
}
|
|
38995
39430
|
}
|
|
38996
39431
|
if (typeof data[key].content === "string" && !["utf8", "usascii", "ascii"].includes(encoding)) {
|
|
@@ -39114,7 +39549,7 @@ var require_shared = __commonJS({
|
|
|
39114
39549
|
var require_mime_types = __commonJS({
|
|
39115
39550
|
"node_modules/nodemailer/lib/mime-funcs/mime-types.js"(exports, module) {
|
|
39116
39551
|
"use strict";
|
|
39117
|
-
var
|
|
39552
|
+
var path27 = __require("path");
|
|
39118
39553
|
var defaultMimeType = "application/octet-stream";
|
|
39119
39554
|
var defaultExtension = "bin";
|
|
39120
39555
|
var mimeTypes = /* @__PURE__ */ new Map([
|
|
@@ -41172,7 +41607,7 @@ var require_mime_types = __commonJS({
|
|
|
41172
41607
|
if (!filename) {
|
|
41173
41608
|
return defaultMimeType;
|
|
41174
41609
|
}
|
|
41175
|
-
let parsed =
|
|
41610
|
+
let parsed = path27.parse(filename);
|
|
41176
41611
|
let extension = (parsed.ext.substr(1) || parsed.name || "").split("?").shift().trim().toLowerCase();
|
|
41177
41612
|
let value = defaultMimeType;
|
|
41178
41613
|
if (extensions.has(extension)) {
|
|
@@ -42574,7 +43009,7 @@ var require_mime_node = __commonJS({
|
|
|
42574
43009
|
"node_modules/nodemailer/lib/mime-node/index.js"(exports, module) {
|
|
42575
43010
|
"use strict";
|
|
42576
43011
|
var crypto12 = __require("crypto");
|
|
42577
|
-
var
|
|
43012
|
+
var fs25 = __require("fs");
|
|
42578
43013
|
var punycode = require_punycode();
|
|
42579
43014
|
var PassThrough = __require("stream").PassThrough;
|
|
42580
43015
|
var shared = require_shared();
|
|
@@ -43289,7 +43724,7 @@ var require_mime_node = __commonJS({
|
|
|
43289
43724
|
setImmediate(() => contentStream.emit("error", new Error("File access rejected for " + content.path)));
|
|
43290
43725
|
return contentStream;
|
|
43291
43726
|
}
|
|
43292
|
-
return
|
|
43727
|
+
return fs25.createReadStream(content.path);
|
|
43293
43728
|
} else if (content && typeof content.href === "string") {
|
|
43294
43729
|
if (this.disableUrlAccess) {
|
|
43295
43730
|
contentStream = new PassThrough();
|
|
@@ -44310,8 +44745,8 @@ var require_dkim = __commonJS({
|
|
|
44310
44745
|
var RelaxedBody = require_relaxed_body();
|
|
44311
44746
|
var sign = require_sign();
|
|
44312
44747
|
var PassThrough = __require("stream").PassThrough;
|
|
44313
|
-
var
|
|
44314
|
-
var
|
|
44748
|
+
var fs25 = __require("fs");
|
|
44749
|
+
var path27 = __require("path");
|
|
44315
44750
|
var crypto12 = __require("crypto");
|
|
44316
44751
|
var DKIM_ALGO = "sha256";
|
|
44317
44752
|
var MAX_MESSAGE_SIZE = 128 * 1024;
|
|
@@ -44325,7 +44760,7 @@ var require_dkim = __commonJS({
|
|
|
44325
44760
|
this.chunks = [];
|
|
44326
44761
|
this.chunklen = 0;
|
|
44327
44762
|
this.readPos = 0;
|
|
44328
|
-
this.cachePath = this.cacheDir ?
|
|
44763
|
+
this.cachePath = this.cacheDir ? path27.join(this.cacheDir, "message." + Date.now() + "-" + crypto12.randomBytes(14).toString("hex")) : false;
|
|
44329
44764
|
this.cache = false;
|
|
44330
44765
|
this.headers = false;
|
|
44331
44766
|
this.bodyHash = false;
|
|
@@ -44345,10 +44780,10 @@ var require_dkim = __commonJS({
|
|
|
44345
44780
|
if (!this.cache || !this.cachePath) {
|
|
44346
44781
|
return;
|
|
44347
44782
|
}
|
|
44348
|
-
|
|
44783
|
+
fs25.unlink(this.cachePath, () => false);
|
|
44349
44784
|
}
|
|
44350
44785
|
createReadCache() {
|
|
44351
|
-
this.cache =
|
|
44786
|
+
this.cache = fs25.createReadStream(this.cachePath);
|
|
44352
44787
|
this.cache.once("error", (err) => {
|
|
44353
44788
|
this.cleanup();
|
|
44354
44789
|
this.output.emit("error", err);
|
|
@@ -44404,7 +44839,7 @@ var require_dkim = __commonJS({
|
|
|
44404
44839
|
}
|
|
44405
44840
|
createWriteCache() {
|
|
44406
44841
|
this.output.usingCache = true;
|
|
44407
|
-
this.cache =
|
|
44842
|
+
this.cache = fs25.createWriteStream(this.cachePath);
|
|
44408
44843
|
this.cache.once("error", (err) => {
|
|
44409
44844
|
this.cleanup();
|
|
44410
44845
|
this.relaxedBody.unpipe(this.cache);
|
|
@@ -49293,13 +49728,13 @@ var require_nodemailer = __commonJS({
|
|
|
49293
49728
|
});
|
|
49294
49729
|
|
|
49295
49730
|
// src/mail/mail-sender.ts
|
|
49296
|
-
import
|
|
49297
|
-
import
|
|
49731
|
+
import fs23 from "node:fs/promises";
|
|
49732
|
+
import path24 from "node:path";
|
|
49298
49733
|
async function buildAndSendMail(sender, creds, params) {
|
|
49299
49734
|
const attachments = [];
|
|
49300
49735
|
for (const p of params.attachmentPaths ?? []) {
|
|
49301
|
-
const content = await
|
|
49302
|
-
attachments.push({ filename:
|
|
49736
|
+
const content = await fs23.readFile(p);
|
|
49737
|
+
attachments.push({ filename: path24.basename(p), content });
|
|
49303
49738
|
}
|
|
49304
49739
|
const { messageId } = await sender.send({
|
|
49305
49740
|
from: creds.address,
|
|
@@ -49688,8 +50123,8 @@ var require_req = __commonJS({
|
|
|
49688
50123
|
if (req.originalUrl) {
|
|
49689
50124
|
_req.url = req.originalUrl;
|
|
49690
50125
|
} else {
|
|
49691
|
-
const
|
|
49692
|
-
_req.url = typeof
|
|
50126
|
+
const path27 = req.path;
|
|
50127
|
+
_req.url = typeof path27 === "string" ? path27 : req.url ? req.url.path || req.url : void 0;
|
|
49693
50128
|
}
|
|
49694
50129
|
if (req.query) {
|
|
49695
50130
|
_req.query = req.query;
|
|
@@ -49854,14 +50289,14 @@ var require_redact = __commonJS({
|
|
|
49854
50289
|
}
|
|
49855
50290
|
return obj;
|
|
49856
50291
|
}
|
|
49857
|
-
function parsePath(
|
|
50292
|
+
function parsePath(path27) {
|
|
49858
50293
|
const parts = [];
|
|
49859
50294
|
let current = "";
|
|
49860
50295
|
let inBrackets = false;
|
|
49861
50296
|
let inQuotes = false;
|
|
49862
50297
|
let quoteChar = "";
|
|
49863
|
-
for (let i = 0; i <
|
|
49864
|
-
const char =
|
|
50298
|
+
for (let i = 0; i < path27.length; i++) {
|
|
50299
|
+
const char = path27[i];
|
|
49865
50300
|
if (!inBrackets && char === ".") {
|
|
49866
50301
|
if (current) {
|
|
49867
50302
|
parts.push(current);
|
|
@@ -49992,10 +50427,10 @@ var require_redact = __commonJS({
|
|
|
49992
50427
|
return current;
|
|
49993
50428
|
}
|
|
49994
50429
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
49995
|
-
for (const
|
|
49996
|
-
const parts = parsePath(
|
|
50430
|
+
for (const path27 of paths) {
|
|
50431
|
+
const parts = parsePath(path27);
|
|
49997
50432
|
if (parts.includes("*")) {
|
|
49998
|
-
redactWildcardPath(obj, parts, censor,
|
|
50433
|
+
redactWildcardPath(obj, parts, censor, path27, remove);
|
|
49999
50434
|
} else {
|
|
50000
50435
|
if (remove) {
|
|
50001
50436
|
removeKey(obj, parts);
|
|
@@ -50080,8 +50515,8 @@ var require_redact = __commonJS({
|
|
|
50080
50515
|
}
|
|
50081
50516
|
} else {
|
|
50082
50517
|
if (afterWildcard.includes("*")) {
|
|
50083
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
50084
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
50518
|
+
const wrappedCensor = typeof censor === "function" ? (value, path27) => {
|
|
50519
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path27];
|
|
50085
50520
|
return censor(value, fullPath);
|
|
50086
50521
|
} : censor;
|
|
50087
50522
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -50116,8 +50551,8 @@ var require_redact = __commonJS({
|
|
|
50116
50551
|
return null;
|
|
50117
50552
|
}
|
|
50118
50553
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
50119
|
-
for (const
|
|
50120
|
-
const parts = parsePath(
|
|
50554
|
+
for (const path27 of pathsToClone) {
|
|
50555
|
+
const parts = parsePath(path27);
|
|
50121
50556
|
let current = pathStructure;
|
|
50122
50557
|
for (let i = 0; i < parts.length; i++) {
|
|
50123
50558
|
const part = parts[i];
|
|
@@ -50169,24 +50604,24 @@ var require_redact = __commonJS({
|
|
|
50169
50604
|
}
|
|
50170
50605
|
return cloneSelectively(obj, pathStructure);
|
|
50171
50606
|
}
|
|
50172
|
-
function validatePath(
|
|
50173
|
-
if (typeof
|
|
50607
|
+
function validatePath(path27) {
|
|
50608
|
+
if (typeof path27 !== "string") {
|
|
50174
50609
|
throw new Error("Paths must be (non-empty) strings");
|
|
50175
50610
|
}
|
|
50176
|
-
if (
|
|
50611
|
+
if (path27 === "") {
|
|
50177
50612
|
throw new Error("Invalid redaction path ()");
|
|
50178
50613
|
}
|
|
50179
|
-
if (
|
|
50180
|
-
throw new Error(`Invalid redaction path (${
|
|
50614
|
+
if (path27.includes("..")) {
|
|
50615
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50181
50616
|
}
|
|
50182
|
-
if (
|
|
50183
|
-
throw new Error(`Invalid redaction path (${
|
|
50617
|
+
if (path27.includes(",")) {
|
|
50618
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50184
50619
|
}
|
|
50185
50620
|
let bracketCount = 0;
|
|
50186
50621
|
let inQuotes = false;
|
|
50187
50622
|
let quoteChar = "";
|
|
50188
|
-
for (let i = 0; i <
|
|
50189
|
-
const char =
|
|
50623
|
+
for (let i = 0; i < path27.length; i++) {
|
|
50624
|
+
const char = path27[i];
|
|
50190
50625
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
50191
50626
|
if (!inQuotes) {
|
|
50192
50627
|
inQuotes = true;
|
|
@@ -50200,20 +50635,20 @@ var require_redact = __commonJS({
|
|
|
50200
50635
|
} else if (char === "]" && !inQuotes) {
|
|
50201
50636
|
bracketCount--;
|
|
50202
50637
|
if (bracketCount < 0) {
|
|
50203
|
-
throw new Error(`Invalid redaction path (${
|
|
50638
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50204
50639
|
}
|
|
50205
50640
|
}
|
|
50206
50641
|
}
|
|
50207
50642
|
if (bracketCount !== 0) {
|
|
50208
|
-
throw new Error(`Invalid redaction path (${
|
|
50643
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50209
50644
|
}
|
|
50210
50645
|
}
|
|
50211
50646
|
function validatePaths(paths) {
|
|
50212
50647
|
if (!Array.isArray(paths)) {
|
|
50213
50648
|
throw new TypeError("paths must be an array");
|
|
50214
50649
|
}
|
|
50215
|
-
for (const
|
|
50216
|
-
validatePath(
|
|
50650
|
+
for (const path27 of paths) {
|
|
50651
|
+
validatePath(path27);
|
|
50217
50652
|
}
|
|
50218
50653
|
}
|
|
50219
50654
|
function slowRedact(options = {}) {
|
|
@@ -50381,8 +50816,8 @@ var require_redaction = __commonJS({
|
|
|
50381
50816
|
if (shape[k] === null) {
|
|
50382
50817
|
o[k] = (value) => topCensor(value, [k]);
|
|
50383
50818
|
} else {
|
|
50384
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
50385
|
-
return censor(value, [k, ...
|
|
50819
|
+
const wrappedCensor = typeof censor === "function" ? (value, path27) => {
|
|
50820
|
+
return censor(value, [k, ...path27]);
|
|
50386
50821
|
} : censor;
|
|
50387
50822
|
o[k] = Redact({
|
|
50388
50823
|
paths: shape[k],
|
|
@@ -50600,10 +51035,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
50600
51035
|
var require_sonic_boom = __commonJS({
|
|
50601
51036
|
"node_modules/sonic-boom/index.js"(exports, module) {
|
|
50602
51037
|
"use strict";
|
|
50603
|
-
var
|
|
51038
|
+
var fs25 = __require("fs");
|
|
50604
51039
|
var EventEmitter = __require("events");
|
|
50605
51040
|
var inherits = __require("util").inherits;
|
|
50606
|
-
var
|
|
51041
|
+
var path27 = __require("path");
|
|
50607
51042
|
var sleep4 = require_atomic_sleep();
|
|
50608
51043
|
var assert2 = __require("assert");
|
|
50609
51044
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -50657,20 +51092,20 @@ var require_sonic_boom = __commonJS({
|
|
|
50657
51092
|
const mode = sonic.mode;
|
|
50658
51093
|
if (sonic.sync) {
|
|
50659
51094
|
try {
|
|
50660
|
-
if (sonic.mkdir)
|
|
50661
|
-
const fd =
|
|
51095
|
+
if (sonic.mkdir) fs25.mkdirSync(path27.dirname(file), { recursive: true });
|
|
51096
|
+
const fd = fs25.openSync(file, flags, mode);
|
|
50662
51097
|
fileOpened(null, fd);
|
|
50663
51098
|
} catch (err) {
|
|
50664
51099
|
fileOpened(err);
|
|
50665
51100
|
throw err;
|
|
50666
51101
|
}
|
|
50667
51102
|
} else if (sonic.mkdir) {
|
|
50668
|
-
|
|
51103
|
+
fs25.mkdir(path27.dirname(file), { recursive: true }, (err) => {
|
|
50669
51104
|
if (err) return fileOpened(err);
|
|
50670
|
-
|
|
51105
|
+
fs25.open(file, flags, mode, fileOpened);
|
|
50671
51106
|
});
|
|
50672
51107
|
} else {
|
|
50673
|
-
|
|
51108
|
+
fs25.open(file, flags, mode, fileOpened);
|
|
50674
51109
|
}
|
|
50675
51110
|
}
|
|
50676
51111
|
function SonicBoom(opts) {
|
|
@@ -50711,8 +51146,8 @@ var require_sonic_boom = __commonJS({
|
|
|
50711
51146
|
this.flush = flushBuffer;
|
|
50712
51147
|
this.flushSync = flushBufferSync;
|
|
50713
51148
|
this._actualWrite = actualWriteBuffer;
|
|
50714
|
-
fsWriteSync = () =>
|
|
50715
|
-
fsWrite = () =>
|
|
51149
|
+
fsWriteSync = () => fs25.writeSync(this.fd, this._writingBuf);
|
|
51150
|
+
fsWrite = () => fs25.write(this.fd, this._writingBuf, this.release);
|
|
50716
51151
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
50717
51152
|
this._writingBuf = "";
|
|
50718
51153
|
this.write = write;
|
|
@@ -50721,15 +51156,15 @@ var require_sonic_boom = __commonJS({
|
|
|
50721
51156
|
this._actualWrite = actualWrite;
|
|
50722
51157
|
fsWriteSync = () => {
|
|
50723
51158
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
50724
|
-
return
|
|
51159
|
+
return fs25.writeSync(this.fd, this._writingBuf);
|
|
50725
51160
|
}
|
|
50726
|
-
return
|
|
51161
|
+
return fs25.writeSync(this.fd, this._writingBuf, "utf8");
|
|
50727
51162
|
};
|
|
50728
51163
|
fsWrite = () => {
|
|
50729
51164
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
50730
|
-
return
|
|
51165
|
+
return fs25.write(this.fd, this._writingBuf, this.release);
|
|
50731
51166
|
}
|
|
50732
|
-
return
|
|
51167
|
+
return fs25.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
50733
51168
|
};
|
|
50734
51169
|
} else {
|
|
50735
51170
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -50786,7 +51221,7 @@ var require_sonic_boom = __commonJS({
|
|
|
50786
51221
|
}
|
|
50787
51222
|
}
|
|
50788
51223
|
if (this._fsync) {
|
|
50789
|
-
|
|
51224
|
+
fs25.fsyncSync(this.fd);
|
|
50790
51225
|
}
|
|
50791
51226
|
const len = this._len;
|
|
50792
51227
|
if (this._reopening) {
|
|
@@ -50900,7 +51335,7 @@ var require_sonic_boom = __commonJS({
|
|
|
50900
51335
|
const onDrain = () => {
|
|
50901
51336
|
if (!this._fsync) {
|
|
50902
51337
|
try {
|
|
50903
|
-
|
|
51338
|
+
fs25.fsync(this.fd, (err) => {
|
|
50904
51339
|
this._flushPending = false;
|
|
50905
51340
|
cb(err);
|
|
50906
51341
|
});
|
|
@@ -51002,7 +51437,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51002
51437
|
const fd = this.fd;
|
|
51003
51438
|
this.once("ready", () => {
|
|
51004
51439
|
if (fd !== this.fd) {
|
|
51005
|
-
|
|
51440
|
+
fs25.close(fd, (err) => {
|
|
51006
51441
|
if (err) {
|
|
51007
51442
|
return this.emit("error", err);
|
|
51008
51443
|
}
|
|
@@ -51051,7 +51486,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51051
51486
|
buf = this._bufs[0];
|
|
51052
51487
|
}
|
|
51053
51488
|
try {
|
|
51054
|
-
const n = Buffer.isBuffer(buf) ?
|
|
51489
|
+
const n = Buffer.isBuffer(buf) ? fs25.writeSync(this.fd, buf) : fs25.writeSync(this.fd, buf, "utf8");
|
|
51055
51490
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
51056
51491
|
buf = releasedBufObj.writingBuf;
|
|
51057
51492
|
this._len = releasedBufObj.len;
|
|
@@ -51067,7 +51502,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51067
51502
|
}
|
|
51068
51503
|
}
|
|
51069
51504
|
try {
|
|
51070
|
-
|
|
51505
|
+
fs25.fsyncSync(this.fd);
|
|
51071
51506
|
} catch {
|
|
51072
51507
|
}
|
|
51073
51508
|
}
|
|
@@ -51088,7 +51523,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51088
51523
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
51089
51524
|
}
|
|
51090
51525
|
try {
|
|
51091
|
-
const n =
|
|
51526
|
+
const n = fs25.writeSync(this.fd, buf);
|
|
51092
51527
|
buf = buf.subarray(n);
|
|
51093
51528
|
this._len = Math.max(this._len - n, 0);
|
|
51094
51529
|
if (buf.length <= 0) {
|
|
@@ -51116,13 +51551,13 @@ var require_sonic_boom = __commonJS({
|
|
|
51116
51551
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
51117
51552
|
if (this.sync) {
|
|
51118
51553
|
try {
|
|
51119
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
51554
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs25.writeSync(this.fd, this._writingBuf) : fs25.writeSync(this.fd, this._writingBuf, "utf8");
|
|
51120
51555
|
release(null, written);
|
|
51121
51556
|
} catch (err) {
|
|
51122
51557
|
release(err);
|
|
51123
51558
|
}
|
|
51124
51559
|
} else {
|
|
51125
|
-
|
|
51560
|
+
fs25.write(this.fd, this._writingBuf, release);
|
|
51126
51561
|
}
|
|
51127
51562
|
}
|
|
51128
51563
|
function actualWriteBuffer() {
|
|
@@ -51131,7 +51566,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51131
51566
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
51132
51567
|
if (this.sync) {
|
|
51133
51568
|
try {
|
|
51134
|
-
const written =
|
|
51569
|
+
const written = fs25.writeSync(this.fd, this._writingBuf);
|
|
51135
51570
|
release(null, written);
|
|
51136
51571
|
} catch (err) {
|
|
51137
51572
|
release(err);
|
|
@@ -51140,7 +51575,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51140
51575
|
if (kCopyBuffer) {
|
|
51141
51576
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
51142
51577
|
}
|
|
51143
|
-
|
|
51578
|
+
fs25.write(this.fd, this._writingBuf, release);
|
|
51144
51579
|
}
|
|
51145
51580
|
}
|
|
51146
51581
|
function actualClose(sonic) {
|
|
@@ -51156,12 +51591,12 @@ var require_sonic_boom = __commonJS({
|
|
|
51156
51591
|
sonic._lens = [];
|
|
51157
51592
|
assert2(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
51158
51593
|
try {
|
|
51159
|
-
|
|
51594
|
+
fs25.fsync(sonic.fd, closeWrapped);
|
|
51160
51595
|
} catch {
|
|
51161
51596
|
}
|
|
51162
51597
|
function closeWrapped() {
|
|
51163
51598
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
51164
|
-
|
|
51599
|
+
fs25.close(sonic.fd, done);
|
|
51165
51600
|
} else {
|
|
51166
51601
|
done();
|
|
51167
51602
|
}
|
|
@@ -51997,15 +52432,15 @@ var require_transport = __commonJS({
|
|
|
51997
52432
|
if (!unquoted) {
|
|
51998
52433
|
return false;
|
|
51999
52434
|
}
|
|
52000
|
-
let
|
|
52001
|
-
if (
|
|
52435
|
+
let path27 = unquoted;
|
|
52436
|
+
if (path27.startsWith("file://")) {
|
|
52002
52437
|
try {
|
|
52003
|
-
|
|
52438
|
+
path27 = fileURLToPath(path27);
|
|
52004
52439
|
} catch {
|
|
52005
52440
|
return false;
|
|
52006
52441
|
}
|
|
52007
52442
|
}
|
|
52008
|
-
return isAbsolute(
|
|
52443
|
+
return isAbsolute(path27) && !existsSync(path27);
|
|
52009
52444
|
}
|
|
52010
52445
|
function stripQuotes(value) {
|
|
52011
52446
|
const first = value[0];
|
|
@@ -86072,15 +86507,15 @@ var require_tools2 = __commonJS({
|
|
|
86072
86507
|
* @param {String} path - Mailbox path to encode
|
|
86073
86508
|
* @returns {String} Encoded mailbox path
|
|
86074
86509
|
*/
|
|
86075
|
-
encodePath(connection,
|
|
86076
|
-
|
|
86077
|
-
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&\x00-\x08\x0b-\x0c\x0e-\x1f\u0080-\uffff]/.test(
|
|
86510
|
+
encodePath(connection, path27) {
|
|
86511
|
+
path27 = (path27 || "").toString();
|
|
86512
|
+
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&\x00-\x08\x0b-\x0c\x0e-\x1f\u0080-\uffff]/.test(path27)) {
|
|
86078
86513
|
try {
|
|
86079
|
-
|
|
86514
|
+
path27 = iconv.encode(path27, "utf-7-imap").toString();
|
|
86080
86515
|
} catch {
|
|
86081
86516
|
}
|
|
86082
86517
|
}
|
|
86083
|
-
return
|
|
86518
|
+
return path27;
|
|
86084
86519
|
},
|
|
86085
86520
|
/**
|
|
86086
86521
|
* Decodes a mailbox path from modified UTF-7 if the server does not support UTF8=ACCEPT.
|
|
@@ -86089,15 +86524,15 @@ var require_tools2 = __commonJS({
|
|
|
86089
86524
|
* @param {String} path - Mailbox path to decode
|
|
86090
86525
|
* @returns {String} Decoded mailbox path
|
|
86091
86526
|
*/
|
|
86092
|
-
decodePath(connection,
|
|
86093
|
-
|
|
86094
|
-
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&]/.test(
|
|
86527
|
+
decodePath(connection, path27) {
|
|
86528
|
+
path27 = (path27 || "").toString();
|
|
86529
|
+
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&]/.test(path27)) {
|
|
86095
86530
|
try {
|
|
86096
|
-
|
|
86531
|
+
path27 = iconv.decode(Buffer.from(path27), "utf-7-imap").toString();
|
|
86097
86532
|
} catch {
|
|
86098
86533
|
}
|
|
86099
86534
|
}
|
|
86100
|
-
return
|
|
86535
|
+
return path27;
|
|
86101
86536
|
},
|
|
86102
86537
|
/**
|
|
86103
86538
|
* Normalizes a mailbox path by joining array segments with the namespace delimiter,
|
|
@@ -86108,17 +86543,17 @@ var require_tools2 = __commonJS({
|
|
|
86108
86543
|
* @param {Boolean} [skipNamespace] - If true, skips prepending the namespace prefix
|
|
86109
86544
|
* @returns {String} Normalized mailbox path
|
|
86110
86545
|
*/
|
|
86111
|
-
normalizePath(connection,
|
|
86112
|
-
if (Array.isArray(
|
|
86113
|
-
|
|
86546
|
+
normalizePath(connection, path27, skipNamespace) {
|
|
86547
|
+
if (Array.isArray(path27)) {
|
|
86548
|
+
path27 = path27.join(connection.namespace && connection.namespace.delimiter || "");
|
|
86114
86549
|
}
|
|
86115
|
-
if (
|
|
86550
|
+
if (path27.toUpperCase() === "INBOX") {
|
|
86116
86551
|
return "INBOX";
|
|
86117
86552
|
}
|
|
86118
|
-
if (!skipNamespace && connection.namespace && connection.namespace.prefix && !
|
|
86119
|
-
|
|
86553
|
+
if (!skipNamespace && connection.namespace && connection.namespace.prefix && !path27.startsWith(connection.namespace.prefix)) {
|
|
86554
|
+
path27 = connection.namespace.prefix + path27;
|
|
86120
86555
|
}
|
|
86121
|
-
return
|
|
86556
|
+
return path27;
|
|
86122
86557
|
},
|
|
86123
86558
|
/**
|
|
86124
86559
|
* Compares two mailbox paths for equality after normalization.
|
|
@@ -86449,14 +86884,14 @@ var require_tools2 = __commonJS({
|
|
|
86449
86884
|
}
|
|
86450
86885
|
}
|
|
86451
86886
|
if (map.emailId || map.uid) {
|
|
86452
|
-
let
|
|
86453
|
-
if (/[\u0080-\uffff]/.test(
|
|
86887
|
+
let path27 = mailbox.path;
|
|
86888
|
+
if (/[\u0080-\uffff]/.test(path27)) {
|
|
86454
86889
|
try {
|
|
86455
|
-
|
|
86890
|
+
path27 = iconv.encode(path27, "utf-7-imap").toString();
|
|
86456
86891
|
} catch {
|
|
86457
86892
|
}
|
|
86458
86893
|
}
|
|
86459
|
-
map.id = map.emailId || createHash2("md5").update([
|
|
86894
|
+
map.id = map.emailId || createHash2("md5").update([path27, mailbox.uidValidity?.toString() || "", map.uid.toString()].join(":")).digest("hex");
|
|
86460
86895
|
}
|
|
86461
86896
|
if (map.flags) {
|
|
86462
86897
|
let flagColor = tools.getFlagColor(map.flags);
|
|
@@ -86631,16 +87066,16 @@ var require_tools2 = __commonJS({
|
|
|
86631
87066
|
* @returns {Object} Parsed body structure tree with part numbers, types, parameters, and child nodes
|
|
86632
87067
|
*/
|
|
86633
87068
|
parseBodystructure(entry) {
|
|
86634
|
-
let walk = (node,
|
|
86635
|
-
|
|
87069
|
+
let walk = (node, path27) => {
|
|
87070
|
+
path27 = path27 || [];
|
|
86636
87071
|
let curNode = {}, i = 0, part = 0;
|
|
86637
|
-
if (
|
|
86638
|
-
curNode.part =
|
|
87072
|
+
if (path27.length) {
|
|
87073
|
+
curNode.part = path27.join(".");
|
|
86639
87074
|
}
|
|
86640
87075
|
if (Array.isArray(node[0])) {
|
|
86641
87076
|
curNode.childNodes = [];
|
|
86642
87077
|
while (Array.isArray(node[i])) {
|
|
86643
|
-
curNode.childNodes.push(walk(node[i],
|
|
87078
|
+
curNode.childNodes.push(walk(node[i], path27.concat(++part)));
|
|
86644
87079
|
i++;
|
|
86645
87080
|
}
|
|
86646
87081
|
curNode.type = "multipart/" + ((node[i++] || {}).value || "").toString().toLowerCase();
|
|
@@ -86683,7 +87118,7 @@ var require_tools2 = __commonJS({
|
|
|
86683
87118
|
// the encapsulated message shares the part number with its wrapper.
|
|
86684
87119
|
// Distinction is via suffixes: path.MIME = wrapper headers,
|
|
86685
87120
|
// path.HEADER = encapsulated message headers.
|
|
86686
|
-
walk(node[i],
|
|
87121
|
+
walk(node[i], path27)
|
|
86687
87122
|
];
|
|
86688
87123
|
}
|
|
86689
87124
|
i++;
|
|
@@ -88645,14 +89080,14 @@ var require_select = __commonJS({
|
|
|
88645
89080
|
// update into a silent no-op for the rest of the session.
|
|
88646
89081
|
permanentflags: { key: "permanentFlags", parse: (value) => Array.isArray(value) && new Set(value) }
|
|
88647
89082
|
});
|
|
88648
|
-
module.exports = async (connection,
|
|
89083
|
+
module.exports = async (connection, path27, options) => {
|
|
88649
89084
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
88650
89085
|
return;
|
|
88651
89086
|
}
|
|
88652
89087
|
options = options || {};
|
|
88653
|
-
|
|
88654
|
-
if (!connection.folders.has(
|
|
88655
|
-
let folders = await connection.run("LIST", "",
|
|
89088
|
+
path27 = normalizePath(connection, path27);
|
|
89089
|
+
if (!connection.folders.has(path27)) {
|
|
89090
|
+
let folders = await connection.run("LIST", "", path27);
|
|
88656
89091
|
if (!folders) {
|
|
88657
89092
|
throw new Error("Failed to fetch folders");
|
|
88658
89093
|
}
|
|
@@ -88660,10 +89095,10 @@ var require_select = __commonJS({
|
|
|
88660
89095
|
connection.folders.set(folder.path, folder);
|
|
88661
89096
|
});
|
|
88662
89097
|
}
|
|
88663
|
-
let folderListData = connection.folders.has(
|
|
89098
|
+
let folderListData = connection.folders.has(path27) ? connection.folders.get(path27) : false;
|
|
88664
89099
|
let response;
|
|
88665
89100
|
try {
|
|
88666
|
-
let map = { path:
|
|
89101
|
+
let map = { path: path27 };
|
|
88667
89102
|
if (folderListData) {
|
|
88668
89103
|
["delimiter", "specialUse", "subscribed", "listed"].forEach((key) => {
|
|
88669
89104
|
if (folderListData[key]) {
|
|
@@ -88682,7 +89117,7 @@ var require_select = __commonJS({
|
|
|
88682
89117
|
]);
|
|
88683
89118
|
map.qresync = true;
|
|
88684
89119
|
}
|
|
88685
|
-
let encodedPath = encodePath(connection,
|
|
89120
|
+
let encodedPath = encodePath(connection, path27);
|
|
88686
89121
|
let selectCommand = {
|
|
88687
89122
|
command: !options.readOnly ? "SELECT" : "EXAMINE",
|
|
88688
89123
|
/* c8 ignore next */
|
|
@@ -88742,12 +89177,12 @@ var require_select = __commonJS({
|
|
|
88742
89177
|
// since the client's last known state. Only received when QRESYNC was requested.
|
|
88743
89178
|
// A dummy mailbox object is passed because the mailbox isn't officially open yet.
|
|
88744
89179
|
VANISHED: async (untagged) => {
|
|
88745
|
-
await connection.untaggedVanished(untagged, { path:
|
|
89180
|
+
await connection.untaggedVanished(untagged, { path: path27, uidNext: false, uidValidity: false });
|
|
88746
89181
|
},
|
|
88747
89182
|
// Untagged FETCH during SELECT/EXAMINE: only occurs with QRESYNC, delivering
|
|
88748
89183
|
// updated flags for messages that changed since the client's last modseq.
|
|
88749
89184
|
FETCH: async (untagged) => {
|
|
88750
|
-
await connection.untaggedFetch(untagged, { path:
|
|
89185
|
+
await connection.untaggedFetch(untagged, { path: path27, uidNext: false, uidValidity: false });
|
|
88751
89186
|
}
|
|
88752
89187
|
}
|
|
88753
89188
|
});
|
|
@@ -88761,13 +89196,13 @@ var require_select = __commonJS({
|
|
|
88761
89196
|
}
|
|
88762
89197
|
let currentMailbox = connection.mailbox;
|
|
88763
89198
|
connection.mailbox = false;
|
|
88764
|
-
if (currentMailbox && currentMailbox.path !==
|
|
89199
|
+
if (currentMailbox && currentMailbox.path !== path27) {
|
|
88765
89200
|
connection.emit("mailboxClose", currentMailbox);
|
|
88766
89201
|
}
|
|
88767
89202
|
connection.mailbox = map;
|
|
88768
89203
|
connection.currentSelectCommand = selectCommand;
|
|
88769
89204
|
connection.state = connection.states.SELECTED;
|
|
88770
|
-
if (!currentMailbox || currentMailbox.path !==
|
|
89205
|
+
if (!currentMailbox || currentMailbox.path !== path27) {
|
|
88771
89206
|
connection.emit("mailboxOpen", connection.mailbox);
|
|
88772
89207
|
}
|
|
88773
89208
|
response.next();
|
|
@@ -88982,17 +89417,17 @@ var require_create = __commonJS({
|
|
|
88982
89417
|
"node_modules/imapflow/lib/commands/create.js"(exports, module) {
|
|
88983
89418
|
"use strict";
|
|
88984
89419
|
var { encodePath, normalizePath, getStatusCode, enhanceCommandError } = require_tools2();
|
|
88985
|
-
module.exports = async (connection,
|
|
89420
|
+
module.exports = async (connection, path27) => {
|
|
88986
89421
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
88987
89422
|
return;
|
|
88988
89423
|
}
|
|
88989
|
-
|
|
89424
|
+
path27 = normalizePath(connection, path27);
|
|
88990
89425
|
let response;
|
|
88991
89426
|
try {
|
|
88992
89427
|
let map = {
|
|
88993
|
-
path:
|
|
89428
|
+
path: path27
|
|
88994
89429
|
};
|
|
88995
|
-
response = await connection.exec("CREATE", [{ type: "ATOM", value: encodePath(connection,
|
|
89430
|
+
response = await connection.exec("CREATE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
88996
89431
|
let section = response.response.attributes && response.response.attributes[0] && response.response.attributes[0].section && response.response.attributes[0].section.length ? response.response.attributes[0].section : false;
|
|
88997
89432
|
if (section) {
|
|
88998
89433
|
let key;
|
|
@@ -89018,13 +89453,13 @@ var require_create = __commonJS({
|
|
|
89018
89453
|
}
|
|
89019
89454
|
map.created = true;
|
|
89020
89455
|
response.next();
|
|
89021
|
-
await connection.run("SUBSCRIBE",
|
|
89456
|
+
await connection.run("SUBSCRIBE", path27);
|
|
89022
89457
|
return map;
|
|
89023
89458
|
} catch (err) {
|
|
89024
89459
|
let errorCode = getStatusCode(err.response);
|
|
89025
89460
|
if (errorCode === "ALREADYEXISTS") {
|
|
89026
89461
|
return {
|
|
89027
|
-
path:
|
|
89462
|
+
path: path27,
|
|
89028
89463
|
created: false
|
|
89029
89464
|
};
|
|
89030
89465
|
}
|
|
@@ -89041,20 +89476,20 @@ var require_delete = __commonJS({
|
|
|
89041
89476
|
"node_modules/imapflow/lib/commands/delete.js"(exports, module) {
|
|
89042
89477
|
"use strict";
|
|
89043
89478
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89044
|
-
module.exports = async (connection,
|
|
89479
|
+
module.exports = async (connection, path27) => {
|
|
89045
89480
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89046
89481
|
return;
|
|
89047
89482
|
}
|
|
89048
|
-
|
|
89049
|
-
if (connection.state === connection.states.SELECTED && connection.mailbox.path ===
|
|
89483
|
+
path27 = normalizePath(connection, path27);
|
|
89484
|
+
if (connection.state === connection.states.SELECTED && connection.mailbox.path === path27) {
|
|
89050
89485
|
await connection.run("CLOSE");
|
|
89051
89486
|
}
|
|
89052
89487
|
let response;
|
|
89053
89488
|
try {
|
|
89054
89489
|
let map = {
|
|
89055
|
-
path:
|
|
89490
|
+
path: path27
|
|
89056
89491
|
};
|
|
89057
|
-
response = await connection.exec("DELETE", [{ type: "ATOM", value: encodePath(connection,
|
|
89492
|
+
response = await connection.exec("DELETE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89058
89493
|
response.next();
|
|
89059
89494
|
return map;
|
|
89060
89495
|
} catch (err) {
|
|
@@ -89071,23 +89506,23 @@ var require_rename = __commonJS({
|
|
|
89071
89506
|
"node_modules/imapflow/lib/commands/rename.js"(exports, module) {
|
|
89072
89507
|
"use strict";
|
|
89073
89508
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89074
|
-
module.exports = async (connection,
|
|
89509
|
+
module.exports = async (connection, path27, newPath) => {
|
|
89075
89510
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89076
89511
|
return;
|
|
89077
89512
|
}
|
|
89078
|
-
|
|
89513
|
+
path27 = normalizePath(connection, path27);
|
|
89079
89514
|
newPath = normalizePath(connection, newPath);
|
|
89080
|
-
if (connection.state === connection.states.SELECTED && connection.mailbox.path ===
|
|
89515
|
+
if (connection.state === connection.states.SELECTED && connection.mailbox.path === path27) {
|
|
89081
89516
|
await connection.run("CLOSE");
|
|
89082
89517
|
}
|
|
89083
89518
|
let response;
|
|
89084
89519
|
try {
|
|
89085
89520
|
let map = {
|
|
89086
|
-
path:
|
|
89521
|
+
path: path27,
|
|
89087
89522
|
newPath
|
|
89088
89523
|
};
|
|
89089
89524
|
response = await connection.exec("RENAME", [
|
|
89090
|
-
{ type: "ATOM", value: encodePath(connection,
|
|
89525
|
+
{ type: "ATOM", value: encodePath(connection, path27) },
|
|
89091
89526
|
{ type: "ATOM", value: encodePath(connection, newPath) }
|
|
89092
89527
|
]);
|
|
89093
89528
|
response.next();
|
|
@@ -89134,14 +89569,14 @@ var require_subscribe = __commonJS({
|
|
|
89134
89569
|
"node_modules/imapflow/lib/commands/subscribe.js"(exports, module) {
|
|
89135
89570
|
"use strict";
|
|
89136
89571
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89137
|
-
module.exports = async (connection,
|
|
89572
|
+
module.exports = async (connection, path27) => {
|
|
89138
89573
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89139
89574
|
return;
|
|
89140
89575
|
}
|
|
89141
|
-
|
|
89576
|
+
path27 = normalizePath(connection, path27);
|
|
89142
89577
|
let response;
|
|
89143
89578
|
try {
|
|
89144
|
-
response = await connection.exec("SUBSCRIBE", [{ type: "ATOM", value: encodePath(connection,
|
|
89579
|
+
response = await connection.exec("SUBSCRIBE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89145
89580
|
response.next();
|
|
89146
89581
|
return true;
|
|
89147
89582
|
} catch (err) {
|
|
@@ -89158,14 +89593,14 @@ var require_unsubscribe = __commonJS({
|
|
|
89158
89593
|
"node_modules/imapflow/lib/commands/unsubscribe.js"(exports, module) {
|
|
89159
89594
|
"use strict";
|
|
89160
89595
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89161
|
-
module.exports = async (connection,
|
|
89596
|
+
module.exports = async (connection, path27) => {
|
|
89162
89597
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89163
89598
|
return;
|
|
89164
89599
|
}
|
|
89165
|
-
|
|
89600
|
+
path27 = normalizePath(connection, path27);
|
|
89166
89601
|
let response;
|
|
89167
89602
|
try {
|
|
89168
|
-
response = await connection.exec("UNSUBSCRIBE", [{ type: "ATOM", value: encodePath(connection,
|
|
89603
|
+
response = await connection.exec("UNSUBSCRIBE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89169
89604
|
response.next();
|
|
89170
89605
|
return true;
|
|
89171
89606
|
} catch (err) {
|
|
@@ -89971,11 +90406,11 @@ var require_status = __commonJS({
|
|
|
89971
90406
|
var { encodePath, normalizePath, buildStatusQueryAttributes, isRev2Active } = require_tools2();
|
|
89972
90407
|
var { parseStatusList } = require_status_fields();
|
|
89973
90408
|
var MAILBOX_UPDATERS = {
|
|
89974
|
-
messages: (value, connection,
|
|
90409
|
+
messages: (value, connection, path27) => {
|
|
89975
90410
|
let prevCount = connection.mailbox.exists;
|
|
89976
90411
|
if (prevCount !== value) {
|
|
89977
90412
|
connection.mailbox.exists = value;
|
|
89978
|
-
connection.emit("exists", { path:
|
|
90413
|
+
connection.emit("exists", { path: path27, count: value, prevCount });
|
|
89979
90414
|
}
|
|
89980
90415
|
},
|
|
89981
90416
|
uidNext: (value, connection) => {
|
|
@@ -89985,28 +90420,28 @@ var require_status = __commonJS({
|
|
|
89985
90420
|
connection.mailbox.highestModseq = value;
|
|
89986
90421
|
}
|
|
89987
90422
|
};
|
|
89988
|
-
module.exports = async (connection,
|
|
89989
|
-
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !
|
|
90423
|
+
module.exports = async (connection, path27, query) => {
|
|
90424
|
+
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path27) {
|
|
89990
90425
|
return false;
|
|
89991
90426
|
}
|
|
89992
|
-
|
|
89993
|
-
let encodedPath = encodePath(connection,
|
|
90427
|
+
path27 = normalizePath(connection, path27);
|
|
90428
|
+
let encodedPath = encodePath(connection, path27);
|
|
89994
90429
|
let attributes = [{ type: encodedPath.indexOf("&") >= 0 ? "STRING" : "ATOM", value: encodedPath }];
|
|
89995
90430
|
let queryAttributes = buildStatusQueryAttributes(connection, query);
|
|
89996
90431
|
let syntheticRecent = query && query.recent && isRev2Active(connection);
|
|
89997
90432
|
if (!queryAttributes.length) {
|
|
89998
|
-
return syntheticRecent ? { path:
|
|
90433
|
+
return syntheticRecent ? { path: path27, recent: 0 } : false;
|
|
89999
90434
|
}
|
|
90000
90435
|
attributes.push(queryAttributes);
|
|
90001
90436
|
let response;
|
|
90002
90437
|
try {
|
|
90003
|
-
let map = { path:
|
|
90438
|
+
let map = { path: path27 };
|
|
90004
90439
|
response = await connection.exec("STATUS", attributes, {
|
|
90005
90440
|
untagged: {
|
|
90006
90441
|
// STATUS response: * STATUS <mailbox> (<key> <value> <key> <value> ...)
|
|
90007
90442
|
// Parsed as alternating key-value pairs (i % 2 pattern).
|
|
90008
90443
|
STATUS: async (untagged) => {
|
|
90009
|
-
let updateCurrent = connection.state === connection.states.SELECTED &&
|
|
90444
|
+
let updateCurrent = connection.state === connection.states.SELECTED && path27 === connection.mailbox.path;
|
|
90010
90445
|
let list = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
|
|
90011
90446
|
if (!list) {
|
|
90012
90447
|
return;
|
|
@@ -90014,7 +90449,7 @@ var require_status = __commonJS({
|
|
|
90014
90449
|
parseStatusList(list, (key, value) => {
|
|
90015
90450
|
map[key] = value;
|
|
90016
90451
|
if (updateCurrent && MAILBOX_UPDATERS[key]) {
|
|
90017
|
-
MAILBOX_UPDATERS[key](value, connection,
|
|
90452
|
+
MAILBOX_UPDATERS[key](value, connection, path27);
|
|
90018
90453
|
}
|
|
90019
90454
|
});
|
|
90020
90455
|
}
|
|
@@ -90027,9 +90462,9 @@ var require_status = __commonJS({
|
|
|
90027
90462
|
return map;
|
|
90028
90463
|
} catch (err) {
|
|
90029
90464
|
if (err.responseStatus === "NO") {
|
|
90030
|
-
let folders = await connection.run("LIST", "",
|
|
90465
|
+
let folders = await connection.run("LIST", "", path27, { listOnly: true });
|
|
90031
90466
|
if (folders && !folders.length) {
|
|
90032
|
-
let error2 = new Error(`Mailbox doesn't exist: ${
|
|
90467
|
+
let error2 = new Error(`Mailbox doesn't exist: ${path27}`);
|
|
90033
90468
|
error2.code = "NotFound";
|
|
90034
90469
|
error2.response = err;
|
|
90035
90470
|
throw error2;
|
|
@@ -90176,15 +90611,15 @@ var require_quota = __commonJS({
|
|
|
90176
90611
|
"node_modules/imapflow/lib/commands/quota.js"(exports, module) {
|
|
90177
90612
|
"use strict";
|
|
90178
90613
|
var { encodePath, normalizePath, enhanceCommandError, parseUintValue, isUnsafeKey } = require_tools2();
|
|
90179
|
-
module.exports = async (connection,
|
|
90180
|
-
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !
|
|
90614
|
+
module.exports = async (connection, path27) => {
|
|
90615
|
+
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path27) {
|
|
90181
90616
|
return;
|
|
90182
90617
|
}
|
|
90183
90618
|
if (!connection.capabilities.has("QUOTA")) {
|
|
90184
90619
|
return false;
|
|
90185
90620
|
}
|
|
90186
|
-
|
|
90187
|
-
let map = { path:
|
|
90621
|
+
path27 = normalizePath(connection, path27);
|
|
90622
|
+
let map = { path: path27 };
|
|
90188
90623
|
let processQuotaResponse = (untagged) => {
|
|
90189
90624
|
let attributes = untagged.attributes && untagged.attributes[1];
|
|
90190
90625
|
if (!attributes || !attributes.length) {
|
|
@@ -90224,7 +90659,7 @@ var require_quota = __commonJS({
|
|
|
90224
90659
|
let quotaFound = false;
|
|
90225
90660
|
let response;
|
|
90226
90661
|
try {
|
|
90227
|
-
response = await connection.exec("GETQUOTAROOT", [{ type: "ATOM", value: encodePath(connection,
|
|
90662
|
+
response = await connection.exec("GETQUOTAROOT", [{ type: "ATOM", value: encodePath(connection, path27) }], {
|
|
90228
90663
|
untagged: {
|
|
90229
90664
|
// QUOTAROOT response tells us which quota root applies to this mailbox.
|
|
90230
90665
|
// A mailbox may have zero or one quota root.
|
|
@@ -90367,15 +90802,15 @@ var require_idle = __commonJS({
|
|
|
90367
90802
|
}
|
|
90368
90803
|
}
|
|
90369
90804
|
async function pollOnce2(connection, session) {
|
|
90370
|
-
let
|
|
90805
|
+
let path27 = connection.mailbox && connection.mailbox.path;
|
|
90371
90806
|
switch (connection.missingIdleCommand) {
|
|
90372
90807
|
case "SELECT":
|
|
90373
90808
|
connection.log.debug({ src: "c", msg: `Running SELECT to detect changes in folder`, cid: connection.id });
|
|
90374
|
-
await connection.runInternal("SELECT",
|
|
90809
|
+
await connection.runInternal("SELECT", path27, { readOnly: session.selectCommand.command === "EXAMINE" });
|
|
90375
90810
|
break;
|
|
90376
90811
|
case "STATUS": {
|
|
90377
90812
|
connection.log.debug({ src: "c", msg: `Running STATUS to detect changes in folder`, cid: connection.id });
|
|
90378
|
-
let status = await connection.runInternal("STATUS",
|
|
90813
|
+
let status = await connection.runInternal("STATUS", path27, {
|
|
90379
90814
|
messages: true,
|
|
90380
90815
|
uidNext: true,
|
|
90381
90816
|
uidValidity: true,
|
|
@@ -92062,12 +92497,12 @@ var require_imap_flow = __commonJS({
|
|
|
92062
92497
|
this.emit("flags", updateEvent);
|
|
92063
92498
|
}
|
|
92064
92499
|
}
|
|
92065
|
-
async ensureSelectedMailbox(
|
|
92066
|
-
if (!
|
|
92500
|
+
async ensureSelectedMailbox(path27) {
|
|
92501
|
+
if (!path27) {
|
|
92067
92502
|
return false;
|
|
92068
92503
|
}
|
|
92069
|
-
if (!this.mailbox || !comparePaths(this, this.mailbox.path,
|
|
92070
|
-
return await this.mailboxOpen(
|
|
92504
|
+
if (!this.mailbox || !comparePaths(this, this.mailbox.path, path27)) {
|
|
92505
|
+
return await this.mailboxOpen(path27);
|
|
92071
92506
|
}
|
|
92072
92507
|
return true;
|
|
92073
92508
|
}
|
|
@@ -92482,9 +92917,9 @@ var require_imap_flow = __commonJS({
|
|
|
92482
92917
|
* let quota = await client.getQuota();
|
|
92483
92918
|
* console.log(quota.storage.used, quota.storage.limit)
|
|
92484
92919
|
*/
|
|
92485
|
-
async getQuota(
|
|
92486
|
-
|
|
92487
|
-
return await this.run("QUOTA",
|
|
92920
|
+
async getQuota(path27) {
|
|
92921
|
+
path27 = path27 || "INBOX";
|
|
92922
|
+
return await this.run("QUOTA", path27);
|
|
92488
92923
|
}
|
|
92489
92924
|
/**
|
|
92490
92925
|
* @typedef {Object} ListResponse
|
|
@@ -92594,8 +93029,8 @@ var require_imap_flow = __commonJS({
|
|
|
92594
93029
|
* console.log(info.path);
|
|
92595
93030
|
* // "INBOX.parent.child" // assumes "INBOX." as namespace prefix and "." as delimiter
|
|
92596
93031
|
*/
|
|
92597
|
-
async mailboxCreate(
|
|
92598
|
-
return await this.run("CREATE",
|
|
93032
|
+
async mailboxCreate(path27) {
|
|
93033
|
+
return await this.run("CREATE", path27);
|
|
92599
93034
|
}
|
|
92600
93035
|
/**
|
|
92601
93036
|
* @typedef {Object} MailboxRenameResponse
|
|
@@ -92616,8 +93051,8 @@ var require_imap_flow = __commonJS({
|
|
|
92616
93051
|
* console.log(info.newPath);
|
|
92617
93052
|
* // "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix
|
|
92618
93053
|
*/
|
|
92619
|
-
async mailboxRename(
|
|
92620
|
-
return await this.run("RENAME",
|
|
93054
|
+
async mailboxRename(path27, newPath) {
|
|
93055
|
+
return await this.run("RENAME", path27, newPath);
|
|
92621
93056
|
}
|
|
92622
93057
|
/**
|
|
92623
93058
|
* @typedef {Object} MailboxDeleteResponse
|
|
@@ -92636,8 +93071,8 @@ var require_imap_flow = __commonJS({
|
|
|
92636
93071
|
* console.log(info.path);
|
|
92637
93072
|
* // "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix
|
|
92638
93073
|
*/
|
|
92639
|
-
async mailboxDelete(
|
|
92640
|
-
return await this.run("DELETE",
|
|
93074
|
+
async mailboxDelete(path27) {
|
|
93075
|
+
return await this.run("DELETE", path27);
|
|
92641
93076
|
}
|
|
92642
93077
|
/**
|
|
92643
93078
|
* Subscribes to a mailbox
|
|
@@ -92648,8 +93083,8 @@ var require_imap_flow = __commonJS({
|
|
|
92648
93083
|
* @example
|
|
92649
93084
|
* await client.mailboxSubscribe('Important stuff ❗️');
|
|
92650
93085
|
*/
|
|
92651
|
-
async mailboxSubscribe(
|
|
92652
|
-
return await this.run("SUBSCRIBE",
|
|
93086
|
+
async mailboxSubscribe(path27) {
|
|
93087
|
+
return await this.run("SUBSCRIBE", path27);
|
|
92653
93088
|
}
|
|
92654
93089
|
/**
|
|
92655
93090
|
* Unsubscribes from a mailbox
|
|
@@ -92660,8 +93095,8 @@ var require_imap_flow = __commonJS({
|
|
|
92660
93095
|
* @example
|
|
92661
93096
|
* await client.mailboxUnsubscribe('Important stuff ❗️');
|
|
92662
93097
|
*/
|
|
92663
|
-
async mailboxUnsubscribe(
|
|
92664
|
-
return await this.run("UNSUBSCRIBE",
|
|
93098
|
+
async mailboxUnsubscribe(path27) {
|
|
93099
|
+
return await this.run("UNSUBSCRIBE", path27);
|
|
92665
93100
|
}
|
|
92666
93101
|
/**
|
|
92667
93102
|
* Opens a mailbox to access messages. You can perform message operations only against an opened mailbox.
|
|
@@ -92679,8 +93114,8 @@ var require_imap_flow = __commonJS({
|
|
|
92679
93114
|
* console.log(mailbox.exists);
|
|
92680
93115
|
* // 125
|
|
92681
93116
|
*/
|
|
92682
|
-
async mailboxOpen(
|
|
92683
|
-
return await this.run("SELECT",
|
|
93117
|
+
async mailboxOpen(path27, options) {
|
|
93118
|
+
return await this.run("SELECT", path27, options);
|
|
92684
93119
|
}
|
|
92685
93120
|
/**
|
|
92686
93121
|
* Closes a previously opened mailbox
|
|
@@ -92727,8 +93162,8 @@ var require_imap_flow = __commonJS({
|
|
|
92727
93162
|
* console.log(status.unseen);
|
|
92728
93163
|
* // 123
|
|
92729
93164
|
*/
|
|
92730
|
-
async status(
|
|
92731
|
-
return await this.run("STATUS",
|
|
93165
|
+
async status(path27, query) {
|
|
93166
|
+
return await this.run("STATUS", path27, query);
|
|
92732
93167
|
}
|
|
92733
93168
|
/**
|
|
92734
93169
|
* Starts listening for new or deleted messages from the currently opened mailbox. Only required if {@link ImapFlow#disableAutoIdle} is set to `true`
|
|
@@ -92982,8 +93417,8 @@ var require_imap_flow = __commonJS({
|
|
|
92982
93417
|
* @example
|
|
92983
93418
|
* await client.append('INBOX', rawMessageBuffer, ['\\Seen'], new Date(2000, 1, 1));
|
|
92984
93419
|
*/
|
|
92985
|
-
async append(
|
|
92986
|
-
return await this.run("APPEND",
|
|
93420
|
+
async append(path27, content, flags, idate) {
|
|
93421
|
+
return await this.run("APPEND", path27, content, flags, idate) || false;
|
|
92987
93422
|
}
|
|
92988
93423
|
/**
|
|
92989
93424
|
* @typedef {Object} CopyResponseObject
|
|
@@ -93827,7 +94262,7 @@ var require_imap_flow = __commonJS({
|
|
|
93827
94262
|
await new Promise((resolve2) => setImmediate(resolve2));
|
|
93828
94263
|
}
|
|
93829
94264
|
const lock = this.locks.shift();
|
|
93830
|
-
const { resolve, reject, path:
|
|
94265
|
+
const { resolve, reject, path: path27, options, lockId } = lock;
|
|
93831
94266
|
if (lock.acquireTimer) {
|
|
93832
94267
|
clearTimeout(lock.acquireTimer);
|
|
93833
94268
|
lock.acquireTimer = null;
|
|
@@ -93843,7 +94278,7 @@ var require_imap_flow = __commonJS({
|
|
|
93843
94278
|
this.log.warn({
|
|
93844
94279
|
msg: "Mailbox lock held for a long time",
|
|
93845
94280
|
lockId: lock.lockId,
|
|
93846
|
-
path:
|
|
94281
|
+
path: path27,
|
|
93847
94282
|
heldFor: Date.now() - lock.heldAt,
|
|
93848
94283
|
/* c8 ignore next */
|
|
93849
94284
|
// the held-lock-warning diagnostic with a description set is a timing-dependent log detail
|
|
@@ -93879,52 +94314,52 @@ var require_imap_flow = __commonJS({
|
|
|
93879
94314
|
}
|
|
93880
94315
|
};
|
|
93881
94316
|
if (!this.usable || !this.socket || this.socket.destroyed) {
|
|
93882
|
-
this.log.trace({ msg: "Failed to acquire mailbox lock", path:
|
|
94317
|
+
this.log.trace({ msg: "Failed to acquire mailbox lock", path: path27, lockId, idling: this.idling });
|
|
93883
94318
|
let error2 = new Error("Connection not available");
|
|
93884
94319
|
error2.code = "NoConnection";
|
|
93885
94320
|
reject(error2);
|
|
93886
94321
|
continue;
|
|
93887
94322
|
}
|
|
93888
|
-
if (this.mailbox && this.mailbox.path ===
|
|
94323
|
+
if (this.mailbox && this.mailbox.path === path27 && !!this.mailbox.readOnly === !!options.readOnly) {
|
|
93889
94324
|
this.log.trace({
|
|
93890
94325
|
msg: "Mailbox lock acquired [existing]",
|
|
93891
|
-
path:
|
|
94326
|
+
path: path27,
|
|
93892
94327
|
lockId,
|
|
93893
94328
|
idling: this.idling,
|
|
93894
94329
|
...options.description && { description: options.description }
|
|
93895
94330
|
});
|
|
93896
94331
|
this.currentLock = lock;
|
|
93897
94332
|
armHeldTimer();
|
|
93898
|
-
resolve({ path:
|
|
94333
|
+
resolve({ path: path27, release });
|
|
93899
94334
|
break;
|
|
93900
94335
|
}
|
|
93901
94336
|
try {
|
|
93902
|
-
await this.mailboxOpen(
|
|
94337
|
+
await this.mailboxOpen(path27, options);
|
|
93903
94338
|
this.log.trace({
|
|
93904
94339
|
msg: "Mailbox lock acquired [selected]",
|
|
93905
|
-
path:
|
|
94340
|
+
path: path27,
|
|
93906
94341
|
lockId,
|
|
93907
94342
|
idling: this.idling,
|
|
93908
94343
|
...options.description && { description: options.description }
|
|
93909
94344
|
});
|
|
93910
94345
|
this.currentLock = lock;
|
|
93911
94346
|
armHeldTimer();
|
|
93912
|
-
resolve({ path:
|
|
94347
|
+
resolve({ path: path27, release });
|
|
93913
94348
|
break;
|
|
93914
94349
|
} catch (err) {
|
|
93915
94350
|
if (err.responseStatus === "NO") {
|
|
93916
94351
|
try {
|
|
93917
|
-
let folders = await this.run("LIST", "",
|
|
94352
|
+
let folders = await this.run("LIST", "", path27, { listOnly: true });
|
|
93918
94353
|
if (!folders || !folders.length) {
|
|
93919
94354
|
err.mailboxMissing = true;
|
|
93920
94355
|
}
|
|
93921
94356
|
} catch (E) {
|
|
93922
|
-
this.log.trace({ msg: "Failed to verify failed mailbox", path:
|
|
94357
|
+
this.log.trace({ msg: "Failed to verify failed mailbox", path: path27, err: E });
|
|
93923
94358
|
}
|
|
93924
94359
|
}
|
|
93925
94360
|
this.log.trace({
|
|
93926
94361
|
msg: "Failed to acquire mailbox lock",
|
|
93927
|
-
path:
|
|
94362
|
+
path: path27,
|
|
93928
94363
|
lockId,
|
|
93929
94364
|
idling: this.idling,
|
|
93930
94365
|
...options.description && { description: options.description },
|
|
@@ -93963,13 +94398,13 @@ var require_imap_flow = __commonJS({
|
|
|
93963
94398
|
* lock.release();
|
|
93964
94399
|
* }
|
|
93965
94400
|
*/
|
|
93966
|
-
getMailboxLock(
|
|
94401
|
+
getMailboxLock(path27, options) {
|
|
93967
94402
|
options = options || {};
|
|
93968
|
-
|
|
94403
|
+
path27 = normalizePath(this, path27);
|
|
93969
94404
|
let lockId = ++this.lockCounter;
|
|
93970
94405
|
this.log.trace({
|
|
93971
94406
|
msg: "Requesting lock",
|
|
93972
|
-
path:
|
|
94407
|
+
path: path27,
|
|
93973
94408
|
lockId,
|
|
93974
94409
|
...options.description && { description: options.description },
|
|
93975
94410
|
activeLock: this.currentLock ? {
|
|
@@ -93978,7 +94413,7 @@ var require_imap_flow = __commonJS({
|
|
|
93978
94413
|
} : null
|
|
93979
94414
|
});
|
|
93980
94415
|
let lockPromise = new Promise((resolve, reject) => {
|
|
93981
|
-
let lockEntry = { resolve, reject, path:
|
|
94416
|
+
let lockEntry = { resolve, reject, path: path27, options, lockId };
|
|
93982
94417
|
this.locks.push(lockEntry);
|
|
93983
94418
|
if (Number(options.acquireTimeout) > 0) {
|
|
93984
94419
|
lockEntry.acquireTimer = setTimeout(() => {
|
|
@@ -94067,16 +94502,16 @@ var require_imap_flow = __commonJS({
|
|
|
94067
94502
|
});
|
|
94068
94503
|
|
|
94069
94504
|
// src/mail/mail-fetcher.ts
|
|
94070
|
-
import
|
|
94071
|
-
import
|
|
94505
|
+
import fs24 from "node:fs/promises";
|
|
94506
|
+
import path25 from "node:path";
|
|
94072
94507
|
async function saveAttachments(attachments, downloadDir) {
|
|
94073
94508
|
if (attachments.length === 0) return [];
|
|
94074
|
-
await
|
|
94509
|
+
await fs24.mkdir(downloadDir, { recursive: true });
|
|
94075
94510
|
const saved = [];
|
|
94076
94511
|
for (const a of attachments) {
|
|
94077
|
-
const name =
|
|
94078
|
-
const savedPath =
|
|
94079
|
-
await
|
|
94512
|
+
const name = path25.basename(a.filename) || "attachment";
|
|
94513
|
+
const savedPath = path25.join(downloadDir, name);
|
|
94514
|
+
await fs24.writeFile(savedPath, a.content);
|
|
94080
94515
|
saved.push({ filename: name, savedPath, size: a.content.length });
|
|
94081
94516
|
}
|
|
94082
94517
|
return saved;
|
|
@@ -94207,7 +94642,7 @@ var init_mail_fetcher = __esm({
|
|
|
94207
94642
|
|
|
94208
94643
|
// src/tools/fetch-mail.ts
|
|
94209
94644
|
import os17 from "node:os";
|
|
94210
|
-
import
|
|
94645
|
+
import path26 from "node:path";
|
|
94211
94646
|
function registerFetchMailTool(server, deps = {}) {
|
|
94212
94647
|
const makeFetcher = deps.fetcherFactory ?? ((creds) => new ImapflowMailFetcher(creds));
|
|
94213
94648
|
server.registerTool(
|
|
@@ -94269,7 +94704,7 @@ var init_fetch_mail = __esm({
|
|
|
94269
94704
|
init_mail_fetcher();
|
|
94270
94705
|
init_auth_error();
|
|
94271
94706
|
init_validate();
|
|
94272
|
-
DEFAULT_DOWNLOAD_DIR =
|
|
94707
|
+
DEFAULT_DOWNLOAD_DIR = path26.join(os17.homedir(), ".cogent", "mail-downloads");
|
|
94273
94708
|
}
|
|
94274
94709
|
});
|
|
94275
94710
|
|
|
@@ -94360,9 +94795,74 @@ var init_rotate_mail_creds = __esm({
|
|
|
94360
94795
|
|
|
94361
94796
|
// src/index.ts
|
|
94362
94797
|
var index_exports = {};
|
|
94798
|
+
function shutdown(reason) {
|
|
94799
|
+
if (shuttingDown) return;
|
|
94800
|
+
shuttingDown = true;
|
|
94801
|
+
try {
|
|
94802
|
+
logger.info(`Shutting down: ${reason}`);
|
|
94803
|
+
autoRelay.stop();
|
|
94804
|
+
withdrawBridge(process.cwd(), PROCESS_MARK);
|
|
94805
|
+
heartbeat.stop();
|
|
94806
|
+
if (cloudWsClient) {
|
|
94807
|
+
cloudWsClient.disconnect();
|
|
94808
|
+
}
|
|
94809
|
+
logger.close();
|
|
94810
|
+
} finally {
|
|
94811
|
+
process.exit(0);
|
|
94812
|
+
}
|
|
94813
|
+
}
|
|
94814
|
+
async function clientGone(reason) {
|
|
94815
|
+
if (draining || shuttingDown) return;
|
|
94816
|
+
draining = true;
|
|
94817
|
+
autoRelay.announceDraining();
|
|
94818
|
+
const busy = () => {
|
|
94819
|
+
const d = autoRelay.getDiagnostics();
|
|
94820
|
+
return { requests: stdoutDead ? [] : [...inFlightRequests.values()], wake: d.processing, queued: d.queueLength };
|
|
94821
|
+
};
|
|
94822
|
+
const b0 = busy();
|
|
94823
|
+
if (!b0.requests.length && !b0.wake && !b0.queued) return shutdown(reason);
|
|
94824
|
+
let capMs = drainCapMs(3e5);
|
|
94825
|
+
try {
|
|
94826
|
+
capMs = drainCapMs(getConfig().COGENT_TIMEOUT_MS);
|
|
94827
|
+
} catch {
|
|
94828
|
+
}
|
|
94829
|
+
logger.info(
|
|
94830
|
+
`Client gone (${reason}) \u2014 draining before exit (cap ${Math.round(capMs / 1e3)}s): ${b0.requests.length} MCP request(s) [${b0.requests.join(", ")}], wake running: ${b0.wake}, queued: ${b0.queued}`
|
|
94831
|
+
);
|
|
94832
|
+
cancelPresenceRetry();
|
|
94833
|
+
heartbeat.stop();
|
|
94834
|
+
cloudWsClient?.disconnect();
|
|
94835
|
+
const t0 = Date.now();
|
|
94836
|
+
let b = b0;
|
|
94837
|
+
while (Date.now() - t0 < capMs) {
|
|
94838
|
+
b = busy();
|
|
94839
|
+
if (!b.requests.length && !b.wake && !b.queued) break;
|
|
94840
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
94841
|
+
}
|
|
94842
|
+
if (!stdoutDead) {
|
|
94843
|
+
await new Promise((r) => {
|
|
94844
|
+
const t = setTimeout(r, 1e3);
|
|
94845
|
+
try {
|
|
94846
|
+
process.stdout.write("", () => {
|
|
94847
|
+
clearTimeout(t);
|
|
94848
|
+
r();
|
|
94849
|
+
});
|
|
94850
|
+
} catch {
|
|
94851
|
+
clearTimeout(t);
|
|
94852
|
+
r();
|
|
94853
|
+
}
|
|
94854
|
+
});
|
|
94855
|
+
}
|
|
94856
|
+
const left = b.requests.length || b.wake || b.queued;
|
|
94857
|
+
const undeliverable = stdoutDead && inFlightRequests.size ? ` (${inFlightRequests.size} MCP response(s) undeliverable: stdout closed)` : "";
|
|
94858
|
+
shutdown(
|
|
94859
|
+
left ? `${reason}; drain cap reached after ${Date.now() - t0}ms \u2014 ABANDONED ${b.requests.length} MCP request(s) [${b.requests.join(", ")}], wake running: ${b.wake}, queued: ${b.queued}${undeliverable}` : `${reason}; drained in ${Date.now() - t0}ms (${b0.requests.length} MCP request(s), wake: ${b0.wake}, queued: ${b0.queued})${undeliverable}`
|
|
94860
|
+
);
|
|
94861
|
+
}
|
|
94363
94862
|
async function main() {
|
|
94863
|
+
markBridgeProcess(process.cwd(), SERVER_VERSION);
|
|
94364
94864
|
await runStartup();
|
|
94365
|
-
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
94865
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
94366
94866
|
registerRegisterPeerTool(server);
|
|
94367
94867
|
registerDeregisterPeerTool(server);
|
|
94368
94868
|
registerSendMessageTool(server);
|
|
@@ -94407,7 +94907,31 @@ async function main() {
|
|
|
94407
94907
|
});
|
|
94408
94908
|
}
|
|
94409
94909
|
const transport = new StdioServerTransport();
|
|
94910
|
+
transport.onclose = () => void clientGone("MCP transport closed");
|
|
94410
94911
|
await server.connect(transport);
|
|
94912
|
+
const sdkOnMessage = transport.onmessage;
|
|
94913
|
+
transport.onmessage = (msg) => {
|
|
94914
|
+
if ("method" in msg && "id" in msg) {
|
|
94915
|
+
const tool = msg.method === "tools/call" ? msg.params?.name : void 0;
|
|
94916
|
+
inFlightRequests.set(msg.id, typeof tool === "string" ? `tools/call ${tool}` : msg.method);
|
|
94917
|
+
} else if ("method" in msg && msg.method === "notifications/cancelled") {
|
|
94918
|
+
const id = msg.params?.requestId;
|
|
94919
|
+
if (typeof id === "string" || typeof id === "number") inFlightRequests.delete(id);
|
|
94920
|
+
}
|
|
94921
|
+
sdkOnMessage?.(msg);
|
|
94922
|
+
};
|
|
94923
|
+
const sdkSend = transport.send.bind(transport);
|
|
94924
|
+
transport.send = (msg) => {
|
|
94925
|
+
const settles = !("method" in msg) && "id" in msg ? msg.id : void 0;
|
|
94926
|
+
return sdkSend(msg).finally(() => {
|
|
94927
|
+
if (settles !== void 0) inFlightRequests.delete(settles);
|
|
94928
|
+
});
|
|
94929
|
+
};
|
|
94930
|
+
const stdinIsDevice = startedWithoutClient();
|
|
94931
|
+
if (!process.stdin.isTTY && !stdinIsDevice) {
|
|
94932
|
+
process.stdin.once("end", () => void clientGone("stdin EOF \u2014 the MCP client is gone"));
|
|
94933
|
+
process.stdin.once("close", () => void clientGone("stdin closed \u2014 the MCP client is gone"));
|
|
94934
|
+
}
|
|
94411
94935
|
process.stderr.write(
|
|
94412
94936
|
`${SERVER_NAME} v${SERVER_VERSION} running on stdio
|
|
94413
94937
|
`
|
|
@@ -94432,14 +94956,17 @@ async function main() {
|
|
|
94432
94956
|
"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"
|
|
94433
94957
|
);
|
|
94434
94958
|
}
|
|
94959
|
+
var shuttingDown, draining, stdoutDead, inFlightRequests;
|
|
94435
94960
|
var init_index = __esm({
|
|
94436
94961
|
"src/index.ts"() {
|
|
94437
94962
|
"use strict";
|
|
94438
94963
|
init_mcp();
|
|
94439
94964
|
init_stdio2();
|
|
94440
94965
|
init_constants();
|
|
94966
|
+
init_instructions();
|
|
94441
94967
|
init_npm_update_check();
|
|
94442
94968
|
init_startup();
|
|
94969
|
+
init_config();
|
|
94443
94970
|
init_logger();
|
|
94444
94971
|
init_register_peer();
|
|
94445
94972
|
init_send_message();
|
|
@@ -94455,10 +94982,12 @@ var init_index = __esm({
|
|
|
94455
94982
|
init_fetch_mail();
|
|
94456
94983
|
init_rotate_mail_creds();
|
|
94457
94984
|
init_heartbeat();
|
|
94985
|
+
init_wake_inflight();
|
|
94986
|
+
init_wake_ownership();
|
|
94458
94987
|
process.on("uncaughtException", (err) => {
|
|
94459
94988
|
if (err.code === "EPIPE") {
|
|
94460
|
-
|
|
94461
|
-
|
|
94989
|
+
stdoutDead = true;
|
|
94990
|
+
void clientGone("stdout EPIPE \u2014 the MCP client is gone");
|
|
94462
94991
|
return;
|
|
94463
94992
|
}
|
|
94464
94993
|
logger.error(`Uncaught exception: ${err.message}`, { stack: err.stack });
|
|
@@ -94467,26 +94996,12 @@ var init_index = __esm({
|
|
|
94467
94996
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
94468
94997
|
logger.error(`Unhandled rejection: ${msg}`);
|
|
94469
94998
|
});
|
|
94470
|
-
|
|
94471
|
-
|
|
94472
|
-
|
|
94473
|
-
|
|
94474
|
-
|
|
94475
|
-
|
|
94476
|
-
}
|
|
94477
|
-
logger.close();
|
|
94478
|
-
process.exit(0);
|
|
94479
|
-
});
|
|
94480
|
-
process.on("SIGINT", () => {
|
|
94481
|
-
logger.info("SIGINT received, shutting down");
|
|
94482
|
-
autoRelay.stop();
|
|
94483
|
-
heartbeat.stop();
|
|
94484
|
-
if (cloudWsClient) {
|
|
94485
|
-
cloudWsClient.disconnect();
|
|
94486
|
-
}
|
|
94487
|
-
logger.close();
|
|
94488
|
-
process.exit(0);
|
|
94489
|
-
});
|
|
94999
|
+
shuttingDown = false;
|
|
95000
|
+
draining = false;
|
|
95001
|
+
stdoutDead = false;
|
|
95002
|
+
process.on("SIGTERM", () => shutdown("SIGTERM received"));
|
|
95003
|
+
process.on("SIGINT", () => shutdown("SIGINT received"));
|
|
95004
|
+
inFlightRequests = /* @__PURE__ */ new Map();
|
|
94490
95005
|
main().catch((err) => {
|
|
94491
95006
|
const msg = err instanceof Error ? err.message : String(err);
|
|
94492
95007
|
logger.error(`Fatal startup error: ${msg}`);
|