@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 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, mimeType) => ({
1145
- mimeType,
1146
- content: {
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
- var createBase64Attachment = (content, mimeType) => ({
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(JSON.stringify(redactStructuredValue(value)), "application/json");
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, _rawValue) => isUrlFormSecretKeyName(key) ? `${key}=${REDACTED_VALUE}` : match
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
- return value.replace(
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(([key, value]) => [key.toLowerCase(), sanitizeScalar(value).text]).filter(([key]) => isSafeHeaderName(key));
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 import_zod = __toESM(require("zod"), 1);
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 : import_zod.default.object({});
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
  });