@pidgeon-ai/sdk 1.2.0 → 1.4.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/dist/index.js CHANGED
@@ -43,7 +43,7 @@ function createSseClient({
43
43
  ...options
44
44
  }) {
45
45
  let lastEventId;
46
- const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
46
+ const sleep2 = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
47
47
  const createStream = async function* () {
48
48
  let retryDelay = sseDefaultRetryDelay ?? 3e3;
49
49
  let attempt = 0;
@@ -147,7 +147,7 @@ function createSseClient({
147
147
  break;
148
148
  }
149
149
  const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
150
- await sleep(backoff);
150
+ await sleep2(backoff);
151
151
  }
152
152
  }
153
153
  };
@@ -987,7 +987,7 @@ var messagesSend = (options) => (options.client ?? client).post({
987
987
  ...options.headers
988
988
  }
989
989
  });
990
- var messagesSearch = (options) => (options.client ?? client).get({
990
+ var messagesSearch = (options) => (options?.client ?? client).get({
991
991
  security: [{ scheme: "bearer", type: "http" }],
992
992
  url: "/messages/search",
993
993
  ...options
@@ -1223,6 +1223,11 @@ var appPasswordsRevoke = (options) => (options.client ?? client).delete({
1223
1223
  url: "/app-passwords/{id}",
1224
1224
  ...options
1225
1225
  });
1226
+ var meGet = (options) => (options?.client ?? client).get({
1227
+ security: [{ scheme: "bearer", type: "http" }],
1228
+ url: "/me",
1229
+ ...options
1230
+ });
1226
1231
  var workspaceGet = (options) => (options?.client ?? client).get({
1227
1232
  security: [{ scheme: "bearer", type: "http" }],
1228
1233
  url: "/workspace",
@@ -1238,6 +1243,11 @@ var eventsList = (options) => (options?.client ?? client).get({
1238
1243
  url: "/events",
1239
1244
  ...options
1240
1245
  });
1246
+ var eventsStream = (options) => (options?.client ?? client).sse.get({
1247
+ security: [{ scheme: "bearer", type: "http" }],
1248
+ url: "/events/stream",
1249
+ ...options
1250
+ });
1241
1251
  var eventsGet = (options) => (options.client ?? client).get({
1242
1252
  security: [{ scheme: "bearer", type: "http" }],
1243
1253
  url: "/events/{id}",
@@ -1459,7 +1469,16 @@ var attachmentsDownloadUrl = (options) => (options.client ?? client).get({
1459
1469
  var SIGNATURE_HEADER = "x-pidgeon-signature";
1460
1470
  var TIMESTAMP_HEADER = "x-pidgeon-timestamp";
1461
1471
  async function verifyWebhook(input) {
1462
- const get = (name) => input.headers instanceof Headers ? input.headers.get(name) ?? void 0 : input.headers[name] ?? input.headers[name.toLowerCase()];
1472
+ const get = (name) => {
1473
+ if (input.headers instanceof Headers) return input.headers.get(name) ?? void 0;
1474
+ const direct = input.headers[name];
1475
+ if (direct !== void 0) return direct;
1476
+ const wanted = name.toLowerCase();
1477
+ for (const [key2, value] of Object.entries(input.headers)) {
1478
+ if (key2.toLowerCase() === wanted) return value;
1479
+ }
1480
+ return void 0;
1481
+ };
1463
1482
  const timestamp = get(TIMESTAMP_HEADER);
1464
1483
  const signature = get(SIGNATURE_HEADER);
1465
1484
  if (!timestamp || !signature) throw new Error("This request is not signed.");
@@ -1496,6 +1515,105 @@ function constantTimeEqual(a, b) {
1496
1515
  }
1497
1516
  return difference === 0;
1498
1517
  }
1518
+
1519
+ // src/stream.ts
1520
+ async function* streamEvents(options) {
1521
+ const base = (options.baseUrl ?? "https://pidgeon.ai/api/v1").replace(/\/$/, "");
1522
+ let lastEventId;
1523
+ let backoffMs = 1e3;
1524
+ while (!options.signal?.aborted) {
1525
+ const url = new URL(`${base}/events/stream`);
1526
+ if (options.identityId) url.searchParams.set("identity_id", options.identityId);
1527
+ if (options.type) url.searchParams.set("type", options.type);
1528
+ if (options.after && !lastEventId) url.searchParams.set("after", options.after);
1529
+ let response;
1530
+ try {
1531
+ response = await fetch(url, {
1532
+ headers: {
1533
+ authorization: `Bearer ${options.apiKey}`,
1534
+ accept: "text/event-stream",
1535
+ ...lastEventId ? { "last-event-id": lastEventId } : {}
1536
+ },
1537
+ signal: options.signal
1538
+ });
1539
+ } catch {
1540
+ if (options.signal?.aborted) return;
1541
+ await sleep(backoffMs, options.signal);
1542
+ backoffMs = Math.min(backoffMs * 2, 3e4);
1543
+ continue;
1544
+ }
1545
+ if (response.status === 401 || response.status === 403 || response.status === 404) {
1546
+ throw new Error(
1547
+ `Pidgeon refused the stream: ${response.status} ${await response.text().catch(() => "")}`.trim()
1548
+ );
1549
+ }
1550
+ if (!response.ok || !response.body) {
1551
+ await sleep(backoffMs, options.signal);
1552
+ backoffMs = Math.min(backoffMs * 2, 3e4);
1553
+ continue;
1554
+ }
1555
+ backoffMs = 1e3;
1556
+ for await (const frame of frames(response.body, options.signal)) {
1557
+ if (frame.id) lastEventId = frame.id;
1558
+ if (!frame.data) continue;
1559
+ if (frame.event === "error") continue;
1560
+ let parsed;
1561
+ try {
1562
+ parsed = JSON.parse(frame.data);
1563
+ } catch {
1564
+ continue;
1565
+ }
1566
+ yield parsed;
1567
+ }
1568
+ }
1569
+ }
1570
+ async function* frames(body, signal) {
1571
+ const reader = body.getReader();
1572
+ const decoder = new TextDecoder();
1573
+ let buffer = "";
1574
+ try {
1575
+ while (!signal?.aborted) {
1576
+ const { done, value } = await reader.read();
1577
+ if (done) return;
1578
+ buffer += decoder.decode(value, { stream: true });
1579
+ let boundary = buffer.indexOf("\n\n");
1580
+ while (boundary !== -1) {
1581
+ const block = buffer.slice(0, boundary);
1582
+ buffer = buffer.slice(boundary + 2);
1583
+ boundary = buffer.indexOf("\n\n");
1584
+ const frame = {};
1585
+ const data = [];
1586
+ for (const line of block.split("\n")) {
1587
+ if (line.startsWith(":")) continue;
1588
+ const colon = line.indexOf(":");
1589
+ if (colon === -1) continue;
1590
+ const field = line.slice(0, colon);
1591
+ const value2 = line.slice(colon + 1).replace(/^ /, "");
1592
+ if (field === "id") frame.id = value2;
1593
+ else if (field === "event") frame.event = value2;
1594
+ else if (field === "data") data.push(value2);
1595
+ }
1596
+ if (data.length > 0) frame.data = data.join("\n");
1597
+ if (frame.id || frame.data) yield frame;
1598
+ }
1599
+ }
1600
+ } finally {
1601
+ await reader.cancel().catch(() => void 0);
1602
+ }
1603
+ }
1604
+ function sleep(ms, signal) {
1605
+ return new Promise((resolve) => {
1606
+ const timer = setTimeout(resolve, ms);
1607
+ signal?.addEventListener(
1608
+ "abort",
1609
+ () => {
1610
+ clearTimeout(timer);
1611
+ resolve();
1612
+ },
1613
+ { once: true }
1614
+ );
1615
+ });
1616
+ }
1499
1617
  export {
1500
1618
  SIGNATURE_HEADER,
1501
1619
  TIMESTAMP_HEADER,
@@ -1539,6 +1657,7 @@ export {
1539
1657
  draftsUpdate,
1540
1658
  eventsGet,
1541
1659
  eventsList,
1660
+ eventsStream,
1542
1661
  identitiesAccessCreate,
1543
1662
  identitiesAccessDelete,
1544
1663
  identitiesAccessGet,
@@ -1567,6 +1686,7 @@ export {
1567
1686
  mailboxesEmptyTrash,
1568
1687
  mailboxesList,
1569
1688
  mailboxesListFolder,
1689
+ meGet,
1570
1690
  messagesAct,
1571
1691
  messagesForward,
1572
1692
  messagesGet,
@@ -1584,6 +1704,7 @@ export {
1584
1704
  routingDelete,
1585
1705
  routingList,
1586
1706
  routingUpdate,
1707
+ streamEvents,
1587
1708
  threadsGet,
1588
1709
  threadsLabelsCreate,
1589
1710
  threadsLabelsDelete,