@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/CHANGELOG.md +134 -0
- package/LICENSE +21 -0
- package/dist/index.cjs +128 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +344 -13
- package/dist/index.d.ts +344 -13
- package/dist/index.js +125 -4
- package/dist/index.js.map +1 -1
- package/package.json +7 -3
package/dist/index.js
CHANGED
|
@@ -43,7 +43,7 @@ function createSseClient({
|
|
|
43
43
|
...options
|
|
44
44
|
}) {
|
|
45
45
|
let lastEventId;
|
|
46
|
-
const
|
|
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
|
|
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
|
|
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) =>
|
|
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,
|