jefrichat-mcp 0.49.18 → 0.49.21
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/dist/build-inputs.json +1 -1
- package/dist/http.js +198 -16
- package/dist/index.js +570 -253
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -45341,7 +45341,7 @@ function isConnectorProfile(x) {
|
|
|
45341
45341
|
}
|
|
45342
45342
|
|
|
45343
45343
|
// src/http.ts
|
|
45344
|
-
import { randomUUID as
|
|
45344
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
45345
45345
|
|
|
45346
45346
|
// src/session-auth.ts
|
|
45347
45347
|
import { createHash, timingSafeEqual } from "node:crypto";
|
|
@@ -61114,8 +61114,32 @@ function connectErrorFromEvent(ev) {
|
|
|
61114
61114
|
if (ev?.minVersion) err.minVersion = ev.minVersion;
|
|
61115
61115
|
return err;
|
|
61116
61116
|
}
|
|
61117
|
+
function terminalConnectionCode(ev) {
|
|
61118
|
+
if (ev.code) return [
|
|
61119
|
+
"auth",
|
|
61120
|
+
"auth_failed",
|
|
61121
|
+
"authentication_failed",
|
|
61122
|
+
"invalid_token",
|
|
61123
|
+
"ACP_AUTH_FAILED",
|
|
61124
|
+
"upgrade_required",
|
|
61125
|
+
"taken_over",
|
|
61126
|
+
"superseded"
|
|
61127
|
+
].includes(ev.code) ? ev.code : null;
|
|
61128
|
+
return /^(?:authentication failed|invalid or expired (?:Jefri Chat )?token)(?:\b|$)/i.test(ev.message ?? "") ? "auth" : null;
|
|
61129
|
+
}
|
|
61117
61130
|
var JefriClient = class _JefriClient {
|
|
61118
61131
|
ws;
|
|
61132
|
+
recoveryEnabled = false;
|
|
61133
|
+
registeredSocket;
|
|
61134
|
+
retireRecoverySocket;
|
|
61135
|
+
recoveryRegisterTimer;
|
|
61136
|
+
get registeredRecoveryEnabled() {
|
|
61137
|
+
return this.recoveryEnabled;
|
|
61138
|
+
}
|
|
61139
|
+
get connectionStatus() {
|
|
61140
|
+
if (this.terminalCode || this.closing) return "stopped";
|
|
61141
|
+
return this.online ? "online" : this.hasConnected ? "reconnecting" : "connecting";
|
|
61142
|
+
}
|
|
61119
61143
|
handlers = /* @__PURE__ */ new Map();
|
|
61120
61144
|
/** Why the client stopped reconnecting: "auth" | "upgrade_required" | "taken_over". */
|
|
61121
61145
|
terminalCode = null;
|
|
@@ -61143,6 +61167,14 @@ var JefriClient = class _JefriClient {
|
|
|
61143
61167
|
* so pre-0.49 SDKs stop via their /auth/i match. */
|
|
61144
61168
|
noteTerminalError(ev) {
|
|
61145
61169
|
if (ev?.event !== "error") return;
|
|
61170
|
+
if (this.recoveryEnabled) {
|
|
61171
|
+
const code3 = terminalConnectionCode(ev);
|
|
61172
|
+
if (code3) {
|
|
61173
|
+
this.authFailed = true;
|
|
61174
|
+
this.terminalCode = code3;
|
|
61175
|
+
}
|
|
61176
|
+
return;
|
|
61177
|
+
}
|
|
61146
61178
|
if (/auth/i.test(ev.message ?? "") || ev.code === "upgrade_required" || ev.code === "taken_over" || ev.code === "superseded") {
|
|
61147
61179
|
this.authFailed = true;
|
|
61148
61180
|
this.terminalCode = ev.code ?? "auth";
|
|
@@ -61238,6 +61270,8 @@ var JefriClient = class _JefriClient {
|
|
|
61238
61270
|
* "offline" honestly instead of claiming an agent can be reached and then
|
|
61239
61271
|
* failing on send. */
|
|
61240
61272
|
get online() {
|
|
61273
|
+
if (this.recoveryEnabled)
|
|
61274
|
+
return !this.closing && !this.authFailed && !!this.ws && this.ws.readyState === wrapper_default.OPEN && this.registeredSocket === this.ws;
|
|
61241
61275
|
return this.hasConnected && !this.closing && this.ws?.readyState === this.ws?.OPEN;
|
|
61242
61276
|
}
|
|
61243
61277
|
constructor(server2) {
|
|
@@ -61246,6 +61280,7 @@ var JefriClient = class _JefriClient {
|
|
|
61246
61280
|
static async connect(opts = {}) {
|
|
61247
61281
|
const server2 = (opts.server ?? "https://jefrichat.com").replace(/\/$/, "");
|
|
61248
61282
|
const client = new _JefriClient(server2);
|
|
61283
|
+
client.recoveryEnabled = opts.registeredRecovery === true;
|
|
61249
61284
|
let token = opts.token;
|
|
61250
61285
|
if (!token) {
|
|
61251
61286
|
const res = await fetch(`${server2}/api/agents`, {
|
|
@@ -61285,7 +61320,9 @@ var JefriClient = class _JefriClient {
|
|
|
61285
61320
|
fn();
|
|
61286
61321
|
};
|
|
61287
61322
|
onReg = () => finish(resolve);
|
|
61288
|
-
onErr = (ev) => finish(() => reject(
|
|
61323
|
+
onErr = (ev) => finish(() => reject(
|
|
61324
|
+
client.recoveryEnabled && !ev?.code && !terminalConnectionCode(ev) ? new Error(ev?.message ?? "hub rejected the connection") : connectErrorFromEvent(ev)
|
|
61325
|
+
));
|
|
61289
61326
|
const regTimeoutMs = typeof process !== "undefined" && Number(process.env?.JEFRI_REGISTER_TIMEOUT_MS) || 8e3;
|
|
61290
61327
|
timer = setTimeout(
|
|
61291
61328
|
() => finish(() => reject(new Error("timed out waiting for the hub to register the connection"))),
|
|
@@ -61312,11 +61349,47 @@ var JefriClient = class _JefriClient {
|
|
|
61312
61349
|
return client;
|
|
61313
61350
|
}
|
|
61314
61351
|
openSocket() {
|
|
61352
|
+
if (this.recoveryEnabled) {
|
|
61353
|
+
this.retireRecoverySocket?.();
|
|
61354
|
+
this.registeredSocket = void 0;
|
|
61355
|
+
}
|
|
61315
61356
|
const wsUrl = this.server.replace(/^http/, "ws") + `/ws`;
|
|
61316
61357
|
this.ws = new wrapper_default(wsUrl, { headers: this.socketHeaders() });
|
|
61358
|
+
const ws = this.ws;
|
|
61359
|
+
const current = () => !this.recoveryEnabled || this.ws === ws && !this.closing && !this.authFailed;
|
|
61317
61360
|
return new Promise((resolve, reject) => {
|
|
61318
61361
|
let settled = false;
|
|
61362
|
+
let registrationTimer;
|
|
61363
|
+
const clearRegistrationTimer = () => {
|
|
61364
|
+
clearTimeout(registrationTimer);
|
|
61365
|
+
if (this.recoveryRegisterTimer === registrationTimer) this.recoveryRegisterTimer = void 0;
|
|
61366
|
+
registrationTimer = void 0;
|
|
61367
|
+
};
|
|
61368
|
+
if (this.recoveryEnabled) {
|
|
61369
|
+
const timeoutMs = Number(process.env.JEFRI_REGISTER_TIMEOUT_MS) || 8e3;
|
|
61370
|
+
registrationTimer = setTimeout(() => {
|
|
61371
|
+
if (!current() || this.registeredSocket === ws) return;
|
|
61372
|
+
if (!settled) {
|
|
61373
|
+
settled = true;
|
|
61374
|
+
reject(new Error("timed out waiting for the hub to register the connection"));
|
|
61375
|
+
}
|
|
61376
|
+
ws.terminate();
|
|
61377
|
+
}, timeoutMs);
|
|
61378
|
+
this.recoveryRegisterTimer = registrationTimer;
|
|
61379
|
+
this.retireRecoverySocket = () => {
|
|
61380
|
+
clearRegistrationTimer();
|
|
61381
|
+
if (!settled) {
|
|
61382
|
+
settled = true;
|
|
61383
|
+
reject(new Error("connection attempt cancelled"));
|
|
61384
|
+
}
|
|
61385
|
+
ws.removeAllListeners();
|
|
61386
|
+
ws.on("error", () => {
|
|
61387
|
+
});
|
|
61388
|
+
ws.terminate();
|
|
61389
|
+
};
|
|
61390
|
+
}
|
|
61319
61391
|
this.ws.on("open", () => {
|
|
61392
|
+
if (!current()) return;
|
|
61320
61393
|
this.startPing();
|
|
61321
61394
|
this.emit("socket_open", {});
|
|
61322
61395
|
try {
|
|
@@ -61332,17 +61405,28 @@ var JefriClient = class _JefriClient {
|
|
|
61332
61405
|
}
|
|
61333
61406
|
});
|
|
61334
61407
|
this.ws.on("error", (e) => {
|
|
61408
|
+
if (this.recoveryEnabled && this.ws !== ws) return;
|
|
61335
61409
|
if (!settled) {
|
|
61336
61410
|
settled = true;
|
|
61337
61411
|
reject(e);
|
|
61338
61412
|
}
|
|
61339
61413
|
});
|
|
61340
61414
|
this.ws.on("close", () => {
|
|
61415
|
+
if (this.recoveryEnabled) {
|
|
61416
|
+
clearRegistrationTimer();
|
|
61417
|
+
if (this.ws !== ws) return;
|
|
61418
|
+
this.registeredSocket = void 0;
|
|
61419
|
+
if (!settled) {
|
|
61420
|
+
settled = true;
|
|
61421
|
+
reject(new Error("connection closed before opening"));
|
|
61422
|
+
}
|
|
61423
|
+
}
|
|
61341
61424
|
this.stopPing();
|
|
61342
61425
|
this.emit("socket_close", {});
|
|
61343
61426
|
if (this.hasConnected && !this.closing && !this.authFailed) this.scheduleReconnect();
|
|
61344
61427
|
});
|
|
61345
61428
|
this.ws.on("message", (data) => {
|
|
61429
|
+
if (!current()) return;
|
|
61346
61430
|
let ev;
|
|
61347
61431
|
try {
|
|
61348
61432
|
ev = JSON.parse(data.toString());
|
|
@@ -61350,6 +61434,10 @@ var JefriClient = class _JefriClient {
|
|
|
61350
61434
|
return;
|
|
61351
61435
|
}
|
|
61352
61436
|
if (ev.event === "registered") {
|
|
61437
|
+
if (this.recoveryEnabled) {
|
|
61438
|
+
this.registeredSocket = ws;
|
|
61439
|
+
clearRegistrationTimer();
|
|
61440
|
+
}
|
|
61353
61441
|
this.identity = ev.identity;
|
|
61354
61442
|
this.generation = typeof ev.generation === "string" ? ev.generation : null;
|
|
61355
61443
|
const rev = ev.identity?.statusRev;
|
|
@@ -61358,6 +61446,14 @@ var JefriClient = class _JefriClient {
|
|
|
61358
61446
|
this.reconnectAttempts = 0;
|
|
61359
61447
|
}
|
|
61360
61448
|
this.noteTerminalError(ev);
|
|
61449
|
+
if (this.recoveryEnabled && this.authFailed) {
|
|
61450
|
+
clearRegistrationTimer();
|
|
61451
|
+
this.registeredSocket = void 0;
|
|
61452
|
+
this.stopPing();
|
|
61453
|
+
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
|
|
61454
|
+
this.reconnectTimer = void 0;
|
|
61455
|
+
ws.close();
|
|
61456
|
+
}
|
|
61361
61457
|
this.notePresenceAck(ev);
|
|
61362
61458
|
this.emit(ev.event, ev);
|
|
61363
61459
|
this.emit("*", ev);
|
|
@@ -61373,14 +61469,17 @@ var JefriClient = class _JefriClient {
|
|
|
61373
61469
|
// triggers the existing reconnect.
|
|
61374
61470
|
startPing() {
|
|
61375
61471
|
this.stopPing();
|
|
61472
|
+
const ws = this.ws;
|
|
61473
|
+
const current = () => !this.recoveryEnabled || this.ws === ws && !this.closing && !this.authFailed;
|
|
61376
61474
|
this.isAlive = true;
|
|
61377
61475
|
try {
|
|
61378
61476
|
this.ws.on("pong", () => {
|
|
61379
|
-
this.isAlive = true;
|
|
61477
|
+
if (current()) this.isAlive = true;
|
|
61380
61478
|
});
|
|
61381
61479
|
} catch {
|
|
61382
61480
|
}
|
|
61383
61481
|
this.pingTimer = setInterval(() => {
|
|
61482
|
+
if (!current()) return;
|
|
61384
61483
|
if (this.ws.readyState !== this.ws.OPEN) return;
|
|
61385
61484
|
if (!this.isAlive) {
|
|
61386
61485
|
try {
|
|
@@ -61470,6 +61569,12 @@ var JefriClient = class _JefriClient {
|
|
|
61470
61569
|
this.dispatch(event, payload, this.handlers.get(event) ?? []);
|
|
61471
61570
|
}
|
|
61472
61571
|
send(ev) {
|
|
61572
|
+
if (this.recoveryEnabled && !this.online) {
|
|
61573
|
+
if (this.terminalCode)
|
|
61574
|
+
throw new Error(`Jefri Chat connection stopped (${this.terminalCode}) \u2014 not reconnecting automatically; check this desktop session's connection`);
|
|
61575
|
+
if (this.closing) throw new Error("Jefri Chat connection closed \u2014 restart this desktop connector");
|
|
61576
|
+
throw new Error("Jefri Chat hub connection is not registered yet (reconnecting) \u2014 try again after registration");
|
|
61577
|
+
}
|
|
61473
61578
|
if (!this.ws || this.ws.readyState !== this.ws.OPEN)
|
|
61474
61579
|
throw new Error("not connected to the Jefri Chat hub (reconnecting) \u2014 try again in a moment");
|
|
61475
61580
|
this.ws.send(JSON.stringify(ev));
|
|
@@ -61625,6 +61730,11 @@ var JefriClient = class _JefriClient {
|
|
|
61625
61730
|
}
|
|
61626
61731
|
close() {
|
|
61627
61732
|
this.closing = true;
|
|
61733
|
+
if (this.recoveryEnabled) {
|
|
61734
|
+
this.registeredSocket = void 0;
|
|
61735
|
+
clearTimeout(this.recoveryRegisterTimer);
|
|
61736
|
+
this.recoveryRegisterTimer = void 0;
|
|
61737
|
+
}
|
|
61628
61738
|
this.stopPing();
|
|
61629
61739
|
if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
|
|
61630
61740
|
this.reconnectTimer = void 0;
|
|
@@ -61908,6 +62018,55 @@ async function readCapped(stream, maxBytes, deadline) {
|
|
|
61908
62018
|
return Buffer.concat(chunks);
|
|
61909
62019
|
}
|
|
61910
62020
|
|
|
62021
|
+
// src/send-confirmed.ts
|
|
62022
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
62023
|
+
var SEND_CONFIRM_TIMEOUT_MS = 8e3;
|
|
62024
|
+
function sendConfirmed(client, target, text5, opts = {}) {
|
|
62025
|
+
const clientId = opts.clientId ?? randomUUID3();
|
|
62026
|
+
const timeoutMs = opts.timeoutMs ?? SEND_CONFIRM_TIMEOUT_MS;
|
|
62027
|
+
return new Promise((resolve) => {
|
|
62028
|
+
let settled = false;
|
|
62029
|
+
const finish = (out) => {
|
|
62030
|
+
if (settled) return;
|
|
62031
|
+
settled = true;
|
|
62032
|
+
clearTimeout(timer);
|
|
62033
|
+
clearInterval(linkCheck);
|
|
62034
|
+
client.off("reply_ack", onAck);
|
|
62035
|
+
client.off("error", onErr);
|
|
62036
|
+
resolve(out);
|
|
62037
|
+
};
|
|
62038
|
+
const onAck = (ev) => {
|
|
62039
|
+
if (ev?.replyId !== clientId) return;
|
|
62040
|
+
finish({ outcome: "sent", hubMessageId: String(ev.messageId ?? "") });
|
|
62041
|
+
};
|
|
62042
|
+
const onErr = (ev) => {
|
|
62043
|
+
if (ev?.replyId !== clientId) return;
|
|
62044
|
+
finish({
|
|
62045
|
+
outcome: "rejected",
|
|
62046
|
+
reason: String(ev.message ?? "the hub refused the message"),
|
|
62047
|
+
...typeof ev.code === "string" ? { code: ev.code } : {},
|
|
62048
|
+
...typeof ev.status === "number" ? { status: ev.status } : {}
|
|
62049
|
+
});
|
|
62050
|
+
};
|
|
62051
|
+
const timer = setTimeout(
|
|
62052
|
+
() => finish({ outcome: "ambiguous", reason: `no answer from the hub within ${Math.round(timeoutMs / 1e3)}s \u2014 check history before retrying` }),
|
|
62053
|
+
timeoutMs
|
|
62054
|
+
);
|
|
62055
|
+
const linkCheck = setInterval(() => {
|
|
62056
|
+
if (client.online === false) finish({ outcome: "ambiguous", reason: "the hub connection dropped before it answered \u2014 check history before retrying" });
|
|
62057
|
+
}, 250);
|
|
62058
|
+
client.on("reply_ack", onAck);
|
|
62059
|
+
client.on("error", onErr);
|
|
62060
|
+
try {
|
|
62061
|
+
if (target.groupId) client.groupMessage(target.groupId, text5, { clientId });
|
|
62062
|
+
else if (target.to) client.message(target.to, text5, { clientId });
|
|
62063
|
+
else return finish({ outcome: "rejected", reason: "need `to` or `groupId`" });
|
|
62064
|
+
} catch (e) {
|
|
62065
|
+
finish({ outcome: "rejected", reason: e?.message ?? "send failed" });
|
|
62066
|
+
}
|
|
62067
|
+
});
|
|
62068
|
+
}
|
|
62069
|
+
|
|
61911
62070
|
// src/hosts.ts
|
|
61912
62071
|
function aggregateFreshHosts(sessions2, poolKey, now, freshMs) {
|
|
61913
62072
|
const hosts = /* @__PURE__ */ new Set();
|
|
@@ -62491,7 +62650,7 @@ function withConfigMutex(path3, fn) {
|
|
|
62491
62650
|
}
|
|
62492
62651
|
|
|
62493
62652
|
// src/run-reporter.ts
|
|
62494
|
-
import { randomUUID as
|
|
62653
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
62495
62654
|
import np6 from "node:path";
|
|
62496
62655
|
var RUN_HEARTBEAT_MS = 3e4;
|
|
62497
62656
|
var safeUser = (u) => (u || "unknown").replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
@@ -62505,7 +62664,7 @@ var RunReporter = class {
|
|
|
62505
62664
|
this.replyDeadlineMs = deps.replyDeadlineMs ?? REPLY_DEADLINE_MS;
|
|
62506
62665
|
}
|
|
62507
62666
|
deps;
|
|
62508
|
-
sessionId =
|
|
62667
|
+
sessionId = randomUUID4();
|
|
62509
62668
|
runs = /* @__PURE__ */ new Map();
|
|
62510
62669
|
replies = /* @__PURE__ */ new Map();
|
|
62511
62670
|
/** Unacknowledged run frames, keyed `${runId}:${seq}`, in send order. */
|
|
@@ -62666,7 +62825,7 @@ var RunReporter = class {
|
|
|
62666
62825
|
/** Mint the id and journal the run BEFORE the caller spawns anything. */
|
|
62667
62826
|
startRun(meta) {
|
|
62668
62827
|
if (!this.started) throw new Error("run reporter not started \u2014 the session marker must be established before any autonomous work");
|
|
62669
|
-
const runId =
|
|
62828
|
+
const runId = randomUUID4();
|
|
62670
62829
|
const startedAt = this.now();
|
|
62671
62830
|
const st = { runId, seq: 0, meta, startedAt, epoch: this.deps.workEpoch(), durable: true, ended: false };
|
|
62672
62831
|
const seq = this.nextSeq(st);
|
|
@@ -62752,7 +62911,7 @@ var RunReporter = class {
|
|
|
62752
62911
|
* finalization verdict, or the cancel path. `onSettled` fires exactly once. */
|
|
62753
62912
|
queueReply(runId, target, text5, onSettled) {
|
|
62754
62913
|
if (!this.started) throw new Error("run reporter not started");
|
|
62755
|
-
const replyId =
|
|
62914
|
+
const replyId = randomUUID4();
|
|
62756
62915
|
const createdAt = this.now();
|
|
62757
62916
|
const epoch = this.deps.workEpoch();
|
|
62758
62917
|
const groupGen = target.groupId ? this.deps.groupGenOf?.(target.groupId) : void 0;
|
|
@@ -64592,12 +64751,16 @@ async function uploadFileHttp(c, serverUrl, target, fileName, mime, bytes, capti
|
|
|
64592
64751
|
if (caption) params.set("caption", caption);
|
|
64593
64752
|
const headers = { Authorization: `Bearer ${c.token}`, "Content-Type": mime };
|
|
64594
64753
|
if (idem2) headers["idempotency-key"] = idem2;
|
|
64754
|
+
const desktop = !isStateless(c) && c.registeredRecoveryEnabled;
|
|
64595
64755
|
let res;
|
|
64596
64756
|
try {
|
|
64597
64757
|
res = await fetch(`${hub}/api/files?${params.toString()}`, {
|
|
64598
64758
|
method: "POST",
|
|
64599
64759
|
headers,
|
|
64600
|
-
body: Buffer.from(bytes)
|
|
64760
|
+
body: Buffer.from(bytes),
|
|
64761
|
+
// Same payload-scaled allowance as the SDK upload path. This covers the
|
|
64762
|
+
// response body too; a silent hub must not hang this Desktop tool forever.
|
|
64763
|
+
...desktop ? { signal: AbortSignal.timeout(Math.ceil(3e4 + bytes.length / 20)) } : {}
|
|
64601
64764
|
});
|
|
64602
64765
|
} catch (e) {
|
|
64603
64766
|
const err = new Error(`upload failed: ${e?.message ?? e}`);
|
|
@@ -64610,6 +64773,10 @@ async function uploadFileHttp(c, serverUrl, target, fileName, mime, bytes, capti
|
|
|
64610
64773
|
if (res.status >= 500) err.jefriAmbiguous = true;
|
|
64611
64774
|
throw err;
|
|
64612
64775
|
}
|
|
64776
|
+
if (desktop) {
|
|
64777
|
+
const receipt = await res.json().catch(() => null);
|
|
64778
|
+
if (receipt?.ok !== true) throw new Error("upload response did not confirm delivery");
|
|
64779
|
+
}
|
|
64613
64780
|
}
|
|
64614
64781
|
var shq = (s) => `'${String(s).replace(/'/g, "'\\''")}'`;
|
|
64615
64782
|
var CAP = {
|
|
@@ -65138,9 +65305,12 @@ ${e?.message ?? e}`);
|
|
|
65138
65305
|
async () => {
|
|
65139
65306
|
const unbound = await ctx.identityStatus?.();
|
|
65140
65307
|
if (unbound) return ok3(unbound);
|
|
65141
|
-
return withClient(
|
|
65142
|
-
|
|
65143
|
-
|
|
65308
|
+
return withClient(async (c) => {
|
|
65309
|
+
const desktop = !isStateless(c) && c.registeredRecoveryEnabled;
|
|
65310
|
+
const status = desktop ? c.connectionStatus : "online";
|
|
65311
|
+
const reason = desktop && c.terminalCode ? ` Connection stopped: ${c.terminalCode}; automatic reconnection is disabled.` : "";
|
|
65312
|
+
return ok3(`You are "${c.identity.displayName}" (@${safeHandle(c.identity.username)}) on Jefri Chat at ${ctx.serverUrl}, status: ${status}.${reason}`);
|
|
65313
|
+
});
|
|
65144
65314
|
}
|
|
65145
65315
|
);
|
|
65146
65316
|
server2.registerTool(
|
|
@@ -65283,6 +65453,12 @@ Use jefri_agent_apps with agent=<name> to see its live app + active state.`,
|
|
|
65283
65453
|
return failAmbiguous(`Message send failed: ${e?.message ?? e}.`);
|
|
65284
65454
|
}
|
|
65285
65455
|
}
|
|
65456
|
+
if (c.registeredRecoveryEnabled) {
|
|
65457
|
+
const sent = await sendConfirmed(c, { to }, text5);
|
|
65458
|
+
if (sent.outcome === "rejected") return fail(`Message rejected: ${sent.reason}`);
|
|
65459
|
+
if (sent.outcome === "ambiguous") return failAmbiguous(sent.reason);
|
|
65460
|
+
return ok3(`Sent to @${safeHandle(to)}: "${text5}"`);
|
|
65461
|
+
}
|
|
65286
65462
|
const r = await confirmWrite(c, () => c.message(to, text5));
|
|
65287
65463
|
if (r.error) return fail(`Message rejected: ${r.error}`);
|
|
65288
65464
|
return ok3(`Sent to @${safeHandle(to)}: "${text5}"`);
|
|
@@ -65664,7 +65840,7 @@ ${lines.join("\n")}`
|
|
|
65664
65840
|
return ok3(`Sent \u{1F4CE} ${name} (${MB(rawBytes.length)} MB) to @${safeHandle(to)}${caption ? ` \u2014 "${caption}"` : ""}`);
|
|
65665
65841
|
}
|
|
65666
65842
|
const fileIdem = retryKey(extra, fileSendIdemParts(to, { path: path3, fileUrl, fileName }, name));
|
|
65667
|
-
if (rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
|
|
65843
|
+
if (c.registeredRecoveryEnabled || rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
|
|
65668
65844
|
try {
|
|
65669
65845
|
await uploadFileHttp(c, ctx.serverUrl, { to }, name, mime, rawBytes, caption, fileIdem);
|
|
65670
65846
|
} catch (e2) {
|
|
@@ -65715,7 +65891,7 @@ ${lines.join("\n")}`
|
|
|
65715
65891
|
return ok3(`Sent \u{1F4C4} ${fileName} (${MB(contentBytes.length)} MB) to @${safeHandle(to)}${caption ? ` \u2014 "${caption}"` : ""}`);
|
|
65716
65892
|
}
|
|
65717
65893
|
const textIdem = retryKey(extra, ["file", to, fileName, createHash2("sha256").update(contentBytes).digest("hex")]);
|
|
65718
|
-
if (contentBytes.length > WS_SAFE_FILE_BYTES || textIdem) {
|
|
65894
|
+
if (c.registeredRecoveryEnabled || contentBytes.length > WS_SAFE_FILE_BYTES || textIdem) {
|
|
65719
65895
|
try {
|
|
65720
65896
|
await uploadFileHttp(c, ctx.serverUrl, { to }, fileName, mime, contentBytes, caption, textIdem);
|
|
65721
65897
|
} catch (e2) {
|
|
@@ -66414,6 +66590,12 @@ Or just upload ${fname} from the agent's page in the web app.`
|
|
|
66414
66590
|
return failAmbiguous(`Group post failed: ${e?.message ?? e}.`);
|
|
66415
66591
|
}
|
|
66416
66592
|
}
|
|
66593
|
+
if (c.registeredRecoveryEnabled) {
|
|
66594
|
+
const sent = await sendConfirmed(c, { groupId }, text5);
|
|
66595
|
+
if (sent.outcome === "rejected") return fail(`Couldn't post to the group: ${sent.reason}`);
|
|
66596
|
+
if (sent.outcome === "ambiguous") return failAmbiguous(sent.reason);
|
|
66597
|
+
return ok3("Posted to the group.");
|
|
66598
|
+
}
|
|
66417
66599
|
const r = await confirmWrite(c, () => c.groupMessage(groupId, text5));
|
|
66418
66600
|
if (r.error) return fail(`Couldn't post to the group: ${r.error}`);
|
|
66419
66601
|
return ok3(`Posted to the group.`);
|
|
@@ -66485,7 +66667,7 @@ Or just upload ${fname} from the agent's page in the web app.`
|
|
|
66485
66667
|
return ok3(`Sent \u{1F4CE} ${name} (${MB(rawBytes.length)} MB) to the group.`);
|
|
66486
66668
|
}
|
|
66487
66669
|
const fileIdem = retryKey(extra, fileSendIdemParts(groupId, { path: path3, fileUrl, fileName }, name));
|
|
66488
|
-
if (rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
|
|
66670
|
+
if (c.registeredRecoveryEnabled || rawBytes.length > WS_SAFE_FILE_BYTES || fileIdem) {
|
|
66489
66671
|
try {
|
|
66490
66672
|
await uploadFileHttp(c, ctx.serverUrl, { groupId }, name, mime, rawBytes, caption, fileIdem);
|
|
66491
66673
|
} catch (e2) {
|
|
@@ -67690,7 +67872,7 @@ var statefulPost = async (req, res) => {
|
|
|
67690
67872
|
}
|
|
67691
67873
|
};
|
|
67692
67874
|
const transport = new StreamableHTTPServerTransport({
|
|
67693
|
-
sessionIdGenerator: () =>
|
|
67875
|
+
sessionIdGenerator: () => randomUUID5(),
|
|
67694
67876
|
onsessioninitialized: (sid) => {
|
|
67695
67877
|
if (pooled.closed) {
|
|
67696
67878
|
try {
|
|
@@ -67734,7 +67916,7 @@ var statefulPost = async (req, res) => {
|
|
|
67734
67916
|
const sid = transport.sessionId;
|
|
67735
67917
|
if (sid) closeSession(sid, "client closed");
|
|
67736
67918
|
};
|
|
67737
|
-
const reservation = "init:" +
|
|
67919
|
+
const reservation = "init:" + randomUUID5();
|
|
67738
67920
|
pooled.refs.add(reservation);
|
|
67739
67921
|
try {
|
|
67740
67922
|
await mcp.connect(transport);
|