@agentcomms/resend 0.13.0 → 0.14.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.
@@ -1,4 +1,4 @@
1
- import { A as CHANGE_POLICIES, C as policyChange, E as removeAccountChange, G as changeToolResult, I as CommsError, K as checkForUpdates, M as SEND_POLICIES, O as showAccount, P as strictToolArguments, R as SEND_LOOKUP, S as policyApprovalRefusal, T as policyWanted, Z as gatedChange, _ as runDoctor, b as listAccounts, c as downloadReceived, d as listReceived, f as listScheduled, ft as toCommsError, g as showSentEmail, h as showReceived, ht as updateToolGate, i as prepareSend, j as MODES, k as ResendContext, l as getMetrics, m as listSuppressions, n as executeSend, o as sendStatus, p as listSentEmails, rt as refuseUnclaimedApproval, s as cancelScheduledChange, u as listDomains, w as policyReport, xt as VERSION } from "./send-D2ZOWO_6.mjs";
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-9pskzeUY.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
@@ -29,19 +29,19 @@ async function buildInstructions(context, pinned) {
29
29
  "",
30
30
  "Sending needs a person’s yes to that exact email. `resend_send_prepare` returns a preview: show it in full and",
31
31
  "wait. Under the account’s `chat` policy `resend_send_execute` then sends it, once. Under `confirm` — and always",
32
- "above 10 recipients — the person runs `agent-resend approve <id>` at their own terminal; you cannot approve it",
33
- "yourself, so say so and wait. Under `never` nothing sends. Never repeat a send whose outcome is unknown: check",
34
- "it with `resend_send_status`.",
32
+ "above 10 recipients — the person runs the approve command the preparation gives, at their own terminal;",
33
+ "you cannot approve it yourself, so say so; resend_send_wait tells you when they have. Under `never` nothing",
34
+ "sends. Never repeat a send whose outcome is unknown: check it with `resend_send_status`.",
35
35
  "",
36
- "Read-only is enforced by agent-resend, not by the key: Resend has no read-only key.",
37
- "A key is added only by a person at a terminal (`agent-resend account add`). Never ask for one in chat.",
36
+ "Read-only is enforced by this package’s own code, not by the key: Resend has no read-only key.",
37
+ "A key is added only by a person, at their own terminal. Never ask for one in chat.",
38
38
  "",
39
39
  pinned ? `This server is pinned to "${pinned}"; the account argument may be omitted.` : "Pass `account` on every call — there is no default.",
40
40
  names.length > 0 ? `Known accounts — "can send" means only after a person approves: ${listOf(names)}.` : "No account is connected yet.",
41
41
  "",
42
42
  "Changing an account (send mode, a looser policy, removing it) or cancelling an email scheduled elsewhere returns",
43
43
  "`approvalRequired` and a preview: show it and ask. Under the `chat` change policy call again with `approvalId`",
44
- "after their yes; under `confirm` they run `agent-resend approve <id>` first. Tightening applies at once."
44
+ "after their yes; under `confirm` they first run the approve command the result gives. Tightening applies at once."
45
45
  ].join("\n");
46
46
  }
47
47
  async function createResendMcpServer(options = {}) {
@@ -56,7 +56,7 @@ async function createResendMcpServer(options = {}) {
56
56
  version: VERSION
57
57
  }, { instructions: await buildInstructions(context, pinned) });
