@agentcomms/resend 0.15.0 → 0.15.1
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/cli.mjs +2 -2
- package/dist/index.d.mts +16 -0
- package/dist/index.mjs +2 -2
- package/dist/{send-B16eep8e.mjs → send-BcM5UKMt.mjs} +158 -59
- package/dist/{server-DjrE3qeD.mjs → server-EV5f6d28.mjs} +1 -1
- package/dist/{stdio-entry-B-cIFAoE.mjs → stdio-entry-Ea4hMItp.mjs} +1 -1
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as exemptFromUpdateGate, B as UPDATE_CHECK_CHILD_COMMAND, C as policyChange, D as sendPolicyOf, E as removeAccountChange, Et as writeResult, F as CHANNEL_SERVERS, G as canPrompt, H as approvalsOf, I as CommsError, J as cliHandoffs, L as EXIT_CODES, N as checkNewName, Nt as VERSION, O as showAccount, Ot as RESEND_CALLER, Q as escapeForDisplay, R as PATH_OPTIONS, S as policyApprovalRefusal, T as policyWanted, Tt as wholeNumber, U as approveChangeAtTerminal, V as agentMarker, W as approveRefusedHint, X as commandPathOf, Y as colorEnabled, Z as describeFenceReport, _ as runDoctor, _t as serverPruneChange, a as revokeSendApproval, at as kindOf, b as listAccounts, bt as truncateDisplay, c as downloadReceived, ct as pathOverridesFromCliOptions, d as listReceived, dt as renderInstall, f as listScheduled, ft as renderPrune, g as showSentEmail, gt as serverInstallChange, h as showReceived, ht as runUpdateCheckChild, i as prepareSend, it as installExitStatus, k as ResendContext, l as getMetrics, lt as refuseUnclaimedApproval, m as listSuppressions, mt as runCommand, n as executeSend, nt as handoffSentence, o as sendStatus, ot as openCore, p as listSentEmails, pt as resolvePaths, r as finishSendApproval, rt as handoffSentenceToFill, s as cancelScheduledChange, st as paint, t as beginSendApproval, tt as gatedChangeAtTerminal, u as listDomains, ut as renderApprovalWait, v as addAccountChange, vt as terminalUpdateHooks, w as policyReport, wt as waitForApproval, x as modeOf, xt as updateGateAtTerminal, y as inspectKey, z as SEND_LOOKUP } from "./send-
|
|
2
|
+
import { $ as exemptFromUpdateGate, B as UPDATE_CHECK_CHILD_COMMAND, C as policyChange, D as sendPolicyOf, E as removeAccountChange, Et as writeResult, F as CHANNEL_SERVERS, G as canPrompt, H as approvalsOf, I as CommsError, J as cliHandoffs, L as EXIT_CODES, N as checkNewName, Nt as VERSION, O as showAccount, Ot as RESEND_CALLER, Q as escapeForDisplay, R as PATH_OPTIONS, S as policyApprovalRefusal, T as policyWanted, Tt as wholeNumber, U as approveChangeAtTerminal, V as agentMarker, W as approveRefusedHint, X as commandPathOf, Y as colorEnabled, Z as describeFenceReport, _ as runDoctor, _t as serverPruneChange, a as revokeSendApproval, at as kindOf, b as listAccounts, bt as truncateDisplay, c as downloadReceived, ct as pathOverridesFromCliOptions, d as listReceived, dt as renderInstall, f as listScheduled, ft as renderPrune, g as showSentEmail, gt as serverInstallChange, h as showReceived, ht as runUpdateCheckChild, i as prepareSend, it as installExitStatus, k as ResendContext, l as getMetrics, lt as refuseUnclaimedApproval, m as listSuppressions, mt as runCommand, n as executeSend, nt as handoffSentence, o as sendStatus, ot as openCore, p as listSentEmails, pt as resolvePaths, r as finishSendApproval, rt as handoffSentenceToFill, s as cancelScheduledChange, st as paint, t as beginSendApproval, tt as gatedChangeAtTerminal, u as listDomains, ut as renderApprovalWait, v as addAccountChange, vt as terminalUpdateHooks, w as policyReport, wt as waitForApproval, x as modeOf, xt as updateGateAtTerminal, y as inspectKey, z as SEND_LOOKUP } from "./send-BcM5UKMt.mjs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createInterface } from "node:readline/promises";
|
|
5
5
|
import { stripVTControlCharacters } from "node:util";
|
|
@@ -3497,7 +3497,7 @@ is out: update first, or put it off (the stop names both commands) · 64 usage
|
|
|
3497
3497
|
}));
|
|
3498
3498
|
const mcp = program.command("mcp").description("run the MCP server on stdio, for a coding agent to connect to").option("--account <name>", "pin the server to one account; every tool then acts on it and no other").action(async (flags) => {
|
|
3499
3499
|
ran = true;
|
|
3500
|
-
const startResendStdioServer = deps.startMcp ?? (await import("./stdio-entry-
|
|
3500
|
+
const startResendStdioServer = deps.startMcp ?? (await import("./stdio-entry-Ea4hMItp.mjs")).startResendStdioServer;
|
|
3501
3501
|
const core = coreForInvocation();
|
|
3502
3502
|
await startResendStdioServer({
|
|
3503
3503
|
...deps,
|
package/dist/index.d.mts
CHANGED
|
@@ -6203,6 +6203,20 @@ interface Core {
|
|
|
6203
6203
|
handoffs?: CliHandoffs | undefined;
|
|
6204
6204
|
}
|
|
6205
6205
|
//#endregion
|
|
6206
|
+
//#region ../core/dist/index.d.mts
|
|
6207
|
+
interface SendPacing {
|
|
6208
|
+
/**
|
|
6209
|
+
* The wait before the next attempt, after a refusal that says "later" — or null when the send should stop now: no
|
|
6210
|
+
* retries left, or the wait would run past the budget. A null spends no retry. `providerWaitMs` is the provider's own
|
|
6211
|
+
* wait, when it gave a usable one.
|
|
6212
|
+
*/
|
|
6213
|
+
next(providerWaitMs?: number): number | null;
|
|
6214
|
+
/** Waits that long. */
|
|
6215
|
+
wait(ms: number): Promise<void>;
|
|
6216
|
+
/** The retries granted so far. */
|
|
6217
|
+
readonly retries: number;
|
|
6218
|
+
}
|
|
6219
|
+
//#endregion
|
|
6206
6220
|
//#region src/caller.d.ts
|
|
6207
6221
|
/** This package's name, as its manifest has it: what core checks a caller against. */
|
|
6208
6222
|
export declare const PACKAGE_NAME = "@agentcomms/resend";
|
|
@@ -13436,6 +13450,8 @@ interface ResendContextOptions {
|
|
|
13436
13450
|
fetch?: FetchLike | undefined;
|
|
13437
13451
|
/** The throttle's clock and pause. Tests shorten the pause; nothing a person or an agent passes can. */
|
|
13438
13452
|
throttle?: ThrottleOptions | undefined;
|
|
13453
|
+
/** How a throttled send waits (design 2026-10-08 §R2): core's pacing; a test injects one on the throttle's clock. */
|
|
13454
|
+
sendPacing?: (() => SendPacing) | undefined;
|
|
13439
13455
|
}
|
|
13440
13456
|
//#endregion
|
|
13441
13457
|
//#region src/mcp/server.d.ts
|
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { At as RESEND_API_ORIGIN, Dt as PACKAGE_NAME, Mt as ROUTES, Nt as VERSION, Ot as RESEND_CALLER, jt as RESEND_DOWNLOAD_ORIGIN, kt as REFUSED } from "./send-
|
|
2
|
-
import { t as createResendMcpServer } from "./server-
|
|
1
|
+
import { At as RESEND_API_ORIGIN, Dt as PACKAGE_NAME, Mt as ROUTES, Nt as VERSION, Ot as RESEND_CALLER, jt as RESEND_DOWNLOAD_ORIGIN, kt as REFUSED } from "./send-BcM5UKMt.mjs";
|
|
2
|
+
import { t as createResendMcpServer } from "./server-EV5f6d28.mjs";
|
|
3
3
|
//#region src/index.ts
|
|
4
4
|
/**
|
|
5
5
|
* The library entry of `@agentcomms/resend`.
|
|
@@ -12,7 +12,7 @@ import { execFile, spawn } from "node:child_process";
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/version.ts
|
|
14
14
|
/** The package version, read from package.json at build time. */
|
|
15
|
-
const VERSION$1 = "0.15.
|
|
15
|
+
const VERSION$1 = "0.15.1";
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/api/routes.ts
|
|
18
18
|
/**
|
|
@@ -201,7 +201,7 @@ const RESEND_CALLER = Object.freeze({
|
|
|
201
201
|
packageName: PACKAGE_NAME
|
|
202
202
|
});
|
|
203
203
|
//#endregion
|
|
204
|
-
//#region ../core/dist/update-check-
|
|
204
|
+
//#region ../core/dist/update-check-CZwCVNLB.mjs
|
|
205
205
|
/**
|
|
206
206
|
* Every failure a user or an agent can act on carries a specific, stable code from this registry, a message, an
|
|
207
207
|
* optional one-line hint and structured `details`. The code decides the process exit status; agents and skills branch
|
|
@@ -9040,7 +9040,7 @@ function folding(platform) {
|
|
|
9040
9040
|
return platform === "win32" ? (text) => text.toLowerCase() : (text) => text;
|
|
9041
9041
|
}
|
|
9042
9042
|
/** The package version, read from package.json at build time. */
|
|
9043
|
-
const VERSION = "0.15.
|
|
9043
|
+
const VERSION = "0.15.1";
|
|
9044
9044
|
/**
|
|
9045
9045
|
* Versions as semver writes and orders them — what an update compares, and what the daily update check's reader needs
|
|
9046
9046
|
* to decide whether the release it last heard of is newer than the one running.
|
|
@@ -11726,7 +11726,7 @@ function serverPruneChange(core, env, request, own) {
|
|
|
11726
11726
|
};
|
|
11727
11727
|
const { packageName, version } = ownProduct(request.channel, own) ?? {
|
|
11728
11728
|
packageName: channelServer(request.channel).packageName,
|
|
11729
|
-
version: "0.15.
|
|
11729
|
+
version: "0.15.1"
|
|
11730
11730
|
};
|
|
11731
11731
|
const product = {
|
|
11732
11732
|
packageName,
|
|
@@ -13443,7 +13443,7 @@ function terminalUpdateHooks(core, env, options) {
|
|
|
13443
13443
|
};
|
|
13444
13444
|
}
|
|
13445
13445
|
//#endregion
|
|
13446
|
-
//#region ../core/dist/tool-arguments-
|
|
13446
|
+
//#region ../core/dist/tool-arguments-jABbxaql.mjs
|
|
13447
13447
|
const APPLIED = Symbol.for("agentcomms.strictToolArguments");
|
|
13448
13448
|
const TARGET = "draft-2020-12";
|
|
13449
13449
|
/**
|
|
@@ -24523,6 +24523,30 @@ function hiddenReason(element) {
|
|
|
24523
24523
|
if (element.attribs.style && hidesContent(parseStyle(element.attribs.style))) return `inline style: ${element.attribs.style.slice(0, 120)}`;
|
|
24524
24524
|
return "hidden by a stylesheet rule";
|
|
24525
24525
|
}
|
|
24526
|
+
const BASE_MS = 1e3;
|
|
24527
|
+
function sendPacing(options = {}) {
|
|
24528
|
+
const maxRetries = options.maxRetries ?? 3;
|
|
24529
|
+
const budgetMs = options.budgetMs ?? 45e3;
|
|
24530
|
+
const now = options.now ?? Date.now;
|
|
24531
|
+
const sleep = options.sleep ?? ((ms) => setTimeout$1(ms).then(() => void 0));
|
|
24532
|
+
const random = options.random ?? Math.random;
|
|
24533
|
+
const startedAt = now();
|
|
24534
|
+
let retries = 0;
|
|
24535
|
+
return {
|
|
24536
|
+
next(providerWaitMs) {
|
|
24537
|
+
if (retries >= maxRetries) return null;
|
|
24538
|
+
const step = BASE_MS * 2 ** retries;
|
|
24539
|
+
const delay = typeof providerWaitMs === "number" && Number.isFinite(providerWaitMs) && providerWaitMs >= 0 ? Math.ceil(providerWaitMs) : Math.round(step / 2 + step / 2 * random());
|
|
24540
|
+
if (now() - startedAt + delay > budgetMs) return null;
|
|
24541
|
+
retries += 1;
|
|
24542
|
+
return delay;
|
|
24543
|
+
},
|
|
24544
|
+
wait: (ms) => sleep(ms),
|
|
24545
|
+
get retries() {
|
|
24546
|
+
return retries;
|
|
24547
|
+
}
|
|
24548
|
+
};
|
|
24549
|
+
}
|
|
24526
24550
|
/** The reason a send is recorded `failed` when its lease was lost before any provider step began. */
|
|
24527
24551
|
const LEASE_LOST_BEFORE_SEND = "lease-lost-before-send";
|
|
24528
24552
|
/**
|
|
@@ -24918,6 +24942,8 @@ var ResendContext = class {
|
|
|
24918
24942
|
handoffs;
|
|
24919
24943
|
accounts;
|
|
24920
24944
|
#fetch;
|
|
24945
|
+
/** A fresh pacing for each send: how a throttled one waits before it tries again. */
|
|
24946
|
+
sendPacing;
|
|
24921
24947
|
#throttle;
|
|
24922
24948
|
#teamDomains = /* @__PURE__ */ new Map();
|
|
24923
24949
|
constructor(options = {}) {
|
|
@@ -24935,6 +24961,7 @@ var ResendContext = class {
|
|
|
24935
24961
|
this.accounts = new AccountStore(() => this.core.config.load(), this.handoffs);
|
|
24936
24962
|
this.#fetch = options.fetch;
|
|
24937
24963
|
this.#throttle = new Throttle(this.core.paths.stateDir, options.throttle);
|
|
24964
|
+
this.sendPacing = options.sendPacing ?? (() => sendPacing());
|
|
24938
24965
|
}
|
|
24939
24966
|
config() {
|
|
24940
24967
|
return this.core.config.load();
|
|
@@ -25145,6 +25172,65 @@ const REFUSED_BEFORE_ACTING = /* @__PURE__ */ new Set([
|
|
|
25145
25172
|
function writeOutcomeOf(status) {
|
|
25146
25173
|
return status !== void 0 && REFUSED_BEFORE_ACTING.has(status) ? "not-sent" : "unknown";
|
|
25147
25174
|
}
|
|
25175
|
+
/**
|
|
25176
|
+
* The limit a send's refusal names, or undefined when it names none.
|
|
25177
|
+
*
|
|
25178
|
+
* Only a `429` Resend gave before acting: `rate_limit_exceeded` (or no name) is requests per second; `daily_quota_exceeded`
|
|
25179
|
+
* resets at midnight UTC; `monthly_quota_exceeded` needs a larger plan (resend.com/docs/api-reference/errors, read
|
|
25180
|
+
* 2026-10-08).
|
|
25181
|
+
*/
|
|
25182
|
+
function sendThrottleOf(error, nowMs = Date.now()) {
|
|
25183
|
+
if (!(error instanceof CommsError)) return void 0;
|
|
25184
|
+
const details = error.details ?? {};
|
|
25185
|
+
if (details.status !== 429 || details.outcome !== "not-sent") return void 0;
|
|
25186
|
+
const name = details.resendError;
|
|
25187
|
+
const limit = name === "daily_quota_exceeded" ? "daily-quota" : name === "monthly_quota_exceeded" ? "monthly-quota" : name === "rate_limit_exceeded" || name === "http_429" || name === void 0 ? "rate" : void 0;
|
|
25188
|
+
if (limit === void 0) return void 0;
|
|
25189
|
+
if (limit === "monthly-quota") return { limit };
|
|
25190
|
+
if (limit === "daily-quota") {
|
|
25191
|
+
const midnight = new Date(nowMs);
|
|
25192
|
+
midnight.setUTCHours(24, 0, 0, 0);
|
|
25193
|
+
return {
|
|
25194
|
+
limit,
|
|
25195
|
+
retryAt: midnight.toISOString()
|
|
25196
|
+
};
|
|
25197
|
+
}
|
|
25198
|
+
const seconds = details.retryAfterSeconds;
|
|
25199
|
+
if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds < 0) return { limit };
|
|
25200
|
+
const waitMs = Math.max(1, seconds) * 1e3;
|
|
25201
|
+
return {
|
|
25202
|
+
limit,
|
|
25203
|
+
waitMs,
|
|
25204
|
+
retryAt: new Date(nowMs + waitMs).toISOString()
|
|
25205
|
+
};
|
|
25206
|
+
}
|
|
25207
|
+
/**
|
|
25208
|
+
* The refusal a throttled send ends with, once it stops (design 2026-10-08 §R4, §R5). Nothing was sent; the send's
|
|
25209
|
+
* no-send bookkeeping says so in front of these words.
|
|
25210
|
+
*/
|
|
25211
|
+
function throttledRefusal(throttle, retries, cause) {
|
|
25212
|
+
const tried = retries === 0 ? "" : ` (tried ${retries + 1} times)`;
|
|
25213
|
+
const details = {
|
|
25214
|
+
limit: throttle.limit,
|
|
25215
|
+
retries,
|
|
25216
|
+
...throttle.retryAt ? { retryAt: throttle.retryAt } : {}
|
|
25217
|
+
};
|
|
25218
|
+
if (throttle.limit === "monthly-quota") return new CommsError("TRANSIENT", "this Resend team's monthly sending quota is used up", {
|
|
25219
|
+
hint: "A larger Resend plan raises it. Prepare the send again once it has.",
|
|
25220
|
+
details,
|
|
25221
|
+
cause
|
|
25222
|
+
});
|
|
25223
|
+
if (throttle.limit === "daily-quota") return new CommsError("TRANSIENT", "this Resend team's daily sending quota is used up", {
|
|
25224
|
+
hint: `It resets at midnight UTC (${throttle.retryAt}). Prepare the send again then, or move to a plan without a daily quota.`,
|
|
25225
|
+
details,
|
|
25226
|
+
cause
|
|
25227
|
+
});
|
|
25228
|
+
return new CommsError("TRANSIENT", `Resend is rate-limiting this team${tried}`, {
|
|
25229
|
+
hint: throttle.retryAt ? `Prepare the send again after ${throttle.retryAt}.` : "Prepare the send again in a minute.",
|
|
25230
|
+
details,
|
|
25231
|
+
cause
|
|
25232
|
+
});
|
|
25233
|
+
}
|
|
25148
25234
|
/** One API request. Resolves to the parsed JSON body of a 2xx, or throws a `CommsError` whose text holds no key. */
|
|
25149
25235
|
async function resendRequest(transport, method, path, options = {}) {
|
|
25150
25236
|
const writing = method !== "GET";
|
|
@@ -27545,65 +27631,78 @@ async function claimAndSend(context, named, name, options, known, _seen, legacyD
|
|
|
27545
27631
|
} catch (error) {
|
|
27546
27632
|
throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, error);
|
|
27547
27633
|
}
|
|
27548
|
-
const
|
|
27549
|
-
if (!fenced.proceed) {
|
|
27550
|
-
const stopped = fenced.error ?? new CommsError("UNEXPECTED", "the sending lease ran out before anything was sent");
|
|
27551
|
-
throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, stopped, "settled");
|
|
27552
|
-
}
|
|
27634
|
+
const pacing = context.sendPacing();
|
|
27553
27635
|
let resendId;
|
|
27554
|
-
|
|
27555
|
-
|
|
27556
|
-
|
|
27557
|
-
|
|
27558
|
-
|
|
27559
|
-
requestIssued = true;
|
|
27560
|
-
return innerFetch(...args);
|
|
27561
|
-
}
|
|
27562
|
-
};
|
|
27563
|
-
try {
|
|
27564
|
-
const response = await spendOn(permit, options.approvalId, "emails.send", () => resendRequest(trackedTransport, "POST", "/emails", {
|
|
27565
|
-
body: payloadOf(message, options.approvalId, contents),
|
|
27566
|
-
idempotencyKey: options.approvalId
|
|
27567
|
-
}));
|
|
27568
|
-
resendId = typeof response.id === "string" && response.id.trim() !== "" ? response.id : void 0;
|
|
27569
|
-
} catch (error) {
|
|
27570
|
-
if (!requestIssued) throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, error);
|
|
27571
|
-
const outcome = error instanceof CommsError && error.details?.outcome === "not-sent" ? "not-sent" : error instanceof CommsError && error.code === "SEND_REFUSED" ? "not-sent" : "unknown";
|
|
27572
|
-
const said = error instanceof Error ? error.message : String(error);
|
|
27573
|
-
if (outcome === "not-sent") throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, error);
|
|
27574
|
-
const unrecorded = [];
|
|
27575
|
-
try {
|
|
27576
|
-
await records.record(named.account.id, {
|
|
27577
|
-
approvalId: options.approvalId,
|
|
27578
|
-
event: "unknown",
|
|
27579
|
-
error: said.slice(0, 300)
|
|
27580
|
-
});
|
|
27581
|
-
} catch (failure) {
|
|
27582
|
-
unrecorded.push(`the send record could not record this (${failure instanceof Error ? failure.message : String(failure)})`);
|
|
27636
|
+
for (;;) {
|
|
27637
|
+
const fenced = await fenceOrStop(context.core.approvals, options.approvalId, claimToken, { stepsStarted: 0 });
|
|
27638
|
+
if (!fenced.proceed) {
|
|
27639
|
+
const stopped = fenced.error ?? new CommsError("UNEXPECTED", "the sending lease ran out before anything was sent");
|
|
27640
|
+
throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, stopped, "settled");
|
|
27583
27641
|
}
|
|
27642
|
+
let requestIssued = false;
|
|
27643
|
+
const innerFetch = transport.fetch ?? fetch;
|
|
27644
|
+
const trackedTransport = {
|
|
27645
|
+
...transport,
|
|
27646
|
+
fetch: async (...args) => {
|
|
27647
|
+
requestIssued = true;
|
|
27648
|
+
return innerFetch(...args);
|
|
27649
|
+
}
|
|
27650
|
+
};
|
|
27584
27651
|
try {
|
|
27585
|
-
await
|
|
27586
|
-
|
|
27587
|
-
|
|
27588
|
-
|
|
27589
|
-
|
|
27590
|
-
|
|
27591
|
-
|
|
27592
|
-
|
|
27652
|
+
const response = await spendOn(permit, options.approvalId, "emails.send", () => resendRequest(trackedTransport, "POST", "/emails", {
|
|
27653
|
+
body: payloadOf(message, options.approvalId, contents),
|
|
27654
|
+
idempotencyKey: options.approvalId
|
|
27655
|
+
}));
|
|
27656
|
+
resendId = typeof response.id === "string" && response.id.trim() !== "" ? response.id : void 0;
|
|
27657
|
+
break;
|
|
27658
|
+
} catch (error) {
|
|
27659
|
+
if (!requestIssued) throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, error);
|
|
27660
|
+
const outcome = error instanceof CommsError && error.details?.outcome === "not-sent" ? "not-sent" : error instanceof CommsError && error.code === "SEND_REFUSED" ? "not-sent" : "unknown";
|
|
27661
|
+
const said = error instanceof Error ? error.message : String(error);
|
|
27662
|
+
if (outcome === "not-sent") {
|
|
27663
|
+
const throttle = sendThrottleOf(error, context.now().getTime());
|
|
27664
|
+
const delay = throttle?.limit === "rate" ? pacing.next(throttle.waitMs) : null;
|
|
27665
|
+
if (delay !== null) {
|
|
27666
|
+
await pacing.wait(delay);
|
|
27667
|
+
continue;
|
|
27668
|
+
}
|
|
27669
|
+
const refusal = throttle ? throttledRefusal(throttle, pacing.retries, error) : error;
|
|
27670
|
+
throw await recordNoSend(context, records, bookkeeping, claimToken, claimedApproval, refusal);
|
|
27671
|
+
}
|
|
27672
|
+
const unrecorded = [];
|
|
27673
|
+
try {
|
|
27674
|
+
await records.record(named.account.id, {
|
|
27675
|
+
approvalId: options.approvalId,
|
|
27676
|
+
event: "unknown",
|
|
27677
|
+
error: said.slice(0, 300)
|
|
27678
|
+
});
|
|
27679
|
+
} catch (failure) {
|
|
27680
|
+
unrecorded.push(`the send record could not record this (${failure instanceof Error ? failure.message : String(failure)})`);
|
|
27681
|
+
}
|
|
27682
|
+
try {
|
|
27683
|
+
await context.core.audit.append({
|
|
27684
|
+
inboxId: named.account.id,
|
|
27685
|
+
alias: name,
|
|
27686
|
+
operation: "resend.send.execute",
|
|
27687
|
+
outcome: "failed",
|
|
27688
|
+
surface: context.surface,
|
|
27689
|
+
approvalId: options.approvalId,
|
|
27690
|
+
reason: `outcome unknown: ${said.slice(0, 200)}`
|
|
27691
|
+
});
|
|
27692
|
+
} catch (failure) {
|
|
27693
|
+
unrecorded.push(`the audit log could not record this (${failure instanceof Error ? failure.message : String(failure)})`);
|
|
27694
|
+
}
|
|
27695
|
+
throw new CommsError("SEND_OUTCOME_UNKNOWN", `whether the email was sent is not known: ${said}`, {
|
|
27696
|
+
hint: [`Do not send it again, and do not prepare it again until you know it did not go. ${handoffSentence(statusCommand(context.handoffs, options.approvalId, name), (command) => `Check the Resend dashboard or ask the recipient, and check with ${command}; this approval is not used again.`, { instead: "Check the Resend dashboard or ask the recipient, and check with resend_send_status; this approval is not used again." })}`, ...unrecorded].join(" "),
|
|
27697
|
+
details: {
|
|
27698
|
+
...error instanceof CommsError ? error.details : {},
|
|
27699
|
+
approvalId: options.approvalId,
|
|
27700
|
+
outcome: "unknown",
|
|
27701
|
+
approval: await approvalNow(context, options.approvalId, named.account.id, claimedApproval)
|
|
27702
|
+
},
|
|
27703
|
+
cause: error
|
|
27593
27704
|
});
|
|
27594
|
-
} catch (failure) {
|
|
27595
|
-
unrecorded.push(`the audit log could not record this (${failure instanceof Error ? failure.message : String(failure)})`);
|
|
27596
27705
|
}
|
|
27597
|
-
throw new CommsError("SEND_OUTCOME_UNKNOWN", `whether the email was sent is not known: ${said}`, {
|
|
27598
|
-
hint: [`Do not send it again, and do not prepare it again until you know it did not go. ${handoffSentence(statusCommand(context.handoffs, options.approvalId, name), (command) => `Check the Resend dashboard or ask the recipient, and check with ${command}; this approval is not used again.`, { instead: "Check the Resend dashboard or ask the recipient, and check with resend_send_status; this approval is not used again." })}`, ...unrecorded].join(" "),
|
|
27599
|
-
details: {
|
|
27600
|
-
...error instanceof CommsError ? error.details : {},
|
|
27601
|
-
approvalId: options.approvalId,
|
|
27602
|
-
outcome: "unknown",
|
|
27603
|
-
approval: await approvalNow(context, options.approvalId, named.account.id, claimedApproval)
|
|
27604
|
-
},
|
|
27605
|
-
cause: error
|
|
27606
|
-
});
|
|
27607
27706
|
}
|
|
27608
27707
|
const unrecorded = [];
|
|
27609
27708
|
let approval = null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as CHANGE_POLICIES, C as policyChange, Ct as waitCallOptions, E as removeAccountChange, I as CommsError, K as changeToolResult, M as SEND_POLICIES, Nt as VERSION, O as showAccount, P as strictToolArguments, S as policyApprovalRefusal, St as updateToolGate, T as policyWanted, _ as runDoctor, b as listAccounts, c as downloadReceived, d as listReceived, et as gatedChange, f as listScheduled, g as showSentEmail, h as showReceived, i as prepareSend, j as MODES, k as ResendContext, l as getMetrics, lt as refuseUnclaimedApproval, m as listSuppressions, n as executeSend, o as sendStatus, p as listSentEmails, q as checkForUpdates, s as cancelScheduledChange, u as listDomains, w as policyReport, wt as waitForApproval, yt as toCommsError, z as SEND_LOOKUP } from "./send-
|
|
1
|
+
import { A as CHANGE_POLICIES, C as policyChange, Ct as waitCallOptions, E as removeAccountChange, I as CommsError, K as changeToolResult, M as SEND_POLICIES, Nt as VERSION, O as showAccount, P as strictToolArguments, S as policyApprovalRefusal, St as updateToolGate, T as policyWanted, _ as runDoctor, b as listAccounts, c as downloadReceived, d as listReceived, et as gatedChange, f as listScheduled, g as showSentEmail, h as showReceived, i as prepareSend, j as MODES, k as ResendContext, l as getMetrics, lt as refuseUnclaimedApproval, m as listSuppressions, n as executeSend, o as sendStatus, p as listSentEmails, q as checkForUpdates, s as cancelScheduledChange, u as listDomains, w as policyReport, wt as waitForApproval, yt as toCommsError, z as SEND_LOOKUP } from "./send-BcM5UKMt.mjs";
|
|
2
2
|
import { S as union, c as boolean, g as object, h as number, s as array, x as string } from "./iso-USuVU_sk.mjs";
|
|
3
3
|
import { t as McpServer } from "./mcp-DXXb3Vv3-kCxsVLO4.mjs";
|
|
4
4
|
//#region src/mcp/server.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createResendMcpServer } from "./server-
|
|
1
|
+
import { t as createResendMcpServer } from "./server-EV5f6d28.mjs";
|
|
2
2
|
//#region src/mcp/stdio-entry.ts
|
|
3
3
|
/**
|
|
4
4
|
* Starting the stdio server. On stdio, **stdout is the protocol**: one stray `console.log` corrupts the stream, so
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentcomms/resend",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.1",
|
|
4
4
|
"description": "Resend for coding agents: read domains, sent and received mail, metrics and suppressions, and send mail that nothing sends without a person's approval of exactly what goes out.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"THIRD_PARTY_LICENSES"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@agentcomms/core": "0.15.
|
|
34
|
+
"@agentcomms/core": "0.15.1"
|
|
35
35
|
},
|
|
36
36
|
"optionalDependencies": {
|
|
37
37
|
"@napi-rs/keyring": "2.1.0"
|
|
@@ -97,5 +97,5 @@
|
|
|
97
97
|
"typecheck": "tsc -p tsconfig.json",
|
|
98
98
|
"test": "node --experimental-strip-types --test --test-timeout=600000 \"test/**/*.test.ts\""
|
|
99
99
|
},
|
|
100
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "813bc13b5d4172b66ef2def3020456c8c56c763e"
|
|
101
101
|
}
|