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