58
58
  const reply = (data) => {
59
- const structured = data;
59
+ const structured = JSON.parse(JSON.stringify(data));
60
60
  return {
61
61
  structuredContent: structured,
62
62
  content: [{
@@ -67,12 +67,12 @@ async function createResendMcpServer(options = {}) {
67
67
  };
68
68
  const fail = (error) => {
69
69
  const comms = toCommsError(error);
70
- const structured = { error: {
70
+ const structured = JSON.parse(JSON.stringify({ error: {
71
71
  code: comms.code,
72
72
  message: comms.message,
73
73
  hint: comms.hint ?? null,
74
74
  ...comms.details !== void 0 ? { details: comms.details } : {}
75
- } };
75
+ } }));
76
76
  return {
77
77
  isError: true,
78
78
  structuredContent: structured,
@@ -89,7 +89,10 @@ async function createResendMcpServer(options = {}) {
89
89
  channel: "resend",
90
90
  running: VERSION,
91
91
  exempt: ["resend_doctor"],
92
- approvals: { resend_send_status: SEND_LOOKUP },
92
+ approvals: {
93
+ resend_send_status: SEND_LOOKUP,
94
+ resend_send_wait: { lookup: true }
95
+ },
93
96
  refresh: () => checkForUpdates(context.core, context.env)
94
97
  }));
95
98
  /** Which account a call acts on. A pinned server refuses any other, and re-checks the pin against the id. */
@@ -104,9 +107,9 @@ async function createResendMcpServer(options = {}) {
104
107
  return named;
105
108
  };
106
109
  const runChange = async (change, approvalId) => changeToolResult(await gatedChange(context.core, change, {
110
+ channel: "resend",
107
111
  surface: "mcp",
108
112
  approvalId,
109
- approveCommand: "agent-resend approve",
110
113
  platform: context.platform
111
114
  }));
112
115
  const readsResend = {
@@ -118,7 +121,7 @@ async function createResendMcpServer(options = {}) {
118
121
  openWorldHint: false
119
122
  };
120
123
  const accountArg = { account: string().optional().describe("which account, as `organisation/resend`") };
121
- const approvalArg = { approvalId: string().optional().describe("the approval the preview named, once the person has agreed (or run `agent-resend approve`)") };
124
+ const approvalArg = { approvalId: string().optional().describe("the approval the preview named, once the person has agreed (or run the approve command it gave)") };
122
125
  const number$1 = union([number(), string()]);
123
126
  const words = (values) => string().meta({ enum: [...values] });
124
127
  const paging = {
@@ -134,7 +137,7 @@ async function createResendMcpServer(options = {}) {
134
137
  };
135
138
  server.registerTool("resend_accounts_list", {
136
139
  title: "List accounts",
137
- description: "The connected Resend accounts: each key’s permission, its mode, its send policy, and who enforces what. Read-only is agent-resend’s own promise, never the key’s.",
140
+ description: "The connected Resend accounts: each key’s permission, its mode, its send policy, and who enforces what. Read-only is this package’s own promise, never the key’s.",
138
141
  inputSchema: {},
139
142
  annotations: readsLocal
140
143
  }, wrapped(async () => {
@@ -149,7 +152,7 @@ async function createResendMcpServer(options = {}) {
149
152
  }, wrapped(async (args) => showAccount(context, await resolve(args.account))));
150
153
  server.registerTool("resend_account_remove", {
151
154
  title: "Remove an account",
152
- description: "Forget an account and delete its key from this machine. Returns `approvalRequired` and a preview first: show it and ask; call again with `approvalId` after their yes (under `confirm`, after they run `agent-resend approve <id>` — you cannot approve it yourself).",
155
+ description: "Forget an account and delete its key from this machine. Returns `approvalRequired` and a preview first: show it and ask; call again with `approvalId` after their yes (under `confirm`, after they run the approve command the result gives — you cannot approve it yourself).",
153
156
  inputSchema: {
154
157
  ...accountArg,
155
158
  ...approvalArg
@@ -195,7 +198,7 @@ async function createResendMcpServer(options = {}) {
195
198
  }));
196
199
  server.registerTool("resend_doctor", {
197
200
  title: "Doctor",
198
- description: "What works and what does not, per account — and, plainly, that read-only is enforced by agent-resend’s code, not by the key.",
201
+ description: "What works and what does not, per account — and, plainly, that read-only is enforced by this package’s code, not by the key.",
199
202
  inputSchema: {
200
203
  ...accountArg,
201
204
  offline: boolean().optional().describe("do not ask Resend anything")
@@ -339,7 +342,7 @@ async function createResendMcpServer(options = {}) {
339
342
  }));
340
343
  server.registerTool("resend_send_execute", {
341
344
  title: "Send a prepared email",
342
- description: "Send a prepared email, once, after the person approved its preview. Under `confirm` the person must first run `agent-resend approve <approvalId>` at their own terminal — you cannot approve it yourself. `expect` restates the recipients and subject shown. Never call it again for an email whose outcome is unknown: use `resend_send_status`.",
345
+ description: "Send a prepared email, once, after the person approved its preview. Under `confirm` the person must first run the approve command `resend_send_prepare` gave, at their own terminal — you cannot approve it yourself. `expect` restates the recipients and subject shown. Never call it again for an email whose outcome is unknown: use `resend_send_status`.",
343
346
  inputSchema: {
344
347
  ...accountArg,
345
348
  approvalId: string().describe("the approval `resend_send_prepare` returned"),
@@ -365,7 +368,7 @@ async function createResendMcpServer(options = {}) {
365
368
  }));
366
369
  server.registerTool("resend_send_status", {
367
370
  title: "Send status",
368
- description: "What happened to a send: the approval, the local record, and Resend’s last event. Read only — it never sends again.",
371
+ description: "What happened to a send: the approval, the local record, and its current `outcome` as Resend’s own last event reports it. One event for the whole email, attributed to Resend — never a word about every recipient; an event this version does not interpret comes only inside <untrusted-content>. Read only — it never sends again.",
369
372
  inputSchema: {
370
373
  ...accountArg,
371
374
  approvalId: string()
@@ -375,6 +378,26 @@ async function createResendMcpServer(options = {}) {
375
378
  const name = await resolve(args.account);
376
379
  return sendStatus(context, name, args.approvalId);
377
380
  }));
381
+ server.registerTool("resend_send_wait", {
382
+ title: "Wait for an approval",
383
+ description: `Wait for an approval — a send or a change — to be usable or finished, and say where it stands: pending (with \`claimable\` true when a yes in the chat can use it), approved, being sent, used, failed, unknown, expired, revoked or corrupt. \`waitSeconds\` is 30 when left out, 300 at most, and 0 for its status now. It only looks: it never approves, claims or sends, and never asks Resend. Ended still waiting, wait again — never prepare it again while it is pending or being sent. The same as \`send wait\` in the Resend CLI.`,
384
+ inputSchema: {
385
+ approvalId: string().describe("the approval to wait for"),
386
+ waitSeconds: number().int().min(0).max(300).optional().describe(`how long to wait: 30 when left out, 300 at most, 0 for the status now`)
387
+ },
388
+ annotations: readsLocal
389
+ }, async (args, ctx) => {
390
+ try {
391
+ return reply(await waitForApproval(context.core, args.approvalId, {
392
+ waitSeconds: args.waitSeconds,
393
+ channel: "resend",
394
+ ...pinnedId === void 0 ? {} : { owner: pinnedId },
395
+ ...waitCallOptions(ctx)
396
+ }));
397
+ } catch (error) {
398
+ return fail(error);
399
+ }
400
+ });
378
401
  server.registerTool("resend_scheduled_list", {
379
402
  title: "Scheduled emails",
380
403
  description: "Emails waiting to be sent later, among the most recent 300 sent, and whether this machine scheduled each.",
@@ -1,4 +1,4 @@
1
- import { t as createResendMcpServer } from "./server-CLjdcZDg.mjs";
1
+ import { t as createResendMcpServer } from "./server-DFbgMT3K.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.13.0",
3
+ "version": "0.14.0",
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",
@@ -30,6 +30,9 @@
30
30
  "LICENSE",
31
31
  "THIRD_PARTY_LICENSES"
32
32
  ],
33
+ "dependencies": {
34
+ "@agentcomms/core": "0.14.0"
35
+ },
33
36
  "optionalDependencies": {
34
37
  "@napi-rs/keyring": "2.1.0"
35
38
  },
@@ -37,8 +40,7 @@
37
40
  "@modelcontextprotocol/client": "2.0.0",
38
41
  "@modelcontextprotocol/server": "^2.0.0",
39
42
  "commander": "^15.0.0",
40
- "zod": "^4.6.5",
41
- "@agentcomms/core": "0.13.0"
43
+ "zod": "^4.6.5"
42
44
  },
43
45
  "publishConfig": {
44
46
  "access": "public"
@@ -65,7 +67,7 @@
65
67
  "guarantee": {
66
68
  "ceiling": "code",
67
69
  "floor": "code",
68
- "why": "Resend has no read-only key, and a full-access key can also manage domains and keys: read mode, and send mode's limit to sending, are enforced by agent-resend's own code. A sending-access key can only send, and Resend enforces that."
70
+ "why": "Resend has no read-only key, and a full-access key can also manage domains and keys: read mode, and send mode's limit to sending, are enforced by this package's own code. A sending-access key can only send, and Resend enforces that."
69
71
  }
70
72
  },
71
73
  "narrowing": [
@@ -84,6 +86,7 @@
84
86
  "inbound-cdn.resend.com"
85
87
  ],
86
88
  "approve": "agent-resend approve",
89
+ "approvalGrouping": "draft",
87
90
  "skills": {
88
91
  "prefix": "resend-",
89
92
  "contract": "skills/_shared/contract-resend.md"
@@ -94,5 +97,5 @@
94
97
  "typecheck": "tsc -p tsconfig.json",
95
98
  "test": "node --experimental-strip-types --test --test-timeout=600000 \"test/**/*.test.ts\""
96
99
  },
97
- "gitHead": "afd195efd8cbdaaab148859867a1170684af6ae3"
100
+ "gitHead": "6f6a9de4c7e18e88d779f04de384fbc4e5397352"
98
101
  }