@slates/provider 1.0.0-rc.18 → 1.0.0-rc.19
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.cjs +328 -41
- package/dist/index.d.cts +113 -22
- package/dist/index.d.ts +113 -22
- package/dist/index.module.js +320 -41
- package/package.json +2 -1
- package/src/action/attachment.ts +55 -9
- package/src/action/directUpload.ts +59 -0
- package/src/action/getFileUrlTool.ts +41 -0
- package/src/action/index.ts +1 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/redact.test.ts +103 -0
- package/src/auth/redact.ts +111 -0
- package/src/auth/types.ts +0 -1
- package/src/axios/trace.ts +69 -35
- package/src/context/context.ts +193 -3
- package/src/index.ts +1 -0
package/dist/index.module.js
CHANGED
|
@@ -939,6 +939,9 @@ var SlateActionBuilder = class {
|
|
|
939
939
|
}
|
|
940
940
|
};
|
|
941
941
|
|
|
942
|
+
// src/action/getFileUrlTool.ts
|
|
943
|
+
import { z } from "zod";
|
|
944
|
+
|
|
942
945
|
// src/action/tool.ts
|
|
943
946
|
var SlateTool = class _SlateTool extends SlateAction {
|
|
944
947
|
#handleInvocation;
|
|
@@ -961,6 +964,27 @@ var SlateTool = class _SlateTool extends SlateAction {
|
|
|
961
964
|
};
|
|
962
965
|
var tool = (spec2, params) => SlateTool.create(spec2, params);
|
|
963
966
|
|
|
967
|
+
// src/action/getFileUrlTool.ts
|
|
968
|
+
var GET_FILE_URL_TOOL_ID = "metorial$getFileUrl";
|
|
969
|
+
var getFileUrlToolInputSchema = z.object({
|
|
970
|
+
url: z.string(),
|
|
971
|
+
reference: z.any().nullable()
|
|
972
|
+
});
|
|
973
|
+
var getFileUrlToolOutputSchema = z.object({
|
|
974
|
+
url: z.string(),
|
|
975
|
+
expiresAt: z.string(),
|
|
976
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
977
|
+
query: z.record(z.string(), z.string()).optional()
|
|
978
|
+
});
|
|
979
|
+
var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
980
|
+
key: GET_FILE_URL_TOOL_ID,
|
|
981
|
+
name: "Get File URL",
|
|
982
|
+
description: "Reserved: refreshes an expiring attachment download URL. Hub-internal only."
|
|
983
|
+
}).input(getFileUrlToolInputSchema).output(getFileUrlToolOutputSchema).handleInvocation(async (ctx) => ({
|
|
984
|
+
output: await handleGetFileUrl(ctx),
|
|
985
|
+
message: "ok"
|
|
986
|
+
})).build();
|
|
987
|
+
|
|
964
988
|
// src/action/publicTool.ts
|
|
965
989
|
var SlatePublicTool = class {
|
|
966
990
|
constructor() {
|
|
@@ -1040,23 +1064,35 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
|
|
|
1040
1064
|
var trigger = (spec2, params) => SlateTrigger.create(spec2, params);
|
|
1041
1065
|
|
|
1042
1066
|
// src/action/attachment.ts
|
|
1043
|
-
var createUrlAttachment = (url,
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
type: "url",
|
|
1047
|
-
url
|
|
1067
|
+
var createUrlAttachment = (url, opts = {}) => {
|
|
1068
|
+
if (opts.refreshReference !== void 0 && !opts.refreshAt) {
|
|
1069
|
+
throw new Error("createUrlAttachment: refreshAt is required when refreshReference is set");
|
|
1048
1070
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1071
|
+
return {
|
|
1072
|
+
mimeType: opts.mimeType,
|
|
1073
|
+
attachmentHash: opts.attachmentHash,
|
|
1074
|
+
content: {
|
|
1075
|
+
type: "url",
|
|
1076
|
+
url,
|
|
1077
|
+
...opts.headers ? { headers: opts.headers } : {},
|
|
1078
|
+
...opts.query ? { query: opts.query } : {},
|
|
1079
|
+
...opts.refreshReference !== void 0 ? { refreshReference: opts.refreshReference } : {},
|
|
1080
|
+
...opts.refreshAt ? { refreshAt: opts.refreshAt } : {}
|
|
1081
|
+
}
|
|
1082
|
+
};
|
|
1083
|
+
};
|
|
1084
|
+
var createBase64Attachment = (content, mimeType, attachmentHash) => ({
|
|
1051
1085
|
mimeType,
|
|
1086
|
+
attachmentHash,
|
|
1052
1087
|
content: {
|
|
1053
1088
|
type: "content",
|
|
1054
1089
|
encoding: "base64",
|
|
1055
1090
|
content
|
|
1056
1091
|
}
|
|
1057
1092
|
});
|
|
1058
|
-
var createTextAttachment = (content, mimeType) => ({
|
|
1093
|
+
var createTextAttachment = (content, mimeType, attachmentHash) => ({
|
|
1059
1094
|
mimeType,
|
|
1095
|
+
attachmentHash,
|
|
1060
1096
|
content: {
|
|
1061
1097
|
type: "content",
|
|
1062
1098
|
encoding: "utf-8",
|
|
@@ -1064,6 +1100,44 @@ var createTextAttachment = (content, mimeType) => ({
|
|
|
1064
1100
|
}
|
|
1065
1101
|
});
|
|
1066
1102
|
|
|
1103
|
+
// src/action/directUpload.ts
|
|
1104
|
+
var uploadAttachmentDirect = async (d) => {
|
|
1105
|
+
let baseUrl = d.live.baseUrl.replace(/\/$/, "");
|
|
1106
|
+
let registerRes = await fetch(`${baseUrl}/slates-hub/live-invocation/attachments`, {
|
|
1107
|
+
method: "POST",
|
|
1108
|
+
headers: {
|
|
1109
|
+
"content-type": "application/json",
|
|
1110
|
+
authorization: `Bearer ${d.live.token}`
|
|
1111
|
+
},
|
|
1112
|
+
body: JSON.stringify({
|
|
1113
|
+
attachments: [{ mimeType: d.mimeType, filename: d.filename }]
|
|
1114
|
+
})
|
|
1115
|
+
});
|
|
1116
|
+
if (!registerRes.ok) {
|
|
1117
|
+
throw new Error(
|
|
1118
|
+
`Failed to register attachment for direct upload (status ${registerRes.status})`
|
|
1119
|
+
);
|
|
1120
|
+
}
|
|
1121
|
+
let { attachments } = await registerRes.json();
|
|
1122
|
+
let registration = attachments[0];
|
|
1123
|
+
if (!registration) {
|
|
1124
|
+
throw new Error("Live invocation API returned no attachment registrations");
|
|
1125
|
+
}
|
|
1126
|
+
let putRes = await fetch(registration.uploadUrl, {
|
|
1127
|
+
method: "PUT",
|
|
1128
|
+
...d.body instanceof Uint8Array ? {} : { duplex: "half" },
|
|
1129
|
+
headers: d.mimeType ? { "content-type": d.mimeType } : void 0,
|
|
1130
|
+
body: d.body
|
|
1131
|
+
});
|
|
1132
|
+
if (!putRes.ok) {
|
|
1133
|
+
throw new Error(`Failed to upload attachment content (status ${putRes.status})`);
|
|
1134
|
+
}
|
|
1135
|
+
return {
|
|
1136
|
+
mimeType: d.mimeType,
|
|
1137
|
+
content: { type: "upload_reference", referenceId: registration.referenceId }
|
|
1138
|
+
};
|
|
1139
|
+
};
|
|
1140
|
+
|
|
1067
1141
|
// src/adapter/adapter.ts
|
|
1068
1142
|
var SlateAdapter = class {
|
|
1069
1143
|
constructor(_spec, _tools, _triggers) {
|
|
@@ -1334,6 +1408,76 @@ var normalizeOAuthTokenResponse = (data, options = {}) => {
|
|
|
1334
1408
|
};
|
|
1335
1409
|
};
|
|
1336
1410
|
|
|
1411
|
+
// src/auth/redact.ts
|
|
1412
|
+
var AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX = "$$MT$secret$authConfig$";
|
|
1413
|
+
var AuthConfigSecretRedactor = class {
|
|
1414
|
+
secretToPlaceholder = /* @__PURE__ */ new Map();
|
|
1415
|
+
constructor(authConfig) {
|
|
1416
|
+
if (authConfig) this.buildSecretMap(authConfig);
|
|
1417
|
+
}
|
|
1418
|
+
redact(value) {
|
|
1419
|
+
return this.transform(value, (stringValue) => {
|
|
1420
|
+
return this.secretToPlaceholder.get(stringValue) ?? stringValue;
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1423
|
+
buildSecretMap(value, path = []) {
|
|
1424
|
+
if (typeof value === "string") {
|
|
1425
|
+
if (value.length === 0) return;
|
|
1426
|
+
this.secretToPlaceholder.set(
|
|
1427
|
+
value,
|
|
1428
|
+
`${AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX}${path.join(".")}`
|
|
1429
|
+
);
|
|
1430
|
+
return;
|
|
1431
|
+
}
|
|
1432
|
+
if (Array.isArray(value)) {
|
|
1433
|
+
value.forEach((item, index) => {
|
|
1434
|
+
this.buildSecretMap(item, [...path, String(index)]);
|
|
1435
|
+
});
|
|
1436
|
+
return;
|
|
1437
|
+
}
|
|
1438
|
+
if (this.isPlainObject(value)) {
|
|
1439
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
1440
|
+
this.buildSecretMap(nestedValue, [...path, key]);
|
|
1441
|
+
});
|
|
1442
|
+
}
|
|
1443
|
+
}
|
|
1444
|
+
transform(value, transformString) {
|
|
1445
|
+
if (typeof value === "string") {
|
|
1446
|
+
return transformString(value);
|
|
1447
|
+
}
|
|
1448
|
+
if (Array.isArray(value)) {
|
|
1449
|
+
return value.map((item) => this.transform(item, transformString));
|
|
1450
|
+
}
|
|
1451
|
+
if (this.isPlainObject(value)) {
|
|
1452
|
+
let result = {};
|
|
1453
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
1454
|
+
result[key] = this.transform(nestedValue, transformString);
|
|
1455
|
+
});
|
|
1456
|
+
return result;
|
|
1457
|
+
}
|
|
1458
|
+
return value;
|
|
1459
|
+
}
|
|
1460
|
+
isPlainObject(value) {
|
|
1461
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1462
|
+
}
|
|
1463
|
+
};
|
|
1464
|
+
var redactUrlAttachmentSecrets = (attachments, authConfig) => {
|
|
1465
|
+
if (!authConfig || !attachments) return attachments;
|
|
1466
|
+
let redactor = new AuthConfigSecretRedactor(authConfig);
|
|
1467
|
+
return attachments.map((attachment) => {
|
|
1468
|
+
if (attachment.content.type !== "url") return attachment;
|
|
1469
|
+
if (!attachment.content.headers && !attachment.content.query) return attachment;
|
|
1470
|
+
return {
|
|
1471
|
+
...attachment,
|
|
1472
|
+
content: {
|
|
1473
|
+
...attachment.content,
|
|
1474
|
+
headers: attachment.content.headers ? redactor.redact(attachment.content.headers) : void 0,
|
|
1475
|
+
query: attachment.content.query ? redactor.redact(attachment.content.query) : void 0
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
});
|
|
1479
|
+
};
|
|
1480
|
+
|
|
1337
1481
|
// src/axios/index.ts
|
|
1338
1482
|
import baseAxios, { getAdapter, isAxiosError as isAxiosError2 } from "axios";
|
|
1339
1483
|
|
|
@@ -1612,9 +1756,9 @@ var truncateText = (text) => {
|
|
|
1612
1756
|
truncated: true
|
|
1613
1757
|
};
|
|
1614
1758
|
};
|
|
1615
|
-
var sanitizeFreeText = (text) => {
|
|
1759
|
+
var sanitizeFreeText = (text, redactor) => {
|
|
1616
1760
|
if (!text) return text;
|
|
1617
|
-
let result = text;
|
|
1761
|
+
let result = redactor ? redactor.redact(text) : text;
|
|
1618
1762
|
result = result.replace(
|
|
1619
1763
|
HTTP_AUTH_SCHEME_PATTERN,
|
|
1620
1764
|
(_match, scheme) => `${scheme} ${REDACTED_VALUE}`
|
|
@@ -1632,21 +1776,21 @@ var sanitizeFreeText = (text) => {
|
|
|
1632
1776
|
);
|
|
1633
1777
|
return result;
|
|
1634
1778
|
};
|
|
1635
|
-
var sanitizeScalar = (value) => truncateText(sanitizeFreeText(value));
|
|
1636
|
-
var redactStructuredValue = (value, depth = 0) => {
|
|
1779
|
+
var sanitizeScalar = (value, redactor) => truncateText(sanitizeFreeText(value, redactor));
|
|
1780
|
+
var redactStructuredValue = (value, depth = 0, redactor) => {
|
|
1637
1781
|
if (value == null) return value;
|
|
1638
1782
|
if (depth >= STRUCTURED_DEPTH_LIMIT) return "[truncated]";
|
|
1639
1783
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
1640
|
-
return typeof value === "string" ? sanitizeFreeText(value) : value;
|
|
1784
|
+
return typeof value === "string" ? sanitizeFreeText(value, redactor) : value;
|
|
1641
1785
|
}
|
|
1642
1786
|
if (Array.isArray(value)) {
|
|
1643
|
-
return value.slice(0, STRUCTURED_ENTRY_LIMIT).map((entry) => redactStructuredValue(entry, depth + 1));
|
|
1787
|
+
return value.slice(0, STRUCTURED_ENTRY_LIMIT).map((entry) => redactStructuredValue(entry, depth + 1, redactor));
|
|
1644
1788
|
}
|
|
1645
1789
|
if (isRecord2(value)) {
|
|
1646
1790
|
return Object.fromEntries(
|
|
1647
1791
|
Object.entries(value).slice(0, STRUCTURED_ENTRY_LIMIT).map(([key, entry]) => [
|
|
1648
1792
|
key,
|
|
1649
|
-
isSecretKeyName(key) ? REDACTED_VALUE : redactStructuredValue(entry, depth + 1)
|
|
1793
|
+
isSecretKeyName(key) ? REDACTED_VALUE : redactStructuredValue(entry, depth + 1, redactor)
|
|
1650
1794
|
])
|
|
1651
1795
|
);
|
|
1652
1796
|
}
|
|
@@ -1664,11 +1808,11 @@ var maybeParseJson = (text, contentType) => {
|
|
|
1664
1808
|
return null;
|
|
1665
1809
|
}
|
|
1666
1810
|
};
|
|
1667
|
-
var sanitizeTextBody = (text, contentType) => {
|
|
1811
|
+
var sanitizeTextBody = (text, contentType, redactor) => {
|
|
1668
1812
|
if (!text) return void 0;
|
|
1669
1813
|
let normalizedContentType = normalizeContentType(contentType);
|
|
1670
1814
|
let parsedJson = maybeParseJson(text, normalizedContentType);
|
|
1671
|
-
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson)) : sanitizeFreeText(text);
|
|
1815
|
+
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson, 0, redactor)) : sanitizeFreeText(text, redactor);
|
|
1672
1816
|
let { text: truncatedText, truncated } = truncateText(normalizedText);
|
|
1673
1817
|
return {
|
|
1674
1818
|
...normalizedContentType ? { contentType: normalizedContentType } : {},
|
|
@@ -1684,22 +1828,26 @@ var isBinaryLike = (value) => {
|
|
|
1684
1828
|
if (typeof FormData !== "undefined" && value instanceof FormData) return true;
|
|
1685
1829
|
return false;
|
|
1686
1830
|
};
|
|
1687
|
-
var serializeTextBody = (value, contentType) => {
|
|
1831
|
+
var serializeTextBody = (value, contentType, redactor) => {
|
|
1688
1832
|
let normalizedContentType = normalizeContentType(contentType);
|
|
1689
1833
|
if (value == null || isBinaryLike(value) || !isTextContentType(normalizedContentType)) {
|
|
1690
1834
|
return void 0;
|
|
1691
1835
|
}
|
|
1692
1836
|
if (typeof value === "string") {
|
|
1693
|
-
return sanitizeTextBody(value, normalizedContentType);
|
|
1837
|
+
return sanitizeTextBody(value, normalizedContentType, redactor);
|
|
1694
1838
|
}
|
|
1695
1839
|
if (value instanceof URLSearchParams) {
|
|
1696
|
-
return sanitizeTextBody(value.toString(), normalizedContentType);
|
|
1840
|
+
return sanitizeTextBody(value.toString(), normalizedContentType, redactor);
|
|
1697
1841
|
}
|
|
1698
1842
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
1699
|
-
return sanitizeTextBody(String(value), normalizedContentType);
|
|
1843
|
+
return sanitizeTextBody(String(value), normalizedContentType, redactor);
|
|
1700
1844
|
}
|
|
1701
1845
|
if (Array.isArray(value) || isRecord2(value)) {
|
|
1702
|
-
return sanitizeTextBody(
|
|
1846
|
+
return sanitizeTextBody(
|
|
1847
|
+
JSON.stringify(redactStructuredValue(value, 0, redactor)),
|
|
1848
|
+
"application/json",
|
|
1849
|
+
redactor
|
|
1850
|
+
);
|
|
1703
1851
|
}
|
|
1704
1852
|
return void 0;
|
|
1705
1853
|
};
|
|
@@ -1714,16 +1862,20 @@ var buildUrl = (baseURL, url) => {
|
|
|
1714
1862
|
};
|
|
1715
1863
|
var REDACTED_ENCODED = encodeURIComponent(REDACTED_VALUE);
|
|
1716
1864
|
var decodeRedactedMarker = (value) => REDACTED_ENCODED === REDACTED_VALUE ? value : value.split(REDACTED_ENCODED).join(REDACTED_VALUE);
|
|
1717
|
-
var redactHashFragment = (hash) => {
|
|
1865
|
+
var redactHashFragment = (hash, redactor) => {
|
|
1718
1866
|
if (!hash?.includes("=")) return hash;
|
|
1719
1867
|
let withoutHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
1720
1868
|
let redacted = withoutHash.replace(
|
|
1721
1869
|
/(?<![A-Za-z0-9])([A-Za-z0-9][A-Za-z0-9_\-.]*)=([^&]*)/g,
|
|
1722
|
-
(match, key,
|
|
1870
|
+
(match, key, rawValue) => {
|
|
1871
|
+
if (isUrlFormSecretKeyName(key)) return `${key}=${REDACTED_VALUE}`;
|
|
1872
|
+
let literalRedacted = redactor ? redactor.redact(rawValue) : rawValue;
|
|
1873
|
+
return literalRedacted !== rawValue ? `${key}=${literalRedacted}` : match;
|
|
1874
|
+
}
|
|
1723
1875
|
);
|
|
1724
1876
|
return redacted ? `#${redacted}` : "";
|
|
1725
1877
|
};
|
|
1726
|
-
var sanitizeUrl = (value) => {
|
|
1878
|
+
var sanitizeUrl = (value, redactor) => {
|
|
1727
1879
|
if (!value) return value;
|
|
1728
1880
|
try {
|
|
1729
1881
|
let url = new URL(value);
|
|
@@ -1734,12 +1886,17 @@ var sanitizeUrl = (value) => {
|
|
|
1734
1886
|
for (let key of Array.from(url.searchParams.keys())) {
|
|
1735
1887
|
if (isUrlFormSecretKeyName(key)) {
|
|
1736
1888
|
url.searchParams.set(key, REDACTED_VALUE);
|
|
1889
|
+
continue;
|
|
1737
1890
|
}
|
|
1891
|
+
let rawValue = url.searchParams.get(key) ?? "";
|
|
1892
|
+
let literalRedacted = redactor ? redactor.redact(rawValue) : rawValue;
|
|
1893
|
+
if (literalRedacted !== rawValue) url.searchParams.set(key, literalRedacted);
|
|
1738
1894
|
}
|
|
1739
|
-
url.hash = redactHashFragment(url.hash);
|
|
1895
|
+
url.hash = redactHashFragment(url.hash, redactor);
|
|
1740
1896
|
return decodeRedactedMarker(url.toString());
|
|
1741
1897
|
} catch {
|
|
1742
|
-
|
|
1898
|
+
let text = redactor ? redactor.redact(value) : value;
|
|
1899
|
+
return text.replace(
|
|
1743
1900
|
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
1744
1901
|
(_match, prefix, key, rawValue) => isUrlFormSecretKeyName(key) ? `${prefix}${REDACTED_VALUE}` : `${prefix}${rawValue}`
|
|
1745
1902
|
);
|
|
@@ -1778,8 +1935,10 @@ var headerEntries = (headers) => {
|
|
|
1778
1935
|
}
|
|
1779
1936
|
return [];
|
|
1780
1937
|
};
|
|
1781
|
-
var sanitizeHeaders = (headers) => {
|
|
1782
|
-
let entries = headerEntries(headers).map(
|
|
1938
|
+
var sanitizeHeaders = (headers, redactor) => {
|
|
1939
|
+
let entries = headerEntries(headers).map(
|
|
1940
|
+
([key, value]) => [key.toLowerCase(), sanitizeScalar(value, redactor).text]
|
|
1941
|
+
).filter(([key]) => isSafeHeaderName(key));
|
|
1783
1942
|
if (entries.length === 0) return void 0;
|
|
1784
1943
|
return Object.fromEntries(entries);
|
|
1785
1944
|
};
|
|
@@ -1805,15 +1964,16 @@ var clearTraceDraft = (config2, draft) => {
|
|
|
1805
1964
|
var attachHttpTraceDraft = (config2, context) => {
|
|
1806
1965
|
let traceAwareConfig = config2;
|
|
1807
1966
|
let contentType = getContentType(config2.headers);
|
|
1967
|
+
let redactor = new AuthConfigSecretRedactor(context._getAuthConfigForRedaction());
|
|
1808
1968
|
traceAwareConfig.__slatesHttpTraceDraft = {
|
|
1809
1969
|
context,
|
|
1810
1970
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1811
1971
|
startedAtMs: Date.now(),
|
|
1812
1972
|
request: {
|
|
1813
1973
|
method: (config2.method ?? "GET").toUpperCase(),
|
|
1814
|
-
url: sanitizeUrl(buildUrl(config2.baseURL, config2.url)),
|
|
1815
|
-
...sanitizeHeaders(config2.headers) ? { headers: sanitizeHeaders(config2.headers) } : {},
|
|
1816
|
-
...serializeTextBody(config2.data, contentType) ? { body: serializeTextBody(config2.data, contentType) } : {}
|
|
1974
|
+
url: sanitizeUrl(buildUrl(config2.baseURL, config2.url), redactor),
|
|
1975
|
+
...sanitizeHeaders(config2.headers, redactor) ? { headers: sanitizeHeaders(config2.headers, redactor) } : {},
|
|
1976
|
+
...serializeTextBody(config2.data, contentType, redactor) ? { body: serializeTextBody(config2.data, contentType, redactor) } : {}
|
|
1817
1977
|
}
|
|
1818
1978
|
};
|
|
1819
1979
|
if (isObjectLike(traceAwareConfig)) {
|
|
@@ -1832,6 +1992,7 @@ var recordHttpTraceFromResponse = (response) => {
|
|
|
1832
1992
|
let draft = takeTraceDraft(config2);
|
|
1833
1993
|
if (!draft) return response;
|
|
1834
1994
|
clearTraceDraft(config2, draft);
|
|
1995
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
1835
1996
|
let contentType = getContentType(response.headers);
|
|
1836
1997
|
draft.context.recordHttpTrace({
|
|
1837
1998
|
startedAt: draft.startedAt,
|
|
@@ -1840,8 +2001,8 @@ var recordHttpTraceFromResponse = (response) => {
|
|
|
1840
2001
|
response: {
|
|
1841
2002
|
status: response.status,
|
|
1842
2003
|
...response.statusText ? { statusText: response.statusText } : {},
|
|
1843
|
-
...sanitizeHeaders(response.headers) ? { headers: sanitizeHeaders(response.headers) } : {},
|
|
1844
|
-
...serializeTextBody(response.data, contentType) ? { body: serializeTextBody(response.data, contentType) } : {}
|
|
2004
|
+
...sanitizeHeaders(response.headers, redactor) ? { headers: sanitizeHeaders(response.headers, redactor) } : {},
|
|
2005
|
+
...serializeTextBody(response.data, contentType, redactor) ? { body: serializeTextBody(response.data, contentType, redactor) } : {}
|
|
1845
2006
|
}
|
|
1846
2007
|
});
|
|
1847
2008
|
return response;
|
|
@@ -1851,6 +2012,7 @@ var recordHttpTraceFromError = (error) => {
|
|
|
1851
2012
|
let draft = takeTraceDraft(config2);
|
|
1852
2013
|
if (!draft) return;
|
|
1853
2014
|
clearTraceDraft(config2, draft);
|
|
2015
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
1854
2016
|
let responseContentType = getContentType(error.response?.headers);
|
|
1855
2017
|
draft.context.recordHttpTrace({
|
|
1856
2018
|
startedAt: draft.startedAt,
|
|
@@ -1860,8 +2022,8 @@ var recordHttpTraceFromError = (error) => {
|
|
|
1860
2022
|
response: {
|
|
1861
2023
|
status: error.response.status,
|
|
1862
2024
|
...error.response.statusText ? { statusText: error.response.statusText } : {},
|
|
1863
|
-
...sanitizeHeaders(error.response.headers) ? { headers: sanitizeHeaders(error.response.headers) } : {},
|
|
1864
|
-
...serializeTextBody(error.response.data, responseContentType) ? { body: serializeTextBody(error.response.data, responseContentType) } : {}
|
|
2025
|
+
...sanitizeHeaders(error.response.headers, redactor) ? { headers: sanitizeHeaders(error.response.headers, redactor) } : {},
|
|
2026
|
+
...serializeTextBody(error.response.data, responseContentType, redactor) ? { body: serializeTextBody(error.response.data, responseContentType, redactor) } : {}
|
|
1865
2027
|
}
|
|
1866
2028
|
} : {},
|
|
1867
2029
|
error: {
|
|
@@ -1992,16 +2154,39 @@ var SlateConfig = class _SlateConfig {
|
|
|
1992
2154
|
var config = (schema) => SlateConfig.create(schema);
|
|
1993
2155
|
|
|
1994
2156
|
// src/context/context.ts
|
|
2157
|
+
import { Readable } from "stream";
|
|
2158
|
+
import PQueue from "p-queue";
|
|
2159
|
+
var isBufferLike = (value) => value instanceof Uint8Array || value instanceof ArrayBuffer;
|
|
2160
|
+
var toUint8Array = (value) => value instanceof ArrayBuffer ? new Uint8Array(value) : value;
|
|
2161
|
+
var isReadableStream = (value) => typeof ReadableStream !== "undefined" && value instanceof ReadableStream;
|
|
2162
|
+
var isNodeReadable = (value) => !!value && typeof value === "object" && typeof value.pipe === "function" && typeof value.on === "function";
|
|
2163
|
+
var isResponseLike = (value) => typeof Response !== "undefined" && value instanceof Response;
|
|
2164
|
+
var readStreamToBuffer = async (stream) => {
|
|
2165
|
+
let reader = stream.getReader();
|
|
2166
|
+
let chunks = [];
|
|
2167
|
+
while (true) {
|
|
2168
|
+
let { done, value } = await reader.read();
|
|
2169
|
+
if (done) break;
|
|
2170
|
+
if (value) chunks.push(value);
|
|
2171
|
+
}
|
|
2172
|
+
return Buffer.concat(chunks);
|
|
2173
|
+
};
|
|
1995
2174
|
var SlatePublicContext = class {
|
|
1996
|
-
constructor(input, spec2, logger) {
|
|
2175
|
+
constructor(input, spec2, logger, liveInvocation = null) {
|
|
1997
2176
|
this.spec = spec2;
|
|
1998
2177
|
this.logger = logger;
|
|
1999
2178
|
this.#input = input;
|
|
2179
|
+
this.#liveInvocation = liveInvocation;
|
|
2000
2180
|
}
|
|
2001
2181
|
spec;
|
|
2002
2182
|
logger;
|
|
2003
2183
|
#input;
|
|
2004
2184
|
#httpTraces = [];
|
|
2185
|
+
#liveInvocation;
|
|
2186
|
+
#attachmentsDisabled = false;
|
|
2187
|
+
#attachments = [];
|
|
2188
|
+
#pendingUploads = [];
|
|
2189
|
+
#uploadQueue = new PQueue({ concurrency: 10 });
|
|
2005
2190
|
get specification() {
|
|
2006
2191
|
return this.spec;
|
|
2007
2192
|
}
|
|
@@ -2055,12 +2240,95 @@ var SlatePublicContext = class {
|
|
|
2055
2240
|
progress(message) {
|
|
2056
2241
|
this.logger.progress(message);
|
|
2057
2242
|
}
|
|
2243
|
+
async addAttachment(input) {
|
|
2244
|
+
if (input.type === "url") {
|
|
2245
|
+
this.#attachments.push(
|
|
2246
|
+
createUrlAttachment(input.url.toString(), {
|
|
2247
|
+
mimeType: input.mimeType,
|
|
2248
|
+
headers: input.headers,
|
|
2249
|
+
query: input.query,
|
|
2250
|
+
refreshReference: input.refreshReference,
|
|
2251
|
+
refreshAt: input.refreshAt
|
|
2252
|
+
})
|
|
2253
|
+
);
|
|
2254
|
+
return;
|
|
2255
|
+
}
|
|
2256
|
+
let content = input.content;
|
|
2257
|
+
if (isBufferLike(content)) {
|
|
2258
|
+
let bytes = toUint8Array(content);
|
|
2259
|
+
this.#attachments.push(
|
|
2260
|
+
createBase64Attachment(Buffer.from(bytes).toString("base64"), input.mimeType)
|
|
2261
|
+
);
|
|
2262
|
+
return;
|
|
2263
|
+
}
|
|
2264
|
+
let normalized = await this.#normalizeStreamInput(content, {
|
|
2265
|
+
mimeType: input.mimeType,
|
|
2266
|
+
filename: input.filename
|
|
2267
|
+
});
|
|
2268
|
+
if (!normalized) return;
|
|
2269
|
+
if (!this.#liveInvocation || this.#attachmentsDisabled) {
|
|
2270
|
+
let buffer = await readStreamToBuffer(normalized.stream);
|
|
2271
|
+
this.#attachments.push(
|
|
2272
|
+
createBase64Attachment(buffer.toString("base64"), normalized.mimeType)
|
|
2273
|
+
);
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
let live = this.#liveInvocation;
|
|
2277
|
+
let task = this.#uploadQueue.add(
|
|
2278
|
+
() => uploadAttachmentDirect({
|
|
2279
|
+
live,
|
|
2280
|
+
mimeType: normalized.mimeType,
|
|
2281
|
+
filename: normalized.filename,
|
|
2282
|
+
body: normalized.stream
|
|
2283
|
+
})
|
|
2284
|
+
).then((attachment) => {
|
|
2285
|
+
this.#attachments.push(attachment);
|
|
2286
|
+
}).catch((err) => {
|
|
2287
|
+
this.#attachmentsDisabled = true;
|
|
2288
|
+
this.warn({
|
|
2289
|
+
message: `Attachment dropped: direct upload failed (${err instanceof Error ? err.message : String(err)}).`
|
|
2290
|
+
});
|
|
2291
|
+
});
|
|
2292
|
+
this.#pendingUploads.push(task);
|
|
2293
|
+
}
|
|
2294
|
+
async #normalizeStreamInput(input, opts) {
|
|
2295
|
+
if (isResponseLike(input)) {
|
|
2296
|
+
if (!input.body) {
|
|
2297
|
+
this.warn({ message: "Attachment dropped: response has no body." });
|
|
2298
|
+
return null;
|
|
2299
|
+
}
|
|
2300
|
+
return {
|
|
2301
|
+
stream: input.body,
|
|
2302
|
+
mimeType: opts.mimeType ?? input.headers.get("content-type") ?? void 0,
|
|
2303
|
+
filename: opts.filename
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
if (isReadableStream(input)) {
|
|
2307
|
+
return { stream: input, mimeType: opts.mimeType, filename: opts.filename };
|
|
2308
|
+
}
|
|
2309
|
+
if (isNodeReadable(input)) {
|
|
2310
|
+
return {
|
|
2311
|
+
stream: Readable.toWeb(input),
|
|
2312
|
+
mimeType: opts.mimeType,
|
|
2313
|
+
filename: opts.filename
|
|
2314
|
+
};
|
|
2315
|
+
}
|
|
2316
|
+
this.warn({ message: "Attachment dropped: unsupported attachment input type." });
|
|
2317
|
+
return null;
|
|
2318
|
+
}
|
|
2319
|
+
async _finalizeAttachments() {
|
|
2320
|
+
await Promise.allSettled(this.#pendingUploads);
|
|
2321
|
+
return this.#attachments;
|
|
2322
|
+
}
|
|
2323
|
+
_getAuthConfigForRedaction() {
|
|
2324
|
+
return void 0;
|
|
2325
|
+
}
|
|
2058
2326
|
};
|
|
2059
2327
|
var SlateContext = class extends SlatePublicContext {
|
|
2060
2328
|
#config;
|
|
2061
2329
|
#auth;
|
|
2062
|
-
constructor(config2, input, auth2, spec2, logger) {
|
|
2063
|
-
super(input, spec2, logger);
|
|
2330
|
+
constructor(config2, input, auth2, spec2, logger, liveInvocation = null) {
|
|
2331
|
+
super(input, spec2, logger, liveInvocation);
|
|
2064
2332
|
this.#config = config2;
|
|
2065
2333
|
this.#auth = auth2;
|
|
2066
2334
|
}
|
|
@@ -2070,6 +2338,9 @@ var SlateContext = class extends SlatePublicContext {
|
|
|
2070
2338
|
get auth() {
|
|
2071
2339
|
return Object.freeze(this.#auth);
|
|
2072
2340
|
}
|
|
2341
|
+
_getAuthConfigForRedaction() {
|
|
2342
|
+
return this.#auth;
|
|
2343
|
+
}
|
|
2073
2344
|
};
|
|
2074
2345
|
|
|
2075
2346
|
// src/crypto/hmac.ts
|
|
@@ -2266,7 +2537,7 @@ var Slate = class _Slate {
|
|
|
2266
2537
|
};
|
|
2267
2538
|
|
|
2268
2539
|
// src/specification/specification.ts
|
|
2269
|
-
import
|
|
2540
|
+
import z2 from "zod";
|
|
2270
2541
|
var SlateSpecification = class _SlateSpecification {
|
|
2271
2542
|
constructor(_config, _auth, _params) {
|
|
2272
2543
|
this._config = _config;
|
|
@@ -2283,7 +2554,7 @@ var SlateSpecification = class _SlateSpecification {
|
|
|
2283
2554
|
return this._config.configSchema;
|
|
2284
2555
|
}
|
|
2285
2556
|
get authSchema() {
|
|
2286
|
-
return "outputSchema" in this._auth ? this._auth.outputSchema :
|
|
2557
|
+
return "outputSchema" in this._auth ? this._auth.outputSchema : z2.object({});
|
|
2287
2558
|
}
|
|
2288
2559
|
get config() {
|
|
2289
2560
|
return this._config;
|
|
@@ -2362,6 +2633,9 @@ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
|
|
|
2362
2633
|
};
|
|
2363
2634
|
};
|
|
2364
2635
|
export {
|
|
2636
|
+
AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX,
|
|
2637
|
+
AuthConfigSecretRedactor,
|
|
2638
|
+
GET_FILE_URL_TOOL_ID,
|
|
2365
2639
|
Slate,
|
|
2366
2640
|
SlateAction,
|
|
2367
2641
|
SlateActionBuilder,
|
|
@@ -2400,6 +2674,9 @@ export {
|
|
|
2400
2674
|
getApiErrorStatus,
|
|
2401
2675
|
getBase64ByteLength,
|
|
2402
2676
|
getCurrentContext,
|
|
2677
|
+
getFileUrlTool,
|
|
2678
|
+
getFileUrlToolInputSchema,
|
|
2679
|
+
getFileUrlToolOutputSchema,
|
|
2403
2680
|
getGraphWebhookValidationResponse,
|
|
2404
2681
|
getMetaWebhookVerificationResponse,
|
|
2405
2682
|
getOAuthExpiresAtFromExpiresIn,
|
|
@@ -2417,6 +2694,7 @@ export {
|
|
|
2417
2694
|
normalizeOAuthTokenResponse,
|
|
2418
2695
|
pickDefined,
|
|
2419
2696
|
publicTool,
|
|
2697
|
+
redactUrlAttachmentSecrets,
|
|
2420
2698
|
requestAxios,
|
|
2421
2699
|
requestAxiosData,
|
|
2422
2700
|
runWithContext,
|
|
@@ -2426,6 +2704,7 @@ export {
|
|
|
2426
2704
|
statusLabelForApiError,
|
|
2427
2705
|
tool,
|
|
2428
2706
|
trigger,
|
|
2707
|
+
uploadAttachmentDirect,
|
|
2429
2708
|
validateScopes,
|
|
2430
2709
|
verifyHmacSignature
|
|
2431
2710
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@slates/provider",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.19",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@lowerdeck/error": "^1.1.0",
|
|
35
35
|
"@toon-format/toon": "^2.1.0",
|
|
36
36
|
"axios": "^1.13.2",
|
|
37
|
+
"p-queue": "^6.6.2",
|
|
37
38
|
"zod": "^4.2.1"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|