@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.cjs
CHANGED
|
@@ -30,6 +30,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX: () => AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX,
|
|
34
|
+
AuthConfigSecretRedactor: () => AuthConfigSecretRedactor,
|
|
35
|
+
GET_FILE_URL_TOOL_ID: () => GET_FILE_URL_TOOL_ID,
|
|
33
36
|
Slate: () => Slate,
|
|
34
37
|
SlateAction: () => SlateAction,
|
|
35
38
|
SlateActionBuilder: () => SlateActionBuilder,
|
|
@@ -68,6 +71,9 @@ __export(index_exports, {
|
|
|
68
71
|
getApiErrorStatus: () => getApiErrorStatus,
|
|
69
72
|
getBase64ByteLength: () => getBase64ByteLength,
|
|
70
73
|
getCurrentContext: () => getCurrentContext,
|
|
74
|
+
getFileUrlTool: () => getFileUrlTool,
|
|
75
|
+
getFileUrlToolInputSchema: () => getFileUrlToolInputSchema,
|
|
76
|
+
getFileUrlToolOutputSchema: () => getFileUrlToolOutputSchema,
|
|
71
77
|
getGraphWebhookValidationResponse: () => getGraphWebhookValidationResponse,
|
|
72
78
|
getMetaWebhookVerificationResponse: () => getMetaWebhookVerificationResponse,
|
|
73
79
|
getOAuthExpiresAtFromExpiresIn: () => getOAuthExpiresAtFromExpiresIn,
|
|
@@ -85,6 +91,7 @@ __export(index_exports, {
|
|
|
85
91
|
normalizeOAuthTokenResponse: () => normalizeOAuthTokenResponse,
|
|
86
92
|
pickDefined: () => pickDefined,
|
|
87
93
|
publicTool: () => publicTool,
|
|
94
|
+
redactUrlAttachmentSecrets: () => redactUrlAttachmentSecrets,
|
|
88
95
|
requestAxios: () => requestAxios,
|
|
89
96
|
requestAxiosData: () => requestAxiosData,
|
|
90
97
|
runWithContext: () => runWithContext,
|
|
@@ -94,6 +101,7 @@ __export(index_exports, {
|
|
|
94
101
|
statusLabelForApiError: () => statusLabelForApiError,
|
|
95
102
|
tool: () => tool,
|
|
96
103
|
trigger: () => trigger,
|
|
104
|
+
uploadAttachmentDirect: () => uploadAttachmentDirect,
|
|
97
105
|
validateScopes: () => validateScopes,
|
|
98
106
|
verifyHmacSignature: () => verifyHmacSignature
|
|
99
107
|
});
|
|
@@ -1040,6 +1048,9 @@ var SlateActionBuilder = class {
|
|
|
1040
1048
|
}
|
|
1041
1049
|
};
|
|
1042
1050
|
|
|
1051
|
+
// src/action/getFileUrlTool.ts
|
|
1052
|
+
var import_zod = require("zod");
|
|
1053
|
+
|
|
1043
1054
|
// src/action/tool.ts
|
|
1044
1055
|
var SlateTool = class _SlateTool extends SlateAction {
|
|
1045
1056
|
#handleInvocation;
|
|
@@ -1062,6 +1073,27 @@ var SlateTool = class _SlateTool extends SlateAction {
|
|
|
1062
1073
|
};
|
|
1063
1074
|
var tool = (spec2, params) => SlateTool.create(spec2, params);
|
|
1064
1075
|
|
|
1076
|
+
// src/action/getFileUrlTool.ts
|
|
1077
|
+
var GET_FILE_URL_TOOL_ID = "metorial$getFileUrl";
|
|
1078
|
+
var getFileUrlToolInputSchema = import_zod.z.object({
|
|
1079
|
+
url: import_zod.z.string(),
|
|
1080
|
+
reference: import_zod.z.any().nullable()
|
|
1081
|
+
});
|
|
1082
|
+
var getFileUrlToolOutputSchema = import_zod.z.object({
|
|
1083
|
+
url: import_zod.z.string(),
|
|
1084
|
+
expiresAt: import_zod.z.string(),
|
|
1085
|
+
headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
|
|
1086
|
+
query: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
1087
|
+
});
|
|
1088
|
+
var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
1089
|
+
key: GET_FILE_URL_TOOL_ID,
|
|
1090
|
+
name: "Get File URL",
|
|
1091
|
+
description: "Reserved: refreshes an expiring attachment download URL. Hub-internal only."
|
|
1092
|
+
}).input(getFileUrlToolInputSchema).output(getFileUrlToolOutputSchema).handleInvocation(async (ctx) => ({
|
|
1093
|
+
output: await handleGetFileUrl(ctx),
|
|
1094
|
+
message: "ok"
|
|
1095
|
+
})).build();
|
|
1096
|
+
|
|
1065
1097
|
// src/action/publicTool.ts
|
|
1066
1098
|
var SlatePublicTool = class {
|
|
1067
1099
|
constructor() {
|
|
@@ -1141,23 +1173,35 @@ var SlateTrigger = class _SlateTrigger extends SlateAction {
|
|
|
1141
1173
|
var trigger = (spec2, params) => SlateTrigger.create(spec2, params);
|
|
1142
1174
|
|
|
1143
1175
|
// src/action/attachment.ts
|
|
1144
|
-
var createUrlAttachment = (url,
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
type: "url",
|
|
1148
|
-
url
|
|
1176
|
+
var createUrlAttachment = (url, opts = {}) => {
|
|
1177
|
+
if (opts.refreshReference !== void 0 && !opts.refreshAt) {
|
|
1178
|
+
throw new Error("createUrlAttachment: refreshAt is required when refreshReference is set");
|
|
1149
1179
|
}
|
|
1150
|
-
|
|
1151
|
-
|
|
1180
|
+
return {
|
|
1181
|
+
mimeType: opts.mimeType,
|
|
1182
|
+
attachmentHash: opts.attachmentHash,
|
|
1183
|
+
content: {
|
|
1184
|
+
type: "url",
|
|
1185
|
+
url,
|
|
1186
|
+
...opts.headers ? { headers: opts.headers } : {},
|
|
1187
|
+
...opts.query ? { query: opts.query } : {},
|
|
1188
|
+
...opts.refreshReference !== void 0 ? { refreshReference: opts.refreshReference } : {},
|
|
1189
|
+
...opts.refreshAt ? { refreshAt: opts.refreshAt } : {}
|
|
1190
|
+
}
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1193
|
+
var createBase64Attachment = (content, mimeType, attachmentHash) => ({
|
|
1152
1194
|
mimeType,
|
|
1195
|
+
attachmentHash,
|
|
1153
1196
|
content: {
|
|
1154
1197
|
type: "content",
|
|
1155
1198
|
encoding: "base64",
|
|
1156
1199
|
content
|
|
1157
1200
|
}
|
|
1158
1201
|
});
|
|
1159
|
-
var createTextAttachment = (content, mimeType) => ({
|
|
1202
|
+
var createTextAttachment = (content, mimeType, attachmentHash) => ({
|
|
1160
1203
|
mimeType,
|
|
1204
|
+
attachmentHash,
|
|
1161
1205
|
content: {
|
|
1162
1206
|
type: "content",
|
|
1163
1207
|
encoding: "utf-8",
|
|
@@ -1165,6 +1209,44 @@ var createTextAttachment = (content, mimeType) => ({
|
|
|
1165
1209
|
}
|
|
1166
1210
|
});
|
|
1167
1211
|
|
|
1212
|
+
// src/action/directUpload.ts
|
|
1213
|
+
var uploadAttachmentDirect = async (d) => {
|
|
1214
|
+
let baseUrl = d.live.baseUrl.replace(/\/$/, "");
|
|
1215
|
+
let registerRes = await fetch(`${baseUrl}/slates-hub/live-invocation/attachments`, {
|
|
1216
|
+
method: "POST",
|
|
1217
|
+
headers: {
|
|
1218
|
+
"content-type": "application/json",
|
|
1219
|
+
authorization: `Bearer ${d.live.token}`
|
|
1220
|
+
},
|
|
1221
|
+
body: JSON.stringify({
|
|
1222
|
+
attachments: [{ mimeType: d.mimeType, filename: d.filename }]
|
|
1223
|
+
})
|
|
1224
|
+
});
|
|
1225
|
+
if (!registerRes.ok) {
|
|
1226
|
+
throw new Error(
|
|
1227
|
+
`Failed to register attachment for direct upload (status ${registerRes.status})`
|
|
1228
|
+
);
|
|
1229
|
+
}
|
|
1230
|
+
let { attachments } = await registerRes.json();
|
|
1231
|
+
let registration = attachments[0];
|
|
1232
|
+
if (!registration) {
|
|
1233
|
+
throw new Error("Live invocation API returned no attachment registrations");
|
|
1234
|
+
}
|
|
1235
|
+
let putRes = await fetch(registration.uploadUrl, {
|
|
1236
|
+
method: "PUT",
|
|
1237
|
+
...d.body instanceof Uint8Array ? {} : { duplex: "half" },
|
|
1238
|
+
headers: d.mimeType ? { "content-type": d.mimeType } : void 0,
|
|
1239
|
+
body: d.body
|
|
1240
|
+
});
|
|
1241
|
+
if (!putRes.ok) {
|
|
1242
|
+
throw new Error(`Failed to upload attachment content (status ${putRes.status})`);
|
|
1243
|
+
}
|
|
1244
|
+
return {
|
|
1245
|
+
mimeType: d.mimeType,
|
|
1246
|
+
content: { type: "upload_reference", referenceId: registration.referenceId }
|
|
1247
|
+
};
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1168
1250
|
// src/adapter/adapter.ts
|
|
1169
1251
|
var SlateAdapter = class {
|
|
1170
1252
|
constructor(_spec, _tools, _triggers) {
|
|
@@ -1435,6 +1517,76 @@ var normalizeOAuthTokenResponse = (data, options = {}) => {
|
|
|
1435
1517
|
};
|
|
1436
1518
|
};
|
|
1437
1519
|
|
|
1520
|
+
// src/auth/redact.ts
|
|
1521
|
+
var AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX = "$$MT$secret$authConfig$";
|
|
1522
|
+
var AuthConfigSecretRedactor = class {
|
|
1523
|
+
secretToPlaceholder = /* @__PURE__ */ new Map();
|
|
1524
|
+
constructor(authConfig) {
|
|
1525
|
+
if (authConfig) this.buildSecretMap(authConfig);
|
|
1526
|
+
}
|
|
1527
|
+
redact(value) {
|
|
1528
|
+
return this.transform(value, (stringValue) => {
|
|
1529
|
+
return this.secretToPlaceholder.get(stringValue) ?? stringValue;
|
|
1530
|
+
});
|
|
1531
|
+
}
|
|
1532
|
+
buildSecretMap(value, path = []) {
|
|
1533
|
+
if (typeof value === "string") {
|
|
1534
|
+
if (value.length === 0) return;
|
|
1535
|
+
this.secretToPlaceholder.set(
|
|
1536
|
+
value,
|
|
1537
|
+
`${AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX}${path.join(".")}`
|
|
1538
|
+
);
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
if (Array.isArray(value)) {
|
|
1542
|
+
value.forEach((item, index) => {
|
|
1543
|
+
this.buildSecretMap(item, [...path, String(index)]);
|
|
1544
|
+
});
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
if (this.isPlainObject(value)) {
|
|
1548
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
1549
|
+
this.buildSecretMap(nestedValue, [...path, key]);
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
transform(value, transformString) {
|
|
1554
|
+
if (typeof value === "string") {
|
|
1555
|
+
return transformString(value);
|
|
1556
|
+
}
|
|
1557
|
+
if (Array.isArray(value)) {
|
|
1558
|
+
return value.map((item) => this.transform(item, transformString));
|
|
1559
|
+
}
|
|
1560
|
+
if (this.isPlainObject(value)) {
|
|
1561
|
+
let result = {};
|
|
1562
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
1563
|
+
result[key] = this.transform(nestedValue, transformString);
|
|
1564
|
+
});
|
|
1565
|
+
return result;
|
|
1566
|
+
}
|
|
1567
|
+
return value;
|
|
1568
|
+
}
|
|
1569
|
+
isPlainObject(value) {
|
|
1570
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1571
|
+
}
|
|
1572
|
+
};
|
|
1573
|
+
var redactUrlAttachmentSecrets = (attachments, authConfig) => {
|
|
1574
|
+
if (!authConfig || !attachments) return attachments;
|
|
1575
|
+
let redactor = new AuthConfigSecretRedactor(authConfig);
|
|
1576
|
+
return attachments.map((attachment) => {
|
|
1577
|
+
if (attachment.content.type !== "url") return attachment;
|
|
1578
|
+
if (!attachment.content.headers && !attachment.content.query) return attachment;
|
|
1579
|
+
return {
|
|
1580
|
+
...attachment,
|
|
1581
|
+
content: {
|
|
1582
|
+
...attachment.content,
|
|
1583
|
+
headers: attachment.content.headers ? redactor.redact(attachment.content.headers) : void 0,
|
|
1584
|
+
query: attachment.content.query ? redactor.redact(attachment.content.query) : void 0
|
|
1585
|
+
}
|
|
1586
|
+
};
|
|
1587
|
+
});
|
|
1588
|
+
};
|
|
1589
|
+
|
|
1438
1590
|
// src/axios/index.ts
|
|
1439
1591
|
var import_axios3 = __toESM(require("axios"), 1);
|
|
1440
1592
|
|
|
@@ -1713,9 +1865,9 @@ var truncateText = (text) => {
|
|
|
1713
1865
|
truncated: true
|
|
1714
1866
|
};
|
|
1715
1867
|
};
|
|
1716
|
-
var sanitizeFreeText = (text) => {
|
|
1868
|
+
var sanitizeFreeText = (text, redactor) => {
|
|
1717
1869
|
if (!text) return text;
|
|
1718
|
-
let result = text;
|
|
1870
|
+
let result = redactor ? redactor.redact(text) : text;
|
|
1719
1871
|
result = result.replace(
|
|
1720
1872
|
HTTP_AUTH_SCHEME_PATTERN,
|
|
1721
1873
|
(_match, scheme) => `${scheme} ${REDACTED_VALUE}`
|
|
@@ -1733,21 +1885,21 @@ var sanitizeFreeText = (text) => {
|
|
|
1733
1885
|
);
|
|
1734
1886
|
return result;
|
|
1735
1887
|
};
|
|
1736
|
-
var sanitizeScalar = (value) => truncateText(sanitizeFreeText(value));
|
|
1737
|
-
var redactStructuredValue = (value, depth = 0) => {
|
|
1888
|
+
var sanitizeScalar = (value, redactor) => truncateText(sanitizeFreeText(value, redactor));
|
|
1889
|
+
var redactStructuredValue = (value, depth = 0, redactor) => {
|
|
1738
1890
|
if (value == null) return value;
|
|
1739
1891
|
if (depth >= STRUCTURED_DEPTH_LIMIT) return "[truncated]";
|
|
1740
1892
|
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
1741
|
-
return typeof value === "string" ? sanitizeFreeText(value) : value;
|
|
1893
|
+
return typeof value === "string" ? sanitizeFreeText(value, redactor) : value;
|
|
1742
1894
|
}
|
|
1743
1895
|
if (Array.isArray(value)) {
|
|
1744
|
-
return value.slice(0, STRUCTURED_ENTRY_LIMIT).map((entry) => redactStructuredValue(entry, depth + 1));
|
|
1896
|
+
return value.slice(0, STRUCTURED_ENTRY_LIMIT).map((entry) => redactStructuredValue(entry, depth + 1, redactor));
|
|
1745
1897
|
}
|
|
1746
1898
|
if (isRecord2(value)) {
|
|
1747
1899
|
return Object.fromEntries(
|
|
1748
1900
|
Object.entries(value).slice(0, STRUCTURED_ENTRY_LIMIT).map(([key, entry]) => [
|
|
1749
1901
|
key,
|
|
1750
|
-
isSecretKeyName(key) ? REDACTED_VALUE : redactStructuredValue(entry, depth + 1)
|
|
1902
|
+
isSecretKeyName(key) ? REDACTED_VALUE : redactStructuredValue(entry, depth + 1, redactor)
|
|
1751
1903
|
])
|
|
1752
1904
|
);
|
|
1753
1905
|
}
|
|
@@ -1765,11 +1917,11 @@ var maybeParseJson = (text, contentType) => {
|
|
|
1765
1917
|
return null;
|
|
1766
1918
|
}
|
|
1767
1919
|
};
|
|
1768
|
-
var sanitizeTextBody = (text, contentType) => {
|
|
1920
|
+
var sanitizeTextBody = (text, contentType, redactor) => {
|
|
1769
1921
|
if (!text) return void 0;
|
|
1770
1922
|
let normalizedContentType = normalizeContentType(contentType);
|
|
1771
1923
|
let parsedJson = maybeParseJson(text, normalizedContentType);
|
|
1772
|
-
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson)) : sanitizeFreeText(text);
|
|
1924
|
+
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson, 0, redactor)) : sanitizeFreeText(text, redactor);
|
|
1773
1925
|
let { text: truncatedText, truncated } = truncateText(normalizedText);
|
|
1774
1926
|
return {
|
|
1775
1927
|
...normalizedContentType ? { contentType: normalizedContentType } : {},
|
|
@@ -1785,22 +1937,26 @@ var isBinaryLike = (value) => {
|
|
|
1785
1937
|
if (typeof FormData !== "undefined" && value instanceof FormData) return true;
|
|
1786
1938
|
return false;
|
|
1787
1939
|
};
|
|
1788
|
-
var serializeTextBody = (value, contentType) => {
|
|
1940
|
+
var serializeTextBody = (value, contentType, redactor) => {
|
|
1789
1941
|
let normalizedContentType = normalizeContentType(contentType);
|
|
1790
1942
|
if (value == null || isBinaryLike(value) || !isTextContentType(normalizedContentType)) {
|
|
1791
1943
|
return void 0;
|
|
1792
1944
|
}
|
|
1793
1945
|
if (typeof value === "string") {
|
|
1794
|
-
return sanitizeTextBody(value, normalizedContentType);
|
|
1946
|
+
return sanitizeTextBody(value, normalizedContentType, redactor);
|
|
1795
1947
|
}
|
|
1796
1948
|
if (value instanceof URLSearchParams) {
|
|
1797
|
-
return sanitizeTextBody(value.toString(), normalizedContentType);
|
|
1949
|
+
return sanitizeTextBody(value.toString(), normalizedContentType, redactor);
|
|
1798
1950
|
}
|
|
1799
1951
|
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
1800
|
-
return sanitizeTextBody(String(value), normalizedContentType);
|
|
1952
|
+
return sanitizeTextBody(String(value), normalizedContentType, redactor);
|
|
1801
1953
|
}
|
|
1802
1954
|
if (Array.isArray(value) || isRecord2(value)) {
|
|
1803
|
-
return sanitizeTextBody(
|
|
1955
|
+
return sanitizeTextBody(
|
|
1956
|
+
JSON.stringify(redactStructuredValue(value, 0, redactor)),
|
|
1957
|
+
"application/json",
|
|
1958
|
+
redactor
|
|
1959
|
+
);
|
|
1804
1960
|
}
|
|
1805
1961
|
return void 0;
|
|
1806
1962
|
};
|
|
@@ -1815,16 +1971,20 @@ var buildUrl = (baseURL, url) => {
|
|
|
1815
1971
|
};
|
|
1816
1972
|
var REDACTED_ENCODED = encodeURIComponent(REDACTED_VALUE);
|
|
1817
1973
|
var decodeRedactedMarker = (value) => REDACTED_ENCODED === REDACTED_VALUE ? value : value.split(REDACTED_ENCODED).join(REDACTED_VALUE);
|
|
1818
|
-
var redactHashFragment = (hash) => {
|
|
1974
|
+
var redactHashFragment = (hash, redactor) => {
|
|
1819
1975
|
if (!hash?.includes("=")) return hash;
|
|
1820
1976
|
let withoutHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
1821
1977
|
let redacted = withoutHash.replace(
|
|
1822
1978
|
/(?<![A-Za-z0-9])([A-Za-z0-9][A-Za-z0-9_\-.]*)=([^&]*)/g,
|
|
1823
|
-
(match, key,
|
|
1979
|
+
(match, key, rawValue) => {
|
|
1980
|
+
if (isUrlFormSecretKeyName(key)) return `${key}=${REDACTED_VALUE}`;
|
|
1981
|
+
let literalRedacted = redactor ? redactor.redact(rawValue) : rawValue;
|
|
1982
|
+
return literalRedacted !== rawValue ? `${key}=${literalRedacted}` : match;
|
|
1983
|
+
}
|
|
1824
1984
|
);
|
|
1825
1985
|
return redacted ? `#${redacted}` : "";
|
|
1826
1986
|
};
|
|
1827
|
-
var sanitizeUrl = (value) => {
|
|
1987
|
+
var sanitizeUrl = (value, redactor) => {
|
|
1828
1988
|
if (!value) return value;
|
|
1829
1989
|
try {
|
|
1830
1990
|
let url = new URL(value);
|
|
@@ -1835,12 +1995,17 @@ var sanitizeUrl = (value) => {
|
|
|
1835
1995
|
for (let key of Array.from(url.searchParams.keys())) {
|
|
1836
1996
|
if (isUrlFormSecretKeyName(key)) {
|
|
1837
1997
|
url.searchParams.set(key, REDACTED_VALUE);
|
|
1998
|
+
continue;
|
|
1838
1999
|
}
|
|
2000
|
+
let rawValue = url.searchParams.get(key) ?? "";
|
|
2001
|
+
let literalRedacted = redactor ? redactor.redact(rawValue) : rawValue;
|
|
2002
|
+
if (literalRedacted !== rawValue) url.searchParams.set(key, literalRedacted);
|
|
1839
2003
|
}
|
|
1840
|
-
url.hash = redactHashFragment(url.hash);
|
|
2004
|
+
url.hash = redactHashFragment(url.hash, redactor);
|
|
1841
2005
|
return decodeRedactedMarker(url.toString());
|
|
1842
2006
|
} catch {
|
|
1843
|
-
|
|
2007
|
+
let text = redactor ? redactor.redact(value) : value;
|
|
2008
|
+
return text.replace(
|
|
1844
2009
|
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
1845
2010
|
(_match, prefix, key, rawValue) => isUrlFormSecretKeyName(key) ? `${prefix}${REDACTED_VALUE}` : `${prefix}${rawValue}`
|
|
1846
2011
|
);
|
|
@@ -1879,8 +2044,10 @@ var headerEntries = (headers) => {
|
|
|
1879
2044
|
}
|
|
1880
2045
|
return [];
|
|
1881
2046
|
};
|
|
1882
|
-
var sanitizeHeaders = (headers) => {
|
|
1883
|
-
let entries = headerEntries(headers).map(
|
|
2047
|
+
var sanitizeHeaders = (headers, redactor) => {
|
|
2048
|
+
let entries = headerEntries(headers).map(
|
|
2049
|
+
([key, value]) => [key.toLowerCase(), sanitizeScalar(value, redactor).text]
|
|
2050
|
+
).filter(([key]) => isSafeHeaderName(key));
|
|
1884
2051
|
if (entries.length === 0) return void 0;
|
|
1885
2052
|
return Object.fromEntries(entries);
|
|
1886
2053
|
};
|
|
@@ -1906,15 +2073,16 @@ var clearTraceDraft = (config2, draft) => {
|
|
|
1906
2073
|
var attachHttpTraceDraft = (config2, context) => {
|
|
1907
2074
|
let traceAwareConfig = config2;
|
|
1908
2075
|
let contentType = getContentType(config2.headers);
|
|
2076
|
+
let redactor = new AuthConfigSecretRedactor(context._getAuthConfigForRedaction());
|
|
1909
2077
|
traceAwareConfig.__slatesHttpTraceDraft = {
|
|
1910
2078
|
context,
|
|
1911
2079
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1912
2080
|
startedAtMs: Date.now(),
|
|
1913
2081
|
request: {
|
|
1914
2082
|
method: (config2.method ?? "GET").toUpperCase(),
|
|
1915
|
-
url: sanitizeUrl(buildUrl(config2.baseURL, config2.url)),
|
|
1916
|
-
...sanitizeHeaders(config2.headers) ? { headers: sanitizeHeaders(config2.headers) } : {},
|
|
1917
|
-
...serializeTextBody(config2.data, contentType) ? { body: serializeTextBody(config2.data, contentType) } : {}
|
|
2083
|
+
url: sanitizeUrl(buildUrl(config2.baseURL, config2.url), redactor),
|
|
2084
|
+
...sanitizeHeaders(config2.headers, redactor) ? { headers: sanitizeHeaders(config2.headers, redactor) } : {},
|
|
2085
|
+
...serializeTextBody(config2.data, contentType, redactor) ? { body: serializeTextBody(config2.data, contentType, redactor) } : {}
|
|
1918
2086
|
}
|
|
1919
2087
|
};
|
|
1920
2088
|
if (isObjectLike(traceAwareConfig)) {
|
|
@@ -1933,6 +2101,7 @@ var recordHttpTraceFromResponse = (response) => {
|
|
|
1933
2101
|
let draft = takeTraceDraft(config2);
|
|
1934
2102
|
if (!draft) return response;
|
|
1935
2103
|
clearTraceDraft(config2, draft);
|
|
2104
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
1936
2105
|
let contentType = getContentType(response.headers);
|
|
1937
2106
|
draft.context.recordHttpTrace({
|
|
1938
2107
|
startedAt: draft.startedAt,
|
|
@@ -1941,8 +2110,8 @@ var recordHttpTraceFromResponse = (response) => {
|
|
|
1941
2110
|
response: {
|
|
1942
2111
|
status: response.status,
|
|
1943
2112
|
...response.statusText ? { statusText: response.statusText } : {},
|
|
1944
|
-
...sanitizeHeaders(response.headers) ? { headers: sanitizeHeaders(response.headers) } : {},
|
|
1945
|
-
...serializeTextBody(response.data, contentType) ? { body: serializeTextBody(response.data, contentType) } : {}
|
|
2113
|
+
...sanitizeHeaders(response.headers, redactor) ? { headers: sanitizeHeaders(response.headers, redactor) } : {},
|
|
2114
|
+
...serializeTextBody(response.data, contentType, redactor) ? { body: serializeTextBody(response.data, contentType, redactor) } : {}
|
|
1946
2115
|
}
|
|
1947
2116
|
});
|
|
1948
2117
|
return response;
|
|
@@ -1952,6 +2121,7 @@ var recordHttpTraceFromError = (error) => {
|
|
|
1952
2121
|
let draft = takeTraceDraft(config2);
|
|
1953
2122
|
if (!draft) return;
|
|
1954
2123
|
clearTraceDraft(config2, draft);
|
|
2124
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
1955
2125
|
let responseContentType = getContentType(error.response?.headers);
|
|
1956
2126
|
draft.context.recordHttpTrace({
|
|
1957
2127
|
startedAt: draft.startedAt,
|
|
@@ -1961,8 +2131,8 @@ var recordHttpTraceFromError = (error) => {
|
|
|
1961
2131
|
response: {
|
|
1962
2132
|
status: error.response.status,
|
|
1963
2133
|
...error.response.statusText ? { statusText: error.response.statusText } : {},
|
|
1964
|
-
...sanitizeHeaders(error.response.headers) ? { headers: sanitizeHeaders(error.response.headers) } : {},
|
|
1965
|
-
...serializeTextBody(error.response.data, responseContentType) ? { body: serializeTextBody(error.response.data, responseContentType) } : {}
|
|
2134
|
+
...sanitizeHeaders(error.response.headers, redactor) ? { headers: sanitizeHeaders(error.response.headers, redactor) } : {},
|
|
2135
|
+
...serializeTextBody(error.response.data, responseContentType, redactor) ? { body: serializeTextBody(error.response.data, responseContentType, redactor) } : {}
|
|
1966
2136
|
}
|
|
1967
2137
|
} : {},
|
|
1968
2138
|
error: {
|
|
@@ -2093,16 +2263,39 @@ var SlateConfig = class _SlateConfig {
|
|
|
2093
2263
|
var config = (schema) => SlateConfig.create(schema);
|
|
2094
2264
|
|
|
2095
2265
|
// src/context/context.ts
|
|
2266
|
+
var import_node_stream = require("stream");
|
|
2267
|
+
var import_p_queue = __toESM(require("p-queue"), 1);
|
|
2268
|
+
var isBufferLike = (value) => value instanceof Uint8Array || value instanceof ArrayBuffer;
|
|
2269
|
+
var toUint8Array = (value) => value instanceof ArrayBuffer ? new Uint8Array(value) : value;
|
|
2270
|
+
var isReadableStream = (value) => typeof ReadableStream !== "undefined" && value instanceof ReadableStream;
|
|
2271
|
+
var isNodeReadable = (value) => !!value && typeof value === "object" && typeof value.pipe === "function" && typeof value.on === "function";
|
|
2272
|
+
var isResponseLike = (value) => typeof Response !== "undefined" && value instanceof Response;
|
|
2273
|
+
var readStreamToBuffer = async (stream) => {
|
|
2274
|
+
let reader = stream.getReader();
|
|
2275
|
+
let chunks = [];
|
|
2276
|
+
while (true) {
|
|
2277
|
+
let { done, value } = await reader.read();
|
|
2278
|
+
if (done) break;
|
|
2279
|
+
if (value) chunks.push(value);
|
|
2280
|
+
}
|
|
2281
|
+
return Buffer.concat(chunks);
|
|
2282
|
+
};
|
|
2096
2283
|
var SlatePublicContext = class {
|
|
2097
|
-
constructor(input, spec2, logger) {
|
|
2284
|
+
constructor(input, spec2, logger, liveInvocation = null) {
|
|
2098
2285
|
this.spec = spec2;
|
|
2099
2286
|
this.logger = logger;
|
|
2100
2287
|
this.#input = input;
|
|
2288
|
+
this.#liveInvocation = liveInvocation;
|
|
2101
2289
|
}
|
|
2102
2290
|
spec;
|
|
2103
2291
|
logger;
|
|
2104
2292
|
#input;
|
|
2105
2293
|
#httpTraces = [];
|
|
2294
|
+
#liveInvocation;
|
|
2295
|
+
#attachmentsDisabled = false;
|
|
2296
|
+
#attachments = [];
|
|
2297
|
+
#pendingUploads = [];
|
|
2298
|
+
#uploadQueue = new import_p_queue.default({ concurrency: 10 });
|
|
2106
2299
|
get specification() {
|
|
2107
2300
|
return this.spec;
|
|
2108
2301
|
}
|
|
@@ -2156,12 +2349,95 @@ var SlatePublicContext = class {
|
|
|
2156
2349
|
progress(message) {
|
|
2157
2350
|
this.logger.progress(message);
|
|
2158
2351
|
}
|
|
2352
|
+
async addAttachment(input) {
|
|
2353
|
+
if (input.type === "url") {
|
|
2354
|
+
this.#attachments.push(
|
|
2355
|
+
createUrlAttachment(input.url.toString(), {
|
|
2356
|
+
mimeType: input.mimeType,
|
|
2357
|
+
headers: input.headers,
|
|
2358
|
+
query: input.query,
|
|
2359
|
+
refreshReference: input.refreshReference,
|
|
2360
|
+
refreshAt: input.refreshAt
|
|
2361
|
+
})
|
|
2362
|
+
);
|
|
2363
|
+
return;
|
|
2364
|
+
}
|
|
2365
|
+
let content = input.content;
|
|
2366
|
+
if (isBufferLike(content)) {
|
|
2367
|
+
let bytes = toUint8Array(content);
|
|
2368
|
+
this.#attachments.push(
|
|
2369
|
+
createBase64Attachment(Buffer.from(bytes).toString("base64"), input.mimeType)
|
|
2370
|
+
);
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
let normalized = await this.#normalizeStreamInput(content, {
|
|
2374
|
+
mimeType: input.mimeType,
|
|
2375
|
+
filename: input.filename
|
|
2376
|
+
});
|
|
2377
|
+
if (!normalized) return;
|
|
2378
|
+
if (!this.#liveInvocation || this.#attachmentsDisabled) {
|
|
2379
|
+
let buffer = await readStreamToBuffer(normalized.stream);
|
|
2380
|
+
this.#attachments.push(
|
|
2381
|
+
createBase64Attachment(buffer.toString("base64"), normalized.mimeType)
|
|
2382
|
+
);
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2385
|
+
let live = this.#liveInvocation;
|
|
2386
|
+
let task = this.#uploadQueue.add(
|
|
2387
|
+
() => uploadAttachmentDirect({
|
|
2388
|
+
live,
|
|
2389
|
+
mimeType: normalized.mimeType,
|
|
2390
|
+
filename: normalized.filename,
|
|
2391
|
+
body: normalized.stream
|
|
2392
|
+
})
|
|
2393
|
+
).then((attachment) => {
|
|
2394
|
+
this.#attachments.push(attachment);
|
|
2395
|
+
}).catch((err) => {
|
|
2396
|
+
this.#attachmentsDisabled = true;
|
|
2397
|
+
this.warn({
|
|
2398
|
+
message: `Attachment dropped: direct upload failed (${err instanceof Error ? err.message : String(err)}).`
|
|
2399
|
+
});
|
|
2400
|
+
});
|
|
2401
|
+
this.#pendingUploads.push(task);
|
|
2402
|
+
}
|
|
2403
|
+
async #normalizeStreamInput(input, opts) {
|
|
2404
|
+
if (isResponseLike(input)) {
|
|
2405
|
+
if (!input.body) {
|
|
2406
|
+
this.warn({ message: "Attachment dropped: response has no body." });
|
|
2407
|
+
return null;
|
|
2408
|
+
}
|
|
2409
|
+
return {
|
|
2410
|
+
stream: input.body,
|
|
2411
|
+
mimeType: opts.mimeType ?? input.headers.get("content-type") ?? void 0,
|
|
2412
|
+
filename: opts.filename
|
|
2413
|
+
};
|
|
2414
|
+
}
|
|
2415
|
+
if (isReadableStream(input)) {
|
|
2416
|
+
return { stream: input, mimeType: opts.mimeType, filename: opts.filename };
|
|
2417
|
+
}
|
|
2418
|
+
if (isNodeReadable(input)) {
|
|
2419
|
+
return {
|
|
2420
|
+
stream: import_node_stream.Readable.toWeb(input),
|
|
2421
|
+
mimeType: opts.mimeType,
|
|
2422
|
+
filename: opts.filename
|
|
2423
|
+
};
|
|
2424
|
+
}
|
|
2425
|
+
this.warn({ message: "Attachment dropped: unsupported attachment input type." });
|
|
2426
|
+
return null;
|
|
2427
|
+
}
|
|
2428
|
+
async _finalizeAttachments() {
|
|
2429
|
+
await Promise.allSettled(this.#pendingUploads);
|
|
2430
|
+
return this.#attachments;
|
|
2431
|
+
}
|
|
2432
|
+
_getAuthConfigForRedaction() {
|
|
2433
|
+
return void 0;
|
|
2434
|
+
}
|
|
2159
2435
|
};
|
|
2160
2436
|
var SlateContext = class extends SlatePublicContext {
|
|
2161
2437
|
#config;
|
|
2162
2438
|
#auth;
|
|
2163
|
-
constructor(config2, input, auth2, spec2, logger) {
|
|
2164
|
-
super(input, spec2, logger);
|
|
2439
|
+
constructor(config2, input, auth2, spec2, logger, liveInvocation = null) {
|
|
2440
|
+
super(input, spec2, logger, liveInvocation);
|
|
2165
2441
|
this.#config = config2;
|
|
2166
2442
|
this.#auth = auth2;
|
|
2167
2443
|
}
|
|
@@ -2171,6 +2447,9 @@ var SlateContext = class extends SlatePublicContext {
|
|
|
2171
2447
|
get auth() {
|
|
2172
2448
|
return Object.freeze(this.#auth);
|
|
2173
2449
|
}
|
|
2450
|
+
_getAuthConfigForRedaction() {
|
|
2451
|
+
return this.#auth;
|
|
2452
|
+
}
|
|
2174
2453
|
};
|
|
2175
2454
|
|
|
2176
2455
|
// src/crypto/hmac.ts
|
|
@@ -2367,7 +2646,7 @@ var Slate = class _Slate {
|
|
|
2367
2646
|
};
|
|
2368
2647
|
|
|
2369
2648
|
// src/specification/specification.ts
|
|
2370
|
-
var
|
|
2649
|
+
var import_zod2 = __toESM(require("zod"), 1);
|
|
2371
2650
|
var SlateSpecification = class _SlateSpecification {
|
|
2372
2651
|
constructor(_config, _auth, _params) {
|
|
2373
2652
|
this._config = _config;
|
|
@@ -2384,7 +2663,7 @@ var SlateSpecification = class _SlateSpecification {
|
|
|
2384
2663
|
return this._config.configSchema;
|
|
2385
2664
|
}
|
|
2386
2665
|
get authSchema() {
|
|
2387
|
-
return "outputSchema" in this._auth ? this._auth.outputSchema :
|
|
2666
|
+
return "outputSchema" in this._auth ? this._auth.outputSchema : import_zod2.default.object({});
|
|
2388
2667
|
}
|
|
2389
2668
|
get config() {
|
|
2390
2669
|
return this._config;
|
|
@@ -2464,6 +2743,9 @@ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
|
|
|
2464
2743
|
};
|
|
2465
2744
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2466
2745
|
0 && (module.exports = {
|
|
2746
|
+
AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX,
|
|
2747
|
+
AuthConfigSecretRedactor,
|
|
2748
|
+
GET_FILE_URL_TOOL_ID,
|
|
2467
2749
|
Slate,
|
|
2468
2750
|
SlateAction,
|
|
2469
2751
|
SlateActionBuilder,
|
|
@@ -2502,6 +2784,9 @@ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
|
|
|
2502
2784
|
getApiErrorStatus,
|
|
2503
2785
|
getBase64ByteLength,
|
|
2504
2786
|
getCurrentContext,
|
|
2787
|
+
getFileUrlTool,
|
|
2788
|
+
getFileUrlToolInputSchema,
|
|
2789
|
+
getFileUrlToolOutputSchema,
|
|
2505
2790
|
getGraphWebhookValidationResponse,
|
|
2506
2791
|
getMetaWebhookVerificationResponse,
|
|
2507
2792
|
getOAuthExpiresAtFromExpiresIn,
|
|
@@ -2519,6 +2804,7 @@ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
|
|
|
2519
2804
|
normalizeOAuthTokenResponse,
|
|
2520
2805
|
pickDefined,
|
|
2521
2806
|
publicTool,
|
|
2807
|
+
redactUrlAttachmentSecrets,
|
|
2522
2808
|
requestAxios,
|
|
2523
2809
|
requestAxiosData,
|
|
2524
2810
|
runWithContext,
|
|
@@ -2528,6 +2814,7 @@ var getMetaWebhookVerificationResponse = (request, expectedVerifyToken) => {
|
|
|
2528
2814
|
statusLabelForApiError,
|
|
2529
2815
|
tool,
|
|
2530
2816
|
trigger,
|
|
2817
|
+
uploadAttachmentDirect,
|
|
2531
2818
|
validateScopes,
|
|
2532
2819
|
verifyHmacSignature
|
|
2533
2820
|
});
|