@essentialai/cogent-plugin 3.14.1 → 3.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/bridge/cogent-bridge.mjs +521 -56
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cogent",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "Inter-session communication bridge for Claude Code with Slack integration. Enables CC agents and Slack team members to communicate in real time.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Essential AI Solutions",
|
package/bridge/cogent-bridge.mjs
CHANGED
|
@@ -1259,8 +1259,8 @@ var init_parseUtil = __esm({
|
|
|
1259
1259
|
init_errors();
|
|
1260
1260
|
init_en();
|
|
1261
1261
|
makeIssue = (params) => {
|
|
1262
|
-
const { data, path:
|
|
1263
|
-
const fullPath = [...
|
|
1262
|
+
const { data, path: path16, errorMaps, issueData } = params;
|
|
1263
|
+
const fullPath = [...path16, ...issueData.path || []];
|
|
1264
1264
|
const fullIssue = {
|
|
1265
1265
|
...issueData,
|
|
1266
1266
|
path: fullPath
|
|
@@ -1540,11 +1540,11 @@ var init_types = __esm({
|
|
|
1540
1540
|
init_parseUtil();
|
|
1541
1541
|
init_util();
|
|
1542
1542
|
ParseInputLazyPath = class {
|
|
1543
|
-
constructor(parent, value,
|
|
1543
|
+
constructor(parent, value, path16, key) {
|
|
1544
1544
|
this._cachedPath = [];
|
|
1545
1545
|
this.parent = parent;
|
|
1546
1546
|
this.data = value;
|
|
1547
|
-
this._path =
|
|
1547
|
+
this._path = path16;
|
|
1548
1548
|
this._key = key;
|
|
1549
1549
|
}
|
|
1550
1550
|
get path() {
|
|
@@ -4996,10 +4996,10 @@ function assignProp(target, prop, value) {
|
|
|
4996
4996
|
configurable: true
|
|
4997
4997
|
});
|
|
4998
4998
|
}
|
|
4999
|
-
function getElementAtPath(obj,
|
|
5000
|
-
if (!
|
|
4999
|
+
function getElementAtPath(obj, path16) {
|
|
5000
|
+
if (!path16)
|
|
5001
5001
|
return obj;
|
|
5002
|
-
return
|
|
5002
|
+
return path16.reduce((acc, key) => acc?.[key], obj);
|
|
5003
5003
|
}
|
|
5004
5004
|
function promiseAllObject(promisesObj) {
|
|
5005
5005
|
const keys = Object.keys(promisesObj);
|
|
@@ -5248,11 +5248,11 @@ function aborted(x, startIndex = 0) {
|
|
|
5248
5248
|
}
|
|
5249
5249
|
return false;
|
|
5250
5250
|
}
|
|
5251
|
-
function prefixIssues(
|
|
5251
|
+
function prefixIssues(path16, issues) {
|
|
5252
5252
|
return issues.map((iss) => {
|
|
5253
5253
|
var _a;
|
|
5254
5254
|
(_a = iss).path ?? (_a.path = []);
|
|
5255
|
-
iss.path.unshift(
|
|
5255
|
+
iss.path.unshift(path16);
|
|
5256
5256
|
return iss;
|
|
5257
5257
|
});
|
|
5258
5258
|
}
|
|
@@ -17058,8 +17058,8 @@ var require_utils = __commonJS({
|
|
|
17058
17058
|
}
|
|
17059
17059
|
return ind;
|
|
17060
17060
|
}
|
|
17061
|
-
function removeDotSegments(
|
|
17062
|
-
let input =
|
|
17061
|
+
function removeDotSegments(path16) {
|
|
17062
|
+
let input = path16;
|
|
17063
17063
|
const output = [];
|
|
17064
17064
|
let nextSlash = -1;
|
|
17065
17065
|
let len = 0;
|
|
@@ -17258,8 +17258,8 @@ var require_schemes = __commonJS({
|
|
|
17258
17258
|
wsComponent.secure = void 0;
|
|
17259
17259
|
}
|
|
17260
17260
|
if (wsComponent.resourceName) {
|
|
17261
|
-
const [
|
|
17262
|
-
wsComponent.path =
|
|
17261
|
+
const [path16, query] = wsComponent.resourceName.split("?");
|
|
17262
|
+
wsComponent.path = path16 && path16 !== "/" ? path16 : void 0;
|
|
17263
17263
|
wsComponent.query = query;
|
|
17264
17264
|
wsComponent.resourceName = void 0;
|
|
17265
17265
|
}
|
|
@@ -20612,12 +20612,12 @@ var require_dist = __commonJS({
|
|
|
20612
20612
|
throw new Error(`Unknown format "${name}"`);
|
|
20613
20613
|
return f;
|
|
20614
20614
|
};
|
|
20615
|
-
function addFormats(ajv, list,
|
|
20615
|
+
function addFormats(ajv, list, fs15, exportName) {
|
|
20616
20616
|
var _a;
|
|
20617
20617
|
var _b;
|
|
20618
20618
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
20619
20619
|
for (const f of list)
|
|
20620
|
-
ajv.addFormat(f,
|
|
20620
|
+
ajv.addFormat(f, fs15[f]);
|
|
20621
20621
|
}
|
|
20622
20622
|
module.exports = exports = formatsPlugin;
|
|
20623
20623
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -21729,8 +21729,8 @@ var require_parseUtil = __commonJS({
|
|
|
21729
21729
|
var errors_js_1 = require_errors2();
|
|
21730
21730
|
var en_js_1 = __importDefault(require_en());
|
|
21731
21731
|
var makeIssue2 = (params) => {
|
|
21732
|
-
const { data, path:
|
|
21733
|
-
const fullPath = [...
|
|
21732
|
+
const { data, path: path16, errorMaps, issueData } = params;
|
|
21733
|
+
const fullPath = [...path16, ...issueData.path || []];
|
|
21734
21734
|
const fullIssue = {
|
|
21735
21735
|
...issueData,
|
|
21736
21736
|
path: fullPath
|
|
@@ -21884,11 +21884,11 @@ var require_types2 = __commonJS({
|
|
|
21884
21884
|
var parseUtil_js_1 = require_parseUtil();
|
|
21885
21885
|
var util_js_1 = require_util2();
|
|
21886
21886
|
var ParseInputLazyPath2 = class {
|
|
21887
|
-
constructor(parent, value,
|
|
21887
|
+
constructor(parent, value, path16, key) {
|
|
21888
21888
|
this._cachedPath = [];
|
|
21889
21889
|
this.parent = parent;
|
|
21890
21890
|
this.data = value;
|
|
21891
|
-
this._path =
|
|
21891
|
+
this._path = path16;
|
|
21892
21892
|
this._key = key;
|
|
21893
21893
|
}
|
|
21894
21894
|
get path() {
|
|
@@ -25477,10 +25477,10 @@ var require_zod = __commonJS({
|
|
|
25477
25477
|
};
|
|
25478
25478
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25479
25479
|
exports.z = void 0;
|
|
25480
|
-
var
|
|
25481
|
-
exports.z =
|
|
25480
|
+
var z18 = __importStar(require_external());
|
|
25481
|
+
exports.z = z18;
|
|
25482
25482
|
__exportStar(require_external(), exports);
|
|
25483
|
-
exports.default =
|
|
25483
|
+
exports.default = z18;
|
|
25484
25484
|
}
|
|
25485
25485
|
});
|
|
25486
25486
|
|
|
@@ -26389,8 +26389,8 @@ var init_stdio2 = __esm({
|
|
|
26389
26389
|
// src/constants.ts
|
|
26390
26390
|
import { createRequire } from "node:module";
|
|
26391
26391
|
function resolveVersion() {
|
|
26392
|
-
if ("3.
|
|
26393
|
-
return "3.
|
|
26392
|
+
if ("3.15.0") {
|
|
26393
|
+
return "3.15.0";
|
|
26394
26394
|
}
|
|
26395
26395
|
try {
|
|
26396
26396
|
const require2 = createRequire(import.meta.url);
|
|
@@ -27562,7 +27562,7 @@ var init_http_backend = __esm({
|
|
|
27562
27562
|
* in cloud mode we ignore it and use this.sessionId (the cloud session).
|
|
27563
27563
|
*/
|
|
27564
27564
|
async registerPeer(peerId, _sessionId, cwd, label, clientVersion, mode, _channelSessionId, capabilities, workspaceId, threadId) {
|
|
27565
|
-
const
|
|
27565
|
+
const path16 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27566
27566
|
const body = {
|
|
27567
27567
|
peerId,
|
|
27568
27568
|
cwd,
|
|
@@ -27590,7 +27590,7 @@ var init_http_backend = __esm({
|
|
|
27590
27590
|
body.role = roleCap.slice("role:".length);
|
|
27591
27591
|
}
|
|
27592
27592
|
}
|
|
27593
|
-
return this.http.post(
|
|
27593
|
+
return this.http.post(path16, body);
|
|
27594
27594
|
}
|
|
27595
27595
|
/**
|
|
27596
27596
|
* Deregister a peer from the cloud session.
|
|
@@ -27599,9 +27599,9 @@ var init_http_backend = __esm({
|
|
|
27599
27599
|
* Returns true on success, false if the peer was not found.
|
|
27600
27600
|
*/
|
|
27601
27601
|
async deregisterPeer(peerId) {
|
|
27602
|
-
const
|
|
27602
|
+
const path16 = PATHS.peer.replace(":sessionId", this.sessionId).replace(":peerId", peerId);
|
|
27603
27603
|
try {
|
|
27604
|
-
await this.http.delete(
|
|
27604
|
+
await this.http.delete(path16, {});
|
|
27605
27605
|
return true;
|
|
27606
27606
|
} catch {
|
|
27607
27607
|
return false;
|
|
@@ -27621,8 +27621,8 @@ var init_http_backend = __esm({
|
|
|
27621
27621
|
* GET /api/sessions/:sessionId/peers
|
|
27622
27622
|
*/
|
|
27623
27623
|
async listPeers() {
|
|
27624
|
-
const
|
|
27625
|
-
const result = await this.http.get(
|
|
27624
|
+
const path16 = PATHS.peers.replace(":sessionId", this.sessionId);
|
|
27625
|
+
const result = await this.http.get(path16);
|
|
27626
27626
|
return result.peers;
|
|
27627
27627
|
}
|
|
27628
27628
|
/**
|
|
@@ -27630,8 +27630,8 @@ var init_http_backend = __esm({
|
|
|
27630
27630
|
* Calls the lightweight heartbeat endpoint on the cloud relay server.
|
|
27631
27631
|
*/
|
|
27632
27632
|
async updateLastSeen(peerId) {
|
|
27633
|
-
const
|
|
27634
|
-
await this.http.post(
|
|
27633
|
+
const path16 = PATHS.heartbeat.replace(":sessionId", this.sessionId);
|
|
27634
|
+
await this.http.post(path16, { peerId });
|
|
27635
27635
|
}
|
|
27636
27636
|
/**
|
|
27637
27637
|
* Record a message in the cloud session.
|
|
@@ -27642,7 +27642,7 @@ var init_http_backend = __esm({
|
|
|
27642
27642
|
* the input record to construct a full MessageRecord.
|
|
27643
27643
|
*/
|
|
27644
27644
|
async recordMessage(record2) {
|
|
27645
|
-
const
|
|
27645
|
+
const path16 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27646
27646
|
const body = {
|
|
27647
27647
|
fromPeerId: record2.fromPeerId,
|
|
27648
27648
|
toPeerId: record2.toPeerId,
|
|
@@ -27651,7 +27651,7 @@ var init_http_backend = __esm({
|
|
|
27651
27651
|
if (record2.isRelayEcho === true) {
|
|
27652
27652
|
body.isRelayEcho = true;
|
|
27653
27653
|
}
|
|
27654
|
-
const resp = await this.http.post(
|
|
27654
|
+
const resp = await this.http.post(path16, body);
|
|
27655
27655
|
return {
|
|
27656
27656
|
...record2,
|
|
27657
27657
|
id: resp.id,
|
|
@@ -27665,7 +27665,7 @@ var init_http_backend = __esm({
|
|
|
27665
27665
|
* Supports optional peerId filter and limit (default 300).
|
|
27666
27666
|
*/
|
|
27667
27667
|
async getHistory(peerId, limit, includeRelayEchoes, metadataOnly, dedupInferredEchoes) {
|
|
27668
|
-
const
|
|
27668
|
+
const path16 = PATHS.messages.replace(":sessionId", this.sessionId);
|
|
27669
27669
|
const query = {};
|
|
27670
27670
|
if (peerId) {
|
|
27671
27671
|
query.peerId = peerId;
|
|
@@ -27680,7 +27680,7 @@ var init_http_backend = __esm({
|
|
|
27680
27680
|
if (dedupInferredEchoes) {
|
|
27681
27681
|
query.dedupInferredEchoes = "true";
|
|
27682
27682
|
}
|
|
27683
|
-
const result = await this.http.get(
|
|
27683
|
+
const result = await this.http.get(path16, query);
|
|
27684
27684
|
return result.messages;
|
|
27685
27685
|
}
|
|
27686
27686
|
/**
|
|
@@ -27691,12 +27691,12 @@ var init_http_backend = __esm({
|
|
|
27691
27691
|
* so that get-history shows the actual response (not null).
|
|
27692
27692
|
*/
|
|
27693
27693
|
async updateMessageResponse(messageId, response, durationMs, pending) {
|
|
27694
|
-
const
|
|
27694
|
+
const path16 = PATHS.message.replace(":sessionId", this.sessionId).replace(":messageId", messageId);
|
|
27695
27695
|
const body = { response, durationMs };
|
|
27696
27696
|
if (pending === true) {
|
|
27697
27697
|
body.pending = true;
|
|
27698
27698
|
}
|
|
27699
|
-
await this.http.patch(
|
|
27699
|
+
await this.http.patch(path16, body);
|
|
27700
27700
|
}
|
|
27701
27701
|
/**
|
|
27702
27702
|
* Validate a session.
|
|
@@ -27838,8 +27838,8 @@ var init_http_client = __esm({
|
|
|
27838
27838
|
* Perform an authenticated GET request.
|
|
27839
27839
|
* Appends query parameters to the URL if provided.
|
|
27840
27840
|
*/
|
|
27841
|
-
async get(
|
|
27842
|
-
const url = new URL(
|
|
27841
|
+
async get(path16, query) {
|
|
27842
|
+
const url = new URL(path16, this.baseUrl);
|
|
27843
27843
|
if (query) {
|
|
27844
27844
|
for (const [k, v] of Object.entries(query)) {
|
|
27845
27845
|
url.searchParams.set(k, v);
|
|
@@ -27854,8 +27854,8 @@ var init_http_client = __esm({
|
|
|
27854
27854
|
/**
|
|
27855
27855
|
* Perform an authenticated POST request with a JSON body.
|
|
27856
27856
|
*/
|
|
27857
|
-
async post(
|
|
27858
|
-
const url = new URL(
|
|
27857
|
+
async post(path16, body) {
|
|
27858
|
+
const url = new URL(path16, this.baseUrl);
|
|
27859
27859
|
const resp = await this.fetchWithTimeout(url, {
|
|
27860
27860
|
method: "POST",
|
|
27861
27861
|
headers: this.headers(),
|
|
@@ -27873,8 +27873,8 @@ var init_http_client = __esm({
|
|
|
27873
27873
|
* Perform an authenticated PATCH request with a JSON body.
|
|
27874
27874
|
* Used to update existing resources (e.g., message response fields).
|
|
27875
27875
|
*/
|
|
27876
|
-
async patch(
|
|
27877
|
-
const url = new URL(
|
|
27876
|
+
async patch(path16, body) {
|
|
27877
|
+
const url = new URL(path16, this.baseUrl);
|
|
27878
27878
|
const resp = await this.fetchWithTimeout(url, {
|
|
27879
27879
|
method: "PATCH",
|
|
27880
27880
|
headers: this.headers(),
|
|
@@ -27897,8 +27897,8 @@ var init_http_client = __esm({
|
|
|
27897
27897
|
* "Malformed JSON in request body" 400 from cogent-server <=3.1.2 when
|
|
27898
27898
|
* any client (including third-party tools) DELETEd a peer without a body.
|
|
27899
27899
|
*/
|
|
27900
|
-
async delete(
|
|
27901
|
-
const url = new URL(
|
|
27900
|
+
async delete(path16, body) {
|
|
27901
|
+
const url = new URL(path16, this.baseUrl);
|
|
27902
27902
|
const headers = {
|
|
27903
27903
|
"Authorization": `Bearer ${this.token}`
|
|
27904
27904
|
};
|
|
@@ -32077,14 +32077,14 @@ var init_ws_client = __esm({
|
|
|
32077
32077
|
if (this.pollTimer) return;
|
|
32078
32078
|
const poll = async () => {
|
|
32079
32079
|
try {
|
|
32080
|
-
const
|
|
32080
|
+
const path16 = `/api/sessions/${this.opts.sessionId}/poll`;
|
|
32081
32081
|
const query = {
|
|
32082
32082
|
peerId: this.opts.peerId
|
|
32083
32083
|
};
|
|
32084
32084
|
if (this.lastMessageId) {
|
|
32085
32085
|
query.lastMessageId = this.lastMessageId;
|
|
32086
32086
|
}
|
|
32087
|
-
const result = await this.opts.http.get(
|
|
32087
|
+
const result = await this.opts.http.get(path16, query);
|
|
32088
32088
|
if (result.messages && result.messages.length > 0) {
|
|
32089
32089
|
this.opts.onMessages(result.messages);
|
|
32090
32090
|
this.lastMessageId = result.messages[result.messages.length - 1].id;
|
|
@@ -33882,8 +33882,61 @@ var init_startup = __esm({
|
|
|
33882
33882
|
}
|
|
33883
33883
|
});
|
|
33884
33884
|
|
|
33885
|
-
// src/
|
|
33885
|
+
// src/cloud/mail-credential-store.ts
|
|
33886
33886
|
import crypto3 from "node:crypto";
|
|
33887
|
+
import fs12 from "node:fs/promises";
|
|
33888
|
+
import path12 from "node:path";
|
|
33889
|
+
import os7 from "node:os";
|
|
33890
|
+
function defaultMailCredentialPath(cwd = process.cwd()) {
|
|
33891
|
+
const hash = crypto3.createHash("sha256").update(path12.resolve(cwd)).digest("hex").slice(0, 16);
|
|
33892
|
+
return path12.join(os7.homedir(), ".cogent", "mail-credentials", `${hash}.json`);
|
|
33893
|
+
}
|
|
33894
|
+
function resolveMailCredentialPath(credentialPath) {
|
|
33895
|
+
if (credentialPath) return credentialPath;
|
|
33896
|
+
const envOverride = process.env.COGENT_MAIL_CREDENTIALS_FILE;
|
|
33897
|
+
if (envOverride) return envOverride;
|
|
33898
|
+
return defaultMailCredentialPath();
|
|
33899
|
+
}
|
|
33900
|
+
async function loadMailCredentials(credentialPath) {
|
|
33901
|
+
const filePath = resolveMailCredentialPath(credentialPath);
|
|
33902
|
+
try {
|
|
33903
|
+
return JSON.parse(await fs12.readFile(filePath, "utf-8"));
|
|
33904
|
+
} catch {
|
|
33905
|
+
return null;
|
|
33906
|
+
}
|
|
33907
|
+
}
|
|
33908
|
+
async function saveMailCredentials(creds, credentialPath) {
|
|
33909
|
+
const filePath = resolveMailCredentialPath(credentialPath);
|
|
33910
|
+
await fs12.mkdir(path12.dirname(filePath), { recursive: true, mode: 448 });
|
|
33911
|
+
await fs12.writeFile(filePath, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf-8", mode: 384 });
|
|
33912
|
+
await fs12.chmod(filePath, 384);
|
|
33913
|
+
}
|
|
33914
|
+
async function persistProvisionedMailbox(mailbox, credentialPath) {
|
|
33915
|
+
if (!mailbox?.address || !mailbox.password) return false;
|
|
33916
|
+
await saveMailCredentials(
|
|
33917
|
+
{
|
|
33918
|
+
address: mailbox.address,
|
|
33919
|
+
password: mailbox.password,
|
|
33920
|
+
imapHost: MAIL_DEFAULT_HOST,
|
|
33921
|
+
imapPort: 993,
|
|
33922
|
+
smtpHost: MAIL_DEFAULT_HOST,
|
|
33923
|
+
smtpPort: 465,
|
|
33924
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
33925
|
+
},
|
|
33926
|
+
credentialPath
|
|
33927
|
+
);
|
|
33928
|
+
return true;
|
|
33929
|
+
}
|
|
33930
|
+
var MAIL_DEFAULT_HOST;
|
|
33931
|
+
var init_mail_credential_store = __esm({
|
|
33932
|
+
"src/cloud/mail-credential-store.ts"() {
|
|
33933
|
+
"use strict";
|
|
33934
|
+
MAIL_DEFAULT_HOST = "mail.cogent.tools";
|
|
33935
|
+
}
|
|
33936
|
+
});
|
|
33937
|
+
|
|
33938
|
+
// src/tools/register-peer.ts
|
|
33939
|
+
import crypto4 from "node:crypto";
|
|
33887
33940
|
function registerRegisterPeerTool(server) {
|
|
33888
33941
|
server.registerTool(
|
|
33889
33942
|
"cogent_register_peer",
|
|
@@ -33942,7 +33995,7 @@ function registerRegisterPeerTool(server) {
|
|
|
33942
33995
|
}
|
|
33943
33996
|
}
|
|
33944
33997
|
if (!cloudSessionId) {
|
|
33945
|
-
autoSecret =
|
|
33998
|
+
autoSecret = crypto4.randomBytes(16).toString("hex");
|
|
33946
33999
|
const resp = await fetch(
|
|
33947
34000
|
`${endpoint}/api/sessions`,
|
|
33948
34001
|
{
|
|
@@ -34021,6 +34074,15 @@ function registerRegisterPeerTool(server) {
|
|
|
34021
34074
|
);
|
|
34022
34075
|
}
|
|
34023
34076
|
}
|
|
34077
|
+
try {
|
|
34078
|
+
if (await persistProvisionedMailbox(peer?.mailbox)) {
|
|
34079
|
+
logger.info(`Cogent Mail: saved auto-provisioned mailbox ${peer.mailbox?.address}`);
|
|
34080
|
+
}
|
|
34081
|
+
} catch (err) {
|
|
34082
|
+
logger.warn(
|
|
34083
|
+
`Cogent Mail: could not save auto-provisioned mailbox creds: ${err.message}`
|
|
34084
|
+
);
|
|
34085
|
+
}
|
|
34024
34086
|
const resolution = await resolveSession(
|
|
34025
34087
|
getConfig().COGENT_PLATFORM,
|
|
34026
34088
|
cwd,
|
|
@@ -34103,6 +34165,7 @@ var init_register_peer = __esm({
|
|
|
34103
34165
|
init_backend();
|
|
34104
34166
|
init_errors4();
|
|
34105
34167
|
init_credential_store();
|
|
34168
|
+
init_mail_credential_store();
|
|
34106
34169
|
init_logger();
|
|
34107
34170
|
init_heartbeat();
|
|
34108
34171
|
init_auto_relay();
|
|
@@ -34412,7 +34475,8 @@ var init_peer = __esm({
|
|
|
34412
34475
|
workspaceId: import_zod5.z.string().optional().describe("Durable workspace identifier (Slice 5) \u2014 stable id not tied to the mutable cwd hint"),
|
|
34413
34476
|
threadId: import_zod5.z.string().optional().describe("Durable thread/conversation identifier (Slice 5)"),
|
|
34414
34477
|
role: import_zod5.z.string().max(64).optional().describe("A2A role advertised by this peer (Agent Card)"),
|
|
34415
|
-
capabilities: import_zod5.z.array(import_zod5.z.string().max(64)).max(16).optional().describe("Capability strings \u2192 A2A Agent Card skills[]")
|
|
34478
|
+
capabilities: import_zod5.z.array(import_zod5.z.string().max(64)).max(16).optional().describe("Capability strings \u2192 A2A Agent Card skills[]"),
|
|
34479
|
+
mailboxAddress: import_zod5.z.string().max(320).optional().describe("Auto-provisioned Cogent Mail address (non-secret); NEVER the password")
|
|
34416
34480
|
});
|
|
34417
34481
|
}
|
|
34418
34482
|
});
|
|
@@ -34760,6 +34824,19 @@ function toSkills(peer) {
|
|
|
34760
34824
|
};
|
|
34761
34825
|
});
|
|
34762
34826
|
}
|
|
34827
|
+
function toMailboxExtensions(peer) {
|
|
34828
|
+
const address = peer.mailboxAddress;
|
|
34829
|
+
if (!address)
|
|
34830
|
+
return [];
|
|
34831
|
+
return [
|
|
34832
|
+
{
|
|
34833
|
+
uri: COGENT_MAILBOX_EXTENSION_URI,
|
|
34834
|
+
description: "Cogent Mail mailbox address (non-secret) for this peer.",
|
|
34835
|
+
required: false,
|
|
34836
|
+
params: { address }
|
|
34837
|
+
}
|
|
34838
|
+
];
|
|
34839
|
+
}
|
|
34763
34840
|
function synthDescription(peer) {
|
|
34764
34841
|
const parts = [`Cogent fabric peer on ${peer.platform ?? "cc"}`];
|
|
34765
34842
|
if (peer.role)
|
|
@@ -34775,6 +34852,7 @@ function peerInfoToAgentCard(peer, ctx) {
|
|
|
34775
34852
|
const version2 = ctx.clientVersion ?? peer.clientVersion ?? "0.0.0";
|
|
34776
34853
|
const provider = { organization: `Cogent \xB7 ${peer.platform ?? "cc"}`, url: "https://cogent.tools" };
|
|
34777
34854
|
const skills = toSkills(peer);
|
|
34855
|
+
const extensions = toMailboxExtensions(peer);
|
|
34778
34856
|
if (ctx.cardVersion === "0.3.0") {
|
|
34779
34857
|
return {
|
|
34780
34858
|
protocolVersion: "0.3.0",
|
|
@@ -34783,7 +34861,7 @@ function peerInfoToAgentCard(peer, ctx) {
|
|
|
34783
34861
|
url,
|
|
34784
34862
|
version: version2,
|
|
34785
34863
|
provider,
|
|
34786
|
-
capabilities: {},
|
|
34864
|
+
capabilities: extensions.length ? { extensions } : {},
|
|
34787
34865
|
defaultInputModes: ["text/plain"],
|
|
34788
34866
|
defaultOutputModes: ["text/plain"],
|
|
34789
34867
|
skills,
|
|
@@ -34804,7 +34882,7 @@ function peerInfoToAgentCard(peer, ctx) {
|
|
|
34804
34882
|
tenant: ctx.sessionId
|
|
34805
34883
|
}
|
|
34806
34884
|
],
|
|
34807
|
-
capabilities: { extensions
|
|
34885
|
+
capabilities: { extensions },
|
|
34808
34886
|
defaultInputModes: ["text/plain"],
|
|
34809
34887
|
defaultOutputModes: ["text/plain"],
|
|
34810
34888
|
skills,
|
|
@@ -34813,12 +34891,13 @@ function peerInfoToAgentCard(peer, ctx) {
|
|
|
34813
34891
|
signatures: []
|
|
34814
34892
|
};
|
|
34815
34893
|
}
|
|
34816
|
-
var COGENT_PROTOCOL_BINDING, A2A_PROTOCOL_VERSION;
|
|
34894
|
+
var COGENT_PROTOCOL_BINDING, A2A_PROTOCOL_VERSION, COGENT_MAILBOX_EXTENSION_URI;
|
|
34817
34895
|
var init_agent_card = __esm({
|
|
34818
34896
|
"cogent/dist/a2a/agent-card.js"() {
|
|
34819
34897
|
"use strict";
|
|
34820
34898
|
COGENT_PROTOCOL_BINDING = "COGENT-RELAY";
|
|
34821
34899
|
A2A_PROTOCOL_VERSION = "1.0";
|
|
34900
|
+
COGENT_MAILBOX_EXTENSION_URI = "https://cogent.tools/a2a/ext/mailbox";
|
|
34822
34901
|
}
|
|
34823
34902
|
});
|
|
34824
34903
|
|
|
@@ -35113,7 +35192,7 @@ var init_health_check2 = __esm({
|
|
|
35113
35192
|
});
|
|
35114
35193
|
|
|
35115
35194
|
// src/tools/create-session.ts
|
|
35116
|
-
import
|
|
35195
|
+
import crypto5 from "node:crypto";
|
|
35117
35196
|
function registerCreateSessionTool(server) {
|
|
35118
35197
|
server.registerTool(
|
|
35119
35198
|
"cogent_create_session",
|
|
@@ -35144,7 +35223,7 @@ function registerCreateSessionTool(server) {
|
|
|
35144
35223
|
)
|
|
35145
35224
|
);
|
|
35146
35225
|
}
|
|
35147
|
-
const sessionSecret = secret ??
|
|
35226
|
+
const sessionSecret = secret ?? crypto5.randomBytes(16).toString("hex");
|
|
35148
35227
|
const resp = await fetch(
|
|
35149
35228
|
`${config2.COGENT_ENDPOINT}/api/sessions`,
|
|
35150
35229
|
{
|
|
@@ -35372,6 +35451,386 @@ var init_join_session = __esm({
|
|
|
35372
35451
|
}
|
|
35373
35452
|
});
|
|
35374
35453
|
|
|
35454
|
+
// src/mail/validate.ts
|
|
35455
|
+
function isValidEmail(value) {
|
|
35456
|
+
return value.length <= 254 && EMAIL_RE.test(value);
|
|
35457
|
+
}
|
|
35458
|
+
function assertValidEmail(value, field) {
|
|
35459
|
+
if (!isValidEmail(value)) {
|
|
35460
|
+
throw new BridgeError(
|
|
35461
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
35462
|
+
`${field} is not a valid email address: ${JSON.stringify(value)}`,
|
|
35463
|
+
`Provide a full address like agent-channel@mail.cogent.tools`
|
|
35464
|
+
);
|
|
35465
|
+
}
|
|
35466
|
+
}
|
|
35467
|
+
var EMAIL_RE;
|
|
35468
|
+
var init_validate = __esm({
|
|
35469
|
+
"src/mail/validate.ts"() {
|
|
35470
|
+
"use strict";
|
|
35471
|
+
init_errors4();
|
|
35472
|
+
EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
35473
|
+
}
|
|
35474
|
+
});
|
|
35475
|
+
|
|
35476
|
+
// src/tools/setup-mail.ts
|
|
35477
|
+
function registerSetupMailTool(server) {
|
|
35478
|
+
server.registerTool(
|
|
35479
|
+
"cogent_setup_mail",
|
|
35480
|
+
{
|
|
35481
|
+
title: "Configure this agent's mailbox",
|
|
35482
|
+
description: "Store the agent's mailbox address + password (from the admin Mail panel) locally so cogent_send_mail and cogent_fetch_mail can use them. Hosts default to mail.cogent.tools (IMAP 993 / SMTP 465).",
|
|
35483
|
+
inputSchema: {
|
|
35484
|
+
address: import_zod16.z.string().describe("Full mailbox address, e.g. claude-agent-backend@mail.cogent.tools"),
|
|
35485
|
+
password: import_zod16.z.string().describe("Mailbox password (shown once in the admin Mail panel on create/rotate)"),
|
|
35486
|
+
imapHost: import_zod16.z.string().optional().describe(`IMAP host (default ${DEFAULT_MAIL_HOST})`),
|
|
35487
|
+
imapPort: import_zod16.z.number().int().positive().optional().describe("IMAP port (default 993)"),
|
|
35488
|
+
smtpHost: import_zod16.z.string().optional().describe(`SMTP host (default ${DEFAULT_MAIL_HOST})`),
|
|
35489
|
+
smtpPort: import_zod16.z.number().int().positive().optional().describe("SMTP submission port (default 465)")
|
|
35490
|
+
},
|
|
35491
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
35492
|
+
},
|
|
35493
|
+
async ({ address, password, imapHost, imapPort, smtpHost, smtpPort }) => {
|
|
35494
|
+
try {
|
|
35495
|
+
assertValidEmail(address, "address");
|
|
35496
|
+
await saveMailCredentials({
|
|
35497
|
+
address,
|
|
35498
|
+
password,
|
|
35499
|
+
imapHost: imapHost ?? DEFAULT_MAIL_HOST,
|
|
35500
|
+
imapPort: imapPort ?? 993,
|
|
35501
|
+
smtpHost: smtpHost ?? DEFAULT_MAIL_HOST,
|
|
35502
|
+
smtpPort: smtpPort ?? 465,
|
|
35503
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
35504
|
+
});
|
|
35505
|
+
return successResult({ configured: true, address });
|
|
35506
|
+
} catch (err) {
|
|
35507
|
+
return errorResult(err);
|
|
35508
|
+
}
|
|
35509
|
+
}
|
|
35510
|
+
);
|
|
35511
|
+
}
|
|
35512
|
+
var import_zod16, DEFAULT_MAIL_HOST;
|
|
35513
|
+
var init_setup_mail = __esm({
|
|
35514
|
+
"src/tools/setup-mail.ts"() {
|
|
35515
|
+
"use strict";
|
|
35516
|
+
import_zod16 = __toESM(require_zod(), 1);
|
|
35517
|
+
init_errors4();
|
|
35518
|
+
init_mail_credential_store();
|
|
35519
|
+
init_validate();
|
|
35520
|
+
DEFAULT_MAIL_HOST = MAIL_DEFAULT_HOST;
|
|
35521
|
+
}
|
|
35522
|
+
});
|
|
35523
|
+
|
|
35524
|
+
// src/mail/mail-sender.ts
|
|
35525
|
+
import fs13 from "node:fs/promises";
|
|
35526
|
+
import path13 from "node:path";
|
|
35527
|
+
async function buildAndSendMail(sender, creds, params) {
|
|
35528
|
+
const attachments = [];
|
|
35529
|
+
for (const p of params.attachmentPaths ?? []) {
|
|
35530
|
+
const content = await fs13.readFile(p);
|
|
35531
|
+
attachments.push({ filename: path13.basename(p), content });
|
|
35532
|
+
}
|
|
35533
|
+
const { messageId } = await sender.send({
|
|
35534
|
+
from: creds.address,
|
|
35535
|
+
to: params.to,
|
|
35536
|
+
subject: params.subject,
|
|
35537
|
+
text: params.text,
|
|
35538
|
+
attachments
|
|
35539
|
+
});
|
|
35540
|
+
return { messageId, from: creds.address, to: params.to };
|
|
35541
|
+
}
|
|
35542
|
+
var NodemailerMailSender;
|
|
35543
|
+
var init_mail_sender = __esm({
|
|
35544
|
+
"src/mail/mail-sender.ts"() {
|
|
35545
|
+
"use strict";
|
|
35546
|
+
NodemailerMailSender = class {
|
|
35547
|
+
constructor(creds, transportFactory) {
|
|
35548
|
+
this.creds = creds;
|
|
35549
|
+
this.transportFactory = transportFactory;
|
|
35550
|
+
}
|
|
35551
|
+
creds;
|
|
35552
|
+
transportFactory;
|
|
35553
|
+
async send(mail) {
|
|
35554
|
+
const transport = this.transportFactory ? await this.transportFactory() : await this.defaultTransport();
|
|
35555
|
+
const info = await transport.sendMail({
|
|
35556
|
+
from: mail.from,
|
|
35557
|
+
to: mail.to,
|
|
35558
|
+
subject: mail.subject,
|
|
35559
|
+
text: mail.text,
|
|
35560
|
+
attachments: mail.attachments.map((a) => ({ filename: a.filename, content: a.content }))
|
|
35561
|
+
});
|
|
35562
|
+
return { messageId: info.messageId ?? "" };
|
|
35563
|
+
}
|
|
35564
|
+
async defaultTransport() {
|
|
35565
|
+
const specifier = "nodemailer";
|
|
35566
|
+
const nodemailer = await import(specifier);
|
|
35567
|
+
return nodemailer.createTransport({
|
|
35568
|
+
host: this.creds.smtpHost,
|
|
35569
|
+
port: this.creds.smtpPort,
|
|
35570
|
+
secure: this.creds.smtpPort === 465,
|
|
35571
|
+
// implicit TLS on 465, STARTTLS on 587
|
|
35572
|
+
auth: { user: this.creds.address, pass: this.creds.password }
|
|
35573
|
+
});
|
|
35574
|
+
}
|
|
35575
|
+
};
|
|
35576
|
+
}
|
|
35577
|
+
});
|
|
35578
|
+
|
|
35579
|
+
// src/tools/send-mail.ts
|
|
35580
|
+
function registerSendMailTool(server, deps = {}) {
|
|
35581
|
+
const makeSender = deps.senderFactory ?? ((creds) => new NodemailerMailSender(creds));
|
|
35582
|
+
server.registerTool(
|
|
35583
|
+
"cogent_send_mail",
|
|
35584
|
+
{
|
|
35585
|
+
title: "Send an email from this agent's mailbox",
|
|
35586
|
+
description: "Send an email (with optional file attachments) from this agent's Cogent mailbox to another address. Requires cogent_setup_mail to have stored the mailbox credentials first.",
|
|
35587
|
+
inputSchema: {
|
|
35588
|
+
to: import_zod17.z.string().describe("Recipient email address, e.g. other-agent-backend@mail.cogent.tools"),
|
|
35589
|
+
subject: import_zod17.z.string().describe("Email subject"),
|
|
35590
|
+
body: import_zod17.z.string().describe("Plain-text email body"),
|
|
35591
|
+
attachments: import_zod17.z.array(import_zod17.z.string()).optional().describe("Optional local file paths to attach (each is read and attached by basename)")
|
|
35592
|
+
},
|
|
35593
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
|
|
35594
|
+
},
|
|
35595
|
+
async ({ to, subject, body, attachments }) => {
|
|
35596
|
+
try {
|
|
35597
|
+
assertValidEmail(to, "to");
|
|
35598
|
+
const creds = await loadMailCredentials();
|
|
35599
|
+
if (!creds) {
|
|
35600
|
+
return errorResult(
|
|
35601
|
+
new BridgeError(
|
|
35602
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
35603
|
+
"No mailbox is configured for this agent",
|
|
35604
|
+
"Run cogent_setup_mail with the address + password from the admin Mail panel first"
|
|
35605
|
+
)
|
|
35606
|
+
);
|
|
35607
|
+
}
|
|
35608
|
+
const result = await buildAndSendMail(makeSender(creds), creds, {
|
|
35609
|
+
to: [to],
|
|
35610
|
+
subject,
|
|
35611
|
+
text: body,
|
|
35612
|
+
attachmentPaths: attachments
|
|
35613
|
+
});
|
|
35614
|
+
return successResult({ ...result, attachmentCount: attachments?.length ?? 0 });
|
|
35615
|
+
} catch (err) {
|
|
35616
|
+
return errorResult(err);
|
|
35617
|
+
}
|
|
35618
|
+
}
|
|
35619
|
+
);
|
|
35620
|
+
}
|
|
35621
|
+
var import_zod17;
|
|
35622
|
+
var init_send_mail = __esm({
|
|
35623
|
+
"src/tools/send-mail.ts"() {
|
|
35624
|
+
"use strict";
|
|
35625
|
+
import_zod17 = __toESM(require_zod(), 1);
|
|
35626
|
+
init_errors4();
|
|
35627
|
+
init_mail_credential_store();
|
|
35628
|
+
init_mail_sender();
|
|
35629
|
+
init_validate();
|
|
35630
|
+
}
|
|
35631
|
+
});
|
|
35632
|
+
|
|
35633
|
+
// src/mail/mail-fetcher.ts
|
|
35634
|
+
import fs14 from "node:fs/promises";
|
|
35635
|
+
import path14 from "node:path";
|
|
35636
|
+
async function saveAttachments(attachments, downloadDir) {
|
|
35637
|
+
if (attachments.length === 0) return [];
|
|
35638
|
+
await fs14.mkdir(downloadDir, { recursive: true });
|
|
35639
|
+
const saved = [];
|
|
35640
|
+
for (const a of attachments) {
|
|
35641
|
+
const name = path14.basename(a.filename) || "attachment";
|
|
35642
|
+
const savedPath = path14.join(downloadDir, name);
|
|
35643
|
+
await fs14.writeFile(savedPath, a.content);
|
|
35644
|
+
saved.push({ filename: name, savedPath, size: a.content.length });
|
|
35645
|
+
}
|
|
35646
|
+
return saved;
|
|
35647
|
+
}
|
|
35648
|
+
async function defaultImapSessionFactory(creds) {
|
|
35649
|
+
const specifier = "imapflow";
|
|
35650
|
+
const { ImapFlow } = await import(specifier);
|
|
35651
|
+
const client = new ImapFlow({
|
|
35652
|
+
host: creds.imapHost,
|
|
35653
|
+
port: creds.imapPort,
|
|
35654
|
+
secure: creds.imapPort === 993,
|
|
35655
|
+
auth: { user: creds.address, pass: creds.password },
|
|
35656
|
+
logger: false
|
|
35657
|
+
});
|
|
35658
|
+
await client.connect();
|
|
35659
|
+
await client.mailboxOpen("INBOX");
|
|
35660
|
+
return {
|
|
35661
|
+
async list(unreadOnly) {
|
|
35662
|
+
const criteria = unreadOnly ? { seen: false } : { all: true };
|
|
35663
|
+
const rows = [];
|
|
35664
|
+
for await (const msg of client.fetch(criteria, { uid: true, envelope: true, flags: true })) {
|
|
35665
|
+
const env = msg.envelope ?? {};
|
|
35666
|
+
rows.push({
|
|
35667
|
+
uid: msg.uid,
|
|
35668
|
+
from: env.from?.[0]?.address ?? "",
|
|
35669
|
+
subject: env.subject ?? "",
|
|
35670
|
+
date: env.date instanceof Date ? env.date.toISOString() : String(env.date ?? ""),
|
|
35671
|
+
unread: !hasFlag(msg.flags, "\\Seen")
|
|
35672
|
+
});
|
|
35673
|
+
}
|
|
35674
|
+
return rows.reverse();
|
|
35675
|
+
},
|
|
35676
|
+
async fetch(uid) {
|
|
35677
|
+
const msg = await client.fetchOne(uid, { uid: true, envelope: true, bodyStructure: true }, { uid: true });
|
|
35678
|
+
if (!msg) throw new Error(`no message with uid ${uid}`);
|
|
35679
|
+
const parts = flattenBodyStructure(msg.bodyStructure);
|
|
35680
|
+
let text = "";
|
|
35681
|
+
const attachments = [];
|
|
35682
|
+
for (const p of parts) {
|
|
35683
|
+
if (p.filename) {
|
|
35684
|
+
const dl = await client.download(uid, p.part, { uid: true });
|
|
35685
|
+
attachments.push({ filename: p.filename, content: await streamToBuffer(dl.content) });
|
|
35686
|
+
} else if (p.isText && !text) {
|
|
35687
|
+
const dl = await client.download(uid, p.part, { uid: true });
|
|
35688
|
+
text = (await streamToBuffer(dl.content)).toString("utf-8");
|
|
35689
|
+
}
|
|
35690
|
+
}
|
|
35691
|
+
const env = msg.envelope ?? {};
|
|
35692
|
+
return {
|
|
35693
|
+
from: env.from?.[0]?.address ?? "",
|
|
35694
|
+
subject: env.subject ?? "",
|
|
35695
|
+
date: env.date instanceof Date ? env.date.toISOString() : String(env.date ?? ""),
|
|
35696
|
+
text,
|
|
35697
|
+
attachments
|
|
35698
|
+
};
|
|
35699
|
+
},
|
|
35700
|
+
async close() {
|
|
35701
|
+
try {
|
|
35702
|
+
await client.logout();
|
|
35703
|
+
} catch {
|
|
35704
|
+
}
|
|
35705
|
+
}
|
|
35706
|
+
};
|
|
35707
|
+
}
|
|
35708
|
+
function flattenBodyStructure(node, acc = []) {
|
|
35709
|
+
if (!node || typeof node !== "object") return acc;
|
|
35710
|
+
const n = node;
|
|
35711
|
+
if (Array.isArray(n.childNodes) && n.childNodes.length > 0) {
|
|
35712
|
+
for (const child of n.childNodes) flattenBodyStructure(child, acc);
|
|
35713
|
+
return acc;
|
|
35714
|
+
}
|
|
35715
|
+
const type = (n.type ?? "").toLowerCase();
|
|
35716
|
+
const filename = n.dispositionParameters?.filename ?? n.parameters?.name;
|
|
35717
|
+
const isAttachment = (n.disposition ?? "").toLowerCase() === "attachment" || Boolean(filename);
|
|
35718
|
+
acc.push({
|
|
35719
|
+
part: n.part ?? "1",
|
|
35720
|
+
// single-part messages have no `part`; imapflow addresses them as "1"
|
|
35721
|
+
type,
|
|
35722
|
+
isText: type === "text/plain" && !isAttachment,
|
|
35723
|
+
filename: isAttachment ? filename : void 0
|
|
35724
|
+
});
|
|
35725
|
+
return acc;
|
|
35726
|
+
}
|
|
35727
|
+
function hasFlag(flags, flag) {
|
|
35728
|
+
if (flags instanceof Set) return flags.has(flag);
|
|
35729
|
+
if (Array.isArray(flags)) return flags.includes(flag);
|
|
35730
|
+
return false;
|
|
35731
|
+
}
|
|
35732
|
+
async function streamToBuffer(stream) {
|
|
35733
|
+
const chunks = [];
|
|
35734
|
+
if (!stream) return Buffer.alloc(0);
|
|
35735
|
+
for await (const chunk of stream) chunks.push(Buffer.from(chunk));
|
|
35736
|
+
return Buffer.concat(chunks);
|
|
35737
|
+
}
|
|
35738
|
+
var ImapflowMailFetcher;
|
|
35739
|
+
var init_mail_fetcher = __esm({
|
|
35740
|
+
"src/mail/mail-fetcher.ts"() {
|
|
35741
|
+
"use strict";
|
|
35742
|
+
ImapflowMailFetcher = class {
|
|
35743
|
+
constructor(creds, sessionFactory = defaultImapSessionFactory) {
|
|
35744
|
+
this.creds = creds;
|
|
35745
|
+
this.sessionFactory = sessionFactory;
|
|
35746
|
+
}
|
|
35747
|
+
creds;
|
|
35748
|
+
sessionFactory;
|
|
35749
|
+
async list(opts = {}) {
|
|
35750
|
+
const session = await this.sessionFactory(this.creds);
|
|
35751
|
+
try {
|
|
35752
|
+
let rows = await session.list(opts.unreadOnly ?? false);
|
|
35753
|
+
if (opts.limit && opts.limit > 0) rows = rows.slice(0, opts.limit);
|
|
35754
|
+
return rows;
|
|
35755
|
+
} finally {
|
|
35756
|
+
await session.close();
|
|
35757
|
+
}
|
|
35758
|
+
}
|
|
35759
|
+
async fetchOne(uid, downloadDir) {
|
|
35760
|
+
const session = await this.sessionFactory(this.creds);
|
|
35761
|
+
try {
|
|
35762
|
+
const c2 = await session.fetch(uid);
|
|
35763
|
+
const saved = await saveAttachments(c2.attachments, downloadDir);
|
|
35764
|
+
return { uid, from: c2.from, subject: c2.subject, date: c2.date, text: c2.text, attachments: saved };
|
|
35765
|
+
} finally {
|
|
35766
|
+
await session.close();
|
|
35767
|
+
}
|
|
35768
|
+
}
|
|
35769
|
+
};
|
|
35770
|
+
}
|
|
35771
|
+
});
|
|
35772
|
+
|
|
35773
|
+
// src/tools/fetch-mail.ts
|
|
35774
|
+
import os8 from "node:os";
|
|
35775
|
+
import path15 from "node:path";
|
|
35776
|
+
function registerFetchMailTool(server, deps = {}) {
|
|
35777
|
+
const makeFetcher = deps.fetcherFactory ?? ((creds) => new ImapflowMailFetcher(creds));
|
|
35778
|
+
server.registerTool(
|
|
35779
|
+
"cogent_fetch_mail",
|
|
35780
|
+
{
|
|
35781
|
+
title: "Read this agent's mailbox",
|
|
35782
|
+
description: "List messages in this agent's Cogent mailbox, or fetch one message (text + attachments saved locally) by uid. Requires cogent_setup_mail to have stored the mailbox credentials.",
|
|
35783
|
+
inputSchema: {
|
|
35784
|
+
action: import_zod18.z.enum(["list", "fetch"]).optional().describe("'list' (default) or 'fetch' one message"),
|
|
35785
|
+
uid: import_zod18.z.number().int().positive().optional().describe("Message uid to fetch (required when action='fetch')"),
|
|
35786
|
+
unreadOnly: import_zod18.z.boolean().optional().describe("List only unread messages (default false)"),
|
|
35787
|
+
limit: import_zod18.z.number().int().positive().optional().describe("Max messages to list (default 25)"),
|
|
35788
|
+
downloadDir: import_zod18.z.string().optional().describe(`Directory to save fetched attachments (default ${DEFAULT_DOWNLOAD_DIR})`)
|
|
35789
|
+
},
|
|
35790
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
35791
|
+
},
|
|
35792
|
+
async ({ action, uid, unreadOnly, limit, downloadDir }) => {
|
|
35793
|
+
try {
|
|
35794
|
+
const creds = await loadMailCredentials();
|
|
35795
|
+
if (!creds) {
|
|
35796
|
+
return errorResult(
|
|
35797
|
+
new BridgeError(
|
|
35798
|
+
"INVALID_INPUT" /* INVALID_INPUT */,
|
|
35799
|
+
"No mailbox is configured for this agent",
|
|
35800
|
+
"Run cogent_setup_mail with the address + password from the admin Mail panel first"
|
|
35801
|
+
)
|
|
35802
|
+
);
|
|
35803
|
+
}
|
|
35804
|
+
const fetcher = makeFetcher(creds);
|
|
35805
|
+
if (action === "fetch") {
|
|
35806
|
+
if (uid === void 0) {
|
|
35807
|
+
return errorResult(
|
|
35808
|
+
new BridgeError("INVALID_INPUT" /* INVALID_INPUT */, "uid is required when action='fetch'", "Pass the uid from a cogent_fetch_mail list")
|
|
35809
|
+
);
|
|
35810
|
+
}
|
|
35811
|
+
const message = await fetcher.fetchOne(uid, downloadDir ?? DEFAULT_DOWNLOAD_DIR);
|
|
35812
|
+
return successResult({ mailbox: creds.address, message });
|
|
35813
|
+
}
|
|
35814
|
+
const messages = await fetcher.list({ unreadOnly, limit: limit ?? 25 });
|
|
35815
|
+
return successResult({ mailbox: creds.address, count: messages.length, messages });
|
|
35816
|
+
} catch (err) {
|
|
35817
|
+
return errorResult(err);
|
|
35818
|
+
}
|
|
35819
|
+
}
|
|
35820
|
+
);
|
|
35821
|
+
}
|
|
35822
|
+
var import_zod18, DEFAULT_DOWNLOAD_DIR;
|
|
35823
|
+
var init_fetch_mail = __esm({
|
|
35824
|
+
"src/tools/fetch-mail.ts"() {
|
|
35825
|
+
"use strict";
|
|
35826
|
+
import_zod18 = __toESM(require_zod(), 1);
|
|
35827
|
+
init_errors4();
|
|
35828
|
+
init_mail_credential_store();
|
|
35829
|
+
init_mail_fetcher();
|
|
35830
|
+
DEFAULT_DOWNLOAD_DIR = path15.join(os8.homedir(), ".cogent", "mail-downloads");
|
|
35831
|
+
}
|
|
35832
|
+
});
|
|
35833
|
+
|
|
35375
35834
|
// src/index.ts
|
|
35376
35835
|
var index_exports = {};
|
|
35377
35836
|
async function main() {
|
|
@@ -35385,6 +35844,9 @@ async function main() {
|
|
|
35385
35844
|
registerHealthCheckTool(server);
|
|
35386
35845
|
registerCreateSessionTool(server);
|
|
35387
35846
|
registerJoinSessionTool(server);
|
|
35847
|
+
registerSetupMailTool(server);
|
|
35848
|
+
registerSendMailTool(server);
|
|
35849
|
+
registerFetchMailTool(server);
|
|
35388
35850
|
if (cloudInbox) {
|
|
35389
35851
|
server.registerResource(
|
|
35390
35852
|
"cogent_inbox",
|
|
@@ -35444,6 +35906,9 @@ var init_index = __esm({
|
|
|
35444
35906
|
init_health_check2();
|
|
35445
35907
|
init_create_session();
|
|
35446
35908
|
init_join_session();
|
|
35909
|
+
init_setup_mail();
|
|
35910
|
+
init_send_mail();
|
|
35911
|
+
init_fetch_mail();
|
|
35447
35912
|
init_heartbeat();
|
|
35448
35913
|
process.on("uncaughtException", (err) => {
|
|
35449
35914
|
if (err.code === "EPIPE") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@essentialai/cogent-plugin",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.15.0",
|
|
4
4
|
"description": "Cogent — Claude Code plugin (skills + slash-commands + MCP server) for the cross-agent comms fabric.",
|
|
5
5
|
"author": { "name": "Essential AI Solutions Ltd.", "url": "https://essentialai.uk" },
|
|
6
6
|
"homepage": "https://cogent.tools",
|