@poncho-ai/messaging 0.2.7 → 0.2.8

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,5 +1,5 @@
1
1
 
2
- > @poncho-ai/messaging@0.2.7 build /home/runner/work/poncho-ai/poncho-ai/packages/messaging
2
+ > @poncho-ai/messaging@0.2.8 build /home/runner/work/poncho-ai/poncho-ai/packages/messaging
3
3
  > tsup src/index.ts --format esm --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -7,8 +7,8 @@
7
7
  CLI tsup v8.5.1
8
8
  CLI Target: es2022
9
9
  ESM Build start
10
- ESM dist/index.js 29.65 KB
11
- ESM ⚡️ Build success in 53ms
10
+ ESM dist/index.js 30.13 KB
11
+ ESM ⚡️ Build success in 77ms
12
12
  DTS Build start
13
- DTS ⚡️ Build success in 4785ms
13
+ DTS ⚡️ Build success in 5331ms
14
14
  DTS dist/index.d.ts 8.98 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @poncho-ai/messaging
2
2
 
3
+ ## 0.2.8
4
+
5
+ ### Patch Changes
6
+
7
+ - [`deb134e`](https://github.com/cesr/poncho-ai/commit/deb134e8a6ecf38d85dc200f57998e33406eff61) Thanks [@cesr](https://github.com/cesr)! - Retry Resend API requests on transient socket errors (common on Vercel cold starts).
8
+
3
9
  ## 0.2.7
4
10
 
5
11
  ### Patch Changes
package/dist/index.js CHANGED
@@ -450,6 +450,20 @@ function matchesSenderPattern(sender, patterns) {
450
450
  }
451
451
 
452
452
  // src/adapters/resend/index.ts
453
+ var isSocketError = (err) => err instanceof TypeError && err.message === "fetch failed" && err.cause?.code === "UND_ERR_SOCKET";
454
+ async function fetchWithRetry(input, init, retries = 2) {
455
+ for (let attempt = 0; ; attempt++) {
456
+ try {
457
+ return await fetch(input, init);
458
+ } catch (err) {
459
+ if (attempt < retries && isSocketError(err)) {
460
+ await new Promise((r) => setTimeout(r, 200 * (attempt + 1)));
461
+ continue;
462
+ }
463
+ throw err;
464
+ }
465
+ }
466
+ }
453
467
  function verifySvixSignature(rawBody, svixId, svixTimestamp, svixSignature, secret) {
454
468
  const now = Math.floor(Date.now() / 1e3);
455
469
  const ts = parseInt(svixTimestamp, 10);
@@ -804,7 +818,7 @@ var ResendAdapter = class {
804
818
  let emailHeaders;
805
819
  if (emailId) {
806
820
  try {
807
- const resp = await fetch(
821
+ const resp = await fetchWithRetry(
808
822
  `https://api.resend.com/emails/receiving/${emailId}`,
809
823
  { headers: { Authorization: `Bearer ${this.apiKey}` } }
810
824
  );
@@ -860,7 +874,7 @@ var ResendAdapter = class {
860
874
  if (!emailId || !webhookAttachments || webhookAttachments.length === 0) return [];
861
875
  let attachments = [];
862
876
  try {
863
- const resp = await fetch(
877
+ const resp = await fetchWithRetry(
864
878
  `https://api.resend.com/emails/receiving/${emailId}/attachments`,
865
879
  { headers: { Authorization: `Bearer ${this.apiKey}` } }
866
880
  );
@@ -879,7 +893,7 @@ var ResendAdapter = class {
879
893
  for (const att of attachments) {
880
894
  if (!att.download_url) continue;
881
895
  try {
882
- const resp = await fetch(att.download_url);
896
+ const resp = await fetchWithRetry(att.download_url);
883
897
  if (!resp.ok) continue;
884
898
  const buf = Buffer.from(await resp.arrayBuffer());
885
899
  results.push({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@poncho-ai/messaging",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Messaging platform adapters for Poncho agents (Slack, Telegram, etc.)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -9,6 +9,30 @@ import type {
9
9
  RouteRegistrar,
10
10
  ThreadRef,
11
11
  } from "../../types.js";
12
+
13
+ const isSocketError = (err: unknown): boolean =>
14
+ err instanceof TypeError &&
15
+ err.message === "fetch failed" &&
16
+ (err as { cause?: { code?: string } }).cause?.code === "UND_ERR_SOCKET";
17
+
18
+ async function fetchWithRetry(
19
+ input: string | URL | Request,
20
+ init?: RequestInit,
21
+ retries = 2,
22
+ ): Promise<Response> {
23
+ for (let attempt = 0; ; attempt++) {
24
+ try {
25
+ return await fetch(input, init);
26
+ } catch (err) {
27
+ if (attempt < retries && isSocketError(err)) {
28
+ await new Promise((r) => setTimeout(r, 200 * (attempt + 1)));
29
+ continue;
30
+ }
31
+ throw err;
32
+ }
33
+ }
34
+ }
35
+
12
36
  import {
13
37
  buildReplyHeaders,
14
38
  buildReplySubject,
@@ -550,7 +574,7 @@ export class ResendAdapter implements MessagingAdapter {
550
574
 
551
575
  if (emailId) {
552
576
  try {
553
- const resp = await fetch(
577
+ const resp = await fetchWithRetry(
554
578
  `https://api.resend.com/emails/receiving/${emailId}`,
555
579
  { headers: { Authorization: `Bearer ${this.apiKey}` } },
556
580
  );
@@ -624,7 +648,7 @@ export class ResendAdapter implements MessagingAdapter {
624
648
  // Fetch attachment metadata (with download_url) from the Resend API
625
649
  let attachments: Array<{ filename?: string; content_type?: string; download_url?: string }> = [];
626
650
  try {
627
- const resp = await fetch(
651
+ const resp = await fetchWithRetry(
628
652
  `https://api.resend.com/emails/receiving/${emailId}/attachments`,
629
653
  { headers: { Authorization: `Bearer ${this.apiKey}` } },
630
654
  );
@@ -644,7 +668,7 @@ export class ResendAdapter implements MessagingAdapter {
644
668
  for (const att of attachments) {
645
669
  if (!att.download_url) continue;
646
670
  try {
647
- const resp = await fetch(att.download_url);
671
+ const resp = await fetchWithRetry(att.download_url);
648
672
  if (!resp.ok) continue;
649
673
  const buf = Buffer.from(await resp.arrayBuffer());
650
674
  results.push({