@essentialai/cogent-plugin 3.25.6 → 3.25.7
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 +861 -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.7") {
|
|
26416
|
+
return "3.25.7";
|
|
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,6 +26831,7 @@ 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";
|
|
26807
26836
|
return BridgeErrorCode2;
|
|
26808
26837
|
})(BridgeErrorCode || {});
|
|
@@ -27857,7 +27886,7 @@ var init_http_backend = __esm({
|
|
|
27857
27886
|
* in cloud mode we ignore it and use this.sessionId (the cloud session).
|
|
27858
27887
|
*/
|
|
27859
27888
|
async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId, peerSecret) {
|
|
27860
|
-
const
|
|
27889
|
+
const path27 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27861
27890
|
const body = {
|
|
27862
27891
|
peerId,
|
|
27863
27892
|
cwd,
|
|
@@ -27888,7 +27917,7 @@ var init_http_backend = __esm({
|
|
|
27888
27917
|
if (peerSecret !== void 0 && await relaySupports(this.http, "peer-ownership")) {
|
|
27889
27918
|
body.peerSecret = peerSecret;
|
|
27890
27919
|
}
|
|
27891
|
-
const peer = await this.http.post(
|
|
27920
|
+
const peer = await this.http.post(path27, body);
|
|
27892
27921
|
const issued = peer?.peerSecret;
|
|
27893
27922
|
if (issued) {
|
|
27894
27923
|
try {
|
|
@@ -27908,9 +27937,9 @@ var init_http_backend = __esm({
|
|
|
27908
27937
|
* local mail creds. A 404 (peer not found) resolves to `{ removed: false, ... }`, not a throw.
|
|
27909
27938
|
*/
|
|
27910
27939
|
async deregisterPeer(peerId, peerSecret) {
|
|
27911
|
-
const
|
|
27940
|
+
const path27 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
|
|
27912
27941
|
try {
|
|
27913
|
-
const headers = await this.http.delete(
|
|
27942
|
+
const headers = await this.http.delete(path27, peerSecret ? { peerSecret } : {});
|
|
27914
27943
|
const mailboxDeprovisioned = headers.get(MAILBOX_DEPROVISIONED_HEADER) === "true";
|
|
27915
27944
|
return { removed: true, mailboxDeprovisioned };
|
|
27916
27945
|
} catch (err) {
|
|
@@ -27934,8 +27963,8 @@ var init_http_backend = __esm({
|
|
|
27934
27963
|
* GET /api/sessions/:sessionId/peers
|
|
27935
27964
|
*/
|
|
27936
27965
|
async listPeers() {
|
|
27937
|
-
const
|
|
27938
|
-
const result = await this.http.get(
|
|
27966
|
+
const path27 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27967
|
+
const result = await this.http.get(path27);
|
|
27939
27968
|
return result.peers;
|
|
27940
27969
|
}
|
|
27941
27970
|
/**
|
|
@@ -27943,8 +27972,8 @@ var init_http_backend = __esm({
|
|
|
27943
27972
|
* Calls the lightweight heartbeat endpoint on the cloud relay server.
|
|
27944
27973
|
*/
|
|
27945
27974
|
async updateLastSeen(peerId) {
|
|
27946
|
-
const
|
|
27947
|
-
await this.http.post(
|
|
27975
|
+
const path27 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
|
|
27976
|
+
await this.http.post(path27, { peerId });
|
|
27948
27977
|
}
|
|
27949
27978
|
/**
|
|
27950
27979
|
* Record a message in the cloud session.
|
|
@@ -27955,7 +27984,7 @@ var init_http_backend = __esm({
|
|
|
27955
27984
|
* the input record to construct a full MessageRecord.
|
|
27956
27985
|
*/
|
|
27957
27986
|
async recordMessage(record2) {
|
|
27958
|
-
const
|
|
27987
|
+
const path27 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27959
27988
|
const body = {
|
|
27960
27989
|
fromPeerId: record2.fromPeerId,
|
|
27961
27990
|
toPeerId: record2.toPeerId,
|
|
@@ -27981,7 +28010,7 @@ var init_http_backend = __esm({
|
|
|
27981
28010
|
if (record2.replyExpected === false && await relaySupports(this.http, "terminal-messages")) {
|
|
27982
28011
|
body.replyExpected = false;
|
|
27983
28012
|
}
|
|
27984
|
-
const resp = await this.http.post(
|
|
28013
|
+
const resp = await this.http.post(path27, body);
|
|
27985
28014
|
return {
|
|
27986
28015
|
...record2,
|
|
27987
28016
|
id: resp.id,
|
|
@@ -27995,7 +28024,7 @@ var init_http_backend = __esm({
|
|
|
27995
28024
|
* Supports optional peerId filter and limit (default 300).
|
|
27996
28025
|
*/
|
|
27997
28026
|
async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
|
|
27998
|
-
const
|
|
28027
|
+
const path27 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27999
28028
|
const query = {};
|
|
28000
28029
|
if (peerId) {
|
|
28001
28030
|
query.peerId = peerId;
|
|
@@ -28010,7 +28039,7 @@ var init_http_backend = __esm({
|
|
|
28010
28039
|
if (dedupInferredEchoes) {
|
|
28011
28040
|
query.dedupInferredEchoes = "true";
|
|
28012
28041
|
}
|
|
28013
|
-
const result = await this.http.get(
|
|
28042
|
+
const result = await this.http.get(path27, query);
|
|
28014
28043
|
return result.messages;
|
|
28015
28044
|
}
|
|
28016
28045
|
/**
|
|
@@ -28021,12 +28050,12 @@ var init_http_backend = __esm({
|
|
|
28021
28050
|
* so that get-history shows the actual response (not null).
|
|
28022
28051
|
*/
|
|
28023
28052
|
async updateMessageResponse(messageId, response, durationMs, pending) {
|
|
28024
|
-
const
|
|
28053
|
+
const path27 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
|
|
28025
28054
|
const body = { response, durationMs };
|
|
28026
28055
|
if (pending === true) {
|
|
28027
28056
|
body.pending = true;
|
|
28028
28057
|
}
|
|
28029
|
-
await this.http.patch(
|
|
28058
|
+
await this.http.patch(path27, body);
|
|
28030
28059
|
}
|
|
28031
28060
|
/**
|
|
28032
28061
|
* Validate a session.
|
|
@@ -28200,8 +28229,8 @@ var init_http_client = __esm({
|
|
|
28200
28229
|
* Perform an authenticated GET request.
|
|
28201
28230
|
* Appends query parameters to the URL if provided.
|
|
28202
28231
|
*/
|
|
28203
|
-
async get(
|
|
28204
|
-
const url = new URL(
|
|
28232
|
+
async get(path27, query) {
|
|
28233
|
+
const url = new URL(path27, this.baseUrl);
|
|
28205
28234
|
if (query) {
|
|
28206
28235
|
for (const [k, v] of Object.entries(query)) {
|
|
28207
28236
|
url.searchParams.set(k, v);
|
|
@@ -28216,8 +28245,8 @@ var init_http_client = __esm({
|
|
|
28216
28245
|
/**
|
|
28217
28246
|
* Perform an authenticated POST request with a JSON body.
|
|
28218
28247
|
*/
|
|
28219
|
-
async post(
|
|
28220
|
-
const url = new URL(
|
|
28248
|
+
async post(path27, body) {
|
|
28249
|
+
const url = new URL(path27, this.baseUrl);
|
|
28221
28250
|
const resp = await this.fetchWithTimeout(url, {
|
|
28222
28251
|
method: "POST",
|
|
28223
28252
|
headers: this.headers(),
|
|
@@ -28235,8 +28264,8 @@ var init_http_client = __esm({
|
|
|
28235
28264
|
* Perform an authenticated PATCH request with a JSON body.
|
|
28236
28265
|
* Used to update existing resources (e.g., message response fields).
|
|
28237
28266
|
*/
|
|
28238
|
-
async patch(
|
|
28239
|
-
const url = new URL(
|
|
28267
|
+
async patch(path27, body) {
|
|
28268
|
+
const url = new URL(path27, this.baseUrl);
|
|
28240
28269
|
const resp = await this.fetchWithTimeout(url, {
|
|
28241
28270
|
method: "PATCH",
|
|
28242
28271
|
headers: this.headers(),
|
|
@@ -28261,8 +28290,8 @@ var init_http_client = __esm({
|
|
|
28261
28290
|
* "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
|
|
28262
28291
|
* any client (including third-party tools) DELETEd a peer without a body.
|
|
28263
28292
|
*/
|
|
28264
|
-
async delete(
|
|
28265
|
-
const url = new URL(
|
|
28293
|
+
async delete(path27, body) {
|
|
28294
|
+
const url = new URL(path27, this.baseUrl);
|
|
28266
28295
|
const headers = {
|
|
28267
28296
|
"Authorization": `Bearer ${this.token}`
|
|
28268
28297
|
};
|
|
@@ -32563,14 +32592,14 @@ var init_ws_client = __esm({
|
|
|
32563
32592
|
this.restoreCursor();
|
|
32564
32593
|
const poll = async () => {
|
|
32565
32594
|
try {
|
|
32566
|
-
const
|
|
32595
|
+
const path27 = `/api/sessions/${this.opts.sessionId}/poll`;
|
|
32567
32596
|
const query = {
|
|
32568
32597
|
peerId: this.opts.peerId
|
|
32569
32598
|
};
|
|
32570
32599
|
if (this.lastMessageId) {
|
|
32571
32600
|
query.lastMessageId = this.lastMessageId;
|
|
32572
32601
|
}
|
|
32573
|
-
const result = await this.opts.http.get(
|
|
32602
|
+
const result = await this.opts.http.get(path27, query);
|
|
32574
32603
|
if (result.messages && result.messages.length > 0) {
|
|
32575
32604
|
this.opts.onMessages(result.messages);
|
|
32576
32605
|
this.advanceCursor(result.messages[result.messages.length - 1].id);
|
|
@@ -33487,6 +33516,10 @@ import crypto5 from "node:crypto";
|
|
|
33487
33516
|
import fs15 from "node:fs";
|
|
33488
33517
|
import os11 from "node:os";
|
|
33489
33518
|
import path16 from "node:path";
|
|
33519
|
+
function drainCapMs(timeoutMs) {
|
|
33520
|
+
const t = Number.isFinite(timeoutMs) && timeoutMs > 0 ? timeoutMs : 3e5;
|
|
33521
|
+
return Math.min(INFLIGHT_TIMEOUT_FACTOR * t, INFLIGHT_MAX_MS);
|
|
33522
|
+
}
|
|
33490
33523
|
function hashCwd3(cwd) {
|
|
33491
33524
|
return crypto5.createHash("sha256").update(path16.resolve(cwd)).digest("hex").slice(0, 16);
|
|
33492
33525
|
}
|
|
@@ -33813,12 +33846,36 @@ import crypto8 from "node:crypto";
|
|
|
33813
33846
|
import fs18 from "node:fs";
|
|
33814
33847
|
import os14 from "node:os";
|
|
33815
33848
|
import path19 from "node:path";
|
|
33849
|
+
function agentSessionId(env = process.env) {
|
|
33850
|
+
if (env.COGENT_PLATFORM && env.COGENT_PLATFORM !== "cc") return void 0;
|
|
33851
|
+
const id = env.CLAUDE_CODE_SESSION_ID?.trim();
|
|
33852
|
+
return id && id.length <= 128 ? id : void 0;
|
|
33853
|
+
}
|
|
33854
|
+
function startedWithoutClient() {
|
|
33855
|
+
if (withoutClient === void 0) {
|
|
33856
|
+
try {
|
|
33857
|
+
withoutClient = fs18.fstatSync(0).isCharacterDevice();
|
|
33858
|
+
} catch {
|
|
33859
|
+
withoutClient = false;
|
|
33860
|
+
}
|
|
33861
|
+
}
|
|
33862
|
+
return withoutClient;
|
|
33863
|
+
}
|
|
33816
33864
|
function hashCwd6(cwd) {
|
|
33817
33865
|
return crypto8.createHash("sha256").update(path19.resolve(cwd)).digest("hex").slice(0, 16);
|
|
33818
33866
|
}
|
|
33819
33867
|
function bridgeDirFor(cwd, peerId) {
|
|
33820
33868
|
return path19.join(os14.homedir(), ".cogent", "bridges", `${hashCwd6(cwd)}.${safe4(peerId)}`);
|
|
33821
33869
|
}
|
|
33870
|
+
function isReservedPeerName(peerId) {
|
|
33871
|
+
return safe4(peerId).toLowerCase() === safe4(PROCESS_MARK).toLowerCase();
|
|
33872
|
+
}
|
|
33873
|
+
function registryText(value) {
|
|
33874
|
+
return String(value ?? "").replace(/[^A-Za-z0-9._-]/g, "").slice(0, 64) || "unreadable";
|
|
33875
|
+
}
|
|
33876
|
+
function registryOwnerLabel(o) {
|
|
33877
|
+
return `pid ${registryText(o.pid)} (v${registryText(o.version)}, ${JSON.stringify(String(o.endpoint ?? "").slice(0, 200))})`;
|
|
33878
|
+
}
|
|
33822
33879
|
function pidAlive(pid) {
|
|
33823
33880
|
if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0) return false;
|
|
33824
33881
|
if (pid === process.pid) return true;
|
|
@@ -33829,7 +33886,7 @@ function pidAlive(pid) {
|
|
|
33829
33886
|
return err?.code === "EPERM";
|
|
33830
33887
|
}
|
|
33831
33888
|
}
|
|
33832
|
-
function announceBridge(cwd, peerId, version2, endpoint) {
|
|
33889
|
+
function announceBridge(cwd, peerId, version2, endpoint, sessionId = agentSessionId()) {
|
|
33833
33890
|
const dir = bridgeDirFor(cwd, peerId);
|
|
33834
33891
|
try {
|
|
33835
33892
|
fs18.mkdirSync(dir, { recursive: true });
|
|
@@ -33839,13 +33896,30 @@ function announceBridge(cwd, peerId, version2, endpoint) {
|
|
|
33839
33896
|
version: version2,
|
|
33840
33897
|
peerId,
|
|
33841
33898
|
endpoint,
|
|
33842
|
-
cwd: path19.resolve(cwd)
|
|
33899
|
+
cwd: path19.resolve(cwd),
|
|
33900
|
+
parentPid: process.ppid,
|
|
33901
|
+
...sessionId ? { sessionId } : {},
|
|
33902
|
+
// 🔴 A headless bridge never had a client to lose (review r7 FIX2-2, SEC2-2): when its launching
|
|
33903
|
+
// shell exited, the changed parent read as "client gone" and any bridge that started took its name.
|
|
33904
|
+
...startedWithoutClient() ? { noClient: true } : {}
|
|
33843
33905
|
};
|
|
33844
33906
|
fs18.writeFileSync(path19.join(dir, `${process.pid}.json`), JSON.stringify(entry));
|
|
33845
33907
|
} catch (err) {
|
|
33846
33908
|
logger.debug(`wake-ownership: could not announce this bridge (${err.message})`);
|
|
33847
33909
|
}
|
|
33848
33910
|
}
|
|
33911
|
+
function markBridgeDraining(cwd, peerId) {
|
|
33912
|
+
const file = path19.join(bridgeDirFor(cwd, peerId), `${process.pid}.json`);
|
|
33913
|
+
try {
|
|
33914
|
+
const entry = JSON.parse(fs18.readFileSync(file, "utf-8"));
|
|
33915
|
+
fs18.writeFileSync(file, JSON.stringify({ ...entry, draining: true }));
|
|
33916
|
+
} catch {
|
|
33917
|
+
}
|
|
33918
|
+
}
|
|
33919
|
+
function markBridgeProcess(cwd, version2) {
|
|
33920
|
+
listLiveBridges(cwd, PROCESS_MARK);
|
|
33921
|
+
announceBridge(cwd, PROCESS_MARK, version2, "");
|
|
33922
|
+
}
|
|
33849
33923
|
function withdrawBridge(cwd, peerId) {
|
|
33850
33924
|
try {
|
|
33851
33925
|
fs18.unlinkSync(path19.join(bridgeDirFor(cwd, peerId), `${process.pid}.json`));
|
|
@@ -33882,6 +33956,16 @@ function listLiveBridges(cwd, peerId) {
|
|
|
33882
33956
|
live.sort((a, b) => b.startedAt - a.startedAt || b.pid - a.pid);
|
|
33883
33957
|
return live;
|
|
33884
33958
|
}
|
|
33959
|
+
function listLiveBridgesInFolder(cwd) {
|
|
33960
|
+
const prefix = `${hashCwd6(cwd)}.`;
|
|
33961
|
+
let dirs;
|
|
33962
|
+
try {
|
|
33963
|
+
dirs = fs18.readdirSync(path19.join(os14.homedir(), ".cogent", "bridges"));
|
|
33964
|
+
} catch {
|
|
33965
|
+
return [];
|
|
33966
|
+
}
|
|
33967
|
+
return dirs.filter((d) => d.startsWith(prefix)).flatMap((d) => listLiveBridges(cwd, d.slice(prefix.length)));
|
|
33968
|
+
}
|
|
33885
33969
|
function checkWakeOwnership(cwd, peerId) {
|
|
33886
33970
|
let live;
|
|
33887
33971
|
try {
|
|
@@ -33902,13 +33986,14 @@ function checkWakeOwnership(cwd, peerId) {
|
|
|
33902
33986
|
}
|
|
33903
33987
|
return { isOwner: true, liveCount: live.length + 1 };
|
|
33904
33988
|
}
|
|
33905
|
-
var PROCESS_STARTED_AT, safe4;
|
|
33989
|
+
var PROCESS_STARTED_AT, withoutClient, safe4, PROCESS_MARK;
|
|
33906
33990
|
var init_wake_ownership = __esm({
|
|
33907
33991
|
"src/services/wake-ownership.ts"() {
|
|
33908
33992
|
"use strict";
|
|
33909
33993
|
init_logger();
|
|
33910
33994
|
PROCESS_STARTED_AT = Date.now() - Math.floor(process.uptime() * 1e3);
|
|
33911
33995
|
safe4 = (s) => String(s).replace(/[^A-Za-z0-9._-]/g, "_");
|
|
33996
|
+
PROCESS_MARK = ".process";
|
|
33912
33997
|
}
|
|
33913
33998
|
});
|
|
33914
33999
|
|
|
@@ -33927,6 +34012,39 @@ function versionFromArgv(argv) {
|
|
|
33927
34012
|
const m = argv.match(/\/cogent\/(\d+\.\d+\.\d+)\//);
|
|
33928
34013
|
return m ? m[1] : null;
|
|
33929
34014
|
}
|
|
34015
|
+
function versionAtLeast(a, b) {
|
|
34016
|
+
const pa = a.split(/[-+]/)[0].split(".").map(Number);
|
|
34017
|
+
const pb = b.split(/[-+]/)[0].split(".").map(Number);
|
|
34018
|
+
for (let i = 0; i < 3; i++) {
|
|
34019
|
+
const x = pa[i] ?? 0;
|
|
34020
|
+
const y = pb[i] ?? 0;
|
|
34021
|
+
if (x !== y) return x > y;
|
|
34022
|
+
}
|
|
34023
|
+
return true;
|
|
34024
|
+
}
|
|
34025
|
+
function bridgeVersion(argv, readFile = (p) => fs19.readFileSync(p, "utf-8")) {
|
|
34026
|
+
const fromPath = versionFromArgv(argv);
|
|
34027
|
+
if (fromPath) return fromPath;
|
|
34028
|
+
const candidates = [];
|
|
34029
|
+
const pkg = argv.match(/(\S*\/@essentialai\/cogent-bridge(?:-bundled)?)\/dist\/(?:cli|index)\.js(?:\s|$)/);
|
|
34030
|
+
if (pkg) candidates.push(path20.join(pkg[1], "package.json"));
|
|
34031
|
+
const bin = argv.match(/(\S*\/node_modules)\/\.bin\/cogent-bridge(?:\s|$)/);
|
|
34032
|
+
if (bin) {
|
|
34033
|
+
for (const name of ["cogent-bridge", "cogent-bridge-bundled"]) {
|
|
34034
|
+
candidates.push(path20.join(bin[1], "@essentialai", name, "package.json"));
|
|
34035
|
+
}
|
|
34036
|
+
}
|
|
34037
|
+
for (const file of candidates) {
|
|
34038
|
+
try {
|
|
34039
|
+
const pj = JSON.parse(readFile(file));
|
|
34040
|
+
if (typeof pj.name === "string" && pj.name.startsWith("@essentialai/cogent-bridge") && typeof pj.version === "string" && /^\d+\.\d+\.\d+/.test(pj.version)) {
|
|
34041
|
+
return pj.version;
|
|
34042
|
+
}
|
|
34043
|
+
} catch {
|
|
34044
|
+
}
|
|
34045
|
+
}
|
|
34046
|
+
return null;
|
|
34047
|
+
}
|
|
33930
34048
|
function listProcesses() {
|
|
33931
34049
|
let out;
|
|
33932
34050
|
try {
|
|
@@ -33988,25 +34106,13 @@ function ancestorsOf(pid, procs) {
|
|
|
33988
34106
|
}
|
|
33989
34107
|
return seen;
|
|
33990
34108
|
}
|
|
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
34109
|
function findStaleBridges(cwd, procs = listProcesses(), opts = {}) {
|
|
34110
|
+
const versionOf = opts.versionOf ?? ((argv) => bridgeVersion(argv));
|
|
34006
34111
|
const selfPid = opts.selfPid ?? process.pid;
|
|
34007
|
-
const selfStartedAt = opts.selfStartedAt ??
|
|
34112
|
+
const selfStartedAt = opts.selfStartedAt ?? procs.find((p) => p.pid === selfPid)?.startedAt ?? NaN;
|
|
34113
|
+
if (!Number.isFinite(selfStartedAt)) return [];
|
|
34008
34114
|
const cwdOf = opts.cwdOf ?? processCwd;
|
|
34009
|
-
const announced = opts.announced ??
|
|
34115
|
+
const announced = opts.announced ?? new Set(listLiveBridgesInFolder(cwd).map((e) => e.pid));
|
|
34010
34116
|
const target = canonicalPath(cwd);
|
|
34011
34117
|
const ancestors = ancestorsOf(selfPid, procs);
|
|
34012
34118
|
const out = [];
|
|
@@ -34018,10 +34124,11 @@ function findStaleBridges(cwd, procs = listProcesses(), opts = {}) {
|
|
|
34018
34124
|
if (!Number.isFinite(p.startedAt) || p.startedAt >= selfStartedAt) continue;
|
|
34019
34125
|
const theirCwd = cwdOf(p.pid);
|
|
34020
34126
|
if (!theirCwd || canonicalPath(theirCwd) !== target) continue;
|
|
34021
|
-
const ver =
|
|
34127
|
+
const ver = versionOf(p.argv);
|
|
34128
|
+
if (!ver || versionAtLeast(ver, SELF_SUPERSESSION_VERSION)) continue;
|
|
34022
34129
|
out.push({
|
|
34023
34130
|
proc: p,
|
|
34024
|
-
reason: `pid ${p.pid}
|
|
34131
|
+
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
34132
|
});
|
|
34026
34133
|
}
|
|
34027
34134
|
return out;
|
|
@@ -34055,21 +34162,25 @@ function reapStaleBridges(cwd, opts = {}) {
|
|
|
34055
34162
|
}
|
|
34056
34163
|
if (reaped.length) {
|
|
34057
34164
|
logger.warn(
|
|
34058
|
-
`Cogent: reaped ${reaped.length} stale bridge process(es)
|
|
34165
|
+
`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
34166
|
);
|
|
34060
34167
|
}
|
|
34061
34168
|
return reaped;
|
|
34062
34169
|
}
|
|
34170
|
+
var SELF_SUPERSESSION_VERSION;
|
|
34063
34171
|
var init_stale_bridge_reaper = __esm({
|
|
34064
34172
|
"src/services/stale-bridge-reaper.ts"() {
|
|
34065
34173
|
"use strict";
|
|
34066
34174
|
init_logger();
|
|
34067
34175
|
init_wake_ownership();
|
|
34176
|
+
SELF_SUPERSESSION_VERSION = "3.23.4";
|
|
34068
34177
|
}
|
|
34069
34178
|
});
|
|
34070
34179
|
|
|
34071
34180
|
// src/services/auto-relay.ts
|
|
34072
34181
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
34182
|
+
import fs20 from "node:fs";
|
|
34183
|
+
import path21 from "node:path";
|
|
34073
34184
|
function buildStatusNotice(status, peerId, traceId) {
|
|
34074
34185
|
const tail = traceId ? ` (trace ${traceId})` : "";
|
|
34075
34186
|
if (status === RELAY_STATUS.QUEUED) {
|
|
@@ -34196,6 +34307,21 @@ function truncate(s) {
|
|
|
34196
34307
|
const flat = s.replace(/\s+/g, " ").trim();
|
|
34197
34308
|
return flat.length > DIAGNOSTIC_MAX ? `${flat.slice(0, DIAGNOSTIC_MAX - 1)}\u2026` : flat;
|
|
34198
34309
|
}
|
|
34310
|
+
function isInsideOwnFolder(dir) {
|
|
34311
|
+
try {
|
|
34312
|
+
const real = fs20.realpathSync.native(dir);
|
|
34313
|
+
return real === process.cwd() || real.startsWith(process.cwd() + path21.sep);
|
|
34314
|
+
} catch {
|
|
34315
|
+
return false;
|
|
34316
|
+
}
|
|
34317
|
+
}
|
|
34318
|
+
function isOwnFolder(dir) {
|
|
34319
|
+
try {
|
|
34320
|
+
return fs20.realpathSync.native(dir) === fs20.realpathSync.native(process.cwd());
|
|
34321
|
+
} catch {
|
|
34322
|
+
return false;
|
|
34323
|
+
}
|
|
34324
|
+
}
|
|
34199
34325
|
var RELAY_STATUS, STATUS_MARKER_RE, DIAGNOSTIC_MAX, EARLY_ACK_TTL_MS, EARLY_ACK_MAX, AutoRelayService, autoRelay;
|
|
34200
34326
|
var init_auto_relay = __esm({
|
|
34201
34327
|
"src/services/auto-relay.ts"() {
|
|
@@ -34236,6 +34362,8 @@ var init_auto_relay = __esm({
|
|
|
34236
34362
|
*/
|
|
34237
34363
|
pinnedSessionId = null;
|
|
34238
34364
|
localCwd = null;
|
|
34365
|
+
/** Every folder this process announced the current peer name under — what a drain or a stop must cover. */
|
|
34366
|
+
announcedCwds = /* @__PURE__ */ new Set();
|
|
34239
34367
|
/**
|
|
34240
34368
|
* Peer participation mode (3.2.0, Phase 17 OBS-03).
|
|
34241
34369
|
* - "agent" (default): full auto-relay — inbound directed messages run
|
|
@@ -34299,6 +34427,7 @@ var init_auto_relay = __esm({
|
|
|
34299
34427
|
* successful registration so we know which session to inject into.
|
|
34300
34428
|
*/
|
|
34301
34429
|
setLocalPeer(peerId, sessionId, cwd, mode, label, pinnedSessionId) {
|
|
34430
|
+
if (this.localPeerId && this.localPeerId !== peerId) this.withdrawAnnouncement();
|
|
34302
34431
|
this.localPeerId = peerId;
|
|
34303
34432
|
this.localSessionId = sessionId;
|
|
34304
34433
|
this.pinnedSessionId = pinnedSessionId ?? sessionId;
|
|
@@ -34308,7 +34437,12 @@ var init_auto_relay = __esm({
|
|
|
34308
34437
|
logger.info(
|
|
34309
34438
|
`Auto-relay configured for peer ${peerId} (session: ${sessionId}, pinned: ${this.pinnedSessionId}, mode: ${this.localMode}, label: ${this.localLabel})`
|
|
34310
34439
|
);
|
|
34311
|
-
|
|
34440
|
+
const dirs = /* @__PURE__ */ new Set([path21.resolve(cwd)]);
|
|
34441
|
+
if (isInsideOwnFolder(path21.resolve(cwd))) dirs.add(process.cwd());
|
|
34442
|
+
for (const dir of dirs) {
|
|
34443
|
+
this.announcedCwds.add(dir);
|
|
34444
|
+
announceBridge(dir, peerId, CLIENT_VERSION, getConfig().COGENT_ENDPOINT ?? "local");
|
|
34445
|
+
}
|
|
34312
34446
|
this.supersededNotified.clear();
|
|
34313
34447
|
if (!this.reapedStaleBridges) {
|
|
34314
34448
|
this.reapedStaleBridges = true;
|
|
@@ -34683,10 +34817,13 @@ var init_auto_relay = __esm({
|
|
|
34683
34817
|
}
|
|
34684
34818
|
}
|
|
34685
34819
|
if (this.localPeerId && this.localCwd) {
|
|
34686
|
-
const
|
|
34687
|
-
|
|
34688
|
-
|
|
34689
|
-
|
|
34820
|
+
const dirs = /* @__PURE__ */ new Set([path21.resolve(this.localCwd), ...isOwnFolder(this.localCwd) ? [process.cwd()] : []]);
|
|
34821
|
+
for (const dir of dirs) {
|
|
34822
|
+
const own = checkWakeOwnership(dir, this.localPeerId);
|
|
34823
|
+
if (!own.isOwner) {
|
|
34824
|
+
await this._reportSuperseded(msg, own.owner);
|
|
34825
|
+
return;
|
|
34826
|
+
}
|
|
34690
34827
|
}
|
|
34691
34828
|
}
|
|
34692
34829
|
if (this.localPeerId && !this.awarenessOnly.has(msg.id)) {
|
|
@@ -34731,7 +34868,7 @@ var init_auto_relay = __esm({
|
|
|
34731
34868
|
* notice generator.
|
|
34732
34869
|
*/
|
|
34733
34870
|
async _reportSuperseded(msg, owner) {
|
|
34734
|
-
const who = owner ?
|
|
34871
|
+
const who = owner ? registryOwnerLabel(owner) : "a newer bridge";
|
|
34735
34872
|
logger.warn(
|
|
34736
34873
|
`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
34874
|
);
|
|
@@ -35162,6 +35299,24 @@ var init_auto_relay = __esm({
|
|
|
35162
35299
|
activeDeliveryAckWaiters: Array.from(this.deliveryAckWaiters.keys())
|
|
35163
35300
|
};
|
|
35164
35301
|
}
|
|
35302
|
+
/**
|
|
35303
|
+
* Stop claiming this peer's name for this checkout, WITHOUT stopping work already in flight.
|
|
35304
|
+
* Called the moment the MCP client is gone: a draining bridge serves no agent, and while it
|
|
35305
|
+
* counted as the peer's holder, the restarted agent's new bridge stood by behind it (review r2
|
|
35306
|
+
* NEW-1). The announcement is MARKED, not removed — see markBridgeDraining (R3-2). Idempotent.
|
|
35307
|
+
* 🔴 EVERY announcement, not only the last registered cwd's (review r7 SEC2-1, ABC2-2, FIX2-5):
|
|
35308
|
+
* after a register with another spelling of the folder, the one for the bridge's own folder stayed
|
|
35309
|
+
* unmarked, and the restarted agent waited out the drain or stood by for good.
|
|
35310
|
+
*/
|
|
35311
|
+
announceDraining() {
|
|
35312
|
+
if (!this.localPeerId) return;
|
|
35313
|
+
for (const dir of this.announcedCwds) markBridgeDraining(dir, this.localPeerId);
|
|
35314
|
+
}
|
|
35315
|
+
/** Remove this bridge's ownership announcements (graceful shutdown, a rename). Idempotent. */
|
|
35316
|
+
withdrawAnnouncement() {
|
|
35317
|
+
if (this.localPeerId) for (const dir of this.announcedCwds) withdrawBridge(dir, this.localPeerId);
|
|
35318
|
+
this.announcedCwds.clear();
|
|
35319
|
+
}
|
|
35165
35320
|
/**
|
|
35166
35321
|
* Stop the auto-relay service: clear queue and reset state.
|
|
35167
35322
|
*/
|
|
@@ -35181,7 +35336,7 @@ var init_auto_relay = __esm({
|
|
|
35181
35336
|
}
|
|
35182
35337
|
this.deliveryAckWaiters.clear();
|
|
35183
35338
|
this.recentAcks.clear();
|
|
35184
|
-
|
|
35339
|
+
this.withdrawAnnouncement();
|
|
35185
35340
|
this.queue = [];
|
|
35186
35341
|
this.awarenessOnly.clear();
|
|
35187
35342
|
this.supersededNotified.clear();
|
|
@@ -35201,6 +35356,63 @@ var init_auto_relay = __esm({
|
|
|
35201
35356
|
});
|
|
35202
35357
|
|
|
35203
35358
|
// src/services/peer-presence.ts
|
|
35359
|
+
function holderRelation(holderSession, ownSession) {
|
|
35360
|
+
if (holderSession && ownSession) return holderSession === ownSession ? "same-session" : "other-session";
|
|
35361
|
+
return holderSession || ownSession ? "unknown" : "no-session";
|
|
35362
|
+
}
|
|
35363
|
+
function holderClientGone(holder, procs) {
|
|
35364
|
+
if (holder.noClient === true) return false;
|
|
35365
|
+
const byPid = new Map(procs.map((p) => [p.pid, p]));
|
|
35366
|
+
let cur = byPid.get(holder.pid);
|
|
35367
|
+
if (!cur) return false;
|
|
35368
|
+
if (typeof holder.parentPid === "number") return cur.ppid !== holder.parentPid;
|
|
35369
|
+
for (let hops = 0; hops < 3; hops++) {
|
|
35370
|
+
if (cur.ppid === 1) return true;
|
|
35371
|
+
const parent = byPid.get(cur.ppid);
|
|
35372
|
+
if (!parent) return false;
|
|
35373
|
+
const exe = parent.argv.trim().split(/\s+/)[0] ?? "";
|
|
35374
|
+
if (ORPHAN_PARENT_RE.test(exe.split("/").pop() ?? "")) return true;
|
|
35375
|
+
if (!NPX_WRAPPER_RE.test(parent.argv.trim())) return false;
|
|
35376
|
+
cur = parent;
|
|
35377
|
+
}
|
|
35378
|
+
return false;
|
|
35379
|
+
}
|
|
35380
|
+
function insideCodexWakeTurn(selfPid, procs) {
|
|
35381
|
+
const byPid = new Map(procs.map((p) => [p.pid, p]));
|
|
35382
|
+
const seen = /* @__PURE__ */ new Set();
|
|
35383
|
+
let cur = byPid.get(selfPid)?.ppid;
|
|
35384
|
+
while (cur && cur > 1 && !seen.has(cur)) {
|
|
35385
|
+
seen.add(cur);
|
|
35386
|
+
const p = byPid.get(cur);
|
|
35387
|
+
if (!p) break;
|
|
35388
|
+
if (/(^|[\s/])codex(\.js)?\s+exec\s+resume(\s|$)/.test(p.argv)) return true;
|
|
35389
|
+
cur = p.ppid;
|
|
35390
|
+
}
|
|
35391
|
+
return false;
|
|
35392
|
+
}
|
|
35393
|
+
function otherBridgesInFolder(entries, self, listProcs) {
|
|
35394
|
+
let procs = null;
|
|
35395
|
+
return entries.filter(
|
|
35396
|
+
(e) => e.peerId !== PROCESS_MARK && e.pid !== self.pid && !e.draining && holderRelation(e.sessionId, self.sessionId) !== "same-session" && !holderClientGone(e, procs ??= listProcs())
|
|
35397
|
+
);
|
|
35398
|
+
}
|
|
35399
|
+
function anotherAgentSessionAmong(others, ownSession) {
|
|
35400
|
+
return others.some((o) => holderRelation(o.sessionId, ownSession) === "other-session");
|
|
35401
|
+
}
|
|
35402
|
+
function otherBridgeNotice(others, peerId, verdict, ownSession) {
|
|
35403
|
+
const lines = others.map((o) => {
|
|
35404
|
+
const version2 = registryText(o.version);
|
|
35405
|
+
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)`;
|
|
35406
|
+
if (o.peerId !== peerId) {
|
|
35407
|
+
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.`;
|
|
35408
|
+
}
|
|
35409
|
+
if (verdict.isOwner) {
|
|
35410
|
+
return `${who} was registered as '${peerId}'. It is now superseded: this bridge holds '${peerId}' and that bridge has stopped answering for it.`;
|
|
35411
|
+
}
|
|
35412
|
+
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.`;
|
|
35413
|
+
});
|
|
35414
|
+
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.` : "");
|
|
35415
|
+
}
|
|
35204
35416
|
function autoPresenceEnabled(env = process.env) {
|
|
35205
35417
|
const v = env.COGENT_AUTO_PRESENCE;
|
|
35206
35418
|
if (v === void 0 || v === "") return true;
|
|
@@ -35230,11 +35442,42 @@ async function restorePresence(deps) {
|
|
|
35230
35442
|
};
|
|
35231
35443
|
}
|
|
35232
35444
|
const peerId = creds.peerId;
|
|
35233
|
-
if (deps.
|
|
35445
|
+
if (deps.startedByWakeTurn?.()) {
|
|
35234
35446
|
return {
|
|
35235
|
-
state: "
|
|
35447
|
+
state: "deferred",
|
|
35236
35448
|
restored: false,
|
|
35237
|
-
detail: `peer '${peerId}'
|
|
35449
|
+
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`
|
|
35450
|
+
};
|
|
35451
|
+
}
|
|
35452
|
+
const served = deps.peerAlreadyServed(peerId);
|
|
35453
|
+
if (served) {
|
|
35454
|
+
const session = deps.agentSessionId?.();
|
|
35455
|
+
const holder = holderRelation(served.sessionId, session);
|
|
35456
|
+
const servedBy = {
|
|
35457
|
+
...served,
|
|
35458
|
+
...served.version === void 0 ? {} : { version: registryText(served.version) },
|
|
35459
|
+
...served.sessionId === void 0 ? {} : { sessionId: registryText(served.sessionId) }
|
|
35460
|
+
};
|
|
35461
|
+
const started = Number.isFinite(servedBy.startedAt) ? new Date(servedBy.startedAt).toISOString() : "unknown";
|
|
35462
|
+
const recheck = holder === "same-session";
|
|
35463
|
+
const every = deps.recheckSeconds ? ` (re-checked every ${deps.recheckSeconds}s)` : "";
|
|
35464
|
+
const take = `To take '${peerId}' for this agent now, run /cogent:register (cogent_join_session, then cogent_register_peer)`;
|
|
35465
|
+
const why = {
|
|
35466
|
+
"same-session": `That bridge serves this same agent session (${session})`,
|
|
35467
|
+
"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}`,
|
|
35468
|
+
"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}`,
|
|
35469
|
+
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}`
|
|
35470
|
+
};
|
|
35471
|
+
return {
|
|
35472
|
+
state: "standby",
|
|
35473
|
+
restored: false,
|
|
35474
|
+
peerId,
|
|
35475
|
+
servedBy,
|
|
35476
|
+
holder,
|
|
35477
|
+
recheck,
|
|
35478
|
+
// A final standby is evaluated once, so it says "when this bridge started": the health
|
|
35479
|
+
// check keeps showing this text after that bridge is gone.
|
|
35480
|
+
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
35481
|
};
|
|
35239
35482
|
}
|
|
35240
35483
|
if (!autoPresenceEnabled(deps.env ?? process.env)) {
|
|
@@ -35294,15 +35537,22 @@ function logPresence(outcome) {
|
|
|
35294
35537
|
);
|
|
35295
35538
|
} else if (outcome.state === "offline") {
|
|
35296
35539
|
logger.warn(`Presence: OFFLINE \u2014 ${outcome.detail}.`);
|
|
35540
|
+
} else if (outcome.state === "standby" && outcome.holder === "other-session") {
|
|
35541
|
+
logger.warn(`Presence: STANDBY \u2014 ${outcome.detail}.`);
|
|
35542
|
+
} else if (outcome.state === "standby" || outcome.state === "deferred") {
|
|
35543
|
+
logger.info(`Presence: ${outcome.state.toUpperCase()} \u2014 ${outcome.detail}.`);
|
|
35297
35544
|
} else {
|
|
35298
35545
|
logger.debug(`Presence: ${outcome.state} \u2014 ${outcome.detail}.`);
|
|
35299
35546
|
}
|
|
35300
35547
|
}
|
|
35301
|
-
var lastPresence;
|
|
35548
|
+
var ORPHAN_PARENT_RE, NPX_WRAPPER_RE, lastPresence;
|
|
35302
35549
|
var init_peer_presence = __esm({
|
|
35303
35550
|
"src/services/peer-presence.ts"() {
|
|
35304
35551
|
"use strict";
|
|
35305
35552
|
init_logger();
|
|
35553
|
+
init_wake_ownership();
|
|
35554
|
+
ORPHAN_PARENT_RE = /^(init|launchd|systemd)$/;
|
|
35555
|
+
NPX_WRAPPER_RE = /^(?:\S*\/)?(?:sh|bash|dash) -c cogent-bridge\b|^npm exec @essentialai\/cogent-bridge/;
|
|
35306
35556
|
lastPresence = null;
|
|
35307
35557
|
}
|
|
35308
35558
|
});
|
|
@@ -35550,8 +35800,8 @@ __export(startup_exports, {
|
|
|
35550
35800
|
triggerReRegistration: () => triggerReRegistration
|
|
35551
35801
|
});
|
|
35552
35802
|
import os15 from "node:os";
|
|
35553
|
-
import
|
|
35554
|
-
import
|
|
35803
|
+
import path22 from "node:path";
|
|
35804
|
+
import fs21 from "node:fs/promises";
|
|
35555
35805
|
import readline2 from "node:readline";
|
|
35556
35806
|
import { execFile as execFile5 } from "node:child_process";
|
|
35557
35807
|
import { promisify as promisify4 } from "node:util";
|
|
@@ -35569,7 +35819,7 @@ function bindInboxNotifier() {
|
|
|
35569
35819
|
}
|
|
35570
35820
|
async function loadPersistedConfig() {
|
|
35571
35821
|
try {
|
|
35572
|
-
const raw = await
|
|
35822
|
+
const raw = await fs21.readFile(PERSIST_PATH, "utf-8");
|
|
35573
35823
|
return JSON.parse(raw);
|
|
35574
35824
|
} catch {
|
|
35575
35825
|
return {};
|
|
@@ -35577,7 +35827,7 @@ async function loadPersistedConfig() {
|
|
|
35577
35827
|
}
|
|
35578
35828
|
async function savePersistedConfig(config2) {
|
|
35579
35829
|
try {
|
|
35580
|
-
await
|
|
35830
|
+
await fs21.writeFile(PERSIST_PATH, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
35581
35831
|
} catch (err) {
|
|
35582
35832
|
const msg = err instanceof Error ? err.message : String(err);
|
|
35583
35833
|
logger.warn(`Could not save config to ${PERSIST_PATH}: ${msg}`);
|
|
@@ -35612,11 +35862,11 @@ First run detected. Where should cogent-bridge store its data?
|
|
|
35612
35862
|
});
|
|
35613
35863
|
}
|
|
35614
35864
|
async function validateStateDir(statePath) {
|
|
35615
|
-
await
|
|
35616
|
-
const testFile =
|
|
35865
|
+
await fs21.mkdir(statePath, { recursive: true });
|
|
35866
|
+
const testFile = path22.join(statePath, ".write-test");
|
|
35617
35867
|
try {
|
|
35618
|
-
await
|
|
35619
|
-
await
|
|
35868
|
+
await fs21.writeFile(testFile, "test", "utf-8");
|
|
35869
|
+
await fs21.unlink(testFile);
|
|
35620
35870
|
} catch {
|
|
35621
35871
|
throw new BridgeError(
|
|
35622
35872
|
"STARTUP_FAILED" /* STARTUP_FAILED */,
|
|
@@ -35700,9 +35950,15 @@ function cancelPresenceRetry() {
|
|
|
35700
35950
|
if (presenceRetry) clearTimeout(presenceRetry);
|
|
35701
35951
|
presenceRetry = null;
|
|
35702
35952
|
}
|
|
35703
|
-
function
|
|
35953
|
+
function presenceRetryBaseMs() {
|
|
35704
35954
|
const base = Number(process.env.COGENT_PRESENCE_RETRY_MS);
|
|
35705
|
-
return
|
|
35955
|
+
return Number.isFinite(base) && base > 0 ? base : 3e4;
|
|
35956
|
+
}
|
|
35957
|
+
function presenceRetryDelayMs(attempt) {
|
|
35958
|
+
return Math.min(presenceRetryBaseMs() * 2 ** attempt, 3e5);
|
|
35959
|
+
}
|
|
35960
|
+
function standbyRecheckMs() {
|
|
35961
|
+
return Math.max(250, Math.min(presenceRetryBaseMs(), 15e3));
|
|
35706
35962
|
}
|
|
35707
35963
|
async function restorePeerPresence(attempt = 0) {
|
|
35708
35964
|
if (!presenceSupersedeBound) {
|
|
@@ -35716,6 +35972,8 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35716
35972
|
}
|
|
35717
35973
|
const generation = getCloudAttemptGeneration();
|
|
35718
35974
|
const stillCurrent = () => getCloudAttemptGeneration() === generation;
|
|
35975
|
+
let procs = null;
|
|
35976
|
+
const ps = () => procs ??= listProcesses();
|
|
35719
35977
|
const outcome = await restorePresence({
|
|
35720
35978
|
// The endpoint being a relay URL is what makes presence meaningful. We deliberately do
|
|
35721
35979
|
// NOT gate on the active backend being the cloud one: at startup it is still the
|
|
@@ -35728,13 +35986,27 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35728
35986
|
alreadyRegisteredInProcess: () => autoRelay.getDiagnostics().registered,
|
|
35729
35987
|
peerAlreadyServed: (peerId) => {
|
|
35730
35988
|
try {
|
|
35731
|
-
|
|
35989
|
+
const holders = listLiveBridges(process.cwd(), peerId).filter((b) => b.pid !== process.pid && !b.draining);
|
|
35990
|
+
const other = holders.find((b) => {
|
|
35991
|
+
if (!holderClientGone(b, ps())) return true;
|
|
35992
|
+
if (!ignoredHolders.has(b.pid)) {
|
|
35993
|
+
ignoredHolders.add(b.pid);
|
|
35994
|
+
logger.info(
|
|
35995
|
+
`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`
|
|
35996
|
+
);
|
|
35997
|
+
}
|
|
35998
|
+
return false;
|
|
35999
|
+
});
|
|
36000
|
+
return other ? { pid: other.pid, version: other.version, startedAt: other.startedAt, sessionId: other.sessionId } : null;
|
|
35732
36001
|
} catch {
|
|
35733
|
-
return
|
|
36002
|
+
return null;
|
|
35734
36003
|
}
|
|
35735
36004
|
},
|
|
36005
|
+
agentSessionId: () => agentSessionId(),
|
|
36006
|
+
startedByWakeTurn: () => insideCodexWakeTurn(process.pid, ps()),
|
|
35736
36007
|
loadCredentials: () => loadCredentials(),
|
|
35737
36008
|
cwd: () => process.cwd(),
|
|
36009
|
+
recheckSeconds: Math.round(standbyRecheckMs() / 1e3),
|
|
35738
36010
|
goOnline: async ({ peerId, endpoint, sessionId, token, cwd, label, peerSecret }) => {
|
|
35739
36011
|
if (!stillCurrent()) throw new Error(PRESENCE_SUPERSEDED);
|
|
35740
36012
|
await reinitCloudBackend(endpoint, sessionId, token);
|
|
@@ -35754,18 +36026,25 @@ async function restorePeerPresence(attempt = 0) {
|
|
|
35754
36026
|
logPresence(superseded);
|
|
35755
36027
|
return superseded;
|
|
35756
36028
|
}
|
|
36029
|
+
const prev = getPresence();
|
|
35757
36030
|
setPresence(outcome);
|
|
35758
|
-
|
|
35759
|
-
|
|
35760
|
-
|
|
36031
|
+
if (outcome.state === "standby" && prev?.state === "standby" && prev.servedBy.pid === outcome.servedBy.pid) {
|
|
36032
|
+
logger.debug(`Presence: STANDBY (unchanged) \u2014 ${outcome.detail}.`);
|
|
36033
|
+
} else {
|
|
36034
|
+
logPresence(outcome);
|
|
36035
|
+
}
|
|
36036
|
+
const failed = outcome.state === "offline" && outcome.detail.startsWith("presence restore failed");
|
|
36037
|
+
const standby = outcome.state === "standby" && outcome.recheck;
|
|
36038
|
+
if (failed || standby) {
|
|
36039
|
+
const delay = standby ? standbyRecheckMs() : presenceRetryDelayMs(attempt);
|
|
35761
36040
|
cancelPresenceRetry();
|
|
35762
36041
|
presenceRetry = setTimeout(() => {
|
|
35763
36042
|
presenceRetry = null;
|
|
35764
|
-
void restorePeerPresence(attempt + 1).catch(() => {
|
|
36043
|
+
void restorePeerPresence(standby ? 0 : attempt + 1).catch(() => {
|
|
35765
36044
|
});
|
|
35766
36045
|
}, delay);
|
|
35767
36046
|
presenceRetry.unref?.();
|
|
35768
|
-
logger.warn(`presence: restore failed \u2014 retrying in ${Math.round(delay / 1e3)}s`);
|
|
36047
|
+
if (failed) logger.warn(`presence: restore failed \u2014 retrying in ${Math.round(delay / 1e3)}s`);
|
|
35769
36048
|
}
|
|
35770
36049
|
return outcome;
|
|
35771
36050
|
}
|
|
@@ -35899,10 +36178,10 @@ async function runStartup() {
|
|
|
35899
36178
|
if (envStatePath) {
|
|
35900
36179
|
statePath = envStatePath;
|
|
35901
36180
|
} else {
|
|
35902
|
-
const defaultPath =
|
|
36181
|
+
const defaultPath = path22.join(os15.homedir(), ".cogent");
|
|
35903
36182
|
statePath = await firstRunPrompt(defaultPath);
|
|
35904
36183
|
}
|
|
35905
|
-
if (!envStatePath && statePath !==
|
|
36184
|
+
if (!envStatePath && statePath !== path22.join(os15.homedir(), ".cogent")) {
|
|
35906
36185
|
process.env.COGENT_STATE_PATH = statePath;
|
|
35907
36186
|
} else if (!envStatePath) {
|
|
35908
36187
|
process.env.COGENT_STATE_PATH = statePath;
|
|
@@ -35966,7 +36245,7 @@ async function runStartup() {
|
|
|
35966
36245
|
}
|
|
35967
36246
|
initLogger(
|
|
35968
36247
|
config2.COGENT_LOG_LEVEL,
|
|
35969
|
-
|
|
36248
|
+
path22.join(config2.COGENT_STATE_PATH, "logs")
|
|
35970
36249
|
);
|
|
35971
36250
|
if (isCloud && effectiveSessionId && effectiveToken) {
|
|
35972
36251
|
cloudInbox = new MessageInbox();
|
|
@@ -36006,7 +36285,7 @@ async function runPreflights() {
|
|
|
36006
36285
|
await preflightClaude(config2.COGENT_CLAUDE_PATH);
|
|
36007
36286
|
}
|
|
36008
36287
|
}
|
|
36009
|
-
var UUID_V4_RE, execFileAsync3, PERSIST_PATH, legacyWarnEmitted, cloudWsClient, cloudInbox, cloudHttpClient, cloudModeActive, inboxNotifier, notifierBoundTo, reRegistrationInProgress, presenceRetry, presenceSupersedeBound, PRESENCE_SUPERSEDED, pendingLabelResolve;
|
|
36288
|
+
var UUID_V4_RE, execFileAsync3, PERSIST_PATH, legacyWarnEmitted, cloudWsClient, cloudInbox, cloudHttpClient, cloudModeActive, inboxNotifier, notifierBoundTo, reRegistrationInProgress, presenceRetry, ignoredHolders, presenceSupersedeBound, PRESENCE_SUPERSEDED, pendingLabelResolve;
|
|
36010
36289
|
var init_startup = __esm({
|
|
36011
36290
|
"src/startup.ts"() {
|
|
36012
36291
|
"use strict";
|
|
@@ -36022,6 +36301,7 @@ var init_startup = __esm({
|
|
|
36022
36301
|
init_auto_relay();
|
|
36023
36302
|
init_peer_presence();
|
|
36024
36303
|
init_wake_ownership();
|
|
36304
|
+
init_stale_bridge_reaper();
|
|
36025
36305
|
init_heartbeat();
|
|
36026
36306
|
init_codex_preflight();
|
|
36027
36307
|
init_codex_cli();
|
|
@@ -36030,7 +36310,7 @@ var init_startup = __esm({
|
|
|
36030
36310
|
init_auto_relay();
|
|
36031
36311
|
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
36312
|
execFileAsync3 = promisify4(execFile5);
|
|
36033
|
-
PERSIST_PATH =
|
|
36313
|
+
PERSIST_PATH = path22.join(os15.homedir(), ".cogent-config.json");
|
|
36034
36314
|
legacyWarnEmitted = false;
|
|
36035
36315
|
cloudWsClient = null;
|
|
36036
36316
|
cloudInbox = null;
|
|
@@ -36040,6 +36320,7 @@ var init_startup = __esm({
|
|
|
36040
36320
|
notifierBoundTo = null;
|
|
36041
36321
|
reRegistrationInProgress = false;
|
|
36042
36322
|
presenceRetry = null;
|
|
36323
|
+
ignoredHolders = /* @__PURE__ */ new Set();
|
|
36043
36324
|
presenceSupersedeBound = false;
|
|
36044
36325
|
PRESENCE_SUPERSEDED = "presence restore superseded: an explicit cogent_join_session/cogent_create_session ran in this process and owns the channel choice";
|
|
36045
36326
|
pendingLabelResolve = null;
|
|
@@ -36048,12 +36329,12 @@ var init_startup = __esm({
|
|
|
36048
36329
|
|
|
36049
36330
|
// src/cloud/mail-credential-store.ts
|
|
36050
36331
|
import crypto9 from "node:crypto";
|
|
36051
|
-
import
|
|
36052
|
-
import
|
|
36332
|
+
import fs22 from "node:fs/promises";
|
|
36333
|
+
import path23 from "node:path";
|
|
36053
36334
|
import os16 from "node:os";
|
|
36054
36335
|
function defaultMailCredentialPath(cwd = process.cwd()) {
|
|
36055
|
-
const hash = crypto9.createHash("sha256").update(
|
|
36056
|
-
return
|
|
36336
|
+
const hash = crypto9.createHash("sha256").update(path23.resolve(cwd)).digest("hex").slice(0, 16);
|
|
36337
|
+
return path23.join(os16.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
|
|
36057
36338
|
}
|
|
36058
36339
|
function resolveMailCredentialPath(credentialPath) {
|
|
36059
36340
|
if (credentialPath) return credentialPath;
|
|
@@ -36064,16 +36345,16 @@ function resolveMailCredentialPath(credentialPath) {
|
|
|
36064
36345
|
async function loadMailCredentials(credentialPath) {
|
|
36065
36346
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36066
36347
|
try {
|
|
36067
|
-
return JSON.parse(await
|
|
36348
|
+
return JSON.parse(await fs22.readFile(filePath, "utf-8"));
|
|
36068
36349
|
} catch {
|
|
36069
36350
|
return null;
|
|
36070
36351
|
}
|
|
36071
36352
|
}
|
|
36072
36353
|
async function saveMailCredentials(creds, credentialPath) {
|
|
36073
36354
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36074
|
-
await
|
|
36075
|
-
await
|
|
36076
|
-
await
|
|
36355
|
+
await fs22.mkdir(path23.dirname(filePath), { recursive: true, mode: 448 });
|
|
36356
|
+
await fs22.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
36357
|
+
await fs22.chmod(filePath, 384);
|
|
36077
36358
|
}
|
|
36078
36359
|
async function persistProvisionedMailbox(mailbox, credentialPath) {
|
|
36079
36360
|
if (!mailbox?.address || !mailbox.password) return false;
|
|
@@ -36094,7 +36375,7 @@ async function persistProvisionedMailbox(mailbox, credentialPath) {
|
|
|
36094
36375
|
async function clearMailCredentials(credentialPath) {
|
|
36095
36376
|
const filePath = resolveMailCredentialPath(credentialPath);
|
|
36096
36377
|
try {
|
|
36097
|
-
await
|
|
36378
|
+
await fs22.unlink(filePath);
|
|
36098
36379
|
} catch (err) {
|
|
36099
36380
|
if (err.code !== "ENOENT") throw err;
|
|
36100
36381
|
}
|
|
@@ -36143,10 +36424,10 @@ function registerRegisterPeerTool(server) {
|
|
|
36143
36424
|
"cogent_register_peer",
|
|
36144
36425
|
{
|
|
36145
36426
|
title: "Register Peer",
|
|
36146
|
-
description: "
|
|
36427
|
+
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
36428
|
inputSchema: {
|
|
36148
|
-
peerId: import_zod3.z.string().describe("
|
|
36149
|
-
sessionId: import_zod3.z.string().describe("
|
|
36429
|
+
peerId: import_zod3.z.string().describe("The peer name you were given, e.g. 'backend' or 'frontend'. Never invent or suffix one."),
|
|
36430
|
+
sessionId: import_zod3.z.string().describe("This agent session's own resumable id (Claude Code or Codex) \u2014 NOT the channel id"),
|
|
36150
36431
|
cwd: import_zod3.z.string().describe("Absolute path to the project working directory"),
|
|
36151
36432
|
label: import_zod3.z.string().describe("Human-readable label, e.g. 'Cogent_Backend' or 'Cogent_Frontend'"),
|
|
36152
36433
|
peerSecret: import_zod3.z.string().optional().describe(
|
|
@@ -36169,13 +36450,22 @@ function registerRegisterPeerTool(server) {
|
|
|
36169
36450
|
async ({ peerId, sessionId, cwd, label, mode, role, peerSecret: argPeerSecret }) => {
|
|
36170
36451
|
try {
|
|
36171
36452
|
const config2 = getConfig();
|
|
36453
|
+
if (isReservedPeerName(peerId)) {
|
|
36454
|
+
return errorResult(
|
|
36455
|
+
new BridgeError(
|
|
36456
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
36457
|
+
`peerId '${PROCESS_MARK}' is reserved by the bridge`,
|
|
36458
|
+
"Register under another peerId"
|
|
36459
|
+
)
|
|
36460
|
+
);
|
|
36461
|
+
}
|
|
36172
36462
|
const hasExplicitCloudSession = !!config2.COGENT_SESSION_ID || process.env.COGENT_TRUST_PERSISTED_CREDENTIALS === "1";
|
|
36173
36463
|
if (!hasExplicitCloudSession && hasCloudAttemptInProcess() && !hasJoinedInProcess()) {
|
|
36174
36464
|
return errorResult(
|
|
36175
36465
|
new BridgeError(
|
|
36176
36466
|
"JOIN_NOT_CONFIRMED" /* JOIN_NOT_CONFIRMED */,
|
|
36177
36467
|
"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"
|
|
36468
|
+
"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
36469
|
)
|
|
36180
36470
|
);
|
|
36181
36471
|
}
|
|
@@ -36273,7 +36563,7 @@ function registerRegisterPeerTool(server) {
|
|
|
36273
36563
|
new BridgeError(
|
|
36274
36564
|
"JOIN_NOT_CONFIRMED" /* JOIN_NOT_CONFIRMED */,
|
|
36275
36565
|
"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."
|
|
36566
|
+
"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
36567
|
)
|
|
36278
36568
|
);
|
|
36279
36569
|
}
|
|
@@ -36422,9 +36712,25 @@ function registerRegisterPeerTool(server) {
|
|
|
36422
36712
|
}
|
|
36423
36713
|
}
|
|
36424
36714
|
autoRelay.setLocalPeer(peerId, localSessionId, cwd, mode, label, localSessionId);
|
|
36715
|
+
if (isCloudMode()) {
|
|
36716
|
+
setPresence({ state: "online", restored: false, detail: `registered as '${peerId}' by cogent_register_peer` });
|
|
36717
|
+
}
|
|
36718
|
+
let otherBridges;
|
|
36719
|
+
try {
|
|
36720
|
+
const own = agentSessionId();
|
|
36721
|
+
const others = otherBridgesInFolder(listLiveBridgesInFolder(cwd), { pid: process.pid, sessionId: own }, listProcesses);
|
|
36722
|
+
if (others.length) {
|
|
36723
|
+
otherBridges = otherBridgeNotice(others, peerId, checkWakeOwnership(cwd, peerId), own);
|
|
36724
|
+
if (anotherAgentSessionAmong(others, own)) logger.warn(`Register: ${otherBridges}`);
|
|
36725
|
+
else logger.info(`Register: ${otherBridges}`);
|
|
36726
|
+
}
|
|
36727
|
+
} catch (err) {
|
|
36728
|
+
logger.debug(`Register: could not look for other bridges in this folder: ${err.message}`);
|
|
36729
|
+
}
|
|
36425
36730
|
const result = {
|
|
36426
36731
|
success: true,
|
|
36427
36732
|
action: existing ? "updated" : "registered",
|
|
36733
|
+
...otherBridges ? { otherBridgeInThisFolder: otherBridges } : {},
|
|
36428
36734
|
peer,
|
|
36429
36735
|
sessionResolution: {
|
|
36430
36736
|
decision: resolution.decision,
|
|
@@ -36503,6 +36809,9 @@ var init_register_peer = __esm({
|
|
|
36503
36809
|
init_logger();
|
|
36504
36810
|
init_heartbeat();
|
|
36505
36811
|
init_auto_relay();
|
|
36812
|
+
init_wake_ownership();
|
|
36813
|
+
init_peer_presence();
|
|
36814
|
+
init_stale_bridge_reaper();
|
|
36506
36815
|
init_session_resolver();
|
|
36507
36816
|
init_cc_cli();
|
|
36508
36817
|
init_durable_identity();
|
|
@@ -37172,9 +37481,14 @@ var init_ids = __esm({
|
|
|
37172
37481
|
});
|
|
37173
37482
|
|
|
37174
37483
|
// cogent/dist/helpers/validation.js
|
|
37484
|
+
function isValidSessionLabel(value) {
|
|
37485
|
+
return SESSION_LABEL_REGEX.test(value);
|
|
37486
|
+
}
|
|
37487
|
+
var SESSION_LABEL_REGEX;
|
|
37175
37488
|
var init_validation = __esm({
|
|
37176
37489
|
"cogent/dist/helpers/validation.js"() {
|
|
37177
37490
|
"use strict";
|
|
37491
|
+
SESSION_LABEL_REGEX = /^[a-z0-9][a-z0-9-]{1,30}[a-z0-9]$/;
|
|
37178
37492
|
}
|
|
37179
37493
|
});
|
|
37180
37494
|
|
|
@@ -37627,7 +37941,8 @@ function registerHealthCheckTool(server) {
|
|
|
37627
37941
|
// PRESENCE — the agent's own view of whether it is IN its channel, so it can
|
|
37628
37942
|
// answer "am I reachable?" without inferring it from transport internals.
|
|
37629
37943
|
// "online" registered · "offline" owns a peer but is not registered (nobody can
|
|
37630
|
-
// reach it) · "
|
|
37944
|
+
// reach it) · "standby" another live bridge serves this peer, so THIS process is not
|
|
37945
|
+
// registered (servedBy names it) · "deferred" never joined · "local" no relay.
|
|
37631
37946
|
// services/peer-presence.ts carries the vocabulary and how each state arises.
|
|
37632
37947
|
presence: (() => {
|
|
37633
37948
|
const p = getPresence();
|
|
@@ -37638,7 +37953,8 @@ function registerHealthCheckTool(server) {
|
|
|
37638
37953
|
state: p.state,
|
|
37639
37954
|
restored: p.restored,
|
|
37640
37955
|
detail: p.detail,
|
|
37641
|
-
..."peerId" in p ? { peerId: p.peerId } : {}
|
|
37956
|
+
..."peerId" in p ? { peerId: p.peerId } : {},
|
|
37957
|
+
..."servedBy" in p ? { servedBy: p.servedBy } : {}
|
|
37642
37958
|
};
|
|
37643
37959
|
})()
|
|
37644
37960
|
};
|
|
@@ -37725,18 +38041,43 @@ var init_wake_log2 = __esm({
|
|
|
37725
38041
|
}
|
|
37726
38042
|
});
|
|
37727
38043
|
|
|
38044
|
+
// src/tools/channel-text.ts
|
|
38045
|
+
function invalidChannelName(name) {
|
|
38046
|
+
if (isValidSessionLabel(name)) return null;
|
|
38047
|
+
return new BridgeError(
|
|
38048
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
38049
|
+
`Channel names are 3-32 characters: lowercase letters, digits and hyphens. '${name}' is not valid`,
|
|
38050
|
+
"If it differs only by capital letters, retry with it in lowercase; otherwise ask the user."
|
|
38051
|
+
);
|
|
38052
|
+
}
|
|
38053
|
+
function slackMapCommand(o) {
|
|
38054
|
+
return o.team ? `/cogent map ${o.label} <password> <org-id>` : `/cogent map ${o.sessionId} <password>`;
|
|
38055
|
+
}
|
|
38056
|
+
var init_channel_text = __esm({
|
|
38057
|
+
"src/tools/channel-text.ts"() {
|
|
38058
|
+
"use strict";
|
|
38059
|
+
init_dist();
|
|
38060
|
+
init_errors4();
|
|
38061
|
+
}
|
|
38062
|
+
});
|
|
38063
|
+
|
|
37728
38064
|
// src/tools/create-session.ts
|
|
37729
38065
|
import crypto11 from "node:crypto";
|
|
37730
38066
|
function registerCreateSessionTool(server) {
|
|
37731
38067
|
server.registerTool(
|
|
37732
38068
|
"cogent_create_session",
|
|
37733
38069
|
{
|
|
37734
|
-
title: "Create Cloud
|
|
37735
|
-
description: "
|
|
38070
|
+
title: "Create Cloud Channel",
|
|
38071
|
+
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
38072
|
inputSchema: {
|
|
37737
|
-
label: import_zod15.z.string().optional().describe(
|
|
38073
|
+
label: import_zod15.z.string().optional().describe(
|
|
38074
|
+
"The channel name (3-32 characters: lowercase letters, digits, hyphens) \u2014 the same name the join was given. Auto-generated if omitted."
|
|
38075
|
+
),
|
|
37738
38076
|
secret: import_zod15.z.string().min(8).optional().describe(
|
|
37739
|
-
"Shared secret for
|
|
38077
|
+
"Shared secret / password for the channel (min 8 chars). Auto-generated if omitted."
|
|
38078
|
+
),
|
|
38079
|
+
orgId: import_zod15.z.string().min(1).optional().describe(
|
|
38080
|
+
"Org_ID \u2014 the 3rd credential for a Team (business) channel. Provide it to create a Team channel; omit for a free channel."
|
|
37740
38081
|
)
|
|
37741
38082
|
},
|
|
37742
38083
|
annotations: {
|
|
@@ -37746,28 +38087,57 @@ function registerCreateSessionTool(server) {
|
|
|
37746
38087
|
openWorldHint: true
|
|
37747
38088
|
}
|
|
37748
38089
|
},
|
|
37749
|
-
async ({ label, secret }) => {
|
|
38090
|
+
async ({ label, secret, orgId }) => {
|
|
37750
38091
|
try {
|
|
37751
38092
|
markCloudAttemptInProcess();
|
|
38093
|
+
if (label !== void 0 && label.trim() === "") {
|
|
38094
|
+
return errorResult(invalidChannelName(label) ?? new Error("label is empty"));
|
|
38095
|
+
}
|
|
38096
|
+
if (secret !== void 0 && secret.trim() === "") {
|
|
38097
|
+
return errorResult(
|
|
38098
|
+
new BridgeError(
|
|
38099
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
38100
|
+
"The channel password is empty",
|
|
38101
|
+
"Pass the password you were given, or omit `secret` to have one generated."
|
|
38102
|
+
)
|
|
38103
|
+
);
|
|
38104
|
+
}
|
|
38105
|
+
label = label?.trim() || void 0;
|
|
38106
|
+
secret = secret?.trim() || void 0;
|
|
38107
|
+
orgId = orgId?.trim() || void 0;
|
|
37752
38108
|
const config2 = getConfig();
|
|
37753
|
-
|
|
38109
|
+
const endpoint = orgId ? config2.COGENT_TEAM_ENDPOINT : config2.COGENT_ENDPOINT;
|
|
38110
|
+
if (!endpoint) {
|
|
37754
38111
|
return errorResult(
|
|
37755
38112
|
new Error(
|
|
37756
|
-
"COGENT_ENDPOINT not configured. Set it to use cloud mode."
|
|
38113
|
+
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
38114
|
)
|
|
37758
38115
|
);
|
|
37759
38116
|
}
|
|
38117
|
+
if (label !== void 0) {
|
|
38118
|
+
const invalid = invalidChannelName(label);
|
|
38119
|
+
if (invalid) return errorResult(invalid);
|
|
38120
|
+
}
|
|
38121
|
+
const secretWasGenerated = secret === void 0;
|
|
37760
38122
|
const sessionSecret = secret ?? crypto11.randomBytes(16).toString("hex");
|
|
38123
|
+
const createBody = orgId ? { secret: sessionSecret, label, orgId } : { secret: sessionSecret, label };
|
|
37761
38124
|
const resp = await fetch(
|
|
37762
|
-
`${
|
|
38125
|
+
`${endpoint}/api/sessions`,
|
|
37763
38126
|
{
|
|
37764
38127
|
method: "POST",
|
|
37765
38128
|
headers: { "Content-Type": "application/json" },
|
|
37766
|
-
body: JSON.stringify(
|
|
38129
|
+
body: JSON.stringify(createBody)
|
|
37767
38130
|
}
|
|
37768
38131
|
);
|
|
37769
38132
|
if (!resp.ok) {
|
|
37770
38133
|
const body = await resp.text().catch(() => "");
|
|
38134
|
+
if (resp.status === 400 && body.includes("already in use")) {
|
|
38135
|
+
return errorResult(
|
|
38136
|
+
new Error(
|
|
38137
|
+
`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.`
|
|
38138
|
+
)
|
|
38139
|
+
);
|
|
38140
|
+
}
|
|
37771
38141
|
return errorResult(
|
|
37772
38142
|
new Error(
|
|
37773
38143
|
`Failed to create session: HTTP ${resp.status}${body ? ` - ${body}` : ""}`
|
|
@@ -37776,7 +38146,7 @@ function registerCreateSessionTool(server) {
|
|
|
37776
38146
|
}
|
|
37777
38147
|
const data = await resp.json();
|
|
37778
38148
|
await saveCredentials({
|
|
37779
|
-
endpoint
|
|
38149
|
+
endpoint,
|
|
37780
38150
|
sessionId: data.sessionId,
|
|
37781
38151
|
token: data.token,
|
|
37782
38152
|
label: data.label,
|
|
@@ -37786,7 +38156,7 @@ function registerCreateSessionTool(server) {
|
|
|
37786
38156
|
try {
|
|
37787
38157
|
const startupModule = await Promise.resolve().then(() => (init_startup(), startup_exports));
|
|
37788
38158
|
if (typeof startupModule.reinitCloudBackend === "function") {
|
|
37789
|
-
await startupModule.reinitCloudBackend(
|
|
38159
|
+
await startupModule.reinitCloudBackend(endpoint, data.sessionId, data.token);
|
|
37790
38160
|
logger.info(
|
|
37791
38161
|
"Cloud backend reinitialized with new session credentials"
|
|
37792
38162
|
);
|
|
@@ -37794,32 +38164,40 @@ function registerCreateSessionTool(server) {
|
|
|
37794
38164
|
} catch (err) {
|
|
37795
38165
|
logger.debug(`Backend reinit not available: ${err}`);
|
|
37796
38166
|
}
|
|
38167
|
+
const channelName = data.label ?? data.sessionId;
|
|
37797
38168
|
return successResult({
|
|
37798
38169
|
success: true,
|
|
38170
|
+
created: true,
|
|
37799
38171
|
sessionId: data.sessionId,
|
|
37800
38172
|
label: data.label,
|
|
37801
|
-
secret: sessionSecret,
|
|
37802
38173
|
token: data.token,
|
|
37803
38174
|
createdAt: data.createdAt,
|
|
37804
|
-
|
|
37805
|
-
|
|
37806
|
-
|
|
38175
|
+
slackMapCommand: slackMapCommand({ team: !!orgId, label: channelName, sessionId: data.sessionId }),
|
|
38176
|
+
// A secret the CALLER supplied is never echoed back: the caller already has it, and a
|
|
38177
|
+
// tool result can be quoted into a channel by an auto-reply. Only a secret this tool
|
|
38178
|
+
// generated is returned — nothing else knows it.
|
|
38179
|
+
...secretWasGenerated ? {
|
|
38180
|
+
secret: sessionSecret,
|
|
38181
|
+
config_snippet: {
|
|
38182
|
+
env_vars: `COGENT_ENDPOINT=${endpoint}
|
|
38183
|
+
COGENT_SESSION_ID=${channelName}
|
|
37807
38184
|
COGENT_SECRET=${sessionSecret}
|
|
37808
38185
|
COGENT_PLATFORM=${config2.COGENT_PLATFORM}`,
|
|
37809
|
-
|
|
37810
|
-
|
|
37811
|
-
|
|
37812
|
-
|
|
37813
|
-
|
|
37814
|
-
|
|
37815
|
-
|
|
37816
|
-
|
|
37817
|
-
|
|
38186
|
+
mcp_config: {
|
|
38187
|
+
"cogent": {
|
|
38188
|
+
command: "npx",
|
|
38189
|
+
args: ["-y", "@essentialai/cogent-bridge"],
|
|
38190
|
+
env: {
|
|
38191
|
+
COGENT_ENDPOINT: endpoint,
|
|
38192
|
+
COGENT_SESSION_ID: channelName,
|
|
38193
|
+
COGENT_SECRET: sessionSecret,
|
|
38194
|
+
COGENT_PLATFORM: config2.COGENT_PLATFORM
|
|
38195
|
+
}
|
|
37818
38196
|
}
|
|
37819
38197
|
}
|
|
37820
38198
|
}
|
|
37821
|
-
},
|
|
37822
|
-
note:
|
|
38199
|
+
} : {},
|
|
38200
|
+
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
38201
|
});
|
|
37824
38202
|
} catch (err) {
|
|
37825
38203
|
logger.error("create-session failed", { error: err });
|
|
@@ -37837,6 +38215,7 @@ var init_create_session = __esm({
|
|
|
37837
38215
|
init_errors4();
|
|
37838
38216
|
init_credential_store();
|
|
37839
38217
|
init_logger();
|
|
38218
|
+
init_channel_text();
|
|
37840
38219
|
}
|
|
37841
38220
|
});
|
|
37842
38221
|
|
|
@@ -37846,14 +38225,14 @@ function registerJoinSessionTool(server) {
|
|
|
37846
38225
|
"cogent_join_session",
|
|
37847
38226
|
{
|
|
37848
38227
|
title: "Join Cloud Channel",
|
|
37849
|
-
description: '
|
|
38228
|
+
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
38229
|
inputSchema: {
|
|
37851
38230
|
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
|
|
38231
|
+
'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
38232
|
),
|
|
37854
38233
|
secret: import_zod16.z.string().min(1).describe("The shared secret / password for the channel"),
|
|
37855
38234
|
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."
|
|
38235
|
+
"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
38236
|
)
|
|
37858
38237
|
},
|
|
37859
38238
|
annotations: {
|
|
@@ -37881,10 +38260,12 @@ function registerJoinSessionTool(server) {
|
|
|
37881
38260
|
if (UUID_V4_RE2.test(channel)) {
|
|
37882
38261
|
return errorResult(
|
|
37883
38262
|
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
|
|
38263
|
+
`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
38264
|
)
|
|
37886
38265
|
);
|
|
37887
38266
|
}
|
|
38267
|
+
const invalid = invalidChannelName(channel);
|
|
38268
|
+
if (invalid) return errorResult(invalid);
|
|
37888
38269
|
let resolvedSessionId;
|
|
37889
38270
|
let resolvedLabel;
|
|
37890
38271
|
if (orgId) {
|
|
@@ -37896,6 +38277,13 @@ function registerJoinSessionTool(server) {
|
|
|
37896
38277
|
body: JSON.stringify({ label: channel, orgId })
|
|
37897
38278
|
}
|
|
37898
38279
|
);
|
|
38280
|
+
if (resolveResp.status === 404) {
|
|
38281
|
+
return errorResult(new BridgeError(
|
|
38282
|
+
"CHANNEL_NOT_FOUND" /* CHANNEL_NOT_FOUND */,
|
|
38283
|
+
`Team channel '${channel}' was not found on ${endpoint} for this Org_ID (HTTP 404)`,
|
|
38284
|
+
`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.`
|
|
38285
|
+
));
|
|
38286
|
+
}
|
|
37899
38287
|
if (!resolveResp.ok) {
|
|
37900
38288
|
const body = await resolveResp.text().catch(() => "");
|
|
37901
38289
|
return errorResult(new Error(
|
|
@@ -37909,6 +38297,13 @@ function registerJoinSessionTool(server) {
|
|
|
37909
38297
|
const resolveResp = await fetch(
|
|
37910
38298
|
`${endpoint}/api/sessions/resolve/${encodeURIComponent(channel)}`
|
|
37911
38299
|
);
|
|
38300
|
+
if (resolveResp.status === 404) {
|
|
38301
|
+
return errorResult(new BridgeError(
|
|
38302
|
+
"CHANNEL_NOT_FOUND" /* CHANNEL_NOT_FOUND */,
|
|
38303
|
+
`Channel '${channel}' was not found on ${endpoint} (HTTP 404)`,
|
|
38304
|
+
`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.`
|
|
38305
|
+
));
|
|
38306
|
+
}
|
|
37912
38307
|
if (!resolveResp.ok) {
|
|
37913
38308
|
const body = await resolveResp.text().catch(() => "");
|
|
37914
38309
|
return errorResult(new Error(`Failed to resolve channel name "${channel}": HTTP ${resolveResp.status}${body ? ` - ${body}` : ""}`));
|
|
@@ -37928,9 +38323,10 @@ function registerJoinSessionTool(server) {
|
|
|
37928
38323
|
);
|
|
37929
38324
|
if (!resp.ok) {
|
|
37930
38325
|
const body = await resp.text().catch(() => "");
|
|
38326
|
+
const wrong = resp.status === 401 ? `. The password${orgId ? " or Org_ID" : ""} is wrong. Do not retry with guesses - ask the user.` : "";
|
|
37931
38327
|
return errorResult(
|
|
37932
38328
|
new Error(
|
|
37933
|
-
`Failed to join session: HTTP ${resp.status}${body ? ` - ${body}` : ""}`
|
|
38329
|
+
`Failed to join session: HTTP ${resp.status}${body ? ` - ${body}` : ""}${wrong}`
|
|
37934
38330
|
)
|
|
37935
38331
|
);
|
|
37936
38332
|
}
|
|
@@ -37979,6 +38375,11 @@ function registerJoinSessionTool(server) {
|
|
|
37979
38375
|
token: data.token,
|
|
37980
38376
|
label: resolvedLabel ?? data.label ?? channel,
|
|
37981
38377
|
peerCount: data.peerCount,
|
|
38378
|
+
slackMapCommand: slackMapCommand({
|
|
38379
|
+
team: !!orgId,
|
|
38380
|
+
label: resolvedLabel ?? data.label ?? channel,
|
|
38381
|
+
sessionId: data.sessionId
|
|
38382
|
+
}),
|
|
37982
38383
|
note: "Successfully joined session. Credentials saved locally. Cloud backend updated. You can now use cogent_register_peer.",
|
|
37983
38384
|
...updateNudge ? { updateAvailable: updateNudge } : {}
|
|
37984
38385
|
});
|
|
@@ -37999,6 +38400,7 @@ var init_join_session = __esm({
|
|
|
37999
38400
|
init_credential_store();
|
|
38000
38401
|
init_logger();
|
|
38001
38402
|
init_npm_update_check();
|
|
38403
|
+
init_channel_text();
|
|
38002
38404
|
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
38405
|
}
|
|
38004
38406
|
});
|
|
@@ -38233,8 +38635,8 @@ var require_cookies = __commonJS({
|
|
|
38233
38635
|
if (urlparts.hostname !== cookie.domain && (cookie.domain.charAt(0) !== "." || ("." + urlparts.hostname).substr(-cookie.domain.length) !== cookie.domain)) {
|
|
38234
38636
|
return false;
|
|
38235
38637
|
}
|
|
38236
|
-
let
|
|
38237
|
-
if (
|
|
38638
|
+
let path27 = this.getPath(urlparts.pathname);
|
|
38639
|
+
if (path27.substr(0, cookie.path.length) !== cookie.path) {
|
|
38238
38640
|
return false;
|
|
38239
38641
|
}
|
|
38240
38642
|
if (cookie.secure && urlparts.protocol !== "https:") {
|
|
@@ -38294,16 +38696,16 @@ var require_cookies = __commonJS({
|
|
|
38294
38696
|
* @returns {String} Normalized path
|
|
38295
38697
|
*/
|
|
38296
38698
|
getPath(pathname) {
|
|
38297
|
-
let
|
|
38298
|
-
|
|
38299
|
-
|
|
38300
|
-
if (
|
|
38301
|
-
|
|
38699
|
+
let path27 = (pathname || "/").split("/");
|
|
38700
|
+
path27.pop();
|
|
38701
|
+
path27 = path27.join("/").trim();
|
|
38702
|
+
if (path27.charAt(0) !== "/") {
|
|
38703
|
+
path27 = "/" + path27;
|
|
38302
38704
|
}
|
|
38303
|
-
if (
|
|
38304
|
-
|
|
38705
|
+
if (path27.substr(-1) !== "/") {
|
|
38706
|
+
path27 += "/";
|
|
38305
38707
|
}
|
|
38306
|
-
return
|
|
38708
|
+
return path27;
|
|
38307
38709
|
}
|
|
38308
38710
|
};
|
|
38309
38711
|
module.exports = Cookies;
|
|
@@ -38604,7 +39006,7 @@ var require_shared = __commonJS({
|
|
|
38604
39006
|
"use strict";
|
|
38605
39007
|
var urllib = __require("url");
|
|
38606
39008
|
var util2 = __require("util");
|
|
38607
|
-
var
|
|
39009
|
+
var fs25 = __require("fs");
|
|
38608
39010
|
var nmfetch = require_fetch();
|
|
38609
39011
|
var dns = __require("dns");
|
|
38610
39012
|
var net = __require("net");
|
|
@@ -38990,7 +39392,7 @@ var require_shared = __commonJS({
|
|
|
38990
39392
|
}
|
|
38991
39393
|
return callback(null, parsedDataUri.data);
|
|
38992
39394
|
} else if (content.path) {
|
|
38993
|
-
return resolveStream(
|
|
39395
|
+
return resolveStream(fs25.createReadStream(content.path), callback);
|
|
38994
39396
|
}
|
|
38995
39397
|
}
|
|
38996
39398
|
if (typeof data[key].content === "string" && !["utf8", "usascii", "ascii"].includes(encoding)) {
|
|
@@ -39114,7 +39516,7 @@ var require_shared = __commonJS({
|
|
|
39114
39516
|
var require_mime_types = __commonJS({
|
|
39115
39517
|
"node_modules/nodemailer/lib/mime-funcs/mime-types.js"(exports, module) {
|
|
39116
39518
|
"use strict";
|
|
39117
|
-
var
|
|
39519
|
+
var path27 = __require("path");
|
|
39118
39520
|
var defaultMimeType = "application/octet-stream";
|
|
39119
39521
|
var defaultExtension = "bin";
|
|
39120
39522
|
var mimeTypes = /* @__PURE__ */ new Map([
|
|
@@ -41172,7 +41574,7 @@ var require_mime_types = __commonJS({
|
|
|
41172
41574
|
if (!filename) {
|
|
41173
41575
|
return defaultMimeType;
|
|
41174
41576
|
}
|
|
41175
|
-
let parsed =
|
|
41577
|
+
let parsed = path27.parse(filename);
|
|
41176
41578
|
let extension = (parsed.ext.substr(1) || parsed.name || "").split("?").shift().trim().toLowerCase();
|
|
41177
41579
|
let value = defaultMimeType;
|
|
41178
41580
|
if (extensions.has(extension)) {
|
|
@@ -42574,7 +42976,7 @@ var require_mime_node = __commonJS({
|
|
|
42574
42976
|
"node_modules/nodemailer/lib/mime-node/index.js"(exports, module) {
|
|
42575
42977
|
"use strict";
|
|
42576
42978
|
var crypto12 = __require("crypto");
|
|
42577
|
-
var
|
|
42979
|
+
var fs25 = __require("fs");
|
|
42578
42980
|
var punycode = require_punycode();
|
|
42579
42981
|
var PassThrough = __require("stream").PassThrough;
|
|
42580
42982
|
var shared = require_shared();
|
|
@@ -43289,7 +43691,7 @@ var require_mime_node = __commonJS({
|
|
|
43289
43691
|
setImmediate(() => contentStream.emit("error", new Error("File access rejected for " + content.path)));
|
|
43290
43692
|
return contentStream;
|
|
43291
43693
|
}
|
|
43292
|
-
return
|
|
43694
|
+
return fs25.createReadStream(content.path);
|
|
43293
43695
|
} else if (content && typeof content.href === "string") {
|
|
43294
43696
|
if (this.disableUrlAccess) {
|
|
43295
43697
|
contentStream = new PassThrough();
|
|
@@ -44310,8 +44712,8 @@ var require_dkim = __commonJS({
|
|
|
44310
44712
|
var RelaxedBody = require_relaxed_body();
|
|
44311
44713
|
var sign = require_sign();
|
|
44312
44714
|
var PassThrough = __require("stream").PassThrough;
|
|
44313
|
-
var
|
|
44314
|
-
var
|
|
44715
|
+
var fs25 = __require("fs");
|
|
44716
|
+
var path27 = __require("path");
|
|
44315
44717
|
var crypto12 = __require("crypto");
|
|
44316
44718
|
var DKIM_ALGO = "sha256";
|
|
44317
44719
|
var MAX_MESSAGE_SIZE = 128 * 1024;
|
|
@@ -44325,7 +44727,7 @@ var require_dkim = __commonJS({
|
|
|
44325
44727
|
this.chunks = [];
|
|
44326
44728
|
this.chunklen = 0;
|
|
44327
44729
|
this.readPos = 0;
|
|
44328
|
-
this.cachePath = this.cacheDir ?
|
|
44730
|
+
this.cachePath = this.cacheDir ? path27.join(this.cacheDir, "message." + Date.now() + "-" + crypto12.randomBytes(14).toString("hex")) : false;
|
|
44329
44731
|
this.cache = false;
|
|
44330
44732
|
this.headers = false;
|
|
44331
44733
|
this.bodyHash = false;
|
|
@@ -44345,10 +44747,10 @@ var require_dkim = __commonJS({
|
|
|
44345
44747
|
if (!this.cache || !this.cachePath) {
|
|
44346
44748
|
return;
|
|
44347
44749
|
}
|
|
44348
|
-
|
|
44750
|
+
fs25.unlink(this.cachePath, () => false);
|
|
44349
44751
|
}
|
|
44350
44752
|
createReadCache() {
|
|
44351
|
-
this.cache =
|
|
44753
|
+
this.cache = fs25.createReadStream(this.cachePath);
|
|
44352
44754
|
this.cache.once("error", (err) => {
|
|
44353
44755
|
this.cleanup();
|
|
44354
44756
|
this.output.emit("error", err);
|
|
@@ -44404,7 +44806,7 @@ var require_dkim = __commonJS({
|
|
|
44404
44806
|
}
|
|
44405
44807
|
createWriteCache() {
|
|
44406
44808
|
this.output.usingCache = true;
|
|
44407
|
-
this.cache =
|
|
44809
|
+
this.cache = fs25.createWriteStream(this.cachePath);
|
|
44408
44810
|
this.cache.once("error", (err) => {
|
|
44409
44811
|
this.cleanup();
|
|
44410
44812
|
this.relaxedBody.unpipe(this.cache);
|
|
@@ -49293,13 +49695,13 @@ var require_nodemailer = __commonJS({
|
|
|
49293
49695
|
});
|
|
49294
49696
|
|
|
49295
49697
|
// src/mail/mail-sender.ts
|
|
49296
|
-
import
|
|
49297
|
-
import
|
|
49698
|
+
import fs23 from "node:fs/promises";
|
|
49699
|
+
import path24 from "node:path";
|
|
49298
49700
|
async function buildAndSendMail(sender, creds, params) {
|
|
49299
49701
|
const attachments = [];
|
|
49300
49702
|
for (const p of params.attachmentPaths ?? []) {
|
|
49301
|
-
const content = await
|
|
49302
|
-
attachments.push({ filename:
|
|
49703
|
+
const content = await fs23.readFile(p);
|
|
49704
|
+
attachments.push({ filename: path24.basename(p), content });
|
|
49303
49705
|
}
|
|
49304
49706
|
const { messageId } = await sender.send({
|
|
49305
49707
|
from: creds.address,
|
|
@@ -49688,8 +50090,8 @@ var require_req = __commonJS({
|
|
|
49688
50090
|
if (req.originalUrl) {
|
|
49689
50091
|
_req.url = req.originalUrl;
|
|
49690
50092
|
} else {
|
|
49691
|
-
const
|
|
49692
|
-
_req.url = typeof
|
|
50093
|
+
const path27 = req.path;
|
|
50094
|
+
_req.url = typeof path27 === "string" ? path27 : req.url ? req.url.path || req.url : void 0;
|
|
49693
50095
|
}
|
|
49694
50096
|
if (req.query) {
|
|
49695
50097
|
_req.query = req.query;
|
|
@@ -49854,14 +50256,14 @@ var require_redact = __commonJS({
|
|
|
49854
50256
|
}
|
|
49855
50257
|
return obj;
|
|
49856
50258
|
}
|
|
49857
|
-
function parsePath(
|
|
50259
|
+
function parsePath(path27) {
|
|
49858
50260
|
const parts = [];
|
|
49859
50261
|
let current = "";
|
|
49860
50262
|
let inBrackets = false;
|
|
49861
50263
|
let inQuotes = false;
|
|
49862
50264
|
let quoteChar = "";
|
|
49863
|
-
for (let i = 0; i <
|
|
49864
|
-
const char =
|
|
50265
|
+
for (let i = 0; i < path27.length; i++) {
|
|
50266
|
+
const char = path27[i];
|
|
49865
50267
|
if (!inBrackets && char === ".") {
|
|
49866
50268
|
if (current) {
|
|
49867
50269
|
parts.push(current);
|
|
@@ -49992,10 +50394,10 @@ var require_redact = __commonJS({
|
|
|
49992
50394
|
return current;
|
|
49993
50395
|
}
|
|
49994
50396
|
function redactPaths(obj, paths, censor, remove = false) {
|
|
49995
|
-
for (const
|
|
49996
|
-
const parts = parsePath(
|
|
50397
|
+
for (const path27 of paths) {
|
|
50398
|
+
const parts = parsePath(path27);
|
|
49997
50399
|
if (parts.includes("*")) {
|
|
49998
|
-
redactWildcardPath(obj, parts, censor,
|
|
50400
|
+
redactWildcardPath(obj, parts, censor, path27, remove);
|
|
49999
50401
|
} else {
|
|
50000
50402
|
if (remove) {
|
|
50001
50403
|
removeKey(obj, parts);
|
|
@@ -50080,8 +50482,8 @@ var require_redact = __commonJS({
|
|
|
50080
50482
|
}
|
|
50081
50483
|
} else {
|
|
50082
50484
|
if (afterWildcard.includes("*")) {
|
|
50083
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
50084
|
-
const fullPath = [...pathArray.slice(0, pathLength), ...
|
|
50485
|
+
const wrappedCensor = typeof censor === "function" ? (value, path27) => {
|
|
50486
|
+
const fullPath = [...pathArray.slice(0, pathLength), ...path27];
|
|
50085
50487
|
return censor(value, fullPath);
|
|
50086
50488
|
} : censor;
|
|
50087
50489
|
redactWildcardPath(current, afterWildcard, wrappedCensor, originalPath, remove);
|
|
@@ -50116,8 +50518,8 @@ var require_redact = __commonJS({
|
|
|
50116
50518
|
return null;
|
|
50117
50519
|
}
|
|
50118
50520
|
const pathStructure = /* @__PURE__ */ new Map();
|
|
50119
|
-
for (const
|
|
50120
|
-
const parts = parsePath(
|
|
50521
|
+
for (const path27 of pathsToClone) {
|
|
50522
|
+
const parts = parsePath(path27);
|
|
50121
50523
|
let current = pathStructure;
|
|
50122
50524
|
for (let i = 0; i < parts.length; i++) {
|
|
50123
50525
|
const part = parts[i];
|
|
@@ -50169,24 +50571,24 @@ var require_redact = __commonJS({
|
|
|
50169
50571
|
}
|
|
50170
50572
|
return cloneSelectively(obj, pathStructure);
|
|
50171
50573
|
}
|
|
50172
|
-
function validatePath(
|
|
50173
|
-
if (typeof
|
|
50574
|
+
function validatePath(path27) {
|
|
50575
|
+
if (typeof path27 !== "string") {
|
|
50174
50576
|
throw new Error("Paths must be (non-empty) strings");
|
|
50175
50577
|
}
|
|
50176
|
-
if (
|
|
50578
|
+
if (path27 === "") {
|
|
50177
50579
|
throw new Error("Invalid redaction path ()");
|
|
50178
50580
|
}
|
|
50179
|
-
if (
|
|
50180
|
-
throw new Error(`Invalid redaction path (${
|
|
50581
|
+
if (path27.includes("..")) {
|
|
50582
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50181
50583
|
}
|
|
50182
|
-
if (
|
|
50183
|
-
throw new Error(`Invalid redaction path (${
|
|
50584
|
+
if (path27.includes(",")) {
|
|
50585
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50184
50586
|
}
|
|
50185
50587
|
let bracketCount = 0;
|
|
50186
50588
|
let inQuotes = false;
|
|
50187
50589
|
let quoteChar = "";
|
|
50188
|
-
for (let i = 0; i <
|
|
50189
|
-
const char =
|
|
50590
|
+
for (let i = 0; i < path27.length; i++) {
|
|
50591
|
+
const char = path27[i];
|
|
50190
50592
|
if ((char === '"' || char === "'") && bracketCount > 0) {
|
|
50191
50593
|
if (!inQuotes) {
|
|
50192
50594
|
inQuotes = true;
|
|
@@ -50200,20 +50602,20 @@ var require_redact = __commonJS({
|
|
|
50200
50602
|
} else if (char === "]" && !inQuotes) {
|
|
50201
50603
|
bracketCount--;
|
|
50202
50604
|
if (bracketCount < 0) {
|
|
50203
|
-
throw new Error(`Invalid redaction path (${
|
|
50605
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50204
50606
|
}
|
|
50205
50607
|
}
|
|
50206
50608
|
}
|
|
50207
50609
|
if (bracketCount !== 0) {
|
|
50208
|
-
throw new Error(`Invalid redaction path (${
|
|
50610
|
+
throw new Error(`Invalid redaction path (${path27})`);
|
|
50209
50611
|
}
|
|
50210
50612
|
}
|
|
50211
50613
|
function validatePaths(paths) {
|
|
50212
50614
|
if (!Array.isArray(paths)) {
|
|
50213
50615
|
throw new TypeError("paths must be an array");
|
|
50214
50616
|
}
|
|
50215
|
-
for (const
|
|
50216
|
-
validatePath(
|
|
50617
|
+
for (const path27 of paths) {
|
|
50618
|
+
validatePath(path27);
|
|
50217
50619
|
}
|
|
50218
50620
|
}
|
|
50219
50621
|
function slowRedact(options = {}) {
|
|
@@ -50381,8 +50783,8 @@ var require_redaction = __commonJS({
|
|
|
50381
50783
|
if (shape[k] === null) {
|
|
50382
50784
|
o[k] = (value) => topCensor(value, [k]);
|
|
50383
50785
|
} else {
|
|
50384
|
-
const wrappedCensor = typeof censor === "function" ? (value,
|
|
50385
|
-
return censor(value, [k, ...
|
|
50786
|
+
const wrappedCensor = typeof censor === "function" ? (value, path27) => {
|
|
50787
|
+
return censor(value, [k, ...path27]);
|
|
50386
50788
|
} : censor;
|
|
50387
50789
|
o[k] = Redact({
|
|
50388
50790
|
paths: shape[k],
|
|
@@ -50600,10 +51002,10 @@ var require_atomic_sleep = __commonJS({
|
|
|
50600
51002
|
var require_sonic_boom = __commonJS({
|
|
50601
51003
|
"node_modules/sonic-boom/index.js"(exports, module) {
|
|
50602
51004
|
"use strict";
|
|
50603
|
-
var
|
|
51005
|
+
var fs25 = __require("fs");
|
|
50604
51006
|
var EventEmitter = __require("events");
|
|
50605
51007
|
var inherits = __require("util").inherits;
|
|
50606
|
-
var
|
|
51008
|
+
var path27 = __require("path");
|
|
50607
51009
|
var sleep4 = require_atomic_sleep();
|
|
50608
51010
|
var assert2 = __require("assert");
|
|
50609
51011
|
var BUSY_WRITE_TIMEOUT = 100;
|
|
@@ -50657,20 +51059,20 @@ var require_sonic_boom = __commonJS({
|
|
|
50657
51059
|
const mode = sonic.mode;
|
|
50658
51060
|
if (sonic.sync) {
|
|
50659
51061
|
try {
|
|
50660
|
-
if (sonic.mkdir)
|
|
50661
|
-
const fd =
|
|
51062
|
+
if (sonic.mkdir) fs25.mkdirSync(path27.dirname(file), { recursive: true });
|
|
51063
|
+
const fd = fs25.openSync(file, flags, mode);
|
|
50662
51064
|
fileOpened(null, fd);
|
|
50663
51065
|
} catch (err) {
|
|
50664
51066
|
fileOpened(err);
|
|
50665
51067
|
throw err;
|
|
50666
51068
|
}
|
|
50667
51069
|
} else if (sonic.mkdir) {
|
|
50668
|
-
|
|
51070
|
+
fs25.mkdir(path27.dirname(file), { recursive: true }, (err) => {
|
|
50669
51071
|
if (err) return fileOpened(err);
|
|
50670
|
-
|
|
51072
|
+
fs25.open(file, flags, mode, fileOpened);
|
|
50671
51073
|
});
|
|
50672
51074
|
} else {
|
|
50673
|
-
|
|
51075
|
+
fs25.open(file, flags, mode, fileOpened);
|
|
50674
51076
|
}
|
|
50675
51077
|
}
|
|
50676
51078
|
function SonicBoom(opts) {
|
|
@@ -50711,8 +51113,8 @@ var require_sonic_boom = __commonJS({
|
|
|
50711
51113
|
this.flush = flushBuffer;
|
|
50712
51114
|
this.flushSync = flushBufferSync;
|
|
50713
51115
|
this._actualWrite = actualWriteBuffer;
|
|
50714
|
-
fsWriteSync = () =>
|
|
50715
|
-
fsWrite = () =>
|
|
51116
|
+
fsWriteSync = () => fs25.writeSync(this.fd, this._writingBuf);
|
|
51117
|
+
fsWrite = () => fs25.write(this.fd, this._writingBuf, this.release);
|
|
50716
51118
|
} else if (contentMode === void 0 || contentMode === kContentModeUtf8) {
|
|
50717
51119
|
this._writingBuf = "";
|
|
50718
51120
|
this.write = write;
|
|
@@ -50721,15 +51123,15 @@ var require_sonic_boom = __commonJS({
|
|
|
50721
51123
|
this._actualWrite = actualWrite;
|
|
50722
51124
|
fsWriteSync = () => {
|
|
50723
51125
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
50724
|
-
return
|
|
51126
|
+
return fs25.writeSync(this.fd, this._writingBuf);
|
|
50725
51127
|
}
|
|
50726
|
-
return
|
|
51128
|
+
return fs25.writeSync(this.fd, this._writingBuf, "utf8");
|
|
50727
51129
|
};
|
|
50728
51130
|
fsWrite = () => {
|
|
50729
51131
|
if (Buffer.isBuffer(this._writingBuf)) {
|
|
50730
|
-
return
|
|
51132
|
+
return fs25.write(this.fd, this._writingBuf, this.release);
|
|
50731
51133
|
}
|
|
50732
|
-
return
|
|
51134
|
+
return fs25.write(this.fd, this._writingBuf, "utf8", this.release);
|
|
50733
51135
|
};
|
|
50734
51136
|
} else {
|
|
50735
51137
|
throw new Error(`SonicBoom supports "${kContentModeUtf8}" and "${kContentModeBuffer}", but passed ${contentMode}`);
|
|
@@ -50786,7 +51188,7 @@ var require_sonic_boom = __commonJS({
|
|
|
50786
51188
|
}
|
|
50787
51189
|
}
|
|
50788
51190
|
if (this._fsync) {
|
|
50789
|
-
|
|
51191
|
+
fs25.fsyncSync(this.fd);
|
|
50790
51192
|
}
|
|
50791
51193
|
const len = this._len;
|
|
50792
51194
|
if (this._reopening) {
|
|
@@ -50900,7 +51302,7 @@ var require_sonic_boom = __commonJS({
|
|
|
50900
51302
|
const onDrain = () => {
|
|
50901
51303
|
if (!this._fsync) {
|
|
50902
51304
|
try {
|
|
50903
|
-
|
|
51305
|
+
fs25.fsync(this.fd, (err) => {
|
|
50904
51306
|
this._flushPending = false;
|
|
50905
51307
|
cb(err);
|
|
50906
51308
|
});
|
|
@@ -51002,7 +51404,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51002
51404
|
const fd = this.fd;
|
|
51003
51405
|
this.once("ready", () => {
|
|
51004
51406
|
if (fd !== this.fd) {
|
|
51005
|
-
|
|
51407
|
+
fs25.close(fd, (err) => {
|
|
51006
51408
|
if (err) {
|
|
51007
51409
|
return this.emit("error", err);
|
|
51008
51410
|
}
|
|
@@ -51051,7 +51453,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51051
51453
|
buf = this._bufs[0];
|
|
51052
51454
|
}
|
|
51053
51455
|
try {
|
|
51054
|
-
const n = Buffer.isBuffer(buf) ?
|
|
51456
|
+
const n = Buffer.isBuffer(buf) ? fs25.writeSync(this.fd, buf) : fs25.writeSync(this.fd, buf, "utf8");
|
|
51055
51457
|
const releasedBufObj = releaseWritingBuf(buf, this._len, n);
|
|
51056
51458
|
buf = releasedBufObj.writingBuf;
|
|
51057
51459
|
this._len = releasedBufObj.len;
|
|
@@ -51067,7 +51469,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51067
51469
|
}
|
|
51068
51470
|
}
|
|
51069
51471
|
try {
|
|
51070
|
-
|
|
51472
|
+
fs25.fsyncSync(this.fd);
|
|
51071
51473
|
} catch {
|
|
51072
51474
|
}
|
|
51073
51475
|
}
|
|
@@ -51088,7 +51490,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51088
51490
|
buf = mergeBuf(this._bufs[0], this._lens[0]);
|
|
51089
51491
|
}
|
|
51090
51492
|
try {
|
|
51091
|
-
const n =
|
|
51493
|
+
const n = fs25.writeSync(this.fd, buf);
|
|
51092
51494
|
buf = buf.subarray(n);
|
|
51093
51495
|
this._len = Math.max(this._len - n, 0);
|
|
51094
51496
|
if (buf.length <= 0) {
|
|
@@ -51116,13 +51518,13 @@ var require_sonic_boom = __commonJS({
|
|
|
51116
51518
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : this._bufs.shift() || "";
|
|
51117
51519
|
if (this.sync) {
|
|
51118
51520
|
try {
|
|
51119
|
-
const written = Buffer.isBuffer(this._writingBuf) ?
|
|
51521
|
+
const written = Buffer.isBuffer(this._writingBuf) ? fs25.writeSync(this.fd, this._writingBuf) : fs25.writeSync(this.fd, this._writingBuf, "utf8");
|
|
51120
51522
|
release(null, written);
|
|
51121
51523
|
} catch (err) {
|
|
51122
51524
|
release(err);
|
|
51123
51525
|
}
|
|
51124
51526
|
} else {
|
|
51125
|
-
|
|
51527
|
+
fs25.write(this.fd, this._writingBuf, release);
|
|
51126
51528
|
}
|
|
51127
51529
|
}
|
|
51128
51530
|
function actualWriteBuffer() {
|
|
@@ -51131,7 +51533,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51131
51533
|
this._writingBuf = this._writingBuf.length ? this._writingBuf : mergeBuf(this._bufs.shift(), this._lens.shift());
|
|
51132
51534
|
if (this.sync) {
|
|
51133
51535
|
try {
|
|
51134
|
-
const written =
|
|
51536
|
+
const written = fs25.writeSync(this.fd, this._writingBuf);
|
|
51135
51537
|
release(null, written);
|
|
51136
51538
|
} catch (err) {
|
|
51137
51539
|
release(err);
|
|
@@ -51140,7 +51542,7 @@ var require_sonic_boom = __commonJS({
|
|
|
51140
51542
|
if (kCopyBuffer) {
|
|
51141
51543
|
this._writingBuf = Buffer.from(this._writingBuf);
|
|
51142
51544
|
}
|
|
51143
|
-
|
|
51545
|
+
fs25.write(this.fd, this._writingBuf, release);
|
|
51144
51546
|
}
|
|
51145
51547
|
}
|
|
51146
51548
|
function actualClose(sonic) {
|
|
@@ -51156,12 +51558,12 @@ var require_sonic_boom = __commonJS({
|
|
|
51156
51558
|
sonic._lens = [];
|
|
51157
51559
|
assert2(typeof sonic.fd === "number", `sonic.fd must be a number, got ${typeof sonic.fd}`);
|
|
51158
51560
|
try {
|
|
51159
|
-
|
|
51561
|
+
fs25.fsync(sonic.fd, closeWrapped);
|
|
51160
51562
|
} catch {
|
|
51161
51563
|
}
|
|
51162
51564
|
function closeWrapped() {
|
|
51163
51565
|
if (sonic.fd !== 1 && sonic.fd !== 2) {
|
|
51164
|
-
|
|
51566
|
+
fs25.close(sonic.fd, done);
|
|
51165
51567
|
} else {
|
|
51166
51568
|
done();
|
|
51167
51569
|
}
|
|
@@ -51997,15 +52399,15 @@ var require_transport = __commonJS({
|
|
|
51997
52399
|
if (!unquoted) {
|
|
51998
52400
|
return false;
|
|
51999
52401
|
}
|
|
52000
|
-
let
|
|
52001
|
-
if (
|
|
52402
|
+
let path27 = unquoted;
|
|
52403
|
+
if (path27.startsWith("file://")) {
|
|
52002
52404
|
try {
|
|
52003
|
-
|
|
52405
|
+
path27 = fileURLToPath(path27);
|
|
52004
52406
|
} catch {
|
|
52005
52407
|
return false;
|
|
52006
52408
|
}
|
|
52007
52409
|
}
|
|
52008
|
-
return isAbsolute(
|
|
52410
|
+
return isAbsolute(path27) && !existsSync(path27);
|
|
52009
52411
|
}
|
|
52010
52412
|
function stripQuotes(value) {
|
|
52011
52413
|
const first = value[0];
|
|
@@ -86072,15 +86474,15 @@ var require_tools2 = __commonJS({
|
|
|
86072
86474
|
* @param {String} path - Mailbox path to encode
|
|
86073
86475
|
* @returns {String} Encoded mailbox path
|
|
86074
86476
|
*/
|
|
86075
|
-
encodePath(connection,
|
|
86076
|
-
|
|
86077
|
-
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&\x00-\x08\x0b-\x0c\x0e-\x1f\u0080-\uffff]/.test(
|
|
86477
|
+
encodePath(connection, path27) {
|
|
86478
|
+
path27 = (path27 || "").toString();
|
|
86479
|
+
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&\x00-\x08\x0b-\x0c\x0e-\x1f\u0080-\uffff]/.test(path27)) {
|
|
86078
86480
|
try {
|
|
86079
|
-
|
|
86481
|
+
path27 = iconv.encode(path27, "utf-7-imap").toString();
|
|
86080
86482
|
} catch {
|
|
86081
86483
|
}
|
|
86082
86484
|
}
|
|
86083
|
-
return
|
|
86485
|
+
return path27;
|
|
86084
86486
|
},
|
|
86085
86487
|
/**
|
|
86086
86488
|
* Decodes a mailbox path from modified UTF-7 if the server does not support UTF8=ACCEPT.
|
|
@@ -86089,15 +86491,15 @@ var require_tools2 = __commonJS({
|
|
|
86089
86491
|
* @param {String} path - Mailbox path to decode
|
|
86090
86492
|
* @returns {String} Decoded mailbox path
|
|
86091
86493
|
*/
|
|
86092
|
-
decodePath(connection,
|
|
86093
|
-
|
|
86094
|
-
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&]/.test(
|
|
86494
|
+
decodePath(connection, path27) {
|
|
86495
|
+
path27 = (path27 || "").toString();
|
|
86496
|
+
if (!connection.enabled.has("UTF8=ACCEPT") && !tools.isRev2Active(connection) && /[&]/.test(path27)) {
|
|
86095
86497
|
try {
|
|
86096
|
-
|
|
86498
|
+
path27 = iconv.decode(Buffer.from(path27), "utf-7-imap").toString();
|
|
86097
86499
|
} catch {
|
|
86098
86500
|
}
|
|
86099
86501
|
}
|
|
86100
|
-
return
|
|
86502
|
+
return path27;
|
|
86101
86503
|
},
|
|
86102
86504
|
/**
|
|
86103
86505
|
* Normalizes a mailbox path by joining array segments with the namespace delimiter,
|
|
@@ -86108,17 +86510,17 @@ var require_tools2 = __commonJS({
|
|
|
86108
86510
|
* @param {Boolean} [skipNamespace] - If true, skips prepending the namespace prefix
|
|
86109
86511
|
* @returns {String} Normalized mailbox path
|
|
86110
86512
|
*/
|
|
86111
|
-
normalizePath(connection,
|
|
86112
|
-
if (Array.isArray(
|
|
86113
|
-
|
|
86513
|
+
normalizePath(connection, path27, skipNamespace) {
|
|
86514
|
+
if (Array.isArray(path27)) {
|
|
86515
|
+
path27 = path27.join(connection.namespace && connection.namespace.delimiter || "");
|
|
86114
86516
|
}
|
|
86115
|
-
if (
|
|
86517
|
+
if (path27.toUpperCase() === "INBOX") {
|
|
86116
86518
|
return "INBOX";
|
|
86117
86519
|
}
|
|
86118
|
-
if (!skipNamespace && connection.namespace && connection.namespace.prefix && !
|
|
86119
|
-
|
|
86520
|
+
if (!skipNamespace && connection.namespace && connection.namespace.prefix && !path27.startsWith(connection.namespace.prefix)) {
|
|
86521
|
+
path27 = connection.namespace.prefix + path27;
|
|
86120
86522
|
}
|
|
86121
|
-
return
|
|
86523
|
+
return path27;
|
|
86122
86524
|
},
|
|
86123
86525
|
/**
|
|
86124
86526
|
* Compares two mailbox paths for equality after normalization.
|
|
@@ -86449,14 +86851,14 @@ var require_tools2 = __commonJS({
|
|
|
86449
86851
|
}
|
|
86450
86852
|
}
|
|
86451
86853
|
if (map.emailId || map.uid) {
|
|
86452
|
-
let
|
|
86453
|
-
if (/[\u0080-\uffff]/.test(
|
|
86854
|
+
let path27 = mailbox.path;
|
|
86855
|
+
if (/[\u0080-\uffff]/.test(path27)) {
|
|
86454
86856
|
try {
|
|
86455
|
-
|
|
86857
|
+
path27 = iconv.encode(path27, "utf-7-imap").toString();
|
|
86456
86858
|
} catch {
|
|
86457
86859
|
}
|
|
86458
86860
|
}
|
|
86459
|
-
map.id = map.emailId || createHash2("md5").update([
|
|
86861
|
+
map.id = map.emailId || createHash2("md5").update([path27, mailbox.uidValidity?.toString() || "", map.uid.toString()].join(":")).digest("hex");
|
|
86460
86862
|
}
|
|
86461
86863
|
if (map.flags) {
|
|
86462
86864
|
let flagColor = tools.getFlagColor(map.flags);
|
|
@@ -86631,16 +87033,16 @@ var require_tools2 = __commonJS({
|
|
|
86631
87033
|
* @returns {Object} Parsed body structure tree with part numbers, types, parameters, and child nodes
|
|
86632
87034
|
*/
|
|
86633
87035
|
parseBodystructure(entry) {
|
|
86634
|
-
let walk = (node,
|
|
86635
|
-
|
|
87036
|
+
let walk = (node, path27) => {
|
|
87037
|
+
path27 = path27 || [];
|
|
86636
87038
|
let curNode = {}, i = 0, part = 0;
|
|
86637
|
-
if (
|
|
86638
|
-
curNode.part =
|
|
87039
|
+
if (path27.length) {
|
|
87040
|
+
curNode.part = path27.join(".");
|
|
86639
87041
|
}
|
|
86640
87042
|
if (Array.isArray(node[0])) {
|
|
86641
87043
|
curNode.childNodes = [];
|
|
86642
87044
|
while (Array.isArray(node[i])) {
|
|
86643
|
-
curNode.childNodes.push(walk(node[i],
|
|
87045
|
+
curNode.childNodes.push(walk(node[i], path27.concat(++part)));
|
|
86644
87046
|
i++;
|
|
86645
87047
|
}
|
|
86646
87048
|
curNode.type = "multipart/" + ((node[i++] || {}).value || "").toString().toLowerCase();
|
|
@@ -86683,7 +87085,7 @@ var require_tools2 = __commonJS({
|
|
|
86683
87085
|
// the encapsulated message shares the part number with its wrapper.
|
|
86684
87086
|
// Distinction is via suffixes: path.MIME = wrapper headers,
|
|
86685
87087
|
// path.HEADER = encapsulated message headers.
|
|
86686
|
-
walk(node[i],
|
|
87088
|
+
walk(node[i], path27)
|
|
86687
87089
|
];
|
|
86688
87090
|
}
|
|
86689
87091
|
i++;
|
|
@@ -88645,14 +89047,14 @@ var require_select = __commonJS({
|
|
|
88645
89047
|
// update into a silent no-op for the rest of the session.
|
|
88646
89048
|
permanentflags: { key: "permanentFlags", parse: (value) => Array.isArray(value) && new Set(value) }
|
|
88647
89049
|
});
|
|
88648
|
-
module.exports = async (connection,
|
|
89050
|
+
module.exports = async (connection, path27, options) => {
|
|
88649
89051
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
88650
89052
|
return;
|
|
88651
89053
|
}
|
|
88652
89054
|
options = options || {};
|
|
88653
|
-
|
|
88654
|
-
if (!connection.folders.has(
|
|
88655
|
-
let folders = await connection.run("LIST", "",
|
|
89055
|
+
path27 = normalizePath(connection, path27);
|
|
89056
|
+
if (!connection.folders.has(path27)) {
|
|
89057
|
+
let folders = await connection.run("LIST", "", path27);
|
|
88656
89058
|
if (!folders) {
|
|
88657
89059
|
throw new Error("Failed to fetch folders");
|
|
88658
89060
|
}
|
|
@@ -88660,10 +89062,10 @@ var require_select = __commonJS({
|
|
|
88660
89062
|
connection.folders.set(folder.path, folder);
|
|
88661
89063
|
});
|
|
88662
89064
|
}
|
|
88663
|
-
let folderListData = connection.folders.has(
|
|
89065
|
+
let folderListData = connection.folders.has(path27) ? connection.folders.get(path27) : false;
|
|
88664
89066
|
let response;
|
|
88665
89067
|
try {
|
|
88666
|
-
let map = { path:
|
|
89068
|
+
let map = { path: path27 };
|
|
88667
89069
|
if (folderListData) {
|
|
88668
89070
|
["delimiter", "specialUse", "subscribed", "listed"].forEach((key) => {
|
|
88669
89071
|
if (folderListData[key]) {
|
|
@@ -88682,7 +89084,7 @@ var require_select = __commonJS({
|
|
|
88682
89084
|
]);
|
|
88683
89085
|
map.qresync = true;
|
|
88684
89086
|
}
|
|
88685
|
-
let encodedPath = encodePath(connection,
|
|
89087
|
+
let encodedPath = encodePath(connection, path27);
|
|
88686
89088
|
let selectCommand = {
|
|
88687
89089
|
command: !options.readOnly ? "SELECT" : "EXAMINE",
|
|
88688
89090
|
/* c8 ignore next */
|
|
@@ -88742,12 +89144,12 @@ var require_select = __commonJS({
|
|
|
88742
89144
|
// since the client's last known state. Only received when QRESYNC was requested.
|
|
88743
89145
|
// A dummy mailbox object is passed because the mailbox isn't officially open yet.
|
|
88744
89146
|
VANISHED: async (untagged) => {
|
|
88745
|
-
await connection.untaggedVanished(untagged, { path:
|
|
89147
|
+
await connection.untaggedVanished(untagged, { path: path27, uidNext: false, uidValidity: false });
|
|
88746
89148
|
},
|
|
88747
89149
|
// Untagged FETCH during SELECT/EXAMINE: only occurs with QRESYNC, delivering
|
|
88748
89150
|
// updated flags for messages that changed since the client's last modseq.
|
|
88749
89151
|
FETCH: async (untagged) => {
|
|
88750
|
-
await connection.untaggedFetch(untagged, { path:
|
|
89152
|
+
await connection.untaggedFetch(untagged, { path: path27, uidNext: false, uidValidity: false });
|
|
88751
89153
|
}
|
|
88752
89154
|
}
|
|
88753
89155
|
});
|
|
@@ -88761,13 +89163,13 @@ var require_select = __commonJS({
|
|
|
88761
89163
|
}
|
|
88762
89164
|
let currentMailbox = connection.mailbox;
|
|
88763
89165
|
connection.mailbox = false;
|
|
88764
|
-
if (currentMailbox && currentMailbox.path !==
|
|
89166
|
+
if (currentMailbox && currentMailbox.path !== path27) {
|
|
88765
89167
|
connection.emit("mailboxClose", currentMailbox);
|
|
88766
89168
|
}
|
|
88767
89169
|
connection.mailbox = map;
|
|
88768
89170
|
connection.currentSelectCommand = selectCommand;
|
|
88769
89171
|
connection.state = connection.states.SELECTED;
|
|
88770
|
-
if (!currentMailbox || currentMailbox.path !==
|
|
89172
|
+
if (!currentMailbox || currentMailbox.path !== path27) {
|
|
88771
89173
|
connection.emit("mailboxOpen", connection.mailbox);
|
|
88772
89174
|
}
|
|
88773
89175
|
response.next();
|
|
@@ -88982,17 +89384,17 @@ var require_create = __commonJS({
|
|
|
88982
89384
|
"node_modules/imapflow/lib/commands/create.js"(exports, module) {
|
|
88983
89385
|
"use strict";
|
|
88984
89386
|
var { encodePath, normalizePath, getStatusCode, enhanceCommandError } = require_tools2();
|
|
88985
|
-
module.exports = async (connection,
|
|
89387
|
+
module.exports = async (connection, path27) => {
|
|
88986
89388
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
88987
89389
|
return;
|
|
88988
89390
|
}
|
|
88989
|
-
|
|
89391
|
+
path27 = normalizePath(connection, path27);
|
|
88990
89392
|
let response;
|
|
88991
89393
|
try {
|
|
88992
89394
|
let map = {
|
|
88993
|
-
path:
|
|
89395
|
+
path: path27
|
|
88994
89396
|
};
|
|
88995
|
-
response = await connection.exec("CREATE", [{ type: "ATOM", value: encodePath(connection,
|
|
89397
|
+
response = await connection.exec("CREATE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
88996
89398
|
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
89399
|
if (section) {
|
|
88998
89400
|
let key;
|
|
@@ -89018,13 +89420,13 @@ var require_create = __commonJS({
|
|
|
89018
89420
|
}
|
|
89019
89421
|
map.created = true;
|
|
89020
89422
|
response.next();
|
|
89021
|
-
await connection.run("SUBSCRIBE",
|
|
89423
|
+
await connection.run("SUBSCRIBE", path27);
|
|
89022
89424
|
return map;
|
|
89023
89425
|
} catch (err) {
|
|
89024
89426
|
let errorCode = getStatusCode(err.response);
|
|
89025
89427
|
if (errorCode === "ALREADYEXISTS") {
|
|
89026
89428
|
return {
|
|
89027
|
-
path:
|
|
89429
|
+
path: path27,
|
|
89028
89430
|
created: false
|
|
89029
89431
|
};
|
|
89030
89432
|
}
|
|
@@ -89041,20 +89443,20 @@ var require_delete = __commonJS({
|
|
|
89041
89443
|
"node_modules/imapflow/lib/commands/delete.js"(exports, module) {
|
|
89042
89444
|
"use strict";
|
|
89043
89445
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89044
|
-
module.exports = async (connection,
|
|
89446
|
+
module.exports = async (connection, path27) => {
|
|
89045
89447
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89046
89448
|
return;
|
|
89047
89449
|
}
|
|
89048
|
-
|
|
89049
|
-
if (connection.state === connection.states.SELECTED && connection.mailbox.path ===
|
|
89450
|
+
path27 = normalizePath(connection, path27);
|
|
89451
|
+
if (connection.state === connection.states.SELECTED && connection.mailbox.path === path27) {
|
|
89050
89452
|
await connection.run("CLOSE");
|
|
89051
89453
|
}
|
|
89052
89454
|
let response;
|
|
89053
89455
|
try {
|
|
89054
89456
|
let map = {
|
|
89055
|
-
path:
|
|
89457
|
+
path: path27
|
|
89056
89458
|
};
|
|
89057
|
-
response = await connection.exec("DELETE", [{ type: "ATOM", value: encodePath(connection,
|
|
89459
|
+
response = await connection.exec("DELETE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89058
89460
|
response.next();
|
|
89059
89461
|
return map;
|
|
89060
89462
|
} catch (err) {
|
|
@@ -89071,23 +89473,23 @@ var require_rename = __commonJS({
|
|
|
89071
89473
|
"node_modules/imapflow/lib/commands/rename.js"(exports, module) {
|
|
89072
89474
|
"use strict";
|
|
89073
89475
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89074
|
-
module.exports = async (connection,
|
|
89476
|
+
module.exports = async (connection, path27, newPath) => {
|
|
89075
89477
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89076
89478
|
return;
|
|
89077
89479
|
}
|
|
89078
|
-
|
|
89480
|
+
path27 = normalizePath(connection, path27);
|
|
89079
89481
|
newPath = normalizePath(connection, newPath);
|
|
89080
|
-
if (connection.state === connection.states.SELECTED && connection.mailbox.path ===
|
|
89482
|
+
if (connection.state === connection.states.SELECTED && connection.mailbox.path === path27) {
|
|
89081
89483
|
await connection.run("CLOSE");
|
|
89082
89484
|
}
|
|
89083
89485
|
let response;
|
|
89084
89486
|
try {
|
|
89085
89487
|
let map = {
|
|
89086
|
-
path:
|
|
89488
|
+
path: path27,
|
|
89087
89489
|
newPath
|
|
89088
89490
|
};
|
|
89089
89491
|
response = await connection.exec("RENAME", [
|
|
89090
|
-
{ type: "ATOM", value: encodePath(connection,
|
|
89492
|
+
{ type: "ATOM", value: encodePath(connection, path27) },
|
|
89091
89493
|
{ type: "ATOM", value: encodePath(connection, newPath) }
|
|
89092
89494
|
]);
|
|
89093
89495
|
response.next();
|
|
@@ -89134,14 +89536,14 @@ var require_subscribe = __commonJS({
|
|
|
89134
89536
|
"node_modules/imapflow/lib/commands/subscribe.js"(exports, module) {
|
|
89135
89537
|
"use strict";
|
|
89136
89538
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89137
|
-
module.exports = async (connection,
|
|
89539
|
+
module.exports = async (connection, path27) => {
|
|
89138
89540
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89139
89541
|
return;
|
|
89140
89542
|
}
|
|
89141
|
-
|
|
89543
|
+
path27 = normalizePath(connection, path27);
|
|
89142
89544
|
let response;
|
|
89143
89545
|
try {
|
|
89144
|
-
response = await connection.exec("SUBSCRIBE", [{ type: "ATOM", value: encodePath(connection,
|
|
89546
|
+
response = await connection.exec("SUBSCRIBE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89145
89547
|
response.next();
|
|
89146
89548
|
return true;
|
|
89147
89549
|
} catch (err) {
|
|
@@ -89158,14 +89560,14 @@ var require_unsubscribe = __commonJS({
|
|
|
89158
89560
|
"node_modules/imapflow/lib/commands/unsubscribe.js"(exports, module) {
|
|
89159
89561
|
"use strict";
|
|
89160
89562
|
var { encodePath, normalizePath, enhanceCommandError } = require_tools2();
|
|
89161
|
-
module.exports = async (connection,
|
|
89563
|
+
module.exports = async (connection, path27) => {
|
|
89162
89564
|
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state)) {
|
|
89163
89565
|
return;
|
|
89164
89566
|
}
|
|
89165
|
-
|
|
89567
|
+
path27 = normalizePath(connection, path27);
|
|
89166
89568
|
let response;
|
|
89167
89569
|
try {
|
|
89168
|
-
response = await connection.exec("UNSUBSCRIBE", [{ type: "ATOM", value: encodePath(connection,
|
|
89570
|
+
response = await connection.exec("UNSUBSCRIBE", [{ type: "ATOM", value: encodePath(connection, path27) }]);
|
|
89169
89571
|
response.next();
|
|
89170
89572
|
return true;
|
|
89171
89573
|
} catch (err) {
|
|
@@ -89971,11 +90373,11 @@ var require_status = __commonJS({
|
|
|
89971
90373
|
var { encodePath, normalizePath, buildStatusQueryAttributes, isRev2Active } = require_tools2();
|
|
89972
90374
|
var { parseStatusList } = require_status_fields();
|
|
89973
90375
|
var MAILBOX_UPDATERS = {
|
|
89974
|
-
messages: (value, connection,
|
|
90376
|
+
messages: (value, connection, path27) => {
|
|
89975
90377
|
let prevCount = connection.mailbox.exists;
|
|
89976
90378
|
if (prevCount !== value) {
|
|
89977
90379
|
connection.mailbox.exists = value;
|
|
89978
|
-
connection.emit("exists", { path:
|
|
90380
|
+
connection.emit("exists", { path: path27, count: value, prevCount });
|
|
89979
90381
|
}
|
|
89980
90382
|
},
|
|
89981
90383
|
uidNext: (value, connection) => {
|
|
@@ -89985,28 +90387,28 @@ var require_status = __commonJS({
|
|
|
89985
90387
|
connection.mailbox.highestModseq = value;
|
|
89986
90388
|
}
|
|
89987
90389
|
};
|
|
89988
|
-
module.exports = async (connection,
|
|
89989
|
-
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !
|
|
90390
|
+
module.exports = async (connection, path27, query) => {
|
|
90391
|
+
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path27) {
|
|
89990
90392
|
return false;
|
|
89991
90393
|
}
|
|
89992
|
-
|
|
89993
|
-
let encodedPath = encodePath(connection,
|
|
90394
|
+
path27 = normalizePath(connection, path27);
|
|
90395
|
+
let encodedPath = encodePath(connection, path27);
|
|
89994
90396
|
let attributes = [{ type: encodedPath.indexOf("&") >= 0 ? "STRING" : "ATOM", value: encodedPath }];
|
|
89995
90397
|
let queryAttributes = buildStatusQueryAttributes(connection, query);
|
|
89996
90398
|
let syntheticRecent = query && query.recent && isRev2Active(connection);
|
|
89997
90399
|
if (!queryAttributes.length) {
|
|
89998
|
-
return syntheticRecent ? { path:
|
|
90400
|
+
return syntheticRecent ? { path: path27, recent: 0 } : false;
|
|
89999
90401
|
}
|
|
90000
90402
|
attributes.push(queryAttributes);
|
|
90001
90403
|
let response;
|
|
90002
90404
|
try {
|
|
90003
|
-
let map = { path:
|
|
90405
|
+
let map = { path: path27 };
|
|
90004
90406
|
response = await connection.exec("STATUS", attributes, {
|
|
90005
90407
|
untagged: {
|
|
90006
90408
|
// STATUS response: * STATUS <mailbox> (<key> <value> <key> <value> ...)
|
|
90007
90409
|
// Parsed as alternating key-value pairs (i % 2 pattern).
|
|
90008
90410
|
STATUS: async (untagged) => {
|
|
90009
|
-
let updateCurrent = connection.state === connection.states.SELECTED &&
|
|
90411
|
+
let updateCurrent = connection.state === connection.states.SELECTED && path27 === connection.mailbox.path;
|
|
90010
90412
|
let list = untagged.attributes && Array.isArray(untagged.attributes[1]) ? untagged.attributes[1] : false;
|
|
90011
90413
|
if (!list) {
|
|
90012
90414
|
return;
|
|
@@ -90014,7 +90416,7 @@ var require_status = __commonJS({
|
|
|
90014
90416
|
parseStatusList(list, (key, value) => {
|
|
90015
90417
|
map[key] = value;
|
|
90016
90418
|
if (updateCurrent && MAILBOX_UPDATERS[key]) {
|
|
90017
|
-
MAILBOX_UPDATERS[key](value, connection,
|
|
90419
|
+
MAILBOX_UPDATERS[key](value, connection, path27);
|
|
90018
90420
|
}
|
|
90019
90421
|
});
|
|
90020
90422
|
}
|
|
@@ -90027,9 +90429,9 @@ var require_status = __commonJS({
|
|
|
90027
90429
|
return map;
|
|
90028
90430
|
} catch (err) {
|
|
90029
90431
|
if (err.responseStatus === "NO") {
|
|
90030
|
-
let folders = await connection.run("LIST", "",
|
|
90432
|
+
let folders = await connection.run("LIST", "", path27, { listOnly: true });
|
|
90031
90433
|
if (folders && !folders.length) {
|
|
90032
|
-
let error2 = new Error(`Mailbox doesn't exist: ${
|
|
90434
|
+
let error2 = new Error(`Mailbox doesn't exist: ${path27}`);
|
|
90033
90435
|
error2.code = "NotFound";
|
|
90034
90436
|
error2.response = err;
|
|
90035
90437
|
throw error2;
|
|
@@ -90176,15 +90578,15 @@ var require_quota = __commonJS({
|
|
|
90176
90578
|
"node_modules/imapflow/lib/commands/quota.js"(exports, module) {
|
|
90177
90579
|
"use strict";
|
|
90178
90580
|
var { encodePath, normalizePath, enhanceCommandError, parseUintValue, isUnsafeKey } = require_tools2();
|
|
90179
|
-
module.exports = async (connection,
|
|
90180
|
-
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !
|
|
90581
|
+
module.exports = async (connection, path27) => {
|
|
90582
|
+
if (![connection.states.AUTHENTICATED, connection.states.SELECTED].includes(connection.state) || !path27) {
|
|
90181
90583
|
return;
|
|
90182
90584
|
}
|
|
90183
90585
|
if (!connection.capabilities.has("QUOTA")) {
|
|
90184
90586
|
return false;
|
|
90185
90587
|
}
|
|
90186
|
-
|
|
90187
|
-
let map = { path:
|
|
90588
|
+
path27 = normalizePath(connection, path27);
|
|
90589
|
+
let map = { path: path27 };
|
|
90188
90590
|
let processQuotaResponse = (untagged) => {
|
|
90189
90591
|
let attributes = untagged.attributes && untagged.attributes[1];
|
|
90190
90592
|
if (!attributes || !attributes.length) {
|
|
@@ -90224,7 +90626,7 @@ var require_quota = __commonJS({
|
|
|
90224
90626
|
let quotaFound = false;
|
|
90225
90627
|
let response;
|
|
90226
90628
|
try {
|
|
90227
|
-
response = await connection.exec("GETQUOTAROOT", [{ type: "ATOM", value: encodePath(connection,
|
|
90629
|
+
response = await connection.exec("GETQUOTAROOT", [{ type: "ATOM", value: encodePath(connection, path27) }], {
|
|
90228
90630
|
untagged: {
|
|
90229
90631
|
// QUOTAROOT response tells us which quota root applies to this mailbox.
|
|
90230
90632
|
// A mailbox may have zero or one quota root.
|
|
@@ -90367,15 +90769,15 @@ var require_idle = __commonJS({
|
|
|
90367
90769
|
}
|
|
90368
90770
|
}
|
|
90369
90771
|
async function pollOnce2(connection, session) {
|
|
90370
|
-
let
|
|
90772
|
+
let path27 = connection.mailbox && connection.mailbox.path;
|
|
90371
90773
|
switch (connection.missingIdleCommand) {
|
|
90372
90774
|
case "SELECT":
|
|
90373
90775
|
connection.log.debug({ src: "c", msg: `Running SELECT to detect changes in folder`, cid: connection.id });
|
|
90374
|
-
await connection.runInternal("SELECT",
|
|
90776
|
+
await connection.runInternal("SELECT", path27, { readOnly: session.selectCommand.command === "EXAMINE" });
|
|
90375
90777
|
break;
|
|
90376
90778
|
case "STATUS": {
|
|
90377
90779
|
connection.log.debug({ src: "c", msg: `Running STATUS to detect changes in folder`, cid: connection.id });
|
|
90378
|
-
let status = await connection.runInternal("STATUS",
|
|
90780
|
+
let status = await connection.runInternal("STATUS", path27, {
|
|
90379
90781
|
messages: true,
|
|
90380
90782
|
uidNext: true,
|
|
90381
90783
|
uidValidity: true,
|
|
@@ -92062,12 +92464,12 @@ var require_imap_flow = __commonJS({
|
|
|
92062
92464
|
this.emit("flags", updateEvent);
|
|
92063
92465
|
}
|
|
92064
92466
|
}
|
|
92065
|
-
async ensureSelectedMailbox(
|
|
92066
|
-
if (!
|
|
92467
|
+
async ensureSelectedMailbox(path27) {
|
|
92468
|
+
if (!path27) {
|
|
92067
92469
|
return false;
|
|
92068
92470
|
}
|
|
92069
|
-
if (!this.mailbox || !comparePaths(this, this.mailbox.path,
|
|
92070
|
-
return await this.mailboxOpen(
|
|
92471
|
+
if (!this.mailbox || !comparePaths(this, this.mailbox.path, path27)) {
|
|
92472
|
+
return await this.mailboxOpen(path27);
|
|
92071
92473
|
}
|
|
92072
92474
|
return true;
|
|
92073
92475
|
}
|
|
@@ -92482,9 +92884,9 @@ var require_imap_flow = __commonJS({
|
|
|
92482
92884
|
* let quota = await client.getQuota();
|
|
92483
92885
|
* console.log(quota.storage.used, quota.storage.limit)
|
|
92484
92886
|
*/
|
|
92485
|
-
async getQuota(
|
|
92486
|
-
|
|
92487
|
-
return await this.run("QUOTA",
|
|
92887
|
+
async getQuota(path27) {
|
|
92888
|
+
path27 = path27 || "INBOX";
|
|
92889
|
+
return await this.run("QUOTA", path27);
|
|
92488
92890
|
}
|
|
92489
92891
|
/**
|
|
92490
92892
|
* @typedef {Object} ListResponse
|
|
@@ -92594,8 +92996,8 @@ var require_imap_flow = __commonJS({
|
|
|
92594
92996
|
* console.log(info.path);
|
|
92595
92997
|
* // "INBOX.parent.child" // assumes "INBOX." as namespace prefix and "." as delimiter
|
|
92596
92998
|
*/
|
|
92597
|
-
async mailboxCreate(
|
|
92598
|
-
return await this.run("CREATE",
|
|
92999
|
+
async mailboxCreate(path27) {
|
|
93000
|
+
return await this.run("CREATE", path27);
|
|
92599
93001
|
}
|
|
92600
93002
|
/**
|
|
92601
93003
|
* @typedef {Object} MailboxRenameResponse
|
|
@@ -92616,8 +93018,8 @@ var require_imap_flow = __commonJS({
|
|
|
92616
93018
|
* console.log(info.newPath);
|
|
92617
93019
|
* // "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix
|
|
92618
93020
|
*/
|
|
92619
|
-
async mailboxRename(
|
|
92620
|
-
return await this.run("RENAME",
|
|
93021
|
+
async mailboxRename(path27, newPath) {
|
|
93022
|
+
return await this.run("RENAME", path27, newPath);
|
|
92621
93023
|
}
|
|
92622
93024
|
/**
|
|
92623
93025
|
* @typedef {Object} MailboxDeleteResponse
|
|
@@ -92636,8 +93038,8 @@ var require_imap_flow = __commonJS({
|
|
|
92636
93038
|
* console.log(info.path);
|
|
92637
93039
|
* // "INBOX.Important stuff ❗️" // assumes "INBOX." as namespace prefix
|
|
92638
93040
|
*/
|
|
92639
|
-
async mailboxDelete(
|
|
92640
|
-
return await this.run("DELETE",
|
|
93041
|
+
async mailboxDelete(path27) {
|
|
93042
|
+
return await this.run("DELETE", path27);
|
|
92641
93043
|
}
|
|
92642
93044
|
/**
|
|
92643
93045
|
* Subscribes to a mailbox
|
|
@@ -92648,8 +93050,8 @@ var require_imap_flow = __commonJS({
|
|
|
92648
93050
|
* @example
|
|
92649
93051
|
* await client.mailboxSubscribe('Important stuff ❗️');
|
|
92650
93052
|
*/
|
|
92651
|
-
async mailboxSubscribe(
|
|
92652
|
-
return await this.run("SUBSCRIBE",
|
|
93053
|
+
async mailboxSubscribe(path27) {
|
|
93054
|
+
return await this.run("SUBSCRIBE", path27);
|
|
92653
93055
|
}
|
|
92654
93056
|
/**
|
|
92655
93057
|
* Unsubscribes from a mailbox
|
|
@@ -92660,8 +93062,8 @@ var require_imap_flow = __commonJS({
|
|
|
92660
93062
|
* @example
|
|
92661
93063
|
* await client.mailboxUnsubscribe('Important stuff ❗️');
|
|
92662
93064
|
*/
|
|
92663
|
-
async mailboxUnsubscribe(
|
|
92664
|
-
return await this.run("UNSUBSCRIBE",
|
|
93065
|
+
async mailboxUnsubscribe(path27) {
|
|
93066
|
+
return await this.run("UNSUBSCRIBE", path27);
|
|
92665
93067
|
}
|
|
92666
93068
|
/**
|
|
92667
93069
|
* Opens a mailbox to access messages. You can perform message operations only against an opened mailbox.
|
|
@@ -92679,8 +93081,8 @@ var require_imap_flow = __commonJS({
|
|
|
92679
93081
|
* console.log(mailbox.exists);
|
|
92680
93082
|
* // 125
|
|
92681
93083
|
*/
|
|
92682
|
-
async mailboxOpen(
|
|
92683
|
-
return await this.run("SELECT",
|
|
93084
|
+
async mailboxOpen(path27, options) {
|
|
93085
|
+
return await this.run("SELECT", path27, options);
|
|
92684
93086
|
}
|
|
92685
93087
|
/**
|
|
92686
93088
|
* Closes a previously opened mailbox
|
|
@@ -92727,8 +93129,8 @@ var require_imap_flow = __commonJS({
|
|
|
92727
93129
|
* console.log(status.unseen);
|
|
92728
93130
|
* // 123
|
|
92729
93131
|
*/
|
|
92730
|
-
async status(
|
|
92731
|
-
return await this.run("STATUS",
|
|
93132
|
+
async status(path27, query) {
|
|
93133
|
+
return await this.run("STATUS", path27, query);
|
|
92732
93134
|
}
|
|
92733
93135
|
/**
|
|
92734
93136
|
* Starts listening for new or deleted messages from the currently opened mailbox. Only required if {@link ImapFlow#disableAutoIdle} is set to `true`
|
|
@@ -92982,8 +93384,8 @@ var require_imap_flow = __commonJS({
|
|
|
92982
93384
|
* @example
|
|
92983
93385
|
* await client.append('INBOX', rawMessageBuffer, ['\\Seen'], new Date(2000, 1, 1));
|
|
92984
93386
|
*/
|
|
92985
|
-
async append(
|
|
92986
|
-
return await this.run("APPEND",
|
|
93387
|
+
async append(path27, content, flags, idate) {
|
|
93388
|
+
return await this.run("APPEND", path27, content, flags, idate) || false;
|
|
92987
93389
|
}
|
|
92988
93390
|
/**
|
|
92989
93391
|
* @typedef {Object} CopyResponseObject
|
|
@@ -93827,7 +94229,7 @@ var require_imap_flow = __commonJS({
|
|
|
93827
94229
|
await new Promise((resolve2) => setImmediate(resolve2));
|
|
93828
94230
|
}
|
|
93829
94231
|
const lock = this.locks.shift();
|
|
93830
|
-
const { resolve, reject, path:
|
|
94232
|
+
const { resolve, reject, path: path27, options, lockId } = lock;
|
|
93831
94233
|
if (lock.acquireTimer) {
|
|
93832
94234
|
clearTimeout(lock.acquireTimer);
|
|
93833
94235
|
lock.acquireTimer = null;
|
|
@@ -93843,7 +94245,7 @@ var require_imap_flow = __commonJS({
|
|
|
93843
94245
|
this.log.warn({
|
|
93844
94246
|
msg: "Mailbox lock held for a long time",
|
|
93845
94247
|
lockId: lock.lockId,
|
|
93846
|
-
path:
|
|
94248
|
+
path: path27,
|
|
93847
94249
|
heldFor: Date.now() - lock.heldAt,
|
|
93848
94250
|
/* c8 ignore next */
|
|
93849
94251
|
// the held-lock-warning diagnostic with a description set is a timing-dependent log detail
|
|
@@ -93879,52 +94281,52 @@ var require_imap_flow = __commonJS({
|
|
|
93879
94281
|
}
|
|
93880
94282
|
};
|
|
93881
94283
|
if (!this.usable || !this.socket || this.socket.destroyed) {
|
|
93882
|
-
this.log.trace({ msg: "Failed to acquire mailbox lock", path:
|
|
94284
|
+
this.log.trace({ msg: "Failed to acquire mailbox lock", path: path27, lockId, idling: this.idling });
|
|
93883
94285
|
let error2 = new Error("Connection not available");
|
|
93884
94286
|
error2.code = "NoConnection";
|
|
93885
94287
|
reject(error2);
|
|
93886
94288
|
continue;
|
|
93887
94289
|
}
|
|
93888
|
-
if (this.mailbox && this.mailbox.path ===
|
|
94290
|
+
if (this.mailbox && this.mailbox.path === path27 && !!this.mailbox.readOnly === !!options.readOnly) {
|
|
93889
94291
|
this.log.trace({
|
|
93890
94292
|
msg: "Mailbox lock acquired [existing]",
|
|
93891
|
-
path:
|
|
94293
|
+
path: path27,
|
|
93892
94294
|
lockId,
|
|
93893
94295
|
idling: this.idling,
|
|
93894
94296
|
...options.description && { description: options.description }
|
|
93895
94297
|
});
|
|
93896
94298
|
this.currentLock = lock;
|
|
93897
94299
|
armHeldTimer();
|
|
93898
|
-
resolve({ path:
|
|
94300
|
+
resolve({ path: path27, release });
|
|
93899
94301
|
break;
|
|
93900
94302
|
}
|
|
93901
94303
|
try {
|
|
93902
|
-
await this.mailboxOpen(
|
|
94304
|
+
await this.mailboxOpen(path27, options);
|
|
93903
94305
|
this.log.trace({
|
|
93904
94306
|
msg: "Mailbox lock acquired [selected]",
|
|
93905
|
-
path:
|
|
94307
|
+
path: path27,
|
|
93906
94308
|
lockId,
|
|
93907
94309
|
idling: this.idling,
|
|
93908
94310
|
...options.description && { description: options.description }
|
|
93909
94311
|
});
|
|
93910
94312
|
this.currentLock = lock;
|
|
93911
94313
|
armHeldTimer();
|
|
93912
|
-
resolve({ path:
|
|
94314
|
+
resolve({ path: path27, release });
|
|
93913
94315
|
break;
|
|
93914
94316
|
} catch (err) {
|
|
93915
94317
|
if (err.responseStatus === "NO") {
|
|
93916
94318
|
try {
|
|
93917
|
-
let folders = await this.run("LIST", "",
|
|
94319
|
+
let folders = await this.run("LIST", "", path27, { listOnly: true });
|
|
93918
94320
|
if (!folders || !folders.length) {
|
|
93919
94321
|
err.mailboxMissing = true;
|
|
93920
94322
|
}
|
|
93921
94323
|
} catch (E) {
|
|
93922
|
-
this.log.trace({ msg: "Failed to verify failed mailbox", path:
|
|
94324
|
+
this.log.trace({ msg: "Failed to verify failed mailbox", path: path27, err: E });
|
|
93923
94325
|
}
|
|
93924
94326
|
}
|
|
93925
94327
|
this.log.trace({
|
|
93926
94328
|
msg: "Failed to acquire mailbox lock",
|
|
93927
|
-
path:
|
|
94329
|
+
path: path27,
|
|
93928
94330
|
lockId,
|
|
93929
94331
|
idling: this.idling,
|
|
93930
94332
|
...options.description && { description: options.description },
|
|
@@ -93963,13 +94365,13 @@ var require_imap_flow = __commonJS({
|
|
|
93963
94365
|
* lock.release();
|
|
93964
94366
|
* }
|
|
93965
94367
|
*/
|
|
93966
|
-
getMailboxLock(
|
|
94368
|
+
getMailboxLock(path27, options) {
|
|
93967
94369
|
options = options || {};
|
|
93968
|
-
|
|
94370
|
+
path27 = normalizePath(this, path27);
|
|
93969
94371
|
let lockId = ++this.lockCounter;
|
|
93970
94372
|
this.log.trace({
|
|
93971
94373
|
msg: "Requesting lock",
|
|
93972
|
-
path:
|
|
94374
|
+
path: path27,
|
|
93973
94375
|
lockId,
|
|
93974
94376
|
...options.description && { description: options.description },
|
|
93975
94377
|
activeLock: this.currentLock ? {
|
|
@@ -93978,7 +94380,7 @@ var require_imap_flow = __commonJS({
|
|
|
93978
94380
|
} : null
|
|
93979
94381
|
});
|
|
93980
94382
|
let lockPromise = new Promise((resolve, reject) => {
|
|
93981
|
-
let lockEntry = { resolve, reject, path:
|
|
94383
|
+
let lockEntry = { resolve, reject, path: path27, options, lockId };
|
|
93982
94384
|
this.locks.push(lockEntry);
|
|
93983
94385
|
if (Number(options.acquireTimeout) > 0) {
|
|
93984
94386
|
lockEntry.acquireTimer = setTimeout(() => {
|
|
@@ -94067,16 +94469,16 @@ var require_imap_flow = __commonJS({
|
|
|
94067
94469
|
});
|
|
94068
94470
|
|
|
94069
94471
|
// src/mail/mail-fetcher.ts
|
|
94070
|
-
import
|
|
94071
|
-
import
|
|
94472
|
+
import fs24 from "node:fs/promises";
|
|
94473
|
+
import path25 from "node:path";
|
|
94072
94474
|
async function saveAttachments(attachments, downloadDir) {
|
|
94073
94475
|
if (attachments.length === 0) return [];
|
|
94074
|
-
await
|
|
94476
|
+
await fs24.mkdir(downloadDir, { recursive: true });
|
|
94075
94477
|
const saved = [];
|
|
94076
94478
|
for (const a of attachments) {
|
|
94077
|
-
const name =
|
|
94078
|
-
const savedPath =
|
|
94079
|
-
await
|
|
94479
|
+
const name = path25.basename(a.filename) || "attachment";
|
|
94480
|
+
const savedPath = path25.join(downloadDir, name);
|
|
94481
|
+
await fs24.writeFile(savedPath, a.content);
|
|
94080
94482
|
saved.push({ filename: name, savedPath, size: a.content.length });
|
|
94081
94483
|
}
|
|
94082
94484
|
return saved;
|
|
@@ -94207,7 +94609,7 @@ var init_mail_fetcher = __esm({
|
|
|
94207
94609
|
|
|
94208
94610
|
// src/tools/fetch-mail.ts
|
|
94209
94611
|
import os17 from "node:os";
|
|
94210
|
-
import
|
|
94612
|
+
import path26 from "node:path";
|
|
94211
94613
|
function registerFetchMailTool(server, deps = {}) {
|
|
94212
94614
|
const makeFetcher = deps.fetcherFactory ?? ((creds) => new ImapflowMailFetcher(creds));
|
|
94213
94615
|
server.registerTool(
|
|
@@ -94269,7 +94671,7 @@ var init_fetch_mail = __esm({
|
|
|
94269
94671
|
init_mail_fetcher();
|
|
94270
94672
|
init_auth_error();
|
|
94271
94673
|
init_validate();
|
|
94272
|
-
DEFAULT_DOWNLOAD_DIR =
|
|
94674
|
+
DEFAULT_DOWNLOAD_DIR = path26.join(os17.homedir(), ".cogent", "mail-downloads");
|
|
94273
94675
|
}
|
|
94274
94676
|
});
|
|
94275
94677
|
|
|
@@ -94360,9 +94762,74 @@ var init_rotate_mail_creds = __esm({
|
|
|
94360
94762
|
|
|
94361
94763
|
// src/index.ts
|
|
94362
94764
|
var index_exports = {};
|
|
94765
|
+
function shutdown(reason) {
|
|
94766
|
+
if (shuttingDown) return;
|
|
94767
|
+
shuttingDown = true;
|
|
94768
|
+
try {
|
|
94769
|
+
logger.info(`Shutting down: ${reason}`);
|
|
94770
|
+
autoRelay.stop();
|
|
94771
|
+
withdrawBridge(process.cwd(), PROCESS_MARK);
|
|
94772
|
+
heartbeat.stop();
|
|
94773
|
+
if (cloudWsClient) {
|
|
94774
|
+
cloudWsClient.disconnect();
|
|
94775
|
+
}
|
|
94776
|
+
logger.close();
|
|
94777
|
+
} finally {
|
|
94778
|
+
process.exit(0);
|
|
94779
|
+
}
|
|
94780
|
+
}
|
|
94781
|
+
async function clientGone(reason) {
|
|
94782
|
+
if (draining || shuttingDown) return;
|
|
94783
|
+
draining = true;
|
|
94784
|
+
autoRelay.announceDraining();
|
|
94785
|
+
const busy = () => {
|
|
94786
|
+
const d = autoRelay.getDiagnostics();
|
|
94787
|
+
return { requests: stdoutDead ? [] : [...inFlightRequests.values()], wake: d.processing, queued: d.queueLength };
|
|
94788
|
+
};
|
|
94789
|
+
const b0 = busy();
|
|
94790
|
+
if (!b0.requests.length && !b0.wake && !b0.queued) return shutdown(reason);
|
|
94791
|
+
let capMs = drainCapMs(3e5);
|
|
94792
|
+
try {
|
|
94793
|
+
capMs = drainCapMs(getConfig().COGENT_TIMEOUT_MS);
|
|
94794
|
+
} catch {
|
|
94795
|
+
}
|
|
94796
|
+
logger.info(
|
|
94797
|
+
`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}`
|
|
94798
|
+
);
|
|
94799
|
+
cancelPresenceRetry();
|
|
94800
|
+
heartbeat.stop();
|
|
94801
|
+
cloudWsClient?.disconnect();
|
|
94802
|
+
const t0 = Date.now();
|
|
94803
|
+
let b = b0;
|
|
94804
|
+
while (Date.now() - t0 < capMs) {
|
|
94805
|
+
b = busy();
|
|
94806
|
+
if (!b.requests.length && !b.wake && !b.queued) break;
|
|
94807
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
94808
|
+
}
|
|
94809
|
+
if (!stdoutDead) {
|
|
94810
|
+
await new Promise((r) => {
|
|
94811
|
+
const t = setTimeout(r, 1e3);
|
|
94812
|
+
try {
|
|
94813
|
+
process.stdout.write("", () => {
|
|
94814
|
+
clearTimeout(t);
|
|
94815
|
+
r();
|
|
94816
|
+
});
|
|
94817
|
+
} catch {
|
|
94818
|
+
clearTimeout(t);
|
|
94819
|
+
r();
|
|
94820
|
+
}
|
|
94821
|
+
});
|
|
94822
|
+
}
|
|
94823
|
+
const left = b.requests.length || b.wake || b.queued;
|
|
94824
|
+
const undeliverable = stdoutDead && inFlightRequests.size ? ` (${inFlightRequests.size} MCP response(s) undeliverable: stdout closed)` : "";
|
|
94825
|
+
shutdown(
|
|
94826
|
+
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}`
|
|
94827
|
+
);
|
|
94828
|
+
}
|
|
94363
94829
|
async function main() {
|
|
94830
|
+
markBridgeProcess(process.cwd(), SERVER_VERSION);
|
|
94364
94831
|
await runStartup();
|
|
94365
|
-
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION });
|
|
94832
|
+
const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: SERVER_INSTRUCTIONS });
|
|
94366
94833
|
registerRegisterPeerTool(server);
|
|
94367
94834
|
registerDeregisterPeerTool(server);
|
|
94368
94835
|
registerSendMessageTool(server);
|
|
@@ -94407,7 +94874,31 @@ async function main() {
|
|
|
94407
94874
|
});
|
|
94408
94875
|
}
|
|
94409
94876
|
const transport = new StdioServerTransport();
|
|
94877
|
+
transport.onclose = () => void clientGone("MCP transport closed");
|
|
94410
94878
|
await server.connect(transport);
|
|
94879
|
+
const sdkOnMessage = transport.onmessage;
|
|
94880
|
+
transport.onmessage = (msg) => {
|
|
94881
|
+
if ("method" in msg && "id" in msg) {
|
|
94882
|
+
const tool = msg.method === "tools/call" ? msg.params?.name : void 0;
|
|
94883
|
+
inFlightRequests.set(msg.id, typeof tool === "string" ? `tools/call ${tool}` : msg.method);
|
|
94884
|
+
} else if ("method" in msg && msg.method === "notifications/cancelled") {
|
|
94885
|
+
const id = msg.params?.requestId;
|
|
94886
|
+
if (typeof id === "string" || typeof id === "number") inFlightRequests.delete(id);
|
|
94887
|
+
}
|
|
94888
|
+
sdkOnMessage?.(msg);
|
|
94889
|
+
};
|
|
94890
|
+
const sdkSend = transport.send.bind(transport);
|
|
94891
|
+
transport.send = (msg) => {
|
|
94892
|
+
const settles = !("method" in msg) && "id" in msg ? msg.id : void 0;
|
|
94893
|
+
return sdkSend(msg).finally(() => {
|
|
94894
|
+
if (settles !== void 0) inFlightRequests.delete(settles);
|
|
94895
|
+
});
|
|
94896
|
+
};
|
|
94897
|
+
const stdinIsDevice = startedWithoutClient();
|
|
94898
|
+
if (!process.stdin.isTTY && !stdinIsDevice) {
|
|
94899
|
+
process.stdin.once("end", () => void clientGone("stdin EOF \u2014 the MCP client is gone"));
|
|
94900
|
+
process.stdin.once("close", () => void clientGone("stdin closed \u2014 the MCP client is gone"));
|
|
94901
|
+
}
|
|
94411
94902
|
process.stderr.write(
|
|
94412
94903
|
`${SERVER_NAME} v${SERVER_VERSION} running on stdio
|
|
94413
94904
|
`
|
|
@@ -94432,14 +94923,17 @@ async function main() {
|
|
|
94432
94923
|
"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
94924
|
);
|
|
94434
94925
|
}
|
|
94926
|
+
var shuttingDown, draining, stdoutDead, inFlightRequests;
|
|
94435
94927
|
var init_index = __esm({
|
|
94436
94928
|
"src/index.ts"() {
|
|
94437
94929
|
"use strict";
|
|
94438
94930
|
init_mcp();
|
|
94439
94931
|
init_stdio2();
|
|
94440
94932
|
init_constants();
|
|
94933
|
+
init_instructions();
|
|
94441
94934
|
init_npm_update_check();
|
|
94442
94935
|
init_startup();
|
|
94936
|
+
init_config();
|
|
94443
94937
|
init_logger();
|
|
94444
94938
|
init_register_peer();
|
|
94445
94939
|
init_send_message();
|
|
@@ -94455,10 +94949,12 @@ var init_index = __esm({
|
|
|
94455
94949
|
init_fetch_mail();
|
|
94456
94950
|
init_rotate_mail_creds();
|
|
94457
94951
|
init_heartbeat();
|
|
94952
|
+
init_wake_inflight();
|
|
94953
|
+
init_wake_ownership();
|
|
94458
94954
|
process.on("uncaughtException", (err) => {
|
|
94459
94955
|
if (err.code === "EPIPE") {
|
|
94460
|
-
|
|
94461
|
-
|
|
94956
|
+
stdoutDead = true;
|
|
94957
|
+
void clientGone("stdout EPIPE \u2014 the MCP client is gone");
|
|
94462
94958
|
return;
|
|
94463
94959
|
}
|
|
94464
94960
|
logger.error(`Uncaught exception: ${err.message}`, { stack: err.stack });
|
|
@@ -94467,26 +94963,12 @@ var init_index = __esm({
|
|
|
94467
94963
|
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
94468
94964
|
logger.error(`Unhandled rejection: ${msg}`);
|
|
94469
94965
|
});
|
|
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
|
-
});
|
|
94966
|
+
shuttingDown = false;
|
|
94967
|
+
draining = false;
|
|
94968
|
+
stdoutDead = false;
|
|
94969
|
+
process.on("SIGTERM", () => shutdown("SIGTERM received"));
|
|
94970
|
+
process.on("SIGINT", () => shutdown("SIGINT received"));
|
|
94971
|
+
inFlightRequests = /* @__PURE__ */ new Map();
|
|
94490
94972
|
main().catch((err) => {
|
|
94491
94973
|
const msg = err instanceof Error ? err.message : String(err);
|
|
94492
94974
|
logger.error(`Fatal startup error: ${msg}`);
|