@slates/provider 1.0.0-rc.27 → 1.0.0-rc.29
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 +2305 -1876
- package/dist/index.d.cts +82 -8
- package/dist/index.d.ts +82 -8
- package/dist/index.module.js +2295 -1876
- package/package.json +1 -1
- package/src/action/getFileUrlTool.ts +2 -1
- package/src/action/triggerGroup.ts +65 -3
- package/src/auth/redact.test.ts +60 -2
- package/src/auth/redact.ts +59 -23
- package/src/axios/trace.test.ts +326 -1
- package/src/axios/trace.ts +334 -14
- package/src/error/api.test.ts +123 -1
- package/src/error/api.ts +148 -0
- package/src/error/axios.ts +48 -13
- package/src/error/utils.test.ts +654 -0
- package/src/error/utils.ts +268 -13
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
|
+
API_ERROR_MAX_DETAILS: () => API_ERROR_MAX_DETAILS,
|
|
34
|
+
API_ERROR_MAX_MESSAGE_LENGTH: () => API_ERROR_MAX_MESSAGE_LENGTH,
|
|
35
|
+
API_ERROR_TRUNCATED_PLACEHOLDER: () => API_ERROR_TRUNCATED_PLACEHOLDER,
|
|
33
36
|
AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX: () => AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX,
|
|
34
37
|
AuthConfigSecretRedactor: () => AuthConfigSecretRedactor,
|
|
35
38
|
GET_FILE_URL_TOOL_ID: () => GET_FILE_URL_TOOL_ID,
|
|
@@ -68,8 +71,10 @@ __export(index_exports, {
|
|
|
68
71
|
createSlateError: () => createSlateError,
|
|
69
72
|
createTextAttachment: () => createTextAttachment,
|
|
70
73
|
createUrlAttachment: () => createUrlAttachment,
|
|
74
|
+
decodeApiErrorBody: () => decodeApiErrorBody,
|
|
71
75
|
extractApiErrorMessage: () => extractApiErrorMessage,
|
|
72
76
|
getApiErrorResponse: () => getApiErrorResponse,
|
|
77
|
+
getApiErrorResponseWithBody: () => getApiErrorResponseWithBody,
|
|
73
78
|
getApiErrorStatus: () => getApiErrorStatus,
|
|
74
79
|
getBase64ByteLength: () => getBase64ByteLength,
|
|
75
80
|
getCurrentContext: () => getCurrentContext,
|
|
@@ -86,6 +91,8 @@ __export(index_exports, {
|
|
|
86
91
|
isApiErrorRecord: () => isApiErrorRecord,
|
|
87
92
|
isAxiosErrorLike: () => isAxiosErrorLike,
|
|
88
93
|
isServiceErrorData: () => isServiceErrorData,
|
|
94
|
+
isUrlEmbeddedCredential: () => isUrlEmbeddedCredential,
|
|
95
|
+
looksLikeHtmlErrorBody: () => looksLikeHtmlErrorBody,
|
|
89
96
|
mapServiceErrorCode: () => mapServiceErrorCode,
|
|
90
97
|
mapServiceErrorToSlateErrorInput: () => mapServiceErrorToSlateErrorInput,
|
|
91
98
|
mergeScopes: () => mergeScopes,
|
|
@@ -93,6 +100,8 @@ __export(index_exports, {
|
|
|
93
100
|
normalizeOAuthTokenResponse: () => normalizeOAuthTokenResponse,
|
|
94
101
|
pickDefined: () => pickDefined,
|
|
95
102
|
publicTool: () => publicTool,
|
|
103
|
+
pushBoundedApiErrorDetail: () => pushBoundedApiErrorDetail,
|
|
104
|
+
readApiErrorText: () => readApiErrorText,
|
|
96
105
|
redactUrlAttachmentSecrets: () => redactUrlAttachmentSecrets,
|
|
97
106
|
requestAxios: () => requestAxios,
|
|
98
107
|
requestAxiosData: () => requestAxiosData,
|
|
@@ -105,6 +114,7 @@ __export(index_exports, {
|
|
|
105
114
|
tool: () => tool,
|
|
106
115
|
trigger: () => trigger,
|
|
107
116
|
triggerGroup: () => triggerGroup,
|
|
117
|
+
truncateApiErrorMessage: () => truncateApiErrorMessage,
|
|
108
118
|
uploadAttachmentDirect: () => uploadAttachmentDirect,
|
|
109
119
|
validateScopes: () => validateScopes,
|
|
110
120
|
verifyHmacSignature: () => verifyHmacSignature
|
|
@@ -177,380 +187,639 @@ var SlateAction = class {
|
|
|
177
187
|
|
|
178
188
|
// src/error/api.ts
|
|
179
189
|
var import_error = require("@lowerdeck/error");
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
var
|
|
183
|
-
var
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
var collectApiErrorDetails = (value, details, options = {}) => {
|
|
193
|
-
if (Array.isArray(value)) {
|
|
194
|
-
for (let item of value) {
|
|
195
|
-
collectApiErrorDetails(item, details, options);
|
|
196
|
-
}
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
if (!isApiErrorRecord(value)) {
|
|
200
|
-
pushDetail(details, value, options);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
for (let key of options.detailKeys ?? DEFAULT_DETAIL_KEYS) {
|
|
204
|
-
pushDetail(details, value[key], options);
|
|
190
|
+
|
|
191
|
+
// src/auth/redact.ts
|
|
192
|
+
var AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX = "$$MT$secret$authConfig$";
|
|
193
|
+
var ALWAYS = () => true;
|
|
194
|
+
var AuthConfigSecretRedactor = class {
|
|
195
|
+
// A value shared by several fields keeps every path, so a filter that rejects one
|
|
196
|
+
// field (e.g. `username`) can still match another (e.g. `token`) with the same value.
|
|
197
|
+
secretToPaths = /* @__PURE__ */ new Map();
|
|
198
|
+
constructor(authConfig) {
|
|
199
|
+
if (authConfig) this.buildSecretMap(authConfig);
|
|
205
200
|
}
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
redact(value, wholeValue = ALWAYS) {
|
|
202
|
+
return this.transform(value, (stringValue) => {
|
|
203
|
+
return this.placeholderFor(stringValue, wholeValue) ?? stringValue;
|
|
204
|
+
});
|
|
208
205
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
206
|
+
/**
|
|
207
|
+
* `embeddable` limits which secrets are also replaced inside longer strings;
|
|
208
|
+
* `wholeValue` limits which secrets replace a string that equals them exactly.
|
|
209
|
+
*/
|
|
210
|
+
redactEmbedded(value, embeddable = ALWAYS, wholeValue = ALWAYS) {
|
|
211
|
+
let embeddedPlaceholders = /* @__PURE__ */ new Map();
|
|
212
|
+
for (let secret of this.secretToPaths.keys()) {
|
|
213
|
+
let placeholder = this.placeholderFor(secret, embeddable);
|
|
214
|
+
if (placeholder) embeddedPlaceholders.set(secret, placeholder);
|
|
215
|
+
}
|
|
216
|
+
if (embeddedPlaceholders.size === 0) return this.redact(value, wholeValue);
|
|
217
|
+
let pattern = new RegExp(
|
|
218
|
+
[...embeddedPlaceholders.keys()].sort((a, b) => b.length - a.length).map((secret) => secret.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|"),
|
|
219
|
+
"g"
|
|
220
|
+
);
|
|
221
|
+
return this.transform(value, (stringValue) => {
|
|
222
|
+
let exactPlaceholder = this.placeholderFor(stringValue, wholeValue);
|
|
223
|
+
if (exactPlaceholder) return exactPlaceholder;
|
|
224
|
+
return stringValue.replace(pattern, (secret) => `${embeddedPlaceholders.get(secret)}$$`);
|
|
225
|
+
});
|
|
213
226
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
227
|
+
// The last registered path that passes the filter wins, matching the historical
|
|
228
|
+
// last-write-wins behavior when no filter is given.
|
|
229
|
+
placeholderFor(value, filter) {
|
|
230
|
+
let paths = this.secretToPaths.get(value);
|
|
231
|
+
if (!paths) return void 0;
|
|
232
|
+
for (let index = paths.length - 1; index >= 0; index--) {
|
|
233
|
+
let path = paths[index];
|
|
234
|
+
if (path !== void 0 && filter(value, path))
|
|
235
|
+
return `${AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX}${path}`;
|
|
236
|
+
}
|
|
221
237
|
return void 0;
|
|
222
238
|
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (error instanceof Error && error.message) {
|
|
243
|
-
return error.message;
|
|
244
|
-
}
|
|
245
|
-
return options.fallbackMessage ?? "Unknown error";
|
|
246
|
-
};
|
|
247
|
-
var createApiServiceError = (message, options = {}) => {
|
|
248
|
-
let error = new import_error.ServiceError((0, import_error.badRequestError)({ message }));
|
|
249
|
-
if (options.reason !== void 0) {
|
|
250
|
-
error.data.reason = options.reason;
|
|
251
|
-
}
|
|
252
|
-
if ("upstreamStatus" in options) {
|
|
253
|
-
error.data.upstreamStatus = options.upstreamStatus;
|
|
239
|
+
buildSecretMap(value, path = []) {
|
|
240
|
+
if (typeof value === "string") {
|
|
241
|
+
if (value.length === 0) return;
|
|
242
|
+
let paths = this.secretToPaths.get(value);
|
|
243
|
+
if (paths) paths.push(path.join("."));
|
|
244
|
+
else this.secretToPaths.set(value, [path.join(".")]);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (Array.isArray(value)) {
|
|
248
|
+
value.forEach((item, index) => {
|
|
249
|
+
this.buildSecretMap(item, [...path, String(index)]);
|
|
250
|
+
});
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
if (this.isPlainObject(value)) {
|
|
254
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
255
|
+
this.buildSecretMap(nestedValue, [...path, key]);
|
|
256
|
+
});
|
|
257
|
+
}
|
|
254
258
|
}
|
|
255
|
-
|
|
256
|
-
|
|
259
|
+
transform(value, transformString) {
|
|
260
|
+
if (typeof value === "string") {
|
|
261
|
+
return transformString(value);
|
|
262
|
+
}
|
|
263
|
+
if (Array.isArray(value)) {
|
|
264
|
+
return value.map((item) => this.transform(item, transformString));
|
|
265
|
+
}
|
|
266
|
+
if (this.isPlainObject(value)) {
|
|
267
|
+
let result = {};
|
|
268
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
269
|
+
result[key] = this.transform(nestedValue, transformString);
|
|
270
|
+
});
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
273
|
+
return value;
|
|
257
274
|
}
|
|
258
|
-
|
|
259
|
-
|
|
275
|
+
isPlainObject(value) {
|
|
276
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
260
277
|
}
|
|
261
|
-
return error;
|
|
262
|
-
};
|
|
263
|
-
var helpers = {
|
|
264
|
-
collectDetails: collectApiErrorDetails,
|
|
265
|
-
extractMessage: extractApiErrorMessage,
|
|
266
|
-
getResponse: getApiErrorResponse,
|
|
267
|
-
getStatus: getApiErrorStatus,
|
|
268
|
-
isRecord: isApiErrorRecord,
|
|
269
|
-
statusLabelFor: statusLabelForApiError
|
|
270
278
|
};
|
|
271
|
-
var
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
let
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
return createApiServiceError(fullMessage, {
|
|
289
|
-
reason: options.reason,
|
|
290
|
-
upstreamStatus: status,
|
|
291
|
-
upstreamCode: options.extractUpstreamCode?.(error, response, helpers),
|
|
292
|
-
parent: options.parent ?? error
|
|
279
|
+
var URL_CREDENTIAL_KEY = /^(?:.*[-_])?(?:token|secret|password|api[-_]?key)$/i;
|
|
280
|
+
var isUrlEmbeddedCredential = (secret, path) => secret.length >= 8 && URL_CREDENTIAL_KEY.test(path.split(".").pop() ?? "");
|
|
281
|
+
var redactUrlAttachmentSecrets = (attachments, authConfig) => {
|
|
282
|
+
if (!authConfig || !attachments) return attachments;
|
|
283
|
+
let redactor = new AuthConfigSecretRedactor(authConfig);
|
|
284
|
+
return attachments.map((attachment) => {
|
|
285
|
+
if (attachment.content.type !== "url") return attachment;
|
|
286
|
+
let { url, headers, query } = attachment.content;
|
|
287
|
+
return {
|
|
288
|
+
...attachment,
|
|
289
|
+
content: {
|
|
290
|
+
...attachment.content,
|
|
291
|
+
url: redactor.redactEmbedded(url, isUrlEmbeddedCredential),
|
|
292
|
+
...headers ? { headers: redactor.redactEmbedded(headers) } : {},
|
|
293
|
+
...query ? { query: redactor.redactEmbedded(query) } : {}
|
|
294
|
+
}
|
|
295
|
+
};
|
|
293
296
|
});
|
|
294
297
|
};
|
|
295
298
|
|
|
296
|
-
// src/
|
|
297
|
-
var
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
var
|
|
301
|
-
var
|
|
302
|
-
var
|
|
303
|
-
var
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
"
|
|
320
|
-
"
|
|
321
|
-
"
|
|
322
|
-
"
|
|
323
|
-
"
|
|
324
|
-
"
|
|
325
|
-
"
|
|
326
|
-
|
|
327
|
-
"
|
|
328
|
-
"
|
|
329
|
-
"
|
|
330
|
-
"
|
|
331
|
-
"
|
|
332
|
-
|
|
333
|
-
"
|
|
334
|
-
"
|
|
335
|
-
|
|
336
|
-
"
|
|
337
|
-
"
|
|
338
|
-
"
|
|
339
|
-
"
|
|
340
|
-
|
|
341
|
-
"
|
|
342
|
-
"
|
|
343
|
-
"
|
|
344
|
-
"
|
|
345
|
-
"
|
|
346
|
-
"
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
299
|
+
// src/axios/trace.ts
|
|
300
|
+
var traceDraftsByConfig = /* @__PURE__ */ new WeakMap();
|
|
301
|
+
var traceDraftsByHeaders = /* @__PURE__ */ new WeakMap();
|
|
302
|
+
var TRACE_TEXT_LIMIT = 10 * 1024;
|
|
303
|
+
var REDACTED_VALUE = "[redacted]";
|
|
304
|
+
var STRUCTURED_DEPTH_LIMIT = 6;
|
|
305
|
+
var STRUCTURED_ENTRY_LIMIT = 50;
|
|
306
|
+
var CORE_SECRET_KEY_ATOMS = [
|
|
307
|
+
// HTTP authentication
|
|
308
|
+
"authorization",
|
|
309
|
+
"proxy[-_.]?authorization",
|
|
310
|
+
"www[-_.]?authenticate",
|
|
311
|
+
"bearer",
|
|
312
|
+
// Generic tokens
|
|
313
|
+
"token",
|
|
314
|
+
"tokens",
|
|
315
|
+
"access[-_.]?token",
|
|
316
|
+
"refresh[-_.]?token",
|
|
317
|
+
"id[-_.]?token",
|
|
318
|
+
"auth[-_.]?token",
|
|
319
|
+
"bearer[-_.]?token",
|
|
320
|
+
"session[-_.]?token",
|
|
321
|
+
"api[-_.]?token",
|
|
322
|
+
"app[-_.]?token",
|
|
323
|
+
"user[-_.]?token",
|
|
324
|
+
"oauth[-_.]?token",
|
|
325
|
+
"personal[-_.]?access[-_.]?token",
|
|
326
|
+
"x[-_.]?auth[-_.]?token",
|
|
327
|
+
"x[-_.]?access[-_.]?token",
|
|
328
|
+
"x[-_.]?refresh[-_.]?token",
|
|
329
|
+
// API keys
|
|
330
|
+
"apikey",
|
|
331
|
+
"api[-_.]?key",
|
|
332
|
+
"app[-_.]?key",
|
|
333
|
+
"x[-_.]?api[-_.]?key",
|
|
334
|
+
"x[-_.]?app[-_.]?key",
|
|
335
|
+
// HubSpot legacy API key query param
|
|
336
|
+
"hapikey",
|
|
337
|
+
"access[-_.]?key",
|
|
338
|
+
// OAuth client credentials
|
|
339
|
+
"client[-_.]?secret",
|
|
340
|
+
"client[-_.]?key",
|
|
341
|
+
"consumer[-_.]?secret",
|
|
342
|
+
"consumer[-_.]?key",
|
|
343
|
+
// Cryptographic keys
|
|
344
|
+
"private[-_.]?key",
|
|
345
|
+
"privatekey",
|
|
346
|
+
"secret[-_.]?key",
|
|
347
|
+
"secretkey",
|
|
348
|
+
"secret[-_.]?access[-_.]?key",
|
|
349
|
+
"encryption[-_.]?key",
|
|
350
|
+
"decryption[-_.]?key",
|
|
351
|
+
"signing[-_.]?key",
|
|
352
|
+
"signing[-_.]?secret",
|
|
353
|
+
"master[-_.]?key",
|
|
354
|
+
"master[-_.]?secret",
|
|
355
|
+
"master[-_.]?password",
|
|
356
|
+
"shared[-_.]?secret",
|
|
357
|
+
"webhook[-_.]?secret",
|
|
358
|
+
"webhook[-_.]?signing[-_.]?secret",
|
|
359
|
+
// OAuth codes & PKCE
|
|
360
|
+
"auth[-_.]?code",
|
|
361
|
+
"authcode",
|
|
362
|
+
"authorization[-_.]?code",
|
|
363
|
+
"code[-_.]?verifier",
|
|
364
|
+
"code[-_.]?challenge",
|
|
365
|
+
// Passwords & passcodes
|
|
366
|
+
"password",
|
|
367
|
+
"passwd",
|
|
368
|
+
"pwd",
|
|
369
|
+
"passphrase",
|
|
370
|
+
"pass[-_.]?phrase",
|
|
371
|
+
"pin",
|
|
372
|
+
"passcode",
|
|
373
|
+
// Generic secret markers
|
|
374
|
+
"secret",
|
|
375
|
+
"secrets",
|
|
376
|
+
"credential",
|
|
377
|
+
"credentials",
|
|
378
|
+
"creds",
|
|
379
|
+
"auth",
|
|
380
|
+
"x[-_.]?auth",
|
|
381
|
+
"x[-_.]?auth[-_.]?key",
|
|
382
|
+
// CSRF / XSRF
|
|
383
|
+
"csrf",
|
|
384
|
+
"xsrf",
|
|
385
|
+
"csrf[-_.]?token",
|
|
386
|
+
"xsrf[-_.]?token",
|
|
387
|
+
"x[-_.]?csrf[-_.]?token",
|
|
388
|
+
"x[-_.]?xsrf[-_.]?token",
|
|
389
|
+
// JWT
|
|
390
|
+
"jwt",
|
|
391
|
+
// Sessions & cookies
|
|
392
|
+
"session[-_.]?id",
|
|
393
|
+
"sessionid",
|
|
394
|
+
"sid",
|
|
395
|
+
"sessid",
|
|
396
|
+
"jsessionid",
|
|
397
|
+
"phpsessid",
|
|
398
|
+
"cookie",
|
|
399
|
+
"cookies",
|
|
400
|
+
"set[-_.]?cookie",
|
|
401
|
+
// Signatures / MAC
|
|
402
|
+
"signature",
|
|
403
|
+
"x[-_.]?hub[-_.]?signature",
|
|
404
|
+
"x[-_.]?signature",
|
|
405
|
+
"sig",
|
|
406
|
+
"hmac",
|
|
407
|
+
"mac",
|
|
408
|
+
// Crypto artifacts
|
|
409
|
+
"salt",
|
|
410
|
+
"nonce",
|
|
411
|
+
// Multi-factor / verification
|
|
412
|
+
"otp",
|
|
413
|
+
"totp",
|
|
414
|
+
"mfa",
|
|
415
|
+
"mfa[-_.]?code",
|
|
416
|
+
"2fa",
|
|
417
|
+
"two[-_.]?factor",
|
|
418
|
+
"twofactor",
|
|
419
|
+
"verification[-_.]?code",
|
|
420
|
+
"verify[-_.]?code",
|
|
421
|
+
"confirm(?:ation)?[-_.]?code",
|
|
422
|
+
"sms[-_.]?code",
|
|
423
|
+
"email[-_.]?code",
|
|
424
|
+
// Recovery & seed phrases
|
|
425
|
+
"seed[-_.]?phrase",
|
|
426
|
+
"mnemonic",
|
|
427
|
+
"recovery[-_.]?key",
|
|
428
|
+
"recovery[-_.]?code",
|
|
429
|
+
"recovery[-_.]?phrase",
|
|
430
|
+
// PII / financial
|
|
431
|
+
"card[-_.]?number",
|
|
432
|
+
"card[-_.]?code",
|
|
433
|
+
"cvv",
|
|
434
|
+
"cvc",
|
|
435
|
+
"ccv",
|
|
436
|
+
"cc[-_.]?num(?:ber)?",
|
|
437
|
+
"pan",
|
|
438
|
+
"ssn",
|
|
439
|
+
"social[-_.]?security",
|
|
440
|
+
"license[-_.]?key"
|
|
441
|
+
];
|
|
442
|
+
var URL_FORM_SECRET_KEY_ATOMS = [...CORE_SECRET_KEY_ATOMS, "code"];
|
|
443
|
+
var buildKeyBoundaryPattern = (atoms, flags) => new RegExp(`(?:^|[^A-Za-z0-9])(?:${atoms.join("|")})(?=[^A-Za-z0-9]|$)`, flags);
|
|
444
|
+
var SECRET_KEY_PATTERN = buildKeyBoundaryPattern(CORE_SECRET_KEY_ATOMS, "i");
|
|
445
|
+
var URL_FORM_SECRET_KEY_PATTERN = buildKeyBoundaryPattern(URL_FORM_SECRET_KEY_ATOMS, "i");
|
|
446
|
+
var NON_SECRET_KEY_EXACT = /* @__PURE__ */ new Set([
|
|
447
|
+
"token_type",
|
|
448
|
+
"token-type",
|
|
449
|
+
"tokentype",
|
|
450
|
+
"token_kind",
|
|
451
|
+
"token-kind",
|
|
452
|
+
"tokenkind",
|
|
453
|
+
"token_ttl",
|
|
454
|
+
"token-ttl",
|
|
455
|
+
"token_expires_in",
|
|
456
|
+
"token-expires-in",
|
|
457
|
+
"token_expiry",
|
|
458
|
+
"signature_method",
|
|
459
|
+
"signature-method",
|
|
460
|
+
"signature_type",
|
|
461
|
+
"signature-type",
|
|
462
|
+
"signature_version",
|
|
463
|
+
"signature-version",
|
|
464
|
+
"auth_type",
|
|
465
|
+
"auth-type",
|
|
466
|
+
"auth_method",
|
|
467
|
+
"auth-method",
|
|
468
|
+
"authentication_type",
|
|
469
|
+
"authentication-type",
|
|
470
|
+
"authentication_method",
|
|
471
|
+
"authentication-method",
|
|
472
|
+
"grant_type",
|
|
473
|
+
"grant-type",
|
|
474
|
+
"password_strength",
|
|
475
|
+
"password-strength",
|
|
476
|
+
"password_policy",
|
|
477
|
+
"password-policy",
|
|
478
|
+
"key_type",
|
|
479
|
+
"key-type",
|
|
480
|
+
"key_name",
|
|
481
|
+
"key-name",
|
|
482
|
+
"key_id",
|
|
483
|
+
"key-id",
|
|
484
|
+
"kid"
|
|
485
|
+
]);
|
|
486
|
+
var isSecretKeyName = (name) => {
|
|
487
|
+
let normalized = name.toLowerCase();
|
|
488
|
+
if (NON_SECRET_KEY_EXACT.has(normalized)) return false;
|
|
489
|
+
return SECRET_KEY_PATTERN.test(normalized);
|
|
402
490
|
};
|
|
403
|
-
var
|
|
404
|
-
|
|
405
|
-
|
|
491
|
+
var URL_FORM_EXACT_SECRET_KEYS = /* @__PURE__ */ new Set(["key"]);
|
|
492
|
+
var isUrlFormSecretKeyName = (name) => {
|
|
493
|
+
let normalized = name.toLowerCase();
|
|
494
|
+
if (NON_SECRET_KEY_EXACT.has(normalized)) return false;
|
|
495
|
+
if (URL_FORM_EXACT_SECRET_KEYS.has(normalized)) return true;
|
|
496
|
+
return URL_FORM_SECRET_KEY_PATTERN.test(normalized);
|
|
406
497
|
};
|
|
407
|
-
var
|
|
408
|
-
|
|
409
|
-
|
|
498
|
+
var splitCamelCase = (key) => key.replace(/([a-z0-9])([A-Z])/g, "$1_$2");
|
|
499
|
+
var splitKeyParts = (key) => splitCamelCase(key).toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
500
|
+
var NON_SECRET_KEY_SUFFIXES = /* @__PURE__ */ new Set([
|
|
501
|
+
"count",
|
|
502
|
+
"limit",
|
|
503
|
+
"timeout",
|
|
504
|
+
"expired",
|
|
505
|
+
"expires",
|
|
506
|
+
"expiry",
|
|
507
|
+
"at",
|
|
508
|
+
"valid",
|
|
509
|
+
"url",
|
|
510
|
+
"uri",
|
|
511
|
+
"error",
|
|
512
|
+
"type",
|
|
513
|
+
"id",
|
|
514
|
+
"ids",
|
|
515
|
+
"name"
|
|
516
|
+
]);
|
|
517
|
+
var NON_SECRET_FIELD_KEYS = /* @__PURE__ */ new Set([
|
|
518
|
+
"page_token",
|
|
519
|
+
"next_page_token",
|
|
520
|
+
"prev_page_token",
|
|
521
|
+
"previous_page_token",
|
|
522
|
+
"next_token",
|
|
523
|
+
"continuation_token"
|
|
524
|
+
]);
|
|
525
|
+
var SECRET_ID_QUALIFIERS = /* @__PURE__ */ new Set(["session", "sess", "secret"]);
|
|
526
|
+
var isSecretFieldName = (key) => {
|
|
527
|
+
let parts = splitKeyParts(key);
|
|
528
|
+
if (parts.length === 0) return false;
|
|
529
|
+
let normalized = parts.join("_");
|
|
530
|
+
if (NON_SECRET_FIELD_KEYS.has(normalized)) return false;
|
|
531
|
+
let last = parts[parts.length - 1] ?? "";
|
|
532
|
+
if (parts.length > 1 && NON_SECRET_KEY_SUFFIXES.has(last)) {
|
|
533
|
+
return (last === "id" || last === "ids") && SECRET_ID_QUALIFIERS.has(parts[parts.length - 2] ?? "");
|
|
534
|
+
}
|
|
535
|
+
return isSecretKeyName(key) || isSecretKeyName(normalized) || parts.includes("session");
|
|
536
|
+
};
|
|
537
|
+
var AUTH_CONFIG_CREDENTIAL_SUFFIXES = /* @__PURE__ */ new Set(["key", "keys", "hash"]);
|
|
538
|
+
var HEADER_NAME_VALUE_PATTERN = /^[A-Za-z]+(?:-[A-Za-z]+)*$/;
|
|
539
|
+
var isAuthConfigSecretValue = (secret, path) => {
|
|
540
|
+
let segment = path.split(".").reverse().find((part) => !/^\d+$/.test(part));
|
|
541
|
+
if (!segment) return false;
|
|
542
|
+
let parts = splitKeyParts(segment);
|
|
543
|
+
let last = parts[parts.length - 1] ?? "";
|
|
544
|
+
if (last === "header" && HEADER_NAME_VALUE_PATTERN.test(secret)) return false;
|
|
545
|
+
return isSecretFieldName(segment) || AUTH_CONFIG_CREDENTIAL_SUFFIXES.has(last);
|
|
410
546
|
};
|
|
411
|
-
var
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
547
|
+
var KNOWN_SECRET_VALUE_PATTERNS = [
|
|
548
|
+
// JSON Web Tokens (header.payload.signature)
|
|
549
|
+
/\beyJ[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}\.[A-Za-z0-9_-]{4,}\b/g,
|
|
550
|
+
// AWS access key IDs
|
|
551
|
+
/\b(?:AKIA|ASIA|AGPA|AIDA|ANPA|ANVA|AROA|APKA|ASCA)[A-Z0-9]{16}\b/g,
|
|
552
|
+
// GitHub tokens (PAT / OAuth / server-to-server / user-to-server / refresh)
|
|
553
|
+
/\bgh[pousr]_[A-Za-z0-9]{30,}\b/g,
|
|
554
|
+
// Slack tokens
|
|
555
|
+
/\bxox[abprs]-[A-Za-z0-9-]{10,}\b/g,
|
|
556
|
+
// Stripe secret / public / restricted keys
|
|
557
|
+
/\b(?:sk|rk|pk)_(?:test|live)_[A-Za-z0-9]{16,}\b/g,
|
|
558
|
+
// OpenAI API keys
|
|
559
|
+
/\bsk-(?:proj-)?[A-Za-z0-9_-]{20,}\b/g,
|
|
560
|
+
// Anthropic API keys
|
|
561
|
+
/\bsk-ant-[A-Za-z0-9_-]{20,}\b/g,
|
|
562
|
+
// Google API keys
|
|
563
|
+
/\bAIza[A-Za-z0-9_-]{35}\b/g,
|
|
564
|
+
// SendGrid API keys
|
|
565
|
+
/\bSG\.[A-Za-z0-9_-]{20,}\.[A-Za-z0-9_-]{20,}\b/g,
|
|
566
|
+
// Twilio API keys
|
|
567
|
+
/\bSK[0-9a-fA-F]{32}\b/g,
|
|
568
|
+
// PEM-encoded private keys (multi-line)
|
|
569
|
+
/-----BEGIN[A-Z ]*PRIVATE KEY-----[\s\S]*?-----END[A-Z ]*PRIVATE KEY-----/g,
|
|
570
|
+
// SSH private keys (OpenSSH format)
|
|
571
|
+
/-----BEGIN OPENSSH PRIVATE KEY-----[\s\S]*?-----END OPENSSH PRIVATE KEY-----/g
|
|
572
|
+
];
|
|
573
|
+
var HTTP_AUTH_SCHEME_PATTERN = /\b(bearer|basic|digest|token|negotiate|apikey)\s+([A-Za-z0-9_\-.~+/=]{4,})/gi;
|
|
574
|
+
var GENERIC_KEY_VALUE_PATTERN = /(?<![A-Za-z0-9])([A-Za-z0-9][A-Za-z0-9_\-.]*)(\s*=\s*)([^&#\s;]+)/g;
|
|
575
|
+
var GENERIC_JSON_KEY_VALUE_PATTERN = /"([^"\\]*(?:\\.[^"\\]*)*)"(\s*:\s*)"([^"\\]*(?:\\.[^"\\]*)*)"/g;
|
|
576
|
+
var SAFE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
577
|
+
"accept",
|
|
578
|
+
"accept-encoding",
|
|
579
|
+
"accept-language",
|
|
580
|
+
"cache-control",
|
|
581
|
+
"connection",
|
|
582
|
+
"content-encoding",
|
|
583
|
+
"content-language",
|
|
584
|
+
"content-length",
|
|
585
|
+
"content-type",
|
|
586
|
+
"date",
|
|
587
|
+
"etag",
|
|
588
|
+
"expires",
|
|
589
|
+
"if-modified-since",
|
|
590
|
+
"if-none-match",
|
|
591
|
+
"keep-alive",
|
|
592
|
+
"last-modified",
|
|
593
|
+
"location",
|
|
594
|
+
"origin",
|
|
595
|
+
"pragma",
|
|
596
|
+
"referer",
|
|
597
|
+
"referrer-policy",
|
|
598
|
+
"request-id",
|
|
599
|
+
"retry-after",
|
|
600
|
+
"server",
|
|
601
|
+
"transfer-encoding",
|
|
602
|
+
"user-agent",
|
|
603
|
+
"vary",
|
|
604
|
+
"via",
|
|
605
|
+
"x-correlation-id",
|
|
606
|
+
"x-powered-by",
|
|
607
|
+
"x-request-id",
|
|
608
|
+
"x-slates-provider",
|
|
609
|
+
"x-trace-id"
|
|
610
|
+
]);
|
|
611
|
+
var SAFE_HEADER_PREFIXES = ["ratelimit-", "x-ratelimit-"];
|
|
612
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
613
|
+
var isObjectLike = (value) => typeof value === "object" && value !== null;
|
|
614
|
+
var normalizeContentType = (value) => value?.split(";")[0]?.trim().toLowerCase() || void 0;
|
|
615
|
+
var isTextContentType = (contentType) => !contentType || /(^text\/)|json|xml|html|javascript|graphql|x-www-form-urlencoded|svg/.test(contentType);
|
|
616
|
+
var redactKnownSecretValues = (text) => {
|
|
617
|
+
let result = text;
|
|
618
|
+
for (let pattern of KNOWN_SECRET_VALUE_PATTERNS) {
|
|
619
|
+
result = result.replace(pattern, REDACTED_VALUE);
|
|
620
|
+
}
|
|
621
|
+
return result;
|
|
416
622
|
};
|
|
417
|
-
var
|
|
418
|
-
|
|
419
|
-
return
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
});
|
|
623
|
+
var isSafeHeaderName = (name) => {
|
|
624
|
+
let normalized = name.toLowerCase();
|
|
625
|
+
if (isSecretKeyName(normalized)) return false;
|
|
626
|
+
if (SAFE_HEADER_NAMES.has(normalized)) return true;
|
|
627
|
+
return SAFE_HEADER_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
423
628
|
};
|
|
424
|
-
var
|
|
425
|
-
if (
|
|
629
|
+
var truncateText = (text) => {
|
|
630
|
+
if (text.length <= TRACE_TEXT_LIMIT) {
|
|
631
|
+
return { text, truncated: false };
|
|
632
|
+
}
|
|
426
633
|
return {
|
|
427
|
-
...
|
|
428
|
-
|
|
429
|
-
provider: cleanRecord({
|
|
430
|
-
...base.provider ?? {},
|
|
431
|
-
...override.provider ?? {}
|
|
432
|
-
}),
|
|
433
|
-
upstream: cleanRecord({
|
|
434
|
-
...base.upstream ?? {},
|
|
435
|
-
...override.upstream ?? {}
|
|
436
|
-
}),
|
|
437
|
-
baggage: mergeRecords(base.baggage, override.baggage),
|
|
438
|
-
issues: override.issues ?? base.issues,
|
|
439
|
-
requestTraces: override.requestTraces ?? base.requestTraces
|
|
634
|
+
text: `${text.slice(0, TRACE_TEXT_LIMIT)}...[truncated]`,
|
|
635
|
+
truncated: true
|
|
440
636
|
};
|
|
441
637
|
};
|
|
442
|
-
var
|
|
638
|
+
var sanitizeFreeText = (text, redactor) => {
|
|
639
|
+
if (!text) return text;
|
|
640
|
+
let result = redactor ? redactor.redact(text, isAuthConfigSecretValue) : text;
|
|
641
|
+
result = result.replace(
|
|
642
|
+
HTTP_AUTH_SCHEME_PATTERN,
|
|
643
|
+
(_match, scheme) => `${scheme} ${REDACTED_VALUE}`
|
|
644
|
+
);
|
|
645
|
+
result = redactKnownSecretValues(result);
|
|
646
|
+
result = result.replace(
|
|
647
|
+
GENERIC_KEY_VALUE_PATTERN,
|
|
648
|
+
(match, key, equals, _value) => isUrlFormSecretKeyName(key) ? `${key}${equals}${REDACTED_VALUE}` : match
|
|
649
|
+
);
|
|
650
|
+
result = result.replace(
|
|
651
|
+
GENERIC_JSON_KEY_VALUE_PATTERN,
|
|
652
|
+
(match, key, colon, _value) => isSecretKeyName(key) ? `"${key}"${colon}"${REDACTED_VALUE}"` : match
|
|
653
|
+
);
|
|
654
|
+
return result;
|
|
655
|
+
};
|
|
656
|
+
var PROSE_SAFE_AUTH_SCHEME_PATTERN = /\b(bearer|basic|digest|token|negotiate|apikey)(\s+)([A-Za-z0-9_\-.~+/=]{8,})/gi;
|
|
657
|
+
var looksLikeCredential = (value) => {
|
|
658
|
+
if (/^[A-Za-z][A-Za-z0-9_\-.]*=/.test(value)) return false;
|
|
659
|
+
return /[0-9_\-.~+/=]/.test(value) || /[a-z]/.test(value) && /[A-Z]/.test(value.slice(1));
|
|
660
|
+
};
|
|
661
|
+
var CREDENTIAL_HEADER_VALUE_PATTERN = /\b(proxy-authorization|authorization|x-api-key|api[-_]?key|set-cookie|cookie)(\s*[:=]\s*)(?:(["'])((?:\\.|(?!\3)[^\\\r\n])*)|([^\r\n&]*))/gi;
|
|
662
|
+
var AUTH_SCHEME_WORD_PATTERN = /^(?:bearer|basic|digest|token|negotiate|apikey)$/i;
|
|
663
|
+
var COOKIE_HEADER_NAME_PATTERN = /^(?:set-)?cookie$/i;
|
|
664
|
+
var AUTHORIZATION_HEADER_NAME_PATTERN = /^(?:proxy-)?authorization$/i;
|
|
665
|
+
var COOKIE_PAIRS_PATTERN = /^[^\s;=&"',]+=[^\s;&"',]*(?:;\s*[^\s;=&"',]+=[^\s;&"',]*)*/;
|
|
666
|
+
var HEADER_TOKEN_PATTERN = /^[^\s&"',;]+/;
|
|
667
|
+
var HEADER_SCHEME_PATTERN = /^([A-Za-z][\w-]*)(\s+)([\s\S]*)$/;
|
|
668
|
+
var HEADER_AUTH_PARAMS_PATTERN = /^[A-Za-z][\w-]*\s*=/;
|
|
669
|
+
var redactCredentialHeaderValue = (name, value) => {
|
|
670
|
+
if (COOKIE_HEADER_NAME_PATTERN.test(name)) {
|
|
671
|
+
let pairs = COOKIE_PAIRS_PATTERN.exec(value)?.[0];
|
|
672
|
+
if (pairs) return `${REDACTED_VALUE}${value.slice(pairs.length)}`;
|
|
673
|
+
}
|
|
674
|
+
let scheme = HEADER_SCHEME_PATTERN.exec(value);
|
|
675
|
+
if (scheme) {
|
|
676
|
+
let [, word = "", space = "", rest = ""] = scheme;
|
|
677
|
+
let schemePrefix = `${word}${space}`;
|
|
678
|
+
if (AUTHORIZATION_HEADER_NAME_PATTERN.test(name) && HEADER_AUTH_PARAMS_PATTERN.test(rest)) {
|
|
679
|
+
return `${schemePrefix}${REDACTED_VALUE}`;
|
|
680
|
+
}
|
|
681
|
+
let credential = HEADER_TOKEN_PATTERN.exec(rest)?.[0];
|
|
682
|
+
if (credential === REDACTED_VALUE) return value;
|
|
683
|
+
if (credential && (AUTH_SCHEME_WORD_PATTERN.test(word) || looksLikeCredential(credential))) {
|
|
684
|
+
return `${schemePrefix}${REDACTED_VALUE}${rest.slice(credential.length)}`;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
let token = HEADER_TOKEN_PATTERN.exec(value)?.[0];
|
|
688
|
+
if (token && token !== REDACTED_VALUE && looksLikeCredential(token)) {
|
|
689
|
+
return `${REDACTED_VALUE}${value.slice(token.length)}`;
|
|
690
|
+
}
|
|
691
|
+
return value;
|
|
692
|
+
};
|
|
693
|
+
var GENERIC_SINGLE_QUOTED_KEY_VALUE_PATTERN = /'([^'\\]*(?:\\.[^'\\]*)*)'(\s*:\s*)'([^'\\]*(?:\\.[^'\\]*)*)'/g;
|
|
694
|
+
var PROSE_KEY_VALUE_PATTERN = /(?<![A-Za-z0-9_\-.])([A-Za-z][A-Za-z0-9_\-.]*)([ \t]*:[ \t]*)(["'`]?)([^\s"'`,;&)\]}]+)/g;
|
|
695
|
+
var PROSE_STATE_WORD_PATTERN = /^(?:required|missing|invalid|expired|revoked|empty|blank|null|undefined|none|not|is|was|has|must|should|cannot|incorrect|wrong|malformed|provided|present|absent|unknown|denied|rejected|unauthorized|forbidden|true|false|too|the|a|an)$/i;
|
|
696
|
+
var PROSE_ERROR_CODE_PATTERN = /^[a-z]+(?:_[a-z]+)+$/;
|
|
697
|
+
var redactProseKeyValue = (match, key, separator, quote, value) => {
|
|
698
|
+
if (AUTHORIZATION_HEADER_NAME_PATTERN.test(key) || COOKIE_HEADER_NAME_PATTERN.test(key)) {
|
|
699
|
+
return match;
|
|
700
|
+
}
|
|
701
|
+
if (value.startsWith("[") || value.startsWith(AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX)) {
|
|
702
|
+
return match;
|
|
703
|
+
}
|
|
704
|
+
if (!isSecretFieldName(key)) return match;
|
|
705
|
+
let credential = value.replace(/[.!?:]+$/, "");
|
|
706
|
+
if (!credential || PROSE_ERROR_CODE_PATTERN.test(credential)) return match;
|
|
707
|
+
let compoundKey = splitKeyParts(key).length > 1;
|
|
708
|
+
if (looksLikeCredential(credential) || compoundKey && !PROSE_STATE_WORD_PATTERN.test(credential)) {
|
|
709
|
+
return `${key}${separator}${quote}${REDACTED_VALUE}${value.slice(credential.length)}`;
|
|
710
|
+
}
|
|
711
|
+
return match;
|
|
712
|
+
};
|
|
713
|
+
var sanitizeSecretValuesInText = (text) => {
|
|
714
|
+
if (!text) return text;
|
|
715
|
+
let result = text.replace(
|
|
716
|
+
PROSE_SAFE_AUTH_SCHEME_PATTERN,
|
|
717
|
+
(match, scheme, space, value) => looksLikeCredential(value) ? `${scheme}${space}${REDACTED_VALUE}` : match
|
|
718
|
+
);
|
|
719
|
+
result = result.replace(
|
|
720
|
+
CREDENTIAL_HEADER_VALUE_PATTERN,
|
|
721
|
+
(_match, name, separator, quote, quotedValue, plainValue) => `${name}${separator}${quote ?? ""}${redactCredentialHeaderValue(
|
|
722
|
+
name,
|
|
723
|
+
quote ? quotedValue ?? "" : plainValue ?? ""
|
|
724
|
+
)}`
|
|
725
|
+
);
|
|
726
|
+
result = redactKnownSecretValues(result);
|
|
727
|
+
result = result.replace(
|
|
728
|
+
GENERIC_KEY_VALUE_PATTERN,
|
|
729
|
+
(match, key, equals, value, offset, whole) => {
|
|
730
|
+
if (!isSecretKeyName(key)) return match;
|
|
731
|
+
let rest = whole.slice(offset + match.length);
|
|
732
|
+
if (AUTH_SCHEME_WORD_PATTERN.test(value) && /^\s+\[redacted\]/.test(rest)) return match;
|
|
733
|
+
return `${key}${equals}${REDACTED_VALUE}`;
|
|
734
|
+
}
|
|
735
|
+
);
|
|
736
|
+
result = result.replace(PROSE_KEY_VALUE_PATTERN, redactProseKeyValue);
|
|
737
|
+
result = result.replace(
|
|
738
|
+
GENERIC_SINGLE_QUOTED_KEY_VALUE_PATTERN,
|
|
739
|
+
(match, key, colon, _value) => isSecretKeyName(key) ? `'${key}'${colon}'${REDACTED_VALUE}'` : match
|
|
740
|
+
);
|
|
741
|
+
return result.replace(
|
|
742
|
+
GENERIC_JSON_KEY_VALUE_PATTERN,
|
|
743
|
+
(match, key, colon, _value) => isSecretKeyName(key) ? `"${key}"${colon}"${REDACTED_VALUE}"` : match
|
|
744
|
+
);
|
|
745
|
+
};
|
|
746
|
+
var sanitizeScalar = (value, redactor) => truncateText(sanitizeFreeText(value, redactor));
|
|
747
|
+
var redactStructuredValue = (value, depth = 0, redactor) => {
|
|
443
748
|
if (value == null) return value;
|
|
444
|
-
if (depth >=
|
|
445
|
-
if (typeof value === "string") {
|
|
446
|
-
return value
|
|
447
|
-
}
|
|
448
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
449
|
-
return value;
|
|
749
|
+
if (depth >= STRUCTURED_DEPTH_LIMIT) return "[truncated]";
|
|
750
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
751
|
+
return typeof value === "string" ? sanitizeFreeText(value, redactor) : value;
|
|
450
752
|
}
|
|
451
753
|
if (Array.isArray(value)) {
|
|
452
|
-
return value.slice(0,
|
|
754
|
+
return value.slice(0, STRUCTURED_ENTRY_LIMIT).map((entry) => redactStructuredValue(entry, depth + 1, redactor));
|
|
453
755
|
}
|
|
454
756
|
if (isRecord(value)) {
|
|
455
757
|
return Object.fromEntries(
|
|
456
|
-
Object.entries(value).slice(0,
|
|
758
|
+
Object.entries(value).slice(0, STRUCTURED_ENTRY_LIMIT).map(([key, entry]) => [
|
|
759
|
+
key,
|
|
760
|
+
isSecretKeyName(key) ? REDACTED_VALUE : redactStructuredValue(entry, depth + 1, redactor)
|
|
761
|
+
])
|
|
457
762
|
);
|
|
458
763
|
}
|
|
459
764
|
return String(value);
|
|
460
765
|
};
|
|
461
|
-
var
|
|
462
|
-
let
|
|
766
|
+
var maybeParseJson = (text, contentType) => {
|
|
767
|
+
let trimmed = text.trim();
|
|
768
|
+
if (!trimmed) return null;
|
|
769
|
+
if (!contentType?.includes("json") && !/^[[{]/.test(trimmed)) {
|
|
770
|
+
return null;
|
|
771
|
+
}
|
|
772
|
+
try {
|
|
773
|
+
return JSON.parse(trimmed);
|
|
774
|
+
} catch {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
};
|
|
778
|
+
var sanitizeTextBody = (text, contentType, redactor) => {
|
|
779
|
+
if (!text) return void 0;
|
|
780
|
+
let normalizedContentType = normalizeContentType(contentType);
|
|
781
|
+
let parsedJson = maybeParseJson(text, normalizedContentType);
|
|
782
|
+
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson, 0, redactor)) : sanitizeFreeText(text, redactor);
|
|
783
|
+
let { text: truncatedText, truncated } = truncateText(normalizedText);
|
|
463
784
|
return {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
retryable: normalizeRetryable(code, input.retryable),
|
|
468
|
-
status: normalizeStatus(code, input.status ?? input.upstream?.status),
|
|
469
|
-
issues: input.issues,
|
|
470
|
-
provider: cleanRecord(input.provider),
|
|
471
|
-
upstream: cleanRecord({
|
|
472
|
-
...input.upstream,
|
|
473
|
-
status: input.upstream?.status ?? input.status
|
|
474
|
-
}),
|
|
475
|
-
baggage: cleanRecord(input.baggage),
|
|
476
|
-
requestTraces: input.requestTraces
|
|
785
|
+
...normalizedContentType ? { contentType: normalizedContentType } : {},
|
|
786
|
+
text: truncatedText,
|
|
787
|
+
...truncated ? { truncated: true } : {}
|
|
477
788
|
};
|
|
478
789
|
};
|
|
479
|
-
var
|
|
480
|
-
if (
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (!isRecord(value)) return void 0;
|
|
487
|
-
return value[key];
|
|
790
|
+
var isBinaryLike = (value) => {
|
|
791
|
+
if (typeof Buffer !== "undefined" && Buffer.isBuffer(value)) return true;
|
|
792
|
+
if (value instanceof ArrayBuffer) return true;
|
|
793
|
+
if (ArrayBuffer.isView(value)) return true;
|
|
794
|
+
if (typeof Blob !== "undefined" && value instanceof Blob) return true;
|
|
795
|
+
if (typeof FormData !== "undefined" && value instanceof FormData) return true;
|
|
796
|
+
return false;
|
|
488
797
|
};
|
|
489
|
-
var
|
|
490
|
-
|
|
491
|
-
if (
|
|
492
|
-
|
|
493
|
-
if (typeof message === "string" && message.trim()) return message;
|
|
494
|
-
let description = getResponseField(value, "description");
|
|
495
|
-
if (typeof description === "string" && description.trim()) return description;
|
|
496
|
-
let error = getResponseField(value, "error");
|
|
497
|
-
if (typeof error === "string" && error.trim()) return error;
|
|
498
|
-
if (isRecord(error)) {
|
|
499
|
-
let nested = getNestedMessage(error);
|
|
500
|
-
if (nested) return nested;
|
|
798
|
+
var serializeTextBody = (value, contentType, redactor) => {
|
|
799
|
+
let normalizedContentType = normalizeContentType(contentType);
|
|
800
|
+
if (value == null || isBinaryLike(value) || !isTextContentType(normalizedContentType)) {
|
|
801
|
+
return void 0;
|
|
501
802
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
return errorDescription;
|
|
803
|
+
if (typeof value === "string") {
|
|
804
|
+
return sanitizeTextBody(value, normalizedContentType, redactor);
|
|
505
805
|
}
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
var getNestedCode = (value) => {
|
|
509
|
-
if (!isRecord(value)) return void 0;
|
|
510
|
-
let directCode = getResponseField(value, "code");
|
|
511
|
-
if (typeof directCode === "string" && directCode.trim()) return directCode;
|
|
512
|
-
let errorCode = getResponseField(value, "error_code");
|
|
513
|
-
if (typeof errorCode === "string" && errorCode.trim()) return errorCode;
|
|
514
|
-
let type = getResponseField(value, "type");
|
|
515
|
-
if (typeof type === "string" && type.trim()) return type;
|
|
516
|
-
let error = getResponseField(value, "error");
|
|
517
|
-
if (typeof error === "string" && error.trim()) return error;
|
|
518
|
-
if (isRecord(error)) return getNestedCode(error);
|
|
519
|
-
return void 0;
|
|
520
|
-
};
|
|
521
|
-
var getNestedType = (value) => {
|
|
522
|
-
if (!isRecord(value)) return void 0;
|
|
523
|
-
let type = getResponseField(value, "type");
|
|
524
|
-
if (typeof type === "string" && type.trim()) return type;
|
|
525
|
-
let error = getResponseField(value, "error");
|
|
526
|
-
if (isRecord(error)) {
|
|
527
|
-
let nestedType = getNestedType(error);
|
|
528
|
-
if (nestedType) return nestedType;
|
|
806
|
+
if (value instanceof URLSearchParams) {
|
|
807
|
+
return sanitizeTextBody(value.toString(), normalizedContentType, redactor);
|
|
529
808
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
var getHeaderValue = (headers, key) => {
|
|
533
|
-
if (!headers) return void 0;
|
|
534
|
-
if (typeof headers.get === "function") {
|
|
535
|
-
let value = headers.get(key);
|
|
536
|
-
if (typeof value === "string" && value.trim()) return value;
|
|
809
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
810
|
+
return sanitizeTextBody(String(value), normalizedContentType, redactor);
|
|
537
811
|
}
|
|
538
|
-
if (isRecord(
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (typeof first === "string") return first;
|
|
545
|
-
}
|
|
546
|
-
}
|
|
812
|
+
if (Array.isArray(value) || isRecord(value)) {
|
|
813
|
+
return sanitizeTextBody(
|
|
814
|
+
JSON.stringify(redactStructuredValue(value, 0, redactor)),
|
|
815
|
+
"application/json",
|
|
816
|
+
redactor
|
|
817
|
+
);
|
|
547
818
|
}
|
|
548
819
|
return void 0;
|
|
549
820
|
};
|
|
550
|
-
var
|
|
551
|
-
|
|
552
|
-
let url = error.config?.url;
|
|
553
|
-
if (!url) return void 0;
|
|
821
|
+
var buildUrl = (baseURL, url) => {
|
|
822
|
+
if (!url) return "";
|
|
554
823
|
if (!baseURL) return url;
|
|
555
824
|
try {
|
|
556
825
|
return new URL(url, baseURL).toString();
|
|
@@ -558,1747 +827,1897 @@ var buildRequestUrl = (error) => {
|
|
|
558
827
|
return url;
|
|
559
828
|
}
|
|
560
829
|
};
|
|
561
|
-
var
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
let status = error.response?.status;
|
|
576
|
-
let axiosCode = error.code?.toUpperCase();
|
|
577
|
-
let remoteCode = getNestedCode(data)?.toLowerCase();
|
|
578
|
-
if (axiosCode === "ECONNABORTED" || axiosCode === "ETIMEDOUT" || status === 408 || remoteCode?.includes("timeout")) {
|
|
579
|
-
return "upstream.timeout";
|
|
580
|
-
}
|
|
581
|
-
if (!error.response) {
|
|
582
|
-
return "upstream.network_error";
|
|
583
|
-
}
|
|
584
|
-
if (status === 401) return "auth.invalid";
|
|
585
|
-
if (status === 403) {
|
|
586
|
-
return remoteCode?.includes("rate") ? "upstream.rate_limited" : "permission.denied";
|
|
587
|
-
}
|
|
588
|
-
if (status === 404) return "resource.not_found";
|
|
589
|
-
if (status === 409) return "resource.conflict";
|
|
590
|
-
if (status === 422 || status === 400) return "upstream.invalid_request";
|
|
591
|
-
if (status === 429) return "upstream.rate_limited";
|
|
592
|
-
if (status === 502 || status === 503 || status === 504) return "upstream.unavailable";
|
|
593
|
-
if (status && status >= 500) return "upstream.error";
|
|
594
|
-
return "upstream.error";
|
|
595
|
-
};
|
|
596
|
-
var inferAxiosMessage = (error, data, code) => {
|
|
597
|
-
return getNestedMessage(data) ?? error.response?.statusText ?? error.message ?? getDefaultMessage(code);
|
|
598
|
-
};
|
|
599
|
-
var inferAxiosRetryable = (error, code) => {
|
|
600
|
-
let headerValue = getHeaderValue(error.response?.headers, "retry-after");
|
|
601
|
-
if (headerValue) return true;
|
|
602
|
-
return normalizeRetryable(code, void 0);
|
|
603
|
-
};
|
|
604
|
-
var isAxiosErrorLike = (error) => (0, import_axios.isAxiosError)(error);
|
|
605
|
-
var inferSlateErrorFromAxios = (error, options = {}) => {
|
|
606
|
-
let responseData = error.response ? options.extractResponseData?.(error.response) ?? error.response.data : void 0;
|
|
607
|
-
let code = inferAxiosCode(error, responseData);
|
|
608
|
-
return normalizeSlateErrorInput({
|
|
609
|
-
...getProviderDefaults(),
|
|
610
|
-
...options.defaults,
|
|
611
|
-
code: options.defaults?.code ?? code,
|
|
612
|
-
message: options.defaults?.message ?? inferAxiosMessage(error, responseData, code),
|
|
613
|
-
kind: options.defaults?.kind ?? normalizeKind(options.defaults?.code ?? code),
|
|
614
|
-
retryable: options.defaults?.retryable ?? inferAxiosRetryable(error, options.defaults?.code ?? code),
|
|
615
|
-
status: options.defaults?.status ?? error.response?.status,
|
|
616
|
-
provider: {
|
|
617
|
-
...getProviderDefaults().provider,
|
|
618
|
-
...options.defaults?.provider ?? {}
|
|
619
|
-
},
|
|
620
|
-
upstream: {
|
|
621
|
-
...options.defaults?.upstream ?? {},
|
|
622
|
-
status: error.response?.status ?? options.defaults?.upstream?.status,
|
|
623
|
-
code: getNestedCode(responseData) ?? options.defaults?.upstream?.code,
|
|
624
|
-
type: getNestedType(responseData) ?? options.defaults?.upstream?.type,
|
|
625
|
-
requestId: getHeaderValue(error.response?.headers, "x-request-id") ?? getHeaderValue(error.response?.headers, "request-id") ?? getHeaderValue(error.response?.headers, "x-correlation-id") ?? options.defaults?.upstream?.requestId,
|
|
626
|
-
method: error.config?.method?.toUpperCase() ?? options.defaults?.upstream?.method,
|
|
627
|
-
url: buildRequestUrl(error) ?? options.defaults?.upstream?.url
|
|
628
|
-
},
|
|
629
|
-
baggage: mergeRecords(options.defaults?.baggage, {
|
|
630
|
-
axiosCode: error.code,
|
|
631
|
-
response: sanitizeForBaggage(responseData)
|
|
632
|
-
})
|
|
633
|
-
});
|
|
634
|
-
};
|
|
635
|
-
|
|
636
|
-
// src/error/service.ts
|
|
637
|
-
var import_error2 = require("@lowerdeck/error");
|
|
638
|
-
var SERVICE_ERROR_DATA_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
639
|
-
"status",
|
|
640
|
-
"code",
|
|
641
|
-
"message",
|
|
642
|
-
"hint",
|
|
643
|
-
"description",
|
|
644
|
-
"reason",
|
|
645
|
-
"errors",
|
|
646
|
-
"object",
|
|
647
|
-
"ok"
|
|
648
|
-
]);
|
|
649
|
-
var isStructuredValue = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
650
|
-
var mapServiceErrorCodeByStatus = (status) => {
|
|
651
|
-
if (status === 400) return "request.bad";
|
|
652
|
-
if (status === 401) return "auth.required";
|
|
653
|
-
if (status === 402) return "payment.required";
|
|
654
|
-
if (status === 403) return "permission.denied";
|
|
655
|
-
if (status === 404) return "resource.not_found";
|
|
656
|
-
if (status === 406) return "request.not_acceptable";
|
|
657
|
-
if (status === 409) return "resource.conflict";
|
|
658
|
-
if (status === 410) return "resource.gone";
|
|
659
|
-
if (status === 412) return "request.precondition_failed";
|
|
660
|
-
if (status === 429) return "request.rate_limited";
|
|
661
|
-
if (status === 501) return "operation.not_implemented";
|
|
662
|
-
if (status === 504) return "internal.timeout";
|
|
663
|
-
if (status && status >= 500) return "internal.unexpected";
|
|
664
|
-
return DEFAULT_CODE;
|
|
665
|
-
};
|
|
666
|
-
var normalizeServiceErrorIssues = (errors) => {
|
|
667
|
-
if (!Array.isArray(errors)) return void 0;
|
|
668
|
-
let issues = errors.map((error) => {
|
|
669
|
-
if (!isRecord(error)) {
|
|
670
|
-
return {
|
|
671
|
-
message: String(error)
|
|
672
|
-
};
|
|
830
|
+
var REDACTED_ENCODED = encodeURIComponent(REDACTED_VALUE);
|
|
831
|
+
var decodeRedactedMarker = (value) => REDACTED_ENCODED === REDACTED_VALUE ? value : value.split(REDACTED_ENCODED).join(REDACTED_VALUE);
|
|
832
|
+
var redactQueryValue = (rawValue, redactor) => redactKnownSecretValues(
|
|
833
|
+
redactor ? redactor.redact(rawValue, isAuthConfigSecretValue) : rawValue
|
|
834
|
+
);
|
|
835
|
+
var redactHashFragment = (hash, redactor) => {
|
|
836
|
+
if (!hash?.includes("=")) return hash;
|
|
837
|
+
let withoutHash = hash.startsWith("#") ? hash.slice(1) : hash;
|
|
838
|
+
let redacted = withoutHash.replace(
|
|
839
|
+
/(?<![A-Za-z0-9])([A-Za-z0-9][A-Za-z0-9_\-.]*)=([^&]*)/g,
|
|
840
|
+
(match, key, rawValue) => {
|
|
841
|
+
if (isUrlFormSecretKeyName(key)) return `${key}=${REDACTED_VALUE}`;
|
|
842
|
+
let redactedValue = redactQueryValue(rawValue, redactor);
|
|
843
|
+
return redactedValue !== rawValue ? `${key}=${redactedValue}` : match;
|
|
673
844
|
}
|
|
674
|
-
let path = Array.isArray(error.path) ? error.path.map((entry) => String(entry)) : void 0;
|
|
675
|
-
return {
|
|
676
|
-
...error,
|
|
677
|
-
path,
|
|
678
|
-
code: typeof error.code === "string" ? error.code : void 0,
|
|
679
|
-
message: typeof error.message === "string" ? error.message : typeof error.hint === "string" ? error.hint : "Validation issue"
|
|
680
|
-
};
|
|
681
|
-
});
|
|
682
|
-
return issues.length > 0 ? issues : void 0;
|
|
683
|
-
};
|
|
684
|
-
var getServiceErrorBaggage = (data) => {
|
|
685
|
-
let extraEntries = Object.entries(data).filter(
|
|
686
|
-
([key]) => !SERVICE_ERROR_DATA_RESERVED_KEYS.has(key)
|
|
687
845
|
);
|
|
688
|
-
return
|
|
689
|
-
serviceError: {
|
|
690
|
-
code: data.code,
|
|
691
|
-
status: data.status,
|
|
692
|
-
hint: data.hint,
|
|
693
|
-
description: data.description,
|
|
694
|
-
reason: data.reason
|
|
695
|
-
},
|
|
696
|
-
...extraEntries.length > 0 ? {
|
|
697
|
-
serviceErrorData: sanitizeForBaggage(Object.fromEntries(extraEntries))
|
|
698
|
-
} : {}
|
|
699
|
-
});
|
|
846
|
+
return redacted ? `#${redacted}` : "";
|
|
700
847
|
};
|
|
701
|
-
var
|
|
702
|
-
var
|
|
703
|
-
var
|
|
704
|
-
if (
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
848
|
+
var isEmbeddedPathSecret = (secret, path) => secret.length >= 8 && isAuthConfigSecretValue(secret, path);
|
|
849
|
+
var redactAuthConfigSecretsInText = (text, redactor) => redactor.redactEmbedded(text, isEmbeddedPathSecret, isAuthConfigSecretValue);
|
|
850
|
+
var sanitizeUrl = (value, redactor) => {
|
|
851
|
+
if (!value) return value;
|
|
852
|
+
try {
|
|
853
|
+
let url = new URL(value);
|
|
854
|
+
if (url.username || url.password) {
|
|
855
|
+
url.username = "";
|
|
856
|
+
url.password = "";
|
|
857
|
+
}
|
|
858
|
+
if (redactor) url.pathname = redactAuthConfigSecretsInText(url.pathname, redactor);
|
|
859
|
+
for (let key of Array.from(url.searchParams.keys())) {
|
|
860
|
+
if (isUrlFormSecretKeyName(key)) {
|
|
861
|
+
url.searchParams.set(key, REDACTED_VALUE);
|
|
862
|
+
continue;
|
|
863
|
+
}
|
|
864
|
+
let rawValue = url.searchParams.get(key) ?? "";
|
|
865
|
+
let redactedValue = redactQueryValue(rawValue, redactor);
|
|
866
|
+
if (redactedValue !== rawValue) url.searchParams.set(key, redactedValue);
|
|
867
|
+
}
|
|
868
|
+
url.hash = redactHashFragment(url.hash, redactor);
|
|
869
|
+
return decodeRedactedMarker(url.toString());
|
|
870
|
+
} catch {
|
|
871
|
+
let text = redactor ? redactAuthConfigSecretsInText(value, redactor) : value;
|
|
872
|
+
return text.replace(
|
|
873
|
+
/([?&]([^=&#]+)=)([^&#]+)/g,
|
|
874
|
+
(_match, prefix, key, rawValue) => isUrlFormSecretKeyName(key) ? `${prefix}${REDACTED_VALUE}` : `${prefix}${redactKnownSecretValues(rawValue)}`
|
|
875
|
+
);
|
|
716
876
|
}
|
|
717
|
-
return null;
|
|
718
877
|
};
|
|
719
|
-
var
|
|
720
|
-
|
|
721
|
-
if (
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
kind: defaults.kind,
|
|
726
|
-
retryable: defaults.retryable,
|
|
727
|
-
status: defaults.status,
|
|
728
|
-
provider: defaults.provider,
|
|
729
|
-
upstream: defaults.upstream,
|
|
730
|
-
baggage: defaults.baggage
|
|
731
|
-
};
|
|
878
|
+
var flattenHeaderValue = (value) => {
|
|
879
|
+
if (typeof value === "string") return value;
|
|
880
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
881
|
+
if (Array.isArray(value)) {
|
|
882
|
+
let normalized = value.map((entry) => flattenHeaderValue(entry)).filter((entry) => typeof entry === "string" && entry.length > 0);
|
|
883
|
+
return normalized.length > 0 ? normalized.join(", ") : void 0;
|
|
732
884
|
}
|
|
733
|
-
|
|
734
|
-
return {
|
|
735
|
-
code,
|
|
736
|
-
message: defaults.message ?? data.message,
|
|
737
|
-
kind: defaults.kind ?? normalizeKind(code),
|
|
738
|
-
retryable: defaults.retryable ?? normalizeRetryable(code),
|
|
739
|
-
status: defaults.status ?? data.status,
|
|
740
|
-
issues: defaults.issues ?? normalizeServiceErrorIssues(data.errors),
|
|
741
|
-
provider: defaults.provider,
|
|
742
|
-
upstream: defaults.upstream,
|
|
743
|
-
baggage: cleanRecord({
|
|
744
|
-
...defaults.baggage ?? {},
|
|
745
|
-
...getServiceErrorBaggage(data)
|
|
746
|
-
})
|
|
747
|
-
};
|
|
885
|
+
return void 0;
|
|
748
886
|
};
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
this.cause = input.cause;
|
|
760
|
-
}
|
|
761
|
-
get code() {
|
|
762
|
-
return this.data.code;
|
|
763
|
-
}
|
|
764
|
-
get kind() {
|
|
765
|
-
return this.data.kind;
|
|
887
|
+
var headerEntries = (headers) => {
|
|
888
|
+
if (!headers) return [];
|
|
889
|
+
if (typeof headers.toJSON === "function") {
|
|
890
|
+
let json = headers.toJSON();
|
|
891
|
+
if (isRecord(json)) {
|
|
892
|
+
return Object.entries(json).map(([key, value]) => {
|
|
893
|
+
let flattened = flattenHeaderValue(value);
|
|
894
|
+
return flattened ? [key, flattened] : null;
|
|
895
|
+
}).filter((entry) => entry !== null);
|
|
896
|
+
}
|
|
766
897
|
}
|
|
767
|
-
|
|
768
|
-
return
|
|
898
|
+
if (typeof headers.entries === "function") {
|
|
899
|
+
return Array.from(
|
|
900
|
+
headers.entries()
|
|
901
|
+
).map(([key, value]) => [key, value]);
|
|
769
902
|
}
|
|
770
|
-
|
|
771
|
-
return
|
|
903
|
+
if (isRecord(headers)) {
|
|
904
|
+
return Object.entries(headers).map(([key, value]) => {
|
|
905
|
+
let flattened = flattenHeaderValue(value);
|
|
906
|
+
return flattened ? [key, flattened] : null;
|
|
907
|
+
}).filter((entry) => entry !== null);
|
|
772
908
|
}
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
909
|
+
return [];
|
|
910
|
+
};
|
|
911
|
+
var sanitizeHeaders = (headers, redactor) => {
|
|
912
|
+
let entries = headerEntries(headers).map(
|
|
913
|
+
([key, value]) => [key.toLowerCase(), sanitizeScalar(value, redactor).text]
|
|
914
|
+
).filter(([key]) => isSafeHeaderName(key));
|
|
915
|
+
if (entries.length === 0) return void 0;
|
|
916
|
+
return Object.fromEntries(entries);
|
|
917
|
+
};
|
|
918
|
+
var getContentType = (headers) => headerEntries(headers).find(([key]) => key.toLowerCase() === "content-type")?.[1];
|
|
919
|
+
var takeTraceDraft = (config2) => {
|
|
920
|
+
if (!config2) return void 0;
|
|
921
|
+
let draft = config2.__slatesHttpTraceDraft ?? (isObjectLike(config2) ? traceDraftsByConfig.get(config2) : void 0) ?? (isObjectLike(config2.headers) ? traceDraftsByHeaders.get(config2.headers) : void 0);
|
|
922
|
+
if (!draft) return void 0;
|
|
923
|
+
return draft;
|
|
924
|
+
};
|
|
925
|
+
var clearTraceDraft = (config2, draft) => {
|
|
926
|
+
if (!config2) return;
|
|
927
|
+
if (config2.__slatesHttpTraceDraft === draft) {
|
|
928
|
+
config2.__slatesHttpTraceDraft = void 0;
|
|
777
929
|
}
|
|
778
|
-
|
|
779
|
-
|
|
930
|
+
if (isObjectLike(config2)) {
|
|
931
|
+
traceDraftsByConfig.delete(config2);
|
|
780
932
|
}
|
|
781
|
-
|
|
782
|
-
|
|
933
|
+
if (isObjectLike(config2.headers)) {
|
|
934
|
+
traceDraftsByHeaders.delete(config2.headers);
|
|
783
935
|
}
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
upstream: defaults.upstream,
|
|
799
|
-
baggage: mergeRecords(defaults.baggage, {
|
|
800
|
-
originalName: error.name
|
|
801
|
-
}),
|
|
802
|
-
cause: error
|
|
803
|
-
});
|
|
936
|
+
};
|
|
937
|
+
var attachHttpTraceDraft = (config2, context) => {
|
|
938
|
+
let traceAwareConfig = config2;
|
|
939
|
+
let contentType = getContentType(config2.headers);
|
|
940
|
+
let redactor = new AuthConfigSecretRedactor(context._getAuthConfigForRedaction());
|
|
941
|
+
traceAwareConfig.__slatesHttpTraceDraft = {
|
|
942
|
+
context,
|
|
943
|
+
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
944
|
+
startedAtMs: Date.now(),
|
|
945
|
+
request: {
|
|
946
|
+
method: (config2.method ?? "GET").toUpperCase(),
|
|
947
|
+
url: sanitizeUrl(buildUrl(config2.baseURL, config2.url), redactor),
|
|
948
|
+
...sanitizeHeaders(config2.headers, redactor) ? { headers: sanitizeHeaders(config2.headers, redactor) } : {},
|
|
949
|
+
...serializeTextBody(config2.data, contentType, redactor) ? { body: serializeTextBody(config2.data, contentType, redactor) } : {}
|
|
804
950
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
kind: defaults.kind,
|
|
809
|
-
retryable: defaults.retryable,
|
|
810
|
-
status: defaults.status,
|
|
811
|
-
issues: defaults.issues,
|
|
812
|
-
provider: defaults.provider,
|
|
813
|
-
upstream: defaults.upstream,
|
|
814
|
-
baggage: mergeRecords(defaults.baggage, {
|
|
815
|
-
originalValue: sanitizeForBaggage(error)
|
|
816
|
-
})
|
|
817
|
-
});
|
|
951
|
+
};
|
|
952
|
+
if (isObjectLike(traceAwareConfig)) {
|
|
953
|
+
traceDraftsByConfig.set(traceAwareConfig, traceAwareConfig.__slatesHttpTraceDraft);
|
|
818
954
|
}
|
|
819
|
-
|
|
820
|
-
|
|
955
|
+
if (isObjectLike(traceAwareConfig.headers)) {
|
|
956
|
+
traceDraftsByHeaders.set(
|
|
957
|
+
traceAwareConfig.headers,
|
|
958
|
+
traceAwareConfig.__slatesHttpTraceDraft
|
|
959
|
+
);
|
|
821
960
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
961
|
+
return config2;
|
|
962
|
+
};
|
|
963
|
+
var recordHttpTraceFromResponse = (response) => {
|
|
964
|
+
let config2 = response.config;
|
|
965
|
+
let draft = takeTraceDraft(config2);
|
|
966
|
+
if (!draft) return response;
|
|
967
|
+
clearTraceDraft(config2, draft);
|
|
968
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
969
|
+
let contentType = getContentType(response.headers);
|
|
970
|
+
draft.context.recordHttpTrace({
|
|
971
|
+
startedAt: draft.startedAt,
|
|
972
|
+
durationMs: Math.max(Date.now() - draft.startedAtMs, 0),
|
|
973
|
+
request: draft.request,
|
|
974
|
+
response: {
|
|
975
|
+
status: response.status,
|
|
976
|
+
...response.statusText ? { statusText: response.statusText } : {},
|
|
977
|
+
...sanitizeHeaders(response.headers, redactor) ? { headers: sanitizeHeaders(response.headers, redactor) } : {},
|
|
978
|
+
...serializeTextBody(response.data, contentType, redactor) ? { body: serializeTextBody(response.data, contentType, redactor) } : {}
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
return response;
|
|
982
|
+
};
|
|
983
|
+
var recordHttpTraceFromError = (error) => {
|
|
984
|
+
let config2 = error.config;
|
|
985
|
+
let draft = takeTraceDraft(config2);
|
|
986
|
+
if (!draft) return;
|
|
987
|
+
clearTraceDraft(config2, draft);
|
|
988
|
+
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
989
|
+
let responseContentType = getContentType(error.response?.headers);
|
|
990
|
+
draft.context.recordHttpTrace({
|
|
991
|
+
startedAt: draft.startedAt,
|
|
992
|
+
durationMs: Math.max(Date.now() - draft.startedAtMs, 0),
|
|
993
|
+
request: draft.request,
|
|
994
|
+
...error.response ? {
|
|
995
|
+
response: {
|
|
996
|
+
status: error.response.status,
|
|
997
|
+
...error.response.statusText ? { statusText: error.response.statusText } : {},
|
|
998
|
+
...sanitizeHeaders(error.response.headers, redactor) ? { headers: sanitizeHeaders(error.response.headers, redactor) } : {},
|
|
999
|
+
...serializeTextBody(error.response.data, responseContentType, redactor) ? { body: serializeTextBody(error.response.data, responseContentType, redactor) } : {}
|
|
1000
|
+
}
|
|
1001
|
+
} : {},
|
|
1002
|
+
error: {
|
|
1003
|
+
...error.code ? { code: error.code } : {},
|
|
1004
|
+
message: error.message
|
|
1005
|
+
}
|
|
1006
|
+
});
|
|
1007
|
+
};
|
|
1008
|
+
|
|
1009
|
+
// src/context/hook.ts
|
|
1010
|
+
var import_async_hooks = require("async_hooks");
|
|
1011
|
+
var slateContextStorageKey = /* @__PURE__ */ Symbol.for("slates.provider.context.asyncLocalStorage");
|
|
1012
|
+
var globalWithSlateContext = globalThis;
|
|
1013
|
+
var asyncLocalStorage = globalWithSlateContext[slateContextStorageKey] ?? new import_async_hooks.AsyncLocalStorage();
|
|
1014
|
+
globalWithSlateContext[slateContextStorageKey] = asyncLocalStorage;
|
|
1015
|
+
var runWithContext = (context, fn) => {
|
|
1016
|
+
return asyncLocalStorage.run(context, fn);
|
|
1017
|
+
};
|
|
1018
|
+
var getCurrentContext = () => {
|
|
1019
|
+
let context = asyncLocalStorage.getStore();
|
|
1020
|
+
if (!context) {
|
|
1021
|
+
throw new Error("No Slate context is available");
|
|
831
1022
|
}
|
|
1023
|
+
return context;
|
|
1024
|
+
};
|
|
1025
|
+
|
|
1026
|
+
// src/error/defaults.ts
|
|
1027
|
+
var DEFAULT_CODE = "internal.unexpected";
|
|
1028
|
+
var DEFAULT_MESSAGES = {
|
|
1029
|
+
"declaration.invalid_definition": "The slate definition is invalid.",
|
|
1030
|
+
"context.missing": "No Slate context is available.",
|
|
1031
|
+
"input.invalid": "The provided input is invalid.",
|
|
1032
|
+
"request.bad": "The request is invalid.",
|
|
1033
|
+
"request.invalid_version": "The requested version is invalid.",
|
|
1034
|
+
"request.precondition_failed": "The request precondition failed.",
|
|
1035
|
+
"request.not_acceptable": "The request is not acceptable.",
|
|
1036
|
+
"request.rate_limited": "Too many requests were made in a short period of time.",
|
|
1037
|
+
"config.invalid": "The provided configuration is invalid.",
|
|
1038
|
+
"auth.required": "Authentication is required.",
|
|
1039
|
+
"auth.invalid": "Authentication failed.",
|
|
1040
|
+
"auth.expired": "Authentication has expired.",
|
|
1041
|
+
"permission.denied": "Permission was denied.",
|
|
1042
|
+
"resource.not_found": "The requested resource was not found.",
|
|
1043
|
+
"resource.conflict": "The requested resource is in conflict.",
|
|
1044
|
+
"resource.gone": "The requested resource is no longer available.",
|
|
1045
|
+
"payment.required": "Payment is required to continue.",
|
|
1046
|
+
"operation.not_implemented": "The requested operation is not implemented.",
|
|
1047
|
+
"upstream.invalid_request": "The upstream service rejected the request.",
|
|
1048
|
+
"upstream.rate_limited": "The upstream service rate limited the request.",
|
|
1049
|
+
"upstream.timeout": "The upstream service timed out.",
|
|
1050
|
+
"upstream.network_error": "A network error occurred while contacting the upstream service.",
|
|
1051
|
+
"upstream.unavailable": "The upstream service is unavailable.",
|
|
1052
|
+
"upstream.invalid_response": "The upstream service returned an invalid response.",
|
|
1053
|
+
"upstream.error": "The upstream service returned an error.",
|
|
1054
|
+
"transport.invoke_failed": "The provider transport failed.",
|
|
1055
|
+
"internal.timeout": "The operation timed out.",
|
|
1056
|
+
"internal.unexpected": "An unexpected internal error occurred."
|
|
832
1057
|
};
|
|
833
|
-
var
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
1058
|
+
var SERVICE_ERROR_CODE_MAP = {
|
|
1059
|
+
invalid_data: "input.invalid",
|
|
1060
|
+
bad_request: "request.bad",
|
|
1061
|
+
not_found: "resource.not_found",
|
|
1062
|
+
unauthorized: "auth.required",
|
|
1063
|
+
forbidden: "permission.denied",
|
|
1064
|
+
invalid_version: "request.invalid_version",
|
|
1065
|
+
conflict: "resource.conflict",
|
|
1066
|
+
gone: "resource.gone",
|
|
1067
|
+
payment_required: "payment.required",
|
|
1068
|
+
precondition_failed: "request.precondition_failed",
|
|
1069
|
+
not_acceptable: "request.not_acceptable",
|
|
1070
|
+
not_implemented: "operation.not_implemented",
|
|
1071
|
+
too_many_requests: "request.rate_limited",
|
|
1072
|
+
timeout: "internal.timeout",
|
|
1073
|
+
internal_server_error: "internal.unexpected"
|
|
849
1074
|
};
|
|
850
1075
|
|
|
851
|
-
// src/
|
|
852
|
-
var
|
|
853
|
-
|
|
854
|
-
return
|
|
855
|
-
|
|
856
|
-
|
|
1076
|
+
// src/error/utils.ts
|
|
1077
|
+
var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1078
|
+
var normalizeKind = (code, kind) => {
|
|
1079
|
+
if (kind) return kind;
|
|
1080
|
+
if (code.startsWith("declaration.")) return "declaration";
|
|
1081
|
+
if (code.startsWith("input.")) return "validation";
|
|
1082
|
+
if (code.startsWith("request.")) return "request";
|
|
1083
|
+
if (code.startsWith("config.")) return "config";
|
|
1084
|
+
if (code.startsWith("auth.") || code.startsWith("permission.")) return "auth";
|
|
1085
|
+
if (code.startsWith("resource.")) return "resource";
|
|
1086
|
+
if (code.startsWith("payment.")) return "payment";
|
|
1087
|
+
if (code.startsWith("transport.")) return "transport";
|
|
1088
|
+
if (code.startsWith("upstream.")) return "upstream";
|
|
1089
|
+
return "internal";
|
|
857
1090
|
};
|
|
858
|
-
var
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
1091
|
+
var normalizeStatus = (code, status) => {
|
|
1092
|
+
if (status) return status;
|
|
1093
|
+
if (code === "input.invalid" || code === "request.bad" || code === "config.invalid")
|
|
1094
|
+
return 400;
|
|
1095
|
+
if (code === "request.invalid_version") return 400;
|
|
1096
|
+
if (code === "auth.required" || code === "auth.invalid" || code === "auth.expired")
|
|
1097
|
+
return 401;
|
|
1098
|
+
if (code === "payment.required") return 402;
|
|
1099
|
+
if (code === "permission.denied") return 403;
|
|
1100
|
+
if (code === "resource.not_found") return 404;
|
|
1101
|
+
if (code === "resource.conflict") return 409;
|
|
1102
|
+
if (code === "resource.gone") return 410;
|
|
1103
|
+
if (code === "request.not_acceptable") return 406;
|
|
1104
|
+
if (code === "request.precondition_failed") return 412;
|
|
1105
|
+
if (code === "request.rate_limited" || code === "upstream.rate_limited") return 429;
|
|
1106
|
+
if (code === "operation.not_implemented") return 501;
|
|
1107
|
+
if (code === "upstream.invalid_request") return 400;
|
|
1108
|
+
if (code === "upstream.timeout" || code === "internal.timeout") return 504;
|
|
1109
|
+
if (code === "upstream.unavailable") return 503;
|
|
1110
|
+
if (code === "upstream.error") return 502;
|
|
1111
|
+
return void 0;
|
|
864
1112
|
};
|
|
865
|
-
var
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
return void 0;
|
|
869
|
-
}
|
|
870
|
-
return validateScopes({ AND });
|
|
1113
|
+
var normalizeRetryable = (code, retryable) => {
|
|
1114
|
+
if (typeof retryable === "boolean") return retryable;
|
|
1115
|
+
return code === "request.rate_limited" || code === "upstream.rate_limited" || code === "upstream.timeout" || code === "upstream.network_error" || code === "upstream.unavailable" || code === "upstream.error" || code === "transport.invoke_failed" || code === "internal.timeout";
|
|
871
1116
|
};
|
|
872
|
-
var
|
|
873
|
-
if (
|
|
874
|
-
|
|
875
|
-
}
|
|
876
|
-
return {
|
|
877
|
-
AND: scopes.AND.map((clause) => normalizeClause(clause))
|
|
878
|
-
};
|
|
1117
|
+
var getDefaultMessage = (code, message) => {
|
|
1118
|
+
if (message?.trim()) return message;
|
|
1119
|
+
return DEFAULT_MESSAGES[code] ?? DEFAULT_MESSAGES[DEFAULT_CODE] ?? "An unexpected internal error occurred.";
|
|
879
1120
|
};
|
|
880
|
-
var
|
|
881
|
-
if (
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
return
|
|
885
|
-
AND: [normalizeClause(input)]
|
|
886
|
-
};
|
|
1121
|
+
var cleanRecord = (value) => {
|
|
1122
|
+
if (!value) return void 0;
|
|
1123
|
+
let entries = Object.entries(value).filter(([, entry]) => entry !== void 0);
|
|
1124
|
+
if (entries.length === 0) return void 0;
|
|
1125
|
+
return Object.fromEntries(entries);
|
|
887
1126
|
};
|
|
888
|
-
var
|
|
889
|
-
if (
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
}
|
|
898
|
-
assertScopeValues(input.OR);
|
|
1127
|
+
var mergeRecords = (left, right) => {
|
|
1128
|
+
if (!left && !right) return void 0;
|
|
1129
|
+
return cleanRecord({
|
|
1130
|
+
...left ?? {},
|
|
1131
|
+
...right ?? {}
|
|
1132
|
+
});
|
|
1133
|
+
};
|
|
1134
|
+
var mergeSlateErrorData = (base, override) => {
|
|
1135
|
+
if (!override) return base;
|
|
899
1136
|
return {
|
|
900
|
-
|
|
1137
|
+
...base,
|
|
1138
|
+
...override,
|
|
1139
|
+
provider: cleanRecord({
|
|
1140
|
+
...base.provider ?? {},
|
|
1141
|
+
...override.provider ?? {}
|
|
1142
|
+
}),
|
|
1143
|
+
upstream: cleanRecord({
|
|
1144
|
+
...base.upstream ?? {},
|
|
1145
|
+
...override.upstream ?? {}
|
|
1146
|
+
}),
|
|
1147
|
+
baggage: mergeRecords(base.baggage, override.baggage),
|
|
1148
|
+
issues: override.issues ?? base.issues,
|
|
1149
|
+
requestTraces: override.requestTraces ?? base.requestTraces
|
|
901
1150
|
};
|
|
902
1151
|
};
|
|
903
|
-
var
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
var
|
|
916
|
-
var
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
this.params = params;
|
|
924
|
-
this.factory = factory;
|
|
925
|
-
this.isPublicTool = isPublicTool;
|
|
926
|
-
this.#configSchema = spec2.configSchema;
|
|
927
|
-
this.#authSchema = spec2.authSchema;
|
|
928
|
-
}
|
|
929
|
-
type;
|
|
930
|
-
spec;
|
|
931
|
-
params;
|
|
932
|
-
factory;
|
|
933
|
-
isPublicTool;
|
|
934
|
-
#configSchema;
|
|
935
|
-
#authSchema;
|
|
936
|
-
#inputSchema = null;
|
|
937
|
-
#outputSchema = null;
|
|
938
|
-
#scopes;
|
|
939
|
-
#authMethods;
|
|
940
|
-
#toolParams = null;
|
|
941
|
-
#triggerGroup = null;
|
|
942
|
-
#triggerMatches = null;
|
|
943
|
-
#triggerMap = null;
|
|
944
|
-
#interfaceLocked = false;
|
|
945
|
-
input(schema) {
|
|
946
|
-
if (this.#interfaceLocked) {
|
|
947
|
-
throw new SlateDeclarationError("Adapter contract input schema cannot be changed");
|
|
948
|
-
}
|
|
949
|
-
this.#inputSchema = schema;
|
|
950
|
-
return this;
|
|
951
|
-
}
|
|
952
|
-
output(schema) {
|
|
953
|
-
if (this.#interfaceLocked) {
|
|
954
|
-
throw new SlateDeclarationError("Adapter contract output schema cannot be changed");
|
|
955
|
-
}
|
|
956
|
-
this.#outputSchema = schema;
|
|
957
|
-
return this;
|
|
958
|
-
}
|
|
959
|
-
lockInterface() {
|
|
960
|
-
this.#interfaceLocked = true;
|
|
961
|
-
return this;
|
|
962
|
-
}
|
|
963
|
-
scopes(scopes) {
|
|
964
|
-
validateScopes(scopes);
|
|
965
|
-
this.#scopes = scopes;
|
|
966
|
-
return this;
|
|
967
|
-
}
|
|
968
|
-
authMethods(authMethods) {
|
|
969
|
-
if (this.isPublicTool) {
|
|
970
|
-
throw new SlateDeclarationError("Public tools cannot require authentication methods");
|
|
971
|
-
}
|
|
972
|
-
this.#authMethods = this.validateAuthMethods(authMethods);
|
|
973
|
-
return this;
|
|
974
|
-
}
|
|
975
|
-
validateAuthMethods(authMethods) {
|
|
976
|
-
if (!authMethods) return void 0;
|
|
977
|
-
let normalized = [...new Set(authMethods.map((authMethod) => authMethod.trim()))];
|
|
978
|
-
if (normalized.some((authMethod) => !authMethod)) {
|
|
979
|
-
throw new SlateDeclarationError("Auth method IDs must be non-empty strings");
|
|
980
|
-
}
|
|
981
|
-
return normalized;
|
|
982
|
-
}
|
|
983
|
-
handleInvocation(handler) {
|
|
984
|
-
if (this.type !== "tool") {
|
|
985
|
-
throw new SlateDeclarationError("handleInvocation can only be set for tool actions");
|
|
986
|
-
}
|
|
987
|
-
this.#toolParams = {
|
|
988
|
-
type: "tool",
|
|
989
|
-
handleInvocation: handler
|
|
990
|
-
};
|
|
991
|
-
return this;
|
|
992
|
-
}
|
|
993
|
-
triggerGroup(group) {
|
|
994
|
-
if (this.type !== "trigger") {
|
|
995
|
-
throw new SlateDeclarationError("triggerGroup can only be set for trigger actions");
|
|
996
|
-
}
|
|
997
|
-
this.#triggerGroup = group;
|
|
998
|
-
return this;
|
|
1152
|
+
var BAGGAGE_TRUNCATED_VALUE = "[truncated]";
|
|
1153
|
+
var BAGGAGE_REDACTED_VALUE = "[redacted]";
|
|
1154
|
+
var BAGGAGE_UNSERIALIZABLE_VALUE = "[unserializable]";
|
|
1155
|
+
var BAGGAGE_DEFAULT_MAX_DEPTH = 4;
|
|
1156
|
+
var BAGGAGE_RESPONSE_MAX_DEPTH = 8;
|
|
1157
|
+
var BAGGAGE_MAX_STRING_LENGTH = 2e3;
|
|
1158
|
+
var BAGGAGE_MAX_ARRAY_ITEMS = 20;
|
|
1159
|
+
var BAGGAGE_MAX_OBJECT_KEYS = 30;
|
|
1160
|
+
var BAGGAGE_MAX_SERIALIZED_SIZE = 16384;
|
|
1161
|
+
var BAGGAGE_STRING_TRUNCATION_SUFFIX = "...[truncated]";
|
|
1162
|
+
var BAGGAGE_MIN_STRING_SLICE = 32;
|
|
1163
|
+
var BAGGAGE_SCAN_LENGTH = BAGGAGE_MAX_STRING_LENGTH + 100;
|
|
1164
|
+
var BAGGAGE_REDACTOR_SCAN_LENGTH = BAGGAGE_MAX_STRING_LENGTH * 4;
|
|
1165
|
+
var BAGGAGE_MIN_ENTRY_COST = 6;
|
|
1166
|
+
var getCurrentAuthConfigRedactor = () => {
|
|
1167
|
+
try {
|
|
1168
|
+
let authConfig = getCurrentContext()._getAuthConfigForRedaction();
|
|
1169
|
+
return authConfig ? new AuthConfigSecretRedactor(authConfig) : void 0;
|
|
1170
|
+
} catch {
|
|
1171
|
+
return void 0;
|
|
999
1172
|
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1173
|
+
};
|
|
1174
|
+
var ERROR_TEXT_MAX_LENGTH = BAGGAGE_MAX_STRING_LENGTH * 4;
|
|
1175
|
+
var ERROR_TEXT_SCAN_MARGIN = 512;
|
|
1176
|
+
var sanitizeErrorText = (text, redactor) => {
|
|
1177
|
+
let activeRedactor = redactor === void 0 ? getCurrentAuthConfigRedactor() : redactor;
|
|
1178
|
+
let truncated = text.length > ERROR_TEXT_MAX_LENGTH;
|
|
1179
|
+
let scanned = truncated ? text.slice(0, ERROR_TEXT_MAX_LENGTH + ERROR_TEXT_SCAN_MARGIN) : text;
|
|
1180
|
+
let result = scanned;
|
|
1181
|
+
if (activeRedactor) {
|
|
1182
|
+
try {
|
|
1183
|
+
result = redactAuthConfigSecretsInText(result, activeRedactor);
|
|
1184
|
+
} catch {
|
|
1185
|
+
result = scanned;
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
result = sanitizeSecretValuesInText(result);
|
|
1189
|
+
return truncated ? `${result.slice(0, ERROR_TEXT_MAX_LENGTH)}${BAGGAGE_STRING_TRUNCATION_SUFFIX}` : result;
|
|
1190
|
+
};
|
|
1191
|
+
var NUMERIC_SECRET_KEY_PATTERN = /(?:^|_)(?:pin|passcode|password|passwd|pwd|otp|totp|cvv|cvc|ccv|pan|ssn|card_number|card_code|cc_num(?:ber)?)(?:_|$)|(?:^|_)(?:code|secret|key)$/;
|
|
1192
|
+
var VALIDATION_VOCABULARY_PATTERN = /\b(?:required|invalid|must|blank|empty|missing|too (?:short|long|weak|common|simple)|characters?|(?:does not|doesn't|do not|don't) match|cannot be|can't be|not allowed|not valid|at least|at most|incorrect|already (?:taken|used|exists|in use)|has expired|is expired)\b/i;
|
|
1193
|
+
var isValidationProse = (value) => {
|
|
1194
|
+
let text = value.trim();
|
|
1195
|
+
if (text.length > 300) return false;
|
|
1196
|
+
let words = text.split(/\s+/);
|
|
1197
|
+
if (words.length < 3) return false;
|
|
1198
|
+
if (words.some((word) => word.length > 20 || /[a-z]/i.test(word) && /\d/.test(word))) {
|
|
1199
|
+
return false;
|
|
1200
|
+
}
|
|
1201
|
+
return VALIDATION_VOCABULARY_PATTERN.test(text);
|
|
1202
|
+
};
|
|
1203
|
+
var isKeptUnderSecretKey = (key, value) => {
|
|
1204
|
+
if (typeof value === "boolean") return true;
|
|
1205
|
+
if (typeof value === "number")
|
|
1206
|
+
return !NUMERIC_SECRET_KEY_PATTERN.test(splitKeyParts(key).join("_"));
|
|
1207
|
+
if (typeof value === "string") return isValidationProse(value);
|
|
1208
|
+
if (Array.isArray(value)) {
|
|
1209
|
+
return value.length > 0 && value.length <= BAGGAGE_MAX_ARRAY_ITEMS && value.every((item) => typeof item === "string" && isValidationProse(item));
|
|
1006
1210
|
}
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1211
|
+
return false;
|
|
1212
|
+
};
|
|
1213
|
+
var jsonLength = (value) => JSON.stringify(value).length;
|
|
1214
|
+
var redactLiteralSecrets = (value, redactor) => {
|
|
1215
|
+
if (!redactor) return value;
|
|
1216
|
+
try {
|
|
1217
|
+
return redactAuthConfigSecretsInText(
|
|
1218
|
+
value.slice(0, BAGGAGE_REDACTOR_SCAN_LENGTH),
|
|
1219
|
+
redactor
|
|
1220
|
+
);
|
|
1221
|
+
} catch {
|
|
1222
|
+
return value;
|
|
1013
1223
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
if (
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
if (this.type === "tool" && !this.#toolParams) {
|
|
1030
|
-
throw new SlateDeclarationError("Tool invocation handler is not defined");
|
|
1031
|
-
}
|
|
1032
|
-
if (this.type === "trigger" && !this.#triggerGroup) {
|
|
1033
|
-
throw new SlateDeclarationError("Trigger group is not defined");
|
|
1034
|
-
}
|
|
1035
|
-
if (this.type === "trigger" && !this.#triggerMatches) {
|
|
1036
|
-
throw new SlateDeclarationError("Trigger matches handler is not defined");
|
|
1037
|
-
}
|
|
1038
|
-
if (this.type === "trigger" && !this.#triggerMap) {
|
|
1039
|
-
throw new SlateDeclarationError("Trigger map handler is not defined");
|
|
1224
|
+
};
|
|
1225
|
+
var sanitizeBaggageString = (value, state) => {
|
|
1226
|
+
let literalRedacted = redactLiteralSecrets(value, state.redactor);
|
|
1227
|
+
let text = sanitizeSecretValuesInText(literalRedacted.slice(0, BAGGAGE_SCAN_LENGTH));
|
|
1228
|
+
if (value.length > BAGGAGE_MAX_STRING_LENGTH || literalRedacted.length > BAGGAGE_MAX_STRING_LENGTH || text.length > BAGGAGE_MAX_STRING_LENGTH) {
|
|
1229
|
+
text = `${text.slice(0, BAGGAGE_MAX_STRING_LENGTH)}${BAGGAGE_STRING_TRUNCATION_SUFFIX}`;
|
|
1230
|
+
}
|
|
1231
|
+
let cost = jsonLength(text);
|
|
1232
|
+
if (cost > state.remaining) {
|
|
1233
|
+
let sliceLength = state.remaining - BAGGAGE_STRING_TRUNCATION_SUFFIX.length - 2 - (cost - text.length);
|
|
1234
|
+
text = sliceLength >= BAGGAGE_MIN_STRING_SLICE ? `${text.slice(0, sliceLength)}${BAGGAGE_STRING_TRUNCATION_SUFFIX}` : BAGGAGE_TRUNCATED_VALUE;
|
|
1235
|
+
cost = jsonLength(text);
|
|
1236
|
+
if (cost > state.remaining && text !== BAGGAGE_TRUNCATED_VALUE) {
|
|
1237
|
+
text = BAGGAGE_TRUNCATED_VALUE;
|
|
1238
|
+
cost = jsonLength(text);
|
|
1040
1239
|
}
|
|
1041
|
-
let triggerParams = this.type === "trigger" ? {
|
|
1042
|
-
type: "trigger",
|
|
1043
|
-
triggerGroup: this.#triggerGroup,
|
|
1044
|
-
matches: this.#triggerMatches,
|
|
1045
|
-
map: this.#triggerMap
|
|
1046
|
-
} : null;
|
|
1047
|
-
return this.factory({
|
|
1048
|
-
...this.params,
|
|
1049
|
-
scopes,
|
|
1050
|
-
authMethods,
|
|
1051
|
-
isPublic: this.isPublicTool === true,
|
|
1052
|
-
configSchema: this.#configSchema,
|
|
1053
|
-
authSchema: this.#authSchema,
|
|
1054
|
-
inputSchema: this.#inputSchema,
|
|
1055
|
-
outputSchema: this.#outputSchema,
|
|
1056
|
-
...this.#toolParams,
|
|
1057
|
-
...triggerParams
|
|
1058
|
-
});
|
|
1059
1240
|
}
|
|
1241
|
+
state.remaining -= cost;
|
|
1242
|
+
return text;
|
|
1060
1243
|
};
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
var AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX = "$$MT$secret$authConfig$";
|
|
1067
|
-
var AuthConfigSecretRedactor = class {
|
|
1068
|
-
secretToPlaceholder = /* @__PURE__ */ new Map();
|
|
1069
|
-
constructor(authConfig) {
|
|
1070
|
-
if (authConfig) this.buildSecretMap(authConfig);
|
|
1244
|
+
var sanitizeBaggageValue = (value, depth, maxDepth, state) => {
|
|
1245
|
+
if (value === void 0) return value;
|
|
1246
|
+
if (value === null) {
|
|
1247
|
+
state.remaining -= 4;
|
|
1248
|
+
return value;
|
|
1071
1249
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
});
|
|
1250
|
+
if (depth >= maxDepth) {
|
|
1251
|
+
state.remaining -= jsonLength(BAGGAGE_TRUNCATED_VALUE);
|
|
1252
|
+
return BAGGAGE_TRUNCATED_VALUE;
|
|
1076
1253
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
"g"
|
|
1082
|
-
);
|
|
1083
|
-
return this.transform(value, (stringValue) => {
|
|
1084
|
-
let exactPlaceholder = this.secretToPlaceholder.get(stringValue);
|
|
1085
|
-
if (exactPlaceholder) return exactPlaceholder;
|
|
1086
|
-
return stringValue.replace(
|
|
1087
|
-
pattern,
|
|
1088
|
-
(secret) => `${this.secretToPlaceholder.get(secret)}$$`
|
|
1089
|
-
);
|
|
1090
|
-
});
|
|
1254
|
+
if (typeof value === "string") return sanitizeBaggageString(value, state);
|
|
1255
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
1256
|
+
state.remaining -= String(value).length;
|
|
1257
|
+
return value;
|
|
1091
1258
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
return;
|
|
1106
|
-
}
|
|
1107
|
-
if (this.isPlainObject(value)) {
|
|
1108
|
-
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
1109
|
-
this.buildSecretMap(nestedValue, [...path, key]);
|
|
1110
|
-
});
|
|
1259
|
+
if (typeof value === "bigint") return sanitizeBaggageString(value.toString(), state);
|
|
1260
|
+
if (Array.isArray(value)) {
|
|
1261
|
+
state.remaining -= 2;
|
|
1262
|
+
let items = [];
|
|
1263
|
+
for (let item of value.slice(0, BAGGAGE_MAX_ARRAY_ITEMS)) {
|
|
1264
|
+
if (state.remaining <= 0) break;
|
|
1265
|
+
state.remaining -= 1;
|
|
1266
|
+
if (item === void 0) {
|
|
1267
|
+
state.remaining -= 4;
|
|
1268
|
+
items.push(null);
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1271
|
+
items.push(sanitizeBaggageValue(item, depth + 1, maxDepth, state));
|
|
1111
1272
|
}
|
|
1273
|
+
return items;
|
|
1112
1274
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1275
|
+
if (isRecord2(value)) {
|
|
1276
|
+
state.remaining -= 2;
|
|
1277
|
+
let entries = [];
|
|
1278
|
+
for (let key of Object.keys(value).slice(0, BAGGAGE_MAX_OBJECT_KEYS)) {
|
|
1279
|
+
if (state.remaining < BAGGAGE_MIN_ENTRY_COST) break;
|
|
1280
|
+
let keyCost = jsonLength(key) + 2;
|
|
1281
|
+
if (state.remaining - keyCost <= 0) continue;
|
|
1282
|
+
state.remaining -= keyCost;
|
|
1283
|
+
try {
|
|
1284
|
+
let entry = value[key];
|
|
1285
|
+
if (entry != null && isSecretFieldName(key) && !isKeptUnderSecretKey(key, entry)) {
|
|
1286
|
+
state.remaining -= jsonLength(BAGGAGE_REDACTED_VALUE);
|
|
1287
|
+
entries.push([key, BAGGAGE_REDACTED_VALUE]);
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
entries.push([key, sanitizeBaggageValue(entry, depth + 1, maxDepth, state)]);
|
|
1291
|
+
} catch {
|
|
1292
|
+
state.remaining -= jsonLength(BAGGAGE_UNSERIALIZABLE_VALUE);
|
|
1293
|
+
entries.push([key, BAGGAGE_UNSERIALIZABLE_VALUE]);
|
|
1294
|
+
}
|
|
1126
1295
|
}
|
|
1127
|
-
return
|
|
1128
|
-
}
|
|
1129
|
-
isPlainObject(value) {
|
|
1130
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1296
|
+
return Object.fromEntries(entries);
|
|
1131
1297
|
}
|
|
1298
|
+
return sanitizeBaggageString(String(value), state);
|
|
1132
1299
|
};
|
|
1133
|
-
var
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
if (!attachment.content.headers && !attachment.content.query) return attachment;
|
|
1139
|
-
return {
|
|
1140
|
-
...attachment,
|
|
1141
|
-
content: {
|
|
1142
|
-
...attachment.content,
|
|
1143
|
-
headers: attachment.content.headers ? redactor.redactEmbedded(attachment.content.headers) : void 0,
|
|
1144
|
-
query: attachment.content.query ? redactor.redactEmbedded(attachment.content.query) : void 0
|
|
1145
|
-
}
|
|
1146
|
-
};
|
|
1147
|
-
});
|
|
1148
|
-
};
|
|
1149
|
-
|
|
1150
|
-
// src/action/tool.ts
|
|
1151
|
-
var SlateTool = class _SlateTool extends SlateAction {
|
|
1152
|
-
#handleInvocation;
|
|
1153
|
-
constructor(spec2, inputSchema, outputSchema, params) {
|
|
1154
|
-
super("tool", spec2, inputSchema, outputSchema, params);
|
|
1155
|
-
this.#handleInvocation = params.handleInvocation;
|
|
1156
|
-
}
|
|
1157
|
-
static create(spec2, params) {
|
|
1158
|
-
return new SlateActionBuilder("tool", spec2, params, (params2) => {
|
|
1159
|
-
return _SlateTool.fromCreateParameters(spec2, params2);
|
|
1300
|
+
var sanitizeForBaggage = (value, options = {}) => {
|
|
1301
|
+
try {
|
|
1302
|
+
return sanitizeBaggageValue(value, 0, options.maxDepth ?? BAGGAGE_DEFAULT_MAX_DEPTH, {
|
|
1303
|
+
remaining: options.maxSerializedSize ?? BAGGAGE_MAX_SERIALIZED_SIZE,
|
|
1304
|
+
redactor: options.redactor === null ? void 0 : options.redactor ?? getCurrentAuthConfigRedactor()
|
|
1160
1305
|
});
|
|
1161
|
-
}
|
|
1162
|
-
|
|
1163
|
-
if (params.type !== "tool") throw new Error("Invalid action type for tool");
|
|
1164
|
-
return new _SlateTool(spec2, params.inputSchema, params.outputSchema, params);
|
|
1165
|
-
}
|
|
1166
|
-
get handleInvocation() {
|
|
1167
|
-
return this.#handleInvocation;
|
|
1306
|
+
} catch {
|
|
1307
|
+
return BAGGAGE_UNSERIALIZABLE_VALUE;
|
|
1168
1308
|
}
|
|
1169
1309
|
};
|
|
1170
|
-
var
|
|
1171
|
-
|
|
1172
|
-
// src/action/getFileUrlTool.ts
|
|
1173
|
-
var GET_FILE_URL_TOOL_ID = "metorial$getFileUrl";
|
|
1174
|
-
var getFileUrlToolInputSchema = import_zod.z.object({
|
|
1175
|
-
url: import_zod.z.string(),
|
|
1176
|
-
reference: import_zod.z.any().nullable()
|
|
1177
|
-
});
|
|
1178
|
-
var getFileUrlToolOutputSchema = import_zod.z.object({
|
|
1179
|
-
url: import_zod.z.string(),
|
|
1180
|
-
expiresAt: import_zod.z.string(),
|
|
1181
|
-
headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
|
|
1182
|
-
query: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
1183
|
-
});
|
|
1184
|
-
var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
1185
|
-
key: GET_FILE_URL_TOOL_ID,
|
|
1186
|
-
name: "Get File URL",
|
|
1187
|
-
description: "Reserved: refreshes an expiring attachment download URL. Hub-internal only."
|
|
1188
|
-
}).input(getFileUrlToolInputSchema).output(getFileUrlToolOutputSchema).handleInvocation(async (ctx) => {
|
|
1189
|
-
let output = await handleGetFileUrl(ctx);
|
|
1190
|
-
let redactor = new AuthConfigSecretRedactor(ctx._getAuthConfigForRedaction());
|
|
1310
|
+
var normalizeSlateErrorInput = (input) => {
|
|
1311
|
+
let code = input.code || DEFAULT_CODE;
|
|
1191
1312
|
return {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1313
|
+
code,
|
|
1314
|
+
message: getDefaultMessage(code, input.message),
|
|
1315
|
+
kind: normalizeKind(code, input.kind),
|
|
1316
|
+
retryable: normalizeRetryable(code, input.retryable),
|
|
1317
|
+
status: normalizeStatus(code, input.status ?? input.upstream?.status),
|
|
1318
|
+
issues: input.issues,
|
|
1319
|
+
provider: cleanRecord(input.provider),
|
|
1320
|
+
upstream: cleanRecord({
|
|
1321
|
+
...input.upstream,
|
|
1322
|
+
status: input.upstream?.status ?? input.status
|
|
1323
|
+
}),
|
|
1324
|
+
baggage: cleanRecord(input.baggage),
|
|
1325
|
+
requestTraces: input.requestTraces
|
|
1198
1326
|
};
|
|
1199
|
-
}
|
|
1327
|
+
};
|
|
1328
|
+
var isSlateErrorResponse = (error) => {
|
|
1329
|
+
if (!isRecord2(error)) return false;
|
|
1330
|
+
return typeof error.code === "string" && typeof error.message === "string";
|
|
1331
|
+
};
|
|
1200
1332
|
|
|
1201
|
-
// src/
|
|
1202
|
-
var
|
|
1203
|
-
|
|
1333
|
+
// src/error/api.ts
|
|
1334
|
+
var DEFAULT_DETAIL_KEYS = ["message", "detail", "error", "error_description", "code"];
|
|
1335
|
+
var DEFAULT_NESTED_KEYS = ["errors"];
|
|
1336
|
+
var isApiErrorRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1337
|
+
var pushDetail = (details, value, options = {}) => {
|
|
1338
|
+
if (typeof value !== "string" && (options.includeNumbers === false || typeof value !== "number")) {
|
|
1339
|
+
return;
|
|
1204
1340
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
spec2,
|
|
1209
|
-
params,
|
|
1210
|
-
(params2) => {
|
|
1211
|
-
return SlateTool.fromCreateParameters(spec2, {
|
|
1212
|
-
...params2,
|
|
1213
|
-
isPublic: true
|
|
1214
|
-
});
|
|
1215
|
-
},
|
|
1216
|
-
true
|
|
1217
|
-
);
|
|
1341
|
+
let detail = String(value).trim();
|
|
1342
|
+
if (detail && !details.includes(detail)) {
|
|
1343
|
+
details.push(detail);
|
|
1218
1344
|
}
|
|
1219
1345
|
};
|
|
1220
|
-
var
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
#map;
|
|
1227
|
-
constructor(spec2, inputSchema, outputSchema, params) {
|
|
1228
|
-
super("trigger", spec2, inputSchema, outputSchema, params);
|
|
1229
|
-
this.#triggerGroup = params.triggerGroup;
|
|
1230
|
-
this.#matches = params.matches;
|
|
1231
|
-
this.#map = params.map;
|
|
1232
|
-
}
|
|
1233
|
-
static create(spec2, params) {
|
|
1234
|
-
return new SlateActionBuilder("trigger", spec2, params, (params2) => {
|
|
1235
|
-
if (params2.type !== "trigger") throw new Error("Invalid action type for trigger");
|
|
1236
|
-
return new _SlateTrigger(spec2, params2.inputSchema, params2.outputSchema, params2);
|
|
1237
|
-
});
|
|
1346
|
+
var collectApiErrorDetails = (value, details, options = {}) => {
|
|
1347
|
+
if (Array.isArray(value)) {
|
|
1348
|
+
for (let item of value) {
|
|
1349
|
+
collectApiErrorDetails(item, details, options);
|
|
1350
|
+
}
|
|
1351
|
+
return;
|
|
1238
1352
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1353
|
+
if (!isApiErrorRecord(value)) {
|
|
1354
|
+
pushDetail(details, value, options);
|
|
1355
|
+
return;
|
|
1241
1356
|
}
|
|
1242
|
-
|
|
1243
|
-
|
|
1357
|
+
for (let key of options.detailKeys ?? DEFAULT_DETAIL_KEYS) {
|
|
1358
|
+
pushDetail(details, value[key], options);
|
|
1244
1359
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1360
|
+
for (let key of options.nestedKeys ?? DEFAULT_NESTED_KEYS) {
|
|
1361
|
+
collectApiErrorDetails(value[key], details, options);
|
|
1247
1362
|
}
|
|
1248
1363
|
};
|
|
1249
|
-
var
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
var import_zod2 = require("zod");
|
|
1253
|
-
var SlateDefaultPollingIntervalSeconds = 60 * 10;
|
|
1254
|
-
var SlateTriggerGroup = class _SlateTriggerGroup {
|
|
1255
|
-
constructor(_spec, _params) {
|
|
1256
|
-
this._spec = _spec;
|
|
1257
|
-
this._params = _params;
|
|
1258
|
-
}
|
|
1259
|
-
_spec;
|
|
1260
|
-
_params;
|
|
1261
|
-
static create(spec2, params) {
|
|
1262
|
-
return new SlateTriggerGroupBuilder(spec2, params, (p) => new _SlateTriggerGroup(spec2, p));
|
|
1263
|
-
}
|
|
1264
|
-
get spec() {
|
|
1265
|
-
return this._spec;
|
|
1364
|
+
var getSlateErrorResponse = (error) => {
|
|
1365
|
+
if (error.name !== "SlateError" || !isApiErrorRecord(error.data)) {
|
|
1366
|
+
return void 0;
|
|
1266
1367
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1368
|
+
let data = error.data;
|
|
1369
|
+
let upstream = isApiErrorRecord(data.upstream) ? data.upstream : void 0;
|
|
1370
|
+
let status = upstream?.status ?? data.status;
|
|
1371
|
+
return typeof status === "number" || typeof status === "string" ? { status } : void 0;
|
|
1372
|
+
};
|
|
1373
|
+
var getApiErrorResponse = (error) => {
|
|
1374
|
+
if (!isApiErrorRecord(error)) {
|
|
1375
|
+
return void 0;
|
|
1269
1376
|
}
|
|
1270
|
-
|
|
1271
|
-
return
|
|
1377
|
+
if (!isApiErrorRecord(error.response)) {
|
|
1378
|
+
return getSlateErrorResponse(error);
|
|
1272
1379
|
}
|
|
1273
|
-
|
|
1274
|
-
|
|
1380
|
+
let response = error.response;
|
|
1381
|
+
return {
|
|
1382
|
+
status: typeof response.status === "number" || typeof response.status === "string" ? response.status : void 0,
|
|
1383
|
+
statusText: typeof response.statusText === "string" ? response.statusText : void 0,
|
|
1384
|
+
data: response.data
|
|
1385
|
+
};
|
|
1386
|
+
};
|
|
1387
|
+
var getApiErrorStatus = (error) => getApiErrorResponse(error)?.status;
|
|
1388
|
+
var getApiErrorResponseWithBody = (error) => {
|
|
1389
|
+
let response = getApiErrorResponse(error);
|
|
1390
|
+
if (response?.data !== void 0) return response;
|
|
1391
|
+
if (!isApiErrorRecord(error) || error.name !== "SlateError" || !isApiErrorRecord(error.data)) {
|
|
1392
|
+
return response;
|
|
1393
|
+
}
|
|
1394
|
+
let baggage = isApiErrorRecord(error.data.baggage) ? error.data.baggage : void 0;
|
|
1395
|
+
if (baggage?.response === void 0) return response;
|
|
1396
|
+
return { ...response, data: baggage.response };
|
|
1397
|
+
};
|
|
1398
|
+
var API_ERROR_MAX_DETAILS = 5;
|
|
1399
|
+
var API_ERROR_MAX_MESSAGE_LENGTH = 1e3;
|
|
1400
|
+
var API_ERROR_TRUNCATED_PLACEHOLDER = BAGGAGE_TRUNCATED_VALUE;
|
|
1401
|
+
var BAGGAGE_PLACEHOLDERS = /* @__PURE__ */ new Set([
|
|
1402
|
+
BAGGAGE_TRUNCATED_VALUE,
|
|
1403
|
+
BAGGAGE_REDACTED_VALUE,
|
|
1404
|
+
BAGGAGE_UNSERIALIZABLE_VALUE
|
|
1405
|
+
]);
|
|
1406
|
+
var looksLikeHtmlErrorBody = (value) => /^\s*<!doctype\s+html\b/i.test(value) || /^\s*<(html|head)\b[^>]*>/i.test(value) || /<\/(html|head|body)\s*>/i.test(value) || /^\s*<(title|h[1-6]|p|div|pre|center)\b[^>]*>[\s\S]*<\/\1\s*>/i.test(value);
|
|
1407
|
+
var truncateApiErrorMessage = (value, maxLength = API_ERROR_MAX_MESSAGE_LENGTH) => value.length > maxLength ? `${value.slice(0, maxLength)}...` : value;
|
|
1408
|
+
var readApiErrorText = (value, options = {}) => {
|
|
1409
|
+
if (typeof value !== "string" && (options.includeNumbers === false || typeof value !== "number")) {
|
|
1410
|
+
return void 0;
|
|
1275
1411
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1412
|
+
let text = String(value).trim();
|
|
1413
|
+
if (!text || BAGGAGE_PLACEHOLDERS.has(text) || looksLikeHtmlErrorBody(text)) {
|
|
1414
|
+
return void 0;
|
|
1278
1415
|
}
|
|
1279
|
-
|
|
1280
|
-
|
|
1416
|
+
return text;
|
|
1417
|
+
};
|
|
1418
|
+
var pushBoundedApiErrorDetail = (details, value, options = {}) => {
|
|
1419
|
+
if (details.length >= (options.maxDetails ?? API_ERROR_MAX_DETAILS)) return;
|
|
1420
|
+
let text = readApiErrorText(value, options);
|
|
1421
|
+
if (!text) return;
|
|
1422
|
+
let detail = options.field ? `${options.field}: ${text}` : text;
|
|
1423
|
+
if (!details.includes(detail)) {
|
|
1424
|
+
details.push(detail);
|
|
1281
1425
|
}
|
|
1282
|
-
|
|
1283
|
-
|
|
1426
|
+
};
|
|
1427
|
+
var decodeApiErrorBody = (data, options = {}) => {
|
|
1428
|
+
let text;
|
|
1429
|
+
if (typeof data === "string") {
|
|
1430
|
+
text = data;
|
|
1431
|
+
} else if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
|
|
1432
|
+
let bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
1433
|
+
if (options.maxBytes !== void 0 && bytes.byteLength > options.maxBytes) {
|
|
1434
|
+
bytes = bytes.subarray(0, options.maxBytes);
|
|
1435
|
+
}
|
|
1436
|
+
text = new TextDecoder("utf-8").decode(bytes);
|
|
1437
|
+
} else {
|
|
1438
|
+
return data;
|
|
1284
1439
|
}
|
|
1285
|
-
|
|
1286
|
-
|
|
1440
|
+
let trimmed = text.trim();
|
|
1441
|
+
if (/^[{[]/.test(trimmed)) {
|
|
1442
|
+
try {
|
|
1443
|
+
return JSON.parse(trimmed);
|
|
1444
|
+
} catch {
|
|
1445
|
+
}
|
|
1287
1446
|
}
|
|
1288
|
-
|
|
1289
|
-
|
|
1447
|
+
return trimmed;
|
|
1448
|
+
};
|
|
1449
|
+
var statusLabelForApiError = (status, statusText) => status !== void 0 ? `HTTP ${status}${statusText ? ` ${statusText}` : ""}: ` : "";
|
|
1450
|
+
var extractApiErrorMessage = (error, options = {}) => {
|
|
1451
|
+
let details = [];
|
|
1452
|
+
let response = options.response ?? getApiErrorResponse(error);
|
|
1453
|
+
collectApiErrorDetails(response?.data, details, options);
|
|
1454
|
+
if (details.length > 0) {
|
|
1455
|
+
return details.join(options.separator ?? " - ");
|
|
1290
1456
|
}
|
|
1291
|
-
|
|
1292
|
-
return
|
|
1457
|
+
if (error instanceof Error && error.message) {
|
|
1458
|
+
return error.message;
|
|
1293
1459
|
}
|
|
1460
|
+
return options.fallbackMessage ?? "Unknown error";
|
|
1294
1461
|
};
|
|
1295
|
-
var
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
this.factory = factory;
|
|
1462
|
+
var createApiServiceError = (message, options = {}) => {
|
|
1463
|
+
let error = new import_error.ServiceError((0, import_error.badRequestError)({ message }));
|
|
1464
|
+
if (options.reason !== void 0) {
|
|
1465
|
+
error.data.reason = options.reason;
|
|
1300
1466
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
factory;
|
|
1304
|
-
#source = null;
|
|
1305
|
-
#polling = null;
|
|
1306
|
-
#webhook = null;
|
|
1307
|
-
#routingMatchers = null;
|
|
1308
|
-
polling(props) {
|
|
1309
|
-
if (this.#source) {
|
|
1310
|
-
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
1311
|
-
}
|
|
1312
|
-
this.#source = "polling";
|
|
1313
|
-
this.#polling = {
|
|
1314
|
-
intervalSeconds: props.intervalSeconds ?? SlateDefaultPollingIntervalSeconds,
|
|
1315
|
-
pollEvents: props.pollEvents
|
|
1316
|
-
};
|
|
1317
|
-
return this;
|
|
1467
|
+
if ("upstreamStatus" in options) {
|
|
1468
|
+
error.data.upstreamStatus = options.upstreamStatus;
|
|
1318
1469
|
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
1322
|
-
}
|
|
1323
|
-
if (!!props.autoRegistration === !!props.manualRegistration) {
|
|
1324
|
-
throw new SlateDeclarationError(
|
|
1325
|
-
"Webhook trigger groups require exactly one of autoRegistration or manualRegistration"
|
|
1326
|
-
);
|
|
1327
|
-
}
|
|
1328
|
-
this.#source = "webhook";
|
|
1329
|
-
this.#webhook = {
|
|
1330
|
-
autoRegistration: props.autoRegistration,
|
|
1331
|
-
manualRegistration: props.manualRegistration,
|
|
1332
|
-
process: props.process
|
|
1333
|
-
};
|
|
1334
|
-
return this;
|
|
1470
|
+
if ("upstreamCode" in options) {
|
|
1471
|
+
error.data.upstreamCode = options.upstreamCode;
|
|
1335
1472
|
}
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
return this;
|
|
1473
|
+
if (options.parent instanceof Error) {
|
|
1474
|
+
error.setParent(options.parent);
|
|
1339
1475
|
}
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
routingMatchers: this.#routingMatchers
|
|
1355
|
-
});
|
|
1476
|
+
return error;
|
|
1477
|
+
};
|
|
1478
|
+
var helpers = {
|
|
1479
|
+
collectDetails: collectApiErrorDetails,
|
|
1480
|
+
extractMessage: extractApiErrorMessage,
|
|
1481
|
+
getResponse: getApiErrorResponse,
|
|
1482
|
+
getResponseWithBody: getApiErrorResponseWithBody,
|
|
1483
|
+
getStatus: getApiErrorStatus,
|
|
1484
|
+
isRecord: isApiErrorRecord,
|
|
1485
|
+
statusLabelFor: statusLabelForApiError
|
|
1486
|
+
};
|
|
1487
|
+
var buildApiServiceError = (error, options) => {
|
|
1488
|
+
if (error instanceof import_error.ServiceError) {
|
|
1489
|
+
return error;
|
|
1356
1490
|
}
|
|
1491
|
+
let operation = options.operation ?? "request";
|
|
1492
|
+
let response = options.extractResponse?.(error, helpers) ?? getApiErrorResponse(error);
|
|
1493
|
+
let status = options.extractStatus?.(error, response, helpers) ?? response?.status;
|
|
1494
|
+
let message = options.extractMessage?.(error, helpers) ?? extractApiErrorMessage(error, { ...options, response });
|
|
1495
|
+
let statusLabel = statusLabelForApiError(status, response?.statusText);
|
|
1496
|
+
let fullMessage = options.formatMessage?.({
|
|
1497
|
+
providerLabel: options.providerLabel,
|
|
1498
|
+
operation,
|
|
1499
|
+
statusLabel,
|
|
1500
|
+
message,
|
|
1501
|
+
response,
|
|
1502
|
+
status
|
|
1503
|
+
}) ?? `${options.providerLabel} API ${operation} failed: ${statusLabel}${message}`;
|
|
1504
|
+
return createApiServiceError(fullMessage, {
|
|
1505
|
+
reason: options.reason,
|
|
1506
|
+
upstreamStatus: status,
|
|
1507
|
+
upstreamCode: options.extractUpstreamCode?.(error, response, helpers),
|
|
1508
|
+
parent: options.parent ?? error
|
|
1509
|
+
});
|
|
1357
1510
|
};
|
|
1358
|
-
var triggerGroup = (spec2, params) => SlateTriggerGroup.create(spec2, params);
|
|
1359
1511
|
|
|
1360
|
-
// src/
|
|
1361
|
-
var
|
|
1362
|
-
|
|
1363
|
-
|
|
1512
|
+
// src/error/axios.ts
|
|
1513
|
+
var import_axios = require("axios");
|
|
1514
|
+
var getResponseField = (value, key) => {
|
|
1515
|
+
if (!isRecord2(value)) return void 0;
|
|
1516
|
+
return value[key];
|
|
1517
|
+
};
|
|
1518
|
+
var getNestedMessage = (value) => {
|
|
1519
|
+
if (typeof value === "string") return value;
|
|
1520
|
+
if (!isRecord2(value)) return void 0;
|
|
1521
|
+
let message = getResponseField(value, "message");
|
|
1522
|
+
if (typeof message === "string" && message.trim()) return message;
|
|
1523
|
+
let description = getResponseField(value, "description");
|
|
1524
|
+
if (typeof description === "string" && description.trim()) return description;
|
|
1525
|
+
let error = getResponseField(value, "error");
|
|
1526
|
+
if (typeof error === "string" && error.trim()) return error;
|
|
1527
|
+
if (isRecord2(error)) {
|
|
1528
|
+
let nested = getNestedMessage(error);
|
|
1529
|
+
if (nested) return nested;
|
|
1364
1530
|
}
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1531
|
+
let errorDescription = getResponseField(value, "error_description");
|
|
1532
|
+
if (typeof errorDescription === "string" && errorDescription.trim()) {
|
|
1533
|
+
return errorDescription;
|
|
1534
|
+
}
|
|
1535
|
+
return void 0;
|
|
1536
|
+
};
|
|
1537
|
+
var getNestedCode = (value) => {
|
|
1538
|
+
if (!isRecord2(value)) return void 0;
|
|
1539
|
+
let directCode = getResponseField(value, "code");
|
|
1540
|
+
if (typeof directCode === "string" && directCode.trim()) return directCode;
|
|
1541
|
+
let errorCode = getResponseField(value, "error_code");
|
|
1542
|
+
if (typeof errorCode === "string" && errorCode.trim()) return errorCode;
|
|
1543
|
+
let type = getResponseField(value, "type");
|
|
1544
|
+
if (typeof type === "string" && type.trim()) return type;
|
|
1545
|
+
let error = getResponseField(value, "error");
|
|
1546
|
+
if (typeof error === "string" && error.trim()) return error;
|
|
1547
|
+
if (isRecord2(error)) return getNestedCode(error);
|
|
1548
|
+
return void 0;
|
|
1549
|
+
};
|
|
1550
|
+
var getNestedType = (value) => {
|
|
1551
|
+
if (!isRecord2(value)) return void 0;
|
|
1552
|
+
let type = getResponseField(value, "type");
|
|
1553
|
+
if (typeof type === "string" && type.trim()) return type;
|
|
1554
|
+
let error = getResponseField(value, "error");
|
|
1555
|
+
if (isRecord2(error)) {
|
|
1556
|
+
let nestedType = getNestedType(error);
|
|
1557
|
+
if (nestedType) return nestedType;
|
|
1558
|
+
}
|
|
1559
|
+
return void 0;
|
|
1560
|
+
};
|
|
1561
|
+
var getHeaderValue = (headers, key) => {
|
|
1562
|
+
if (!headers) return void 0;
|
|
1563
|
+
if (typeof headers.get === "function") {
|
|
1564
|
+
let value = headers.get(key);
|
|
1565
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
1566
|
+
}
|
|
1567
|
+
if (isRecord2(headers)) {
|
|
1568
|
+
for (let [headerKey, headerValue] of Object.entries(headers)) {
|
|
1569
|
+
if (headerKey.toLowerCase() !== key.toLowerCase()) continue;
|
|
1570
|
+
if (typeof headerValue === "string" && headerValue.trim()) return headerValue;
|
|
1571
|
+
if (Array.isArray(headerValue)) {
|
|
1572
|
+
let first = headerValue.find((item) => typeof item === "string" && item.trim());
|
|
1573
|
+
if (typeof first === "string") return first;
|
|
1574
|
+
}
|
|
1375
1575
|
}
|
|
1376
|
-
}
|
|
1576
|
+
}
|
|
1577
|
+
return void 0;
|
|
1377
1578
|
};
|
|
1378
|
-
var
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
encoding: "base64",
|
|
1384
|
-
content
|
|
1579
|
+
var sanitizeRequestUrl = (url, redactor) => {
|
|
1580
|
+
try {
|
|
1581
|
+
return sanitizeUrl(url, redactor);
|
|
1582
|
+
} catch {
|
|
1583
|
+
return sanitizeUrl(url);
|
|
1385
1584
|
}
|
|
1386
|
-
}
|
|
1387
|
-
var
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1585
|
+
};
|
|
1586
|
+
var buildRequestUrl = (error, redactor) => {
|
|
1587
|
+
let baseURL = error.config?.baseURL;
|
|
1588
|
+
let url = error.config?.url;
|
|
1589
|
+
if (!url) return void 0;
|
|
1590
|
+
if (!baseURL) return sanitizeRequestUrl(url, redactor);
|
|
1591
|
+
let absoluteUrl = url;
|
|
1592
|
+
try {
|
|
1593
|
+
absoluteUrl = new URL(url, baseURL).toString();
|
|
1594
|
+
} catch {
|
|
1394
1595
|
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1596
|
+
return sanitizeRequestUrl(absoluteUrl, redactor);
|
|
1597
|
+
};
|
|
1598
|
+
var getProviderDefaults = () => {
|
|
1599
|
+
try {
|
|
1600
|
+
let ctx = getCurrentContext();
|
|
1601
|
+
return {
|
|
1602
|
+
provider: {
|
|
1603
|
+
key: ctx.specification.key
|
|
1604
|
+
},
|
|
1605
|
+
...ctx.getHttpTraces().length > 0 ? { requestTraces: ctx.getHttpTraces() } : {}
|
|
1606
|
+
};
|
|
1607
|
+
} catch {
|
|
1608
|
+
return {};
|
|
1406
1609
|
}
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
let
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
sizeBytes += value.byteLength;
|
|
1415
|
-
if (sizeBytes > maxSizeBytes) {
|
|
1416
|
-
await reader.cancel();
|
|
1417
|
-
throw new Error(`Attachment exceeds the maximum size of ${maxSizeBytes} bytes`);
|
|
1418
|
-
}
|
|
1419
|
-
chunks.push(value);
|
|
1610
|
+
};
|
|
1611
|
+
var inferAxiosCode = (error, data) => {
|
|
1612
|
+
let status = error.response?.status;
|
|
1613
|
+
let axiosCode = error.code?.toUpperCase();
|
|
1614
|
+
let remoteCode = getNestedCode(data)?.toLowerCase();
|
|
1615
|
+
if (axiosCode === "ECONNABORTED" || axiosCode === "ETIMEDOUT" || status === 408 || remoteCode?.includes("timeout")) {
|
|
1616
|
+
return "upstream.timeout";
|
|
1420
1617
|
}
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
let offset = 0;
|
|
1424
|
-
for (let chunk of chunks) {
|
|
1425
|
-
bufferedView.set(chunk, offset);
|
|
1426
|
-
offset += chunk.byteLength;
|
|
1618
|
+
if (!error.response) {
|
|
1619
|
+
return "upstream.network_error";
|
|
1427
1620
|
}
|
|
1428
|
-
return
|
|
1621
|
+
if (status === 401) return "auth.invalid";
|
|
1622
|
+
if (status === 403) {
|
|
1623
|
+
return remoteCode?.includes("rate") ? "upstream.rate_limited" : "permission.denied";
|
|
1624
|
+
}
|
|
1625
|
+
if (status === 404) return "resource.not_found";
|
|
1626
|
+
if (status === 409) return "resource.conflict";
|
|
1627
|
+
if (status === 422 || status === 400) return "upstream.invalid_request";
|
|
1628
|
+
if (status === 429) return "upstream.rate_limited";
|
|
1629
|
+
if (status === 502 || status === 503 || status === 504) return "upstream.unavailable";
|
|
1630
|
+
if (status && status >= 500) return "upstream.error";
|
|
1631
|
+
return "upstream.error";
|
|
1429
1632
|
};
|
|
1430
|
-
var
|
|
1431
|
-
let
|
|
1432
|
-
let
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1633
|
+
var inferAxiosMessage = (error, data, code, redactor) => {
|
|
1634
|
+
let message = getNestedMessage(data) ?? error.response?.statusText ?? error.message ?? getDefaultMessage(code);
|
|
1635
|
+
let scrubbed = sanitizeErrorText(message, redactor ?? null);
|
|
1636
|
+
return scrubbed.length > BAGGAGE_MAX_STRING_LENGTH ? `${scrubbed.slice(0, BAGGAGE_MAX_STRING_LENGTH)}...` : scrubbed;
|
|
1637
|
+
};
|
|
1638
|
+
var inferAxiosRetryable = (error, code) => {
|
|
1639
|
+
let headerValue = getHeaderValue(error.response?.headers, "retry-after");
|
|
1640
|
+
if (headerValue) return true;
|
|
1641
|
+
return normalizeRetryable(code, void 0);
|
|
1642
|
+
};
|
|
1643
|
+
var isAxiosErrorLike = (error) => (0, import_axios.isAxiosError)(error);
|
|
1644
|
+
var inferSlateErrorFromAxios = (error, options = {}) => {
|
|
1645
|
+
let responseData = error.response ? options.extractResponseData?.(error.response) ?? error.response.data : void 0;
|
|
1646
|
+
let code = inferAxiosCode(error, responseData);
|
|
1647
|
+
let redactor = getCurrentAuthConfigRedactor();
|
|
1648
|
+
return normalizeSlateErrorInput({
|
|
1649
|
+
...getProviderDefaults(),
|
|
1650
|
+
...options.defaults,
|
|
1651
|
+
code: options.defaults?.code ?? code,
|
|
1652
|
+
message: options.defaults?.message ?? inferAxiosMessage(error, responseData, code, redactor),
|
|
1653
|
+
kind: options.defaults?.kind ?? normalizeKind(options.defaults?.code ?? code),
|
|
1654
|
+
retryable: options.defaults?.retryable ?? inferAxiosRetryable(error, options.defaults?.code ?? code),
|
|
1655
|
+
status: options.defaults?.status ?? error.response?.status,
|
|
1656
|
+
provider: {
|
|
1657
|
+
...getProviderDefaults().provider,
|
|
1658
|
+
...options.defaults?.provider ?? {}
|
|
1438
1659
|
},
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1660
|
+
upstream: {
|
|
1661
|
+
...options.defaults?.upstream ?? {},
|
|
1662
|
+
status: error.response?.status ?? options.defaults?.upstream?.status,
|
|
1663
|
+
code: getNestedCode(responseData) ?? options.defaults?.upstream?.code,
|
|
1664
|
+
type: getNestedType(responseData) ?? options.defaults?.upstream?.type,
|
|
1665
|
+
requestId: getHeaderValue(error.response?.headers, "x-request-id") ?? getHeaderValue(error.response?.headers, "request-id") ?? getHeaderValue(error.response?.headers, "x-correlation-id") ?? options.defaults?.upstream?.requestId,
|
|
1666
|
+
method: error.config?.method?.toUpperCase() ?? options.defaults?.upstream?.method,
|
|
1667
|
+
url: buildRequestUrl(error, redactor) ?? options.defaults?.upstream?.url
|
|
1668
|
+
},
|
|
1669
|
+
baggage: mergeRecords(options.defaults?.baggage, {
|
|
1670
|
+
axiosCode: error.code,
|
|
1671
|
+
response: sanitizeForBaggage(responseData, {
|
|
1672
|
+
maxDepth: BAGGAGE_RESPONSE_MAX_DEPTH,
|
|
1673
|
+
redactor: redactor ?? null
|
|
1674
|
+
})
|
|
1447
1675
|
})
|
|
1448
1676
|
});
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1677
|
+
};
|
|
1678
|
+
|
|
1679
|
+
// src/error/service.ts
|
|
1680
|
+
var import_error2 = require("@lowerdeck/error");
|
|
1681
|
+
var SERVICE_ERROR_DATA_RESERVED_KEYS = /* @__PURE__ */ new Set([
|
|
1682
|
+
"status",
|
|
1683
|
+
"code",
|
|
1684
|
+
"message",
|
|
1685
|
+
"hint",
|
|
1686
|
+
"description",
|
|
1687
|
+
"reason",
|
|
1688
|
+
"errors",
|
|
1689
|
+
"object",
|
|
1690
|
+
"ok"
|
|
1691
|
+
]);
|
|
1692
|
+
var isStructuredValue = (value) => (typeof value === "object" || typeof value === "function") && value !== null;
|
|
1693
|
+
var mapServiceErrorCodeByStatus = (status) => {
|
|
1694
|
+
if (status === 400) return "request.bad";
|
|
1695
|
+
if (status === 401) return "auth.required";
|
|
1696
|
+
if (status === 402) return "payment.required";
|
|
1697
|
+
if (status === 403) return "permission.denied";
|
|
1698
|
+
if (status === 404) return "resource.not_found";
|
|
1699
|
+
if (status === 406) return "request.not_acceptable";
|
|
1700
|
+
if (status === 409) return "resource.conflict";
|
|
1701
|
+
if (status === 410) return "resource.gone";
|
|
1702
|
+
if (status === 412) return "request.precondition_failed";
|
|
1703
|
+
if (status === 429) return "request.rate_limited";
|
|
1704
|
+
if (status === 501) return "operation.not_implemented";
|
|
1705
|
+
if (status === 504) return "internal.timeout";
|
|
1706
|
+
if (status && status >= 500) return "internal.unexpected";
|
|
1707
|
+
return DEFAULT_CODE;
|
|
1708
|
+
};
|
|
1709
|
+
var normalizeServiceErrorIssues = (errors) => {
|
|
1710
|
+
if (!Array.isArray(errors)) return void 0;
|
|
1711
|
+
let issues = errors.map((error) => {
|
|
1712
|
+
if (!isRecord2(error)) {
|
|
1713
|
+
return {
|
|
1714
|
+
message: String(error)
|
|
1715
|
+
};
|
|
1716
|
+
}
|
|
1717
|
+
let path = Array.isArray(error.path) ? error.path.map((entry) => String(entry)) : void 0;
|
|
1718
|
+
return {
|
|
1719
|
+
...error,
|
|
1720
|
+
path,
|
|
1721
|
+
code: typeof error.code === "string" ? error.code : void 0,
|
|
1722
|
+
message: typeof error.message === "string" ? error.message : typeof error.hint === "string" ? error.hint : "Validation issue"
|
|
1723
|
+
};
|
|
1724
|
+
});
|
|
1725
|
+
return issues.length > 0 ? issues : void 0;
|
|
1726
|
+
};
|
|
1727
|
+
var getServiceErrorBaggage = (data) => {
|
|
1728
|
+
let extraEntries = Object.entries(data).filter(
|
|
1729
|
+
([key]) => !SERVICE_ERROR_DATA_RESERVED_KEYS.has(key)
|
|
1730
|
+
);
|
|
1731
|
+
return cleanRecord({
|
|
1732
|
+
serviceError: {
|
|
1733
|
+
code: data.code,
|
|
1734
|
+
status: data.status,
|
|
1735
|
+
hint: data.hint,
|
|
1736
|
+
description: data.description,
|
|
1737
|
+
reason: data.reason
|
|
1464
1738
|
},
|
|
1465
|
-
|
|
1739
|
+
...extraEntries.length > 0 ? {
|
|
1740
|
+
serviceErrorData: sanitizeForBaggage(Object.fromEntries(extraEntries))
|
|
1741
|
+
} : {}
|
|
1466
1742
|
});
|
|
1467
|
-
|
|
1468
|
-
|
|
1743
|
+
};
|
|
1744
|
+
var mapServiceErrorCode = (code, status) => SERVICE_ERROR_CODE_MAP[code] ?? mapServiceErrorCodeByStatus(status);
|
|
1745
|
+
var isServiceErrorData = (value) => isRecord2(value) && typeof value.status === "number" && typeof value.code === "string" && typeof value.message === "string" && !("config" in value) && !("request" in value) && !("response" in value) && !("isAxiosError" in value);
|
|
1746
|
+
var getServiceErrorData = (error) => {
|
|
1747
|
+
if ((0, import_error2.isServiceError)(error)) {
|
|
1748
|
+
return isServiceErrorData(error.data) ? error.data : null;
|
|
1469
1749
|
}
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1750
|
+
if (isServiceErrorData(error)) {
|
|
1751
|
+
return error;
|
|
1752
|
+
}
|
|
1753
|
+
if (isStructuredValue(error) && "data" in error && isServiceErrorData(error.data)) {
|
|
1754
|
+
return error.data;
|
|
1755
|
+
}
|
|
1756
|
+
if (isStructuredValue(error) && "toResponse" in error && typeof error.toResponse === "function") {
|
|
1757
|
+
let response = error.toResponse();
|
|
1758
|
+
return isServiceErrorData(response) ? response : null;
|
|
1759
|
+
}
|
|
1760
|
+
return null;
|
|
1761
|
+
};
|
|
1762
|
+
var mapServiceErrorToSlateErrorInput = (error, defaults = {}) => {
|
|
1763
|
+
let data = getServiceErrorData(error);
|
|
1764
|
+
if (!data) {
|
|
1765
|
+
return {
|
|
1766
|
+
code: defaults.code ?? DEFAULT_CODE,
|
|
1767
|
+
message: defaults.message ?? "An unexpected internal error occurred.",
|
|
1768
|
+
kind: defaults.kind,
|
|
1769
|
+
retryable: defaults.retryable,
|
|
1770
|
+
status: defaults.status,
|
|
1771
|
+
provider: defaults.provider,
|
|
1772
|
+
upstream: defaults.upstream,
|
|
1773
|
+
baggage: defaults.baggage
|
|
1774
|
+
};
|
|
1775
|
+
}
|
|
1776
|
+
let code = defaults.code ?? mapServiceErrorCode(data.code, data.status);
|
|
1777
|
+
return {
|
|
1778
|
+
code,
|
|
1779
|
+
message: defaults.message ?? data.message,
|
|
1780
|
+
kind: defaults.kind ?? normalizeKind(code),
|
|
1781
|
+
retryable: defaults.retryable ?? normalizeRetryable(code),
|
|
1782
|
+
status: defaults.status ?? data.status,
|
|
1783
|
+
issues: defaults.issues ?? normalizeServiceErrorIssues(data.errors),
|
|
1784
|
+
provider: defaults.provider,
|
|
1785
|
+
upstream: defaults.upstream,
|
|
1786
|
+
baggage: cleanRecord({
|
|
1787
|
+
...defaults.baggage ?? {},
|
|
1788
|
+
...getServiceErrorBaggage(data)
|
|
1789
|
+
})
|
|
1473
1790
|
};
|
|
1474
1791
|
};
|
|
1475
1792
|
|
|
1476
|
-
// src/
|
|
1477
|
-
var
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
get spec() {
|
|
1487
|
-
return this._spec;
|
|
1793
|
+
// src/error/base.ts
|
|
1794
|
+
var SlateError = class _SlateError extends Error {
|
|
1795
|
+
cause;
|
|
1796
|
+
data;
|
|
1797
|
+
constructor(input) {
|
|
1798
|
+
let normalized = normalizeSlateErrorInput(input);
|
|
1799
|
+
super(normalized.message);
|
|
1800
|
+
this.name = "SlateError";
|
|
1801
|
+
this.data = normalized;
|
|
1802
|
+
this.cause = input.cause;
|
|
1488
1803
|
}
|
|
1489
|
-
get
|
|
1490
|
-
return this.
|
|
1804
|
+
get code() {
|
|
1805
|
+
return this.data.code;
|
|
1491
1806
|
}
|
|
1492
|
-
get
|
|
1493
|
-
return this.
|
|
1807
|
+
get kind() {
|
|
1808
|
+
return this.data.kind;
|
|
1494
1809
|
}
|
|
1495
|
-
get
|
|
1496
|
-
return this.
|
|
1810
|
+
get status() {
|
|
1811
|
+
return this.data.status;
|
|
1497
1812
|
}
|
|
1498
|
-
get
|
|
1499
|
-
return this.
|
|
1813
|
+
get retryable() {
|
|
1814
|
+
return this.data.retryable;
|
|
1500
1815
|
}
|
|
1501
|
-
|
|
1502
|
-
return
|
|
1816
|
+
toResponse() {
|
|
1817
|
+
return {
|
|
1818
|
+
...this.data
|
|
1819
|
+
};
|
|
1503
1820
|
}
|
|
1504
|
-
|
|
1505
|
-
return
|
|
1821
|
+
toJSON() {
|
|
1822
|
+
return this.toResponse();
|
|
1506
1823
|
}
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
// src/adapter/spec.ts
|
|
1510
|
-
var SlateAdapterSpec = class _SlateAdapterSpec {
|
|
1511
|
-
constructor(_params) {
|
|
1512
|
-
this._params = _params;
|
|
1824
|
+
static is(error) {
|
|
1825
|
+
return error instanceof _SlateError;
|
|
1513
1826
|
}
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
if (
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1827
|
+
static fromUnknown(error, defaults = {}) {
|
|
1828
|
+
if (_SlateError.is(error)) return error;
|
|
1829
|
+
if (isSlateErrorResponse(error)) return new _SlateError({ ...defaults, ...error });
|
|
1830
|
+
if (getServiceErrorData(error)) return _SlateError.fromServiceError(error, defaults);
|
|
1831
|
+
if (isAxiosErrorLike(error)) return _SlateError.fromAxios(error, { defaults });
|
|
1832
|
+
if (error instanceof Error) {
|
|
1833
|
+
return new _SlateError({
|
|
1834
|
+
code: defaults.code ?? DEFAULT_CODE,
|
|
1835
|
+
message: error.message,
|
|
1836
|
+
kind: defaults.kind,
|
|
1837
|
+
retryable: defaults.retryable,
|
|
1838
|
+
status: defaults.status,
|
|
1839
|
+
issues: defaults.issues,
|
|
1840
|
+
provider: defaults.provider,
|
|
1841
|
+
upstream: defaults.upstream,
|
|
1842
|
+
baggage: mergeRecords(defaults.baggage, {
|
|
1843
|
+
originalName: error.name
|
|
1844
|
+
}),
|
|
1845
|
+
cause: error
|
|
1846
|
+
});
|
|
1523
1847
|
}
|
|
1524
|
-
return new
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1848
|
+
return new _SlateError({
|
|
1849
|
+
code: defaults.code ?? DEFAULT_CODE,
|
|
1850
|
+
message: getDefaultMessage(defaults.code ?? DEFAULT_CODE, defaults.message),
|
|
1851
|
+
kind: defaults.kind,
|
|
1852
|
+
retryable: defaults.retryable,
|
|
1853
|
+
status: defaults.status,
|
|
1854
|
+
issues: defaults.issues,
|
|
1855
|
+
provider: defaults.provider,
|
|
1856
|
+
upstream: defaults.upstream,
|
|
1857
|
+
baggage: mergeRecords(defaults.baggage, {
|
|
1858
|
+
originalValue: sanitizeForBaggage(error)
|
|
1859
|
+
})
|
|
1528
1860
|
});
|
|
1529
1861
|
}
|
|
1530
|
-
|
|
1531
|
-
return
|
|
1862
|
+
static fromServiceError(error, defaults = {}) {
|
|
1863
|
+
return new _SlateError(mapServiceErrorToSlateErrorInput(error, defaults));
|
|
1532
1864
|
}
|
|
1533
|
-
|
|
1534
|
-
return
|
|
1865
|
+
static fromAxios(error, options = {}) {
|
|
1866
|
+
if (_SlateError.is(error)) return error;
|
|
1867
|
+
if (getServiceErrorData(error))
|
|
1868
|
+
return _SlateError.fromServiceError(error, options.defaults);
|
|
1869
|
+
if (!isAxiosErrorLike(error)) return _SlateError.fromUnknown(error, options.defaults);
|
|
1870
|
+
let inferred = inferSlateErrorFromAxios(error, options);
|
|
1871
|
+
let mapped = options.mapAxiosError?.(error, inferred);
|
|
1872
|
+
if (_SlateError.is(mapped)) return mapped;
|
|
1873
|
+
return new _SlateError(mergeSlateErrorData(inferred, mapped ?? void 0));
|
|
1535
1874
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1875
|
+
};
|
|
1876
|
+
var createSlateError = (input) => new SlateError(input);
|
|
1877
|
+
|
|
1878
|
+
// src/error/declaration.ts
|
|
1879
|
+
var SlateDeclarationError = class _SlateDeclarationError extends SlateError {
|
|
1880
|
+
constructor(message, input = {}) {
|
|
1881
|
+
super({
|
|
1882
|
+
code: "declaration.invalid_definition",
|
|
1883
|
+
kind: "declaration",
|
|
1884
|
+
message,
|
|
1885
|
+
...input
|
|
1886
|
+
});
|
|
1887
|
+
this.name = "SlateError.DeclarationError";
|
|
1538
1888
|
}
|
|
1539
|
-
|
|
1540
|
-
return
|
|
1889
|
+
static is(error) {
|
|
1890
|
+
return error instanceof _SlateDeclarationError;
|
|
1541
1891
|
}
|
|
1542
|
-
|
|
1543
|
-
|
|
1892
|
+
};
|
|
1893
|
+
|
|
1894
|
+
// src/action/scopes.ts
|
|
1895
|
+
var scopeClause = (...scopes) => {
|
|
1896
|
+
assertScopeValues(scopes);
|
|
1897
|
+
return {
|
|
1898
|
+
OR: [...scopes]
|
|
1899
|
+
};
|
|
1900
|
+
};
|
|
1901
|
+
var anyOf = (...scopes) => ({
|
|
1902
|
+
AND: [scopeClause(...scopes)]
|
|
1903
|
+
});
|
|
1904
|
+
var allOf = (...inputs) => {
|
|
1905
|
+
let AND = inputs.flatMap((input) => normalizeScopes(input).AND);
|
|
1906
|
+
return validateScopes({ AND });
|
|
1907
|
+
};
|
|
1908
|
+
var mergeScopes = (...inputs) => {
|
|
1909
|
+
let AND = inputs.flatMap((input) => input ? input.AND : []);
|
|
1910
|
+
if (AND.length === 0) {
|
|
1911
|
+
return void 0;
|
|
1544
1912
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1913
|
+
return validateScopes({ AND });
|
|
1914
|
+
};
|
|
1915
|
+
var validateScopes = (scopes) => {
|
|
1916
|
+
if (!Array.isArray(scopes.AND) || scopes.AND.length === 0) {
|
|
1917
|
+
throw new SlateDeclarationError("Action scopes must include at least one AND clause");
|
|
1547
1918
|
}
|
|
1548
|
-
|
|
1549
|
-
|
|
1919
|
+
return {
|
|
1920
|
+
AND: scopes.AND.map((clause) => normalizeClause(clause))
|
|
1921
|
+
};
|
|
1922
|
+
};
|
|
1923
|
+
var normalizeScopes = (input) => {
|
|
1924
|
+
if (isScopes(input)) {
|
|
1925
|
+
return validateScopes(input);
|
|
1550
1926
|
}
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
);
|
|
1559
|
-
}
|
|
1560
|
-
if (!action.adapter) {
|
|
1561
|
-
throw new SlateDeclarationError(
|
|
1562
|
-
`Action "${action.key}" must be created with this adapter's tool(), publicTool(), or trigger() helpers`
|
|
1563
|
-
);
|
|
1564
|
-
}
|
|
1565
|
-
if (seenKeys.has(action.key)) {
|
|
1566
|
-
throw new SlateDeclarationError(
|
|
1567
|
-
`Adapter "${this.id}" already has an action with key "${action.key}"`
|
|
1568
|
-
);
|
|
1569
|
-
}
|
|
1570
|
-
seenKeys.add(action.key);
|
|
1571
|
-
}
|
|
1572
|
-
return new SlateAdapter(this, params.tools, params.triggers);
|
|
1927
|
+
return {
|
|
1928
|
+
AND: [normalizeClause(input)]
|
|
1929
|
+
};
|
|
1930
|
+
};
|
|
1931
|
+
var normalizeClause = (input) => {
|
|
1932
|
+
if (typeof input === "string") {
|
|
1933
|
+
return scopeClause(input);
|
|
1573
1934
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
}
|
|
1580
|
-
return {
|
|
1581
|
-
...params,
|
|
1582
|
-
adapter: this.id
|
|
1583
|
-
};
|
|
1935
|
+
if (Array.isArray(input)) {
|
|
1936
|
+
return scopeClause(...input);
|
|
1937
|
+
}
|
|
1938
|
+
if (!isClause(input)) {
|
|
1939
|
+
throw new SlateDeclarationError("Action scope clauses must be strings or OR clauses");
|
|
1584
1940
|
}
|
|
1941
|
+
assertScopeValues(input.OR);
|
|
1942
|
+
return {
|
|
1943
|
+
OR: [...input.OR]
|
|
1944
|
+
};
|
|
1585
1945
|
};
|
|
1586
|
-
var
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
seenIds.add(id);
|
|
1598
|
-
return {
|
|
1599
|
-
id,
|
|
1600
|
-
value: capability.value
|
|
1601
|
-
};
|
|
1602
|
-
});
|
|
1946
|
+
var assertScopeValues = (scopes) => {
|
|
1947
|
+
if (scopes.length === 0) {
|
|
1948
|
+
throw new SlateDeclarationError(
|
|
1949
|
+
"Each action scope clause must include at least one OR scope"
|
|
1950
|
+
);
|
|
1951
|
+
}
|
|
1952
|
+
for (let scope of scopes) {
|
|
1953
|
+
if (typeof scope !== "string" || scope.trim().length === 0) {
|
|
1954
|
+
throw new SlateDeclarationError("Action scopes must be non-empty strings");
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1603
1957
|
};
|
|
1958
|
+
var isClause = (value) => typeof value === "object" && value !== null && "OR" in value && Array.isArray(value.OR);
|
|
1959
|
+
var isScopes = (value) => typeof value === "object" && value !== null && "AND" in value && Array.isArray(value.AND);
|
|
1604
1960
|
|
|
1605
|
-
// src/
|
|
1606
|
-
var
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1961
|
+
// src/action/builder.ts
|
|
1962
|
+
var SlateActionBuilder = class {
|
|
1963
|
+
constructor(type, spec2, params, factory, isPublicTool = false) {
|
|
1964
|
+
this.type = type;
|
|
1965
|
+
this.spec = spec2;
|
|
1966
|
+
this.params = params;
|
|
1967
|
+
this.factory = factory;
|
|
1968
|
+
this.isPublicTool = isPublicTool;
|
|
1969
|
+
this.#configSchema = spec2.configSchema;
|
|
1970
|
+
this.#authSchema = spec2.authSchema;
|
|
1610
1971
|
}
|
|
1611
|
-
|
|
1612
|
-
|
|
1972
|
+
type;
|
|
1973
|
+
spec;
|
|
1974
|
+
params;
|
|
1975
|
+
factory;
|
|
1976
|
+
isPublicTool;
|
|
1977
|
+
#configSchema;
|
|
1978
|
+
#authSchema;
|
|
1979
|
+
#inputSchema = null;
|
|
1980
|
+
#outputSchema = null;
|
|
1981
|
+
#scopes;
|
|
1982
|
+
#authMethods;
|
|
1983
|
+
#toolParams = null;
|
|
1984
|
+
#triggerGroup = null;
|
|
1985
|
+
#triggerMatches = null;
|
|
1986
|
+
#triggerMap = null;
|
|
1987
|
+
#interfaceLocked = false;
|
|
1988
|
+
input(schema) {
|
|
1989
|
+
if (this.#interfaceLocked) {
|
|
1990
|
+
throw new SlateDeclarationError("Adapter contract input schema cannot be changed");
|
|
1991
|
+
}
|
|
1992
|
+
this.#inputSchema = schema;
|
|
1993
|
+
return this;
|
|
1613
1994
|
}
|
|
1614
1995
|
output(schema) {
|
|
1996
|
+
if (this.#interfaceLocked) {
|
|
1997
|
+
throw new SlateDeclarationError("Adapter contract output schema cannot be changed");
|
|
1998
|
+
}
|
|
1615
1999
|
this.#outputSchema = schema;
|
|
1616
2000
|
return this;
|
|
1617
2001
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
if (existingKeys.includes(auth2.key)) {
|
|
1621
|
-
throw new Error(`Auth with key "${auth2.key}" already exists in the auth stack`);
|
|
1622
|
-
}
|
|
1623
|
-
this.#authStack.push(auth2);
|
|
2002
|
+
lockInterface() {
|
|
2003
|
+
this.#interfaceLocked = true;
|
|
1624
2004
|
return this;
|
|
1625
2005
|
}
|
|
1626
|
-
|
|
1627
|
-
|
|
2006
|
+
scopes(scopes) {
|
|
2007
|
+
validateScopes(scopes);
|
|
2008
|
+
this.#scopes = scopes;
|
|
1628
2009
|
return this;
|
|
1629
2010
|
}
|
|
1630
|
-
|
|
1631
|
-
this.
|
|
2011
|
+
authMethods(authMethods) {
|
|
2012
|
+
if (this.isPublicTool) {
|
|
2013
|
+
throw new SlateDeclarationError("Public tools cannot require authentication methods");
|
|
2014
|
+
}
|
|
2015
|
+
this.#authMethods = this.validateAuthMethods(authMethods);
|
|
1632
2016
|
return this;
|
|
1633
2017
|
}
|
|
1634
|
-
|
|
1635
|
-
|
|
2018
|
+
validateAuthMethods(authMethods) {
|
|
2019
|
+
if (!authMethods) return void 0;
|
|
2020
|
+
let normalized = [...new Set(authMethods.map((authMethod) => authMethod.trim()))];
|
|
2021
|
+
if (normalized.some((authMethod) => !authMethod)) {
|
|
2022
|
+
throw new SlateDeclarationError("Auth method IDs must be non-empty strings");
|
|
2023
|
+
}
|
|
2024
|
+
return normalized;
|
|
2025
|
+
}
|
|
2026
|
+
handleInvocation(handler) {
|
|
2027
|
+
if (this.type !== "tool") {
|
|
2028
|
+
throw new SlateDeclarationError("handleInvocation can only be set for tool actions");
|
|
2029
|
+
}
|
|
2030
|
+
this.#toolParams = {
|
|
2031
|
+
type: "tool",
|
|
2032
|
+
handleInvocation: handler
|
|
2033
|
+
};
|
|
1636
2034
|
return this;
|
|
1637
2035
|
}
|
|
1638
|
-
|
|
1639
|
-
this.
|
|
2036
|
+
triggerGroup(group) {
|
|
2037
|
+
if (this.type !== "trigger") {
|
|
2038
|
+
throw new SlateDeclarationError("triggerGroup can only be set for trigger actions");
|
|
2039
|
+
}
|
|
2040
|
+
this.#triggerGroup = group;
|
|
1640
2041
|
return this;
|
|
1641
2042
|
}
|
|
1642
|
-
|
|
1643
|
-
this.
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
});
|
|
2043
|
+
matches(handler) {
|
|
2044
|
+
if (this.type !== "trigger") {
|
|
2045
|
+
throw new SlateDeclarationError("matches can only be set for trigger actions");
|
|
2046
|
+
}
|
|
2047
|
+
this.#triggerMatches = handler;
|
|
1648
2048
|
return this;
|
|
1649
2049
|
}
|
|
1650
|
-
|
|
1651
|
-
|
|
2050
|
+
map(handler) {
|
|
2051
|
+
if (this.type !== "trigger") {
|
|
2052
|
+
throw new SlateDeclarationError("map can only be set for trigger actions");
|
|
2053
|
+
}
|
|
2054
|
+
this.#triggerMap = handler;
|
|
2055
|
+
return this;
|
|
1652
2056
|
}
|
|
1653
|
-
|
|
2057
|
+
build() {
|
|
2058
|
+
let scopes = this.#scopes ?? this.params.scopes;
|
|
2059
|
+
if (scopes) {
|
|
2060
|
+
validateScopes(scopes);
|
|
2061
|
+
}
|
|
2062
|
+
let authMethods = this.validateAuthMethods(this.#authMethods ?? this.params.authMethods);
|
|
2063
|
+
if (this.isPublicTool && authMethods) {
|
|
2064
|
+
throw new SlateDeclarationError("Public tools cannot require authentication methods");
|
|
2065
|
+
}
|
|
2066
|
+
if (!this.#inputSchema) {
|
|
2067
|
+
throw new SlateDeclarationError("Input schema is not defined");
|
|
2068
|
+
}
|
|
1654
2069
|
if (!this.#outputSchema) {
|
|
1655
|
-
throw new
|
|
2070
|
+
throw new SlateDeclarationError("Output schema is not defined");
|
|
1656
2071
|
}
|
|
1657
|
-
|
|
2072
|
+
if (this.type === "tool" && !this.#toolParams) {
|
|
2073
|
+
throw new SlateDeclarationError("Tool invocation handler is not defined");
|
|
2074
|
+
}
|
|
2075
|
+
if (this.type === "trigger" && !this.#triggerGroup) {
|
|
2076
|
+
throw new SlateDeclarationError("Trigger group is not defined");
|
|
2077
|
+
}
|
|
2078
|
+
if (this.type === "trigger" && !this.#triggerMatches) {
|
|
2079
|
+
throw new SlateDeclarationError("Trigger matches handler is not defined");
|
|
2080
|
+
}
|
|
2081
|
+
if (this.type === "trigger" && !this.#triggerMap) {
|
|
2082
|
+
throw new SlateDeclarationError("Trigger map handler is not defined");
|
|
2083
|
+
}
|
|
2084
|
+
let triggerParams = this.type === "trigger" ? {
|
|
2085
|
+
type: "trigger",
|
|
2086
|
+
triggerGroup: this.#triggerGroup,
|
|
2087
|
+
matches: this.#triggerMatches,
|
|
2088
|
+
map: this.#triggerMap
|
|
2089
|
+
} : null;
|
|
2090
|
+
return this.factory({
|
|
2091
|
+
...this.params,
|
|
2092
|
+
scopes,
|
|
2093
|
+
authMethods,
|
|
2094
|
+
isPublic: this.isPublicTool === true,
|
|
2095
|
+
configSchema: this.#configSchema,
|
|
2096
|
+
authSchema: this.#authSchema,
|
|
2097
|
+
inputSchema: this.#inputSchema,
|
|
2098
|
+
outputSchema: this.#outputSchema,
|
|
2099
|
+
...this.#toolParams,
|
|
2100
|
+
...triggerParams
|
|
2101
|
+
});
|
|
1658
2102
|
}
|
|
1659
2103
|
};
|
|
1660
|
-
var auth = () => SlateAuth.create();
|
|
1661
2104
|
|
|
1662
|
-
// src/
|
|
1663
|
-
var
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
expiresInType = "numberLike",
|
|
1672
|
-
message
|
|
1673
|
-
} = options;
|
|
1674
|
-
if (expiresIn === void 0 || expiresIn === null || expiresIn === "") {
|
|
1675
|
-
if (required) {
|
|
1676
|
-
throw createApiServiceError(
|
|
1677
|
-
message ?? formatOAuthTokenResponseMessage(
|
|
1678
|
-
"a valid expires_in value",
|
|
1679
|
-
providerLabel,
|
|
1680
|
-
operation
|
|
1681
|
-
),
|
|
1682
|
-
{ reason: "oauth_token_response" }
|
|
1683
|
-
);
|
|
1684
|
-
}
|
|
1685
|
-
return void 0;
|
|
2105
|
+
// src/action/getFileUrlTool.ts
|
|
2106
|
+
var import_zod = require("zod");
|
|
2107
|
+
|
|
2108
|
+
// src/action/tool.ts
|
|
2109
|
+
var SlateTool = class _SlateTool extends SlateAction {
|
|
2110
|
+
#handleInvocation;
|
|
2111
|
+
constructor(spec2, inputSchema, outputSchema, params) {
|
|
2112
|
+
super("tool", spec2, inputSchema, outputSchema, params);
|
|
2113
|
+
this.#handleInvocation = params.handleInvocation;
|
|
1686
2114
|
}
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
{ reason: "oauth_token_response" }
|
|
1692
|
-
);
|
|
2115
|
+
static create(spec2, params) {
|
|
2116
|
+
return new SlateActionBuilder("tool", spec2, params, (params2) => {
|
|
2117
|
+
return _SlateTool.fromCreateParameters(spec2, params2);
|
|
2118
|
+
});
|
|
1693
2119
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
if (typeof refreshToken === "string") {
|
|
1698
|
-
if (fallbackMode === "falsy" && !refreshToken) {
|
|
1699
|
-
return previousRefreshToken;
|
|
1700
|
-
}
|
|
1701
|
-
return refreshToken;
|
|
2120
|
+
static fromCreateParameters(spec2, params) {
|
|
2121
|
+
if (params.type !== "tool") throw new Error("Invalid action type for tool");
|
|
2122
|
+
return new _SlateTool(spec2, params.inputSchema, params.outputSchema, params);
|
|
1702
2123
|
}
|
|
1703
|
-
|
|
1704
|
-
return
|
|
2124
|
+
get handleInvocation() {
|
|
2125
|
+
return this.#handleInvocation;
|
|
1705
2126
|
}
|
|
1706
|
-
return refreshToken === void 0 || refreshToken === null ? previousRefreshToken : void 0;
|
|
1707
2127
|
};
|
|
1708
|
-
var
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
2128
|
+
var tool = (spec2, params) => SlateTool.create(spec2, params);
|
|
2129
|
+
|
|
2130
|
+
// src/action/getFileUrlTool.ts
|
|
2131
|
+
var GET_FILE_URL_TOOL_ID = "metorial$getFileUrl";
|
|
2132
|
+
var getFileUrlToolInputSchema = import_zod.z.object({
|
|
2133
|
+
url: import_zod.z.string(),
|
|
2134
|
+
reference: import_zod.z.any().nullable()
|
|
2135
|
+
});
|
|
2136
|
+
var getFileUrlToolOutputSchema = import_zod.z.object({
|
|
2137
|
+
url: import_zod.z.string(),
|
|
2138
|
+
expiresAt: import_zod.z.string(),
|
|
2139
|
+
headers: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
|
|
2140
|
+
query: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional()
|
|
2141
|
+
});
|
|
2142
|
+
var getFileUrlTool = (spec2, handleGetFileUrl) => tool(spec2, {
|
|
2143
|
+
key: GET_FILE_URL_TOOL_ID,
|
|
2144
|
+
name: "Get File URL",
|
|
2145
|
+
description: "Reserved: refreshes an expiring attachment download URL. Hub-internal only."
|
|
2146
|
+
}).input(getFileUrlToolInputSchema).output(getFileUrlToolOutputSchema).handleInvocation(async (ctx) => {
|
|
2147
|
+
let output = await handleGetFileUrl(ctx);
|
|
2148
|
+
let redactor = new AuthConfigSecretRedactor(ctx._getAuthConfigForRedaction());
|
|
2149
|
+
return {
|
|
2150
|
+
output: {
|
|
2151
|
+
...output,
|
|
2152
|
+
url: redactor.redactEmbedded(output.url, isUrlEmbeddedCredential),
|
|
2153
|
+
...output.headers ? { headers: redactor.redactEmbedded(output.headers) } : {},
|
|
2154
|
+
...output.query ? { query: redactor.redactEmbedded(output.query) } : {}
|
|
2155
|
+
},
|
|
2156
|
+
message: "ok"
|
|
2157
|
+
};
|
|
2158
|
+
}).build();
|
|
2159
|
+
|
|
2160
|
+
// src/action/publicTool.ts
|
|
2161
|
+
var SlatePublicTool = class {
|
|
2162
|
+
constructor() {
|
|
1723
2163
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
2164
|
+
static create(spec2, params) {
|
|
2165
|
+
return new SlateActionBuilder(
|
|
2166
|
+
"tool",
|
|
2167
|
+
spec2,
|
|
2168
|
+
params,
|
|
2169
|
+
(params2) => {
|
|
2170
|
+
return SlateTool.fromCreateParameters(spec2, {
|
|
2171
|
+
...params2,
|
|
2172
|
+
isPublic: true
|
|
2173
|
+
});
|
|
2174
|
+
},
|
|
2175
|
+
true
|
|
1728
2176
|
);
|
|
1729
2177
|
}
|
|
1730
|
-
return {
|
|
1731
|
-
token: data.access_token,
|
|
1732
|
-
refreshToken: getRefreshToken(
|
|
1733
|
-
data.refresh_token,
|
|
1734
|
-
previousRefreshToken,
|
|
1735
|
-
refreshTokenFallbackMode
|
|
1736
|
-
),
|
|
1737
|
-
expiresAt: getOAuthExpiresAtFromExpiresIn(data.expires_in, {
|
|
1738
|
-
...expiresAtOptions,
|
|
1739
|
-
providerLabel,
|
|
1740
|
-
operation,
|
|
1741
|
-
message: expiresInMessage
|
|
1742
|
-
})
|
|
1743
|
-
};
|
|
1744
2178
|
};
|
|
2179
|
+
var publicTool = (spec2, params) => SlatePublicTool.create(spec2, params);
|
|
1745
2180
|
|
|
1746
|
-
// src/
|
|
1747
|
-
var
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
"app[-_.]?token",
|
|
1773
|
-
"user[-_.]?token",
|
|
1774
|
-
"oauth[-_.]?token",
|
|
1775
|
-
"personal[-_.]?access[-_.]?token",
|
|
1776
|
-
"x[-_.]?auth[-_.]?token",
|
|
1777
|
-
"x[-_.]?access[-_.]?token",
|
|
1778
|
-
"x[-_.]?refresh[-_.]?token",
|
|
1779
|
-
// API keys
|
|
1780
|
-
"apikey",
|
|
1781
|
-
"api[-_.]?key",
|
|
1782
|
-
"app[-_.]?key",
|
|
1783
|
-
"x[-_.]?api[-_.]?key",
|
|
1784
|
-
"x[-_.]?app[-_.]?key",
|
|
1785
|
-
// OAuth client credentials
|
|
1786
|
-
"client[-_.]?secret",
|
|
1787
|
-
"client[-_.]?key",
|
|
1788
|
-
"consumer[-_.]?secret",
|
|
1789
|
-
"consumer[-_.]?key",
|
|
1790
|
-
// Cryptographic keys
|
|
1791
|
-
"private[-_.]?key",
|
|
1792
|
-
"privatekey",
|
|
1793
|
-
"secret[-_.]?key",
|
|
1794
|
-
"secretkey",
|
|
1795
|
-
"secret[-_.]?access[-_.]?key",
|
|
1796
|
-
"encryption[-_.]?key",
|
|
1797
|
-
"decryption[-_.]?key",
|
|
1798
|
-
"signing[-_.]?key",
|
|
1799
|
-
"signing[-_.]?secret",
|
|
1800
|
-
"master[-_.]?key",
|
|
1801
|
-
"master[-_.]?secret",
|
|
1802
|
-
"master[-_.]?password",
|
|
1803
|
-
"shared[-_.]?secret",
|
|
1804
|
-
"webhook[-_.]?secret",
|
|
1805
|
-
"webhook[-_.]?signing[-_.]?secret",
|
|
1806
|
-
// OAuth codes & PKCE
|
|
1807
|
-
"auth[-_.]?code",
|
|
1808
|
-
"authcode",
|
|
1809
|
-
"authorization[-_.]?code",
|
|
1810
|
-
"code[-_.]?verifier",
|
|
1811
|
-
"code[-_.]?challenge",
|
|
1812
|
-
// Passwords & passcodes
|
|
1813
|
-
"password",
|
|
1814
|
-
"passwd",
|
|
1815
|
-
"pwd",
|
|
1816
|
-
"passphrase",
|
|
1817
|
-
"pass[-_.]?phrase",
|
|
1818
|
-
"pin",
|
|
1819
|
-
"passcode",
|
|
1820
|
-
// Generic secret markers
|
|
1821
|
-
"secret",
|
|
1822
|
-
"secrets",
|
|
1823
|
-
"credential",
|
|
1824
|
-
"credentials",
|
|
1825
|
-
"creds",
|
|
1826
|
-
"auth",
|
|
1827
|
-
"x[-_.]?auth",
|
|
1828
|
-
"x[-_.]?auth[-_.]?key",
|
|
1829
|
-
// CSRF / XSRF
|
|
1830
|
-
"csrf",
|
|
1831
|
-
"xsrf",
|
|
1832
|
-
"csrf[-_.]?token",
|
|
1833
|
-
"xsrf[-_.]?token",
|
|
1834
|
-
"x[-_.]?csrf[-_.]?token",
|
|
1835
|
-
"x[-_.]?xsrf[-_.]?token",
|
|
1836
|
-
// JWT
|
|
1837
|
-
"jwt",
|
|
1838
|
-
// Sessions & cookies
|
|
1839
|
-
"session[-_.]?id",
|
|
1840
|
-
"sessionid",
|
|
1841
|
-
"sid",
|
|
1842
|
-
"cookie",
|
|
1843
|
-
"cookies",
|
|
1844
|
-
"set[-_.]?cookie",
|
|
1845
|
-
// Signatures / MAC
|
|
1846
|
-
"signature",
|
|
1847
|
-
"x[-_.]?hub[-_.]?signature",
|
|
1848
|
-
"x[-_.]?signature",
|
|
1849
|
-
"sig",
|
|
1850
|
-
"hmac",
|
|
1851
|
-
"mac",
|
|
1852
|
-
// Crypto artifacts
|
|
1853
|
-
"salt",
|
|
1854
|
-
"nonce",
|
|
1855
|
-
// Multi-factor / verification
|
|
1856
|
-
"otp",
|
|
1857
|
-
"totp",
|
|
1858
|
-
"mfa",
|
|
1859
|
-
"mfa[-_.]?code",
|
|
1860
|
-
"2fa",
|
|
1861
|
-
"two[-_.]?factor",
|
|
1862
|
-
"twofactor",
|
|
1863
|
-
"verification[-_.]?code",
|
|
1864
|
-
"verify[-_.]?code",
|
|
1865
|
-
"confirm(?:ation)?[-_.]?code",
|
|
1866
|
-
"sms[-_.]?code",
|
|
1867
|
-
"email[-_.]?code",
|
|
1868
|
-
// Recovery & seed phrases
|
|
1869
|
-
"seed[-_.]?phrase",
|
|
1870
|
-
"mnemonic",
|
|
1871
|
-
"recovery[-_.]?key",
|
|
1872
|
-
"recovery[-_.]?code",
|
|
1873
|
-
"recovery[-_.]?phrase",
|
|
1874
|
-
// PII / financial
|
|
1875
|
-
"card[-_.]?number",
|
|
1876
|
-
"card[-_.]?code",
|
|
1877
|
-
"cvv",
|
|
1878
|
-
"cvc",
|
|
1879
|
-
"ccv",
|
|
1880
|
-
"cc[-_.]?num(?:ber)?",
|
|
1881
|
-
"pan",
|
|
1882
|
-
"ssn",
|
|
1883
|
-
"social[-_.]?security",
|
|
1884
|
-
"license[-_.]?key"
|
|
1885
|
-
];
|
|
1886
|
-
var URL_FORM_SECRET_KEY_ATOMS = [...CORE_SECRET_KEY_ATOMS, "code"];
|
|
1887
|
-
var buildKeyBoundaryPattern = (atoms, flags) => new RegExp(`(?:^|[^A-Za-z0-9])(?:${atoms.join("|")})(?=[^A-Za-z0-9]|$)`, flags);
|
|
1888
|
-
var SECRET_KEY_PATTERN = buildKeyBoundaryPattern(CORE_SECRET_KEY_ATOMS, "i");
|
|
1889
|
-
var URL_FORM_SECRET_KEY_PATTERN = buildKeyBoundaryPattern(URL_FORM_SECRET_KEY_ATOMS, "i");
|
|
1890
|
-
var NON_SECRET_KEY_EXACT = /* @__PURE__ */ new Set([
|
|
1891
|
-
"token_type",
|
|
1892
|
-
"token-type",
|
|
1893
|
-
"tokentype",
|
|
1894
|
-
"token_kind",
|
|
1895
|
-
"token-kind",
|
|
1896
|
-
"tokenkind",
|
|
1897
|
-
"token_ttl",
|
|
1898
|
-
"token-ttl",
|
|
1899
|
-
"token_expires_in",
|
|
1900
|
-
"token-expires-in",
|
|
1901
|
-
"token_expiry",
|
|
1902
|
-
"signature_method",
|
|
1903
|
-
"signature-method",
|
|
1904
|
-
"signature_type",
|
|
1905
|
-
"signature-type",
|
|
1906
|
-
"signature_version",
|
|
1907
|
-
"signature-version",
|
|
1908
|
-
"auth_type",
|
|
1909
|
-
"auth-type",
|
|
1910
|
-
"auth_method",
|
|
1911
|
-
"auth-method",
|
|
1912
|
-
"authentication_type",
|
|
1913
|
-
"authentication-type",
|
|
1914
|
-
"authentication_method",
|
|
1915
|
-
"authentication-method",
|
|
1916
|
-
"grant_type",
|
|
1917
|
-
"grant-type",
|
|
1918
|
-
"password_strength",
|
|
1919
|
-
"password-strength",
|
|
1920
|
-
"password_policy",
|
|
1921
|
-
"password-policy",
|
|
1922
|
-
"key_type",
|
|
1923
|
-
"key-type",
|
|
1924
|
-
"key_name",
|
|
1925
|
-
"key-name",
|
|
1926
|
-
"key_id",
|
|
1927
|
-
"key-id",
|
|
1928
|
-
"kid"
|
|
1929
|
-
]);
|
|
1930
|
-
var isSecretKeyName = (name) => {
|
|
1931
|
-
let normalized = name.toLowerCase();
|
|
1932
|
-
if (NON_SECRET_KEY_EXACT.has(normalized)) return false;
|
|
1933
|
-
return SECRET_KEY_PATTERN.test(normalized);
|
|
2181
|
+
// src/action/trigger.ts
|
|
2182
|
+
var SlateTrigger = class _SlateTrigger extends SlateAction {
|
|
2183
|
+
#triggerGroup;
|
|
2184
|
+
#matches;
|
|
2185
|
+
#map;
|
|
2186
|
+
constructor(spec2, inputSchema, outputSchema, params) {
|
|
2187
|
+
super("trigger", spec2, inputSchema, outputSchema, params);
|
|
2188
|
+
this.#triggerGroup = params.triggerGroup;
|
|
2189
|
+
this.#matches = params.matches;
|
|
2190
|
+
this.#map = params.map;
|
|
2191
|
+
}
|
|
2192
|
+
static create(spec2, params) {
|
|
2193
|
+
return new SlateActionBuilder("trigger", spec2, params, (params2) => {
|
|
2194
|
+
if (params2.type !== "trigger") throw new Error("Invalid action type for trigger");
|
|
2195
|
+
return new _SlateTrigger(spec2, params2.inputSchema, params2.outputSchema, params2);
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
get triggerGroup() {
|
|
2199
|
+
return this.#triggerGroup;
|
|
2200
|
+
}
|
|
2201
|
+
get matches() {
|
|
2202
|
+
return this.#matches;
|
|
2203
|
+
}
|
|
2204
|
+
get map() {
|
|
2205
|
+
return this.#map;
|
|
2206
|
+
}
|
|
1934
2207
|
};
|
|
1935
|
-
var
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
2208
|
+
var trigger = (spec2, params) => SlateTrigger.create(spec2, params);
|
|
2209
|
+
|
|
2210
|
+
// src/action/triggerGroup.ts
|
|
2211
|
+
var import_zod2 = require("zod");
|
|
2212
|
+
var SlateDefaultPollingIntervalSeconds = 60 * 10;
|
|
2213
|
+
var SlateTriggerGroup = class _SlateTriggerGroup {
|
|
2214
|
+
constructor(_spec, _params) {
|
|
2215
|
+
this._spec = _spec;
|
|
2216
|
+
this._params = _params;
|
|
2217
|
+
}
|
|
2218
|
+
_spec;
|
|
2219
|
+
_params;
|
|
2220
|
+
static create(spec2, params) {
|
|
2221
|
+
return new SlateTriggerGroupBuilder(spec2, params, (p) => new _SlateTriggerGroup(spec2, p));
|
|
2222
|
+
}
|
|
2223
|
+
get spec() {
|
|
2224
|
+
return this._spec;
|
|
2225
|
+
}
|
|
2226
|
+
get key() {
|
|
2227
|
+
return this._params.key;
|
|
2228
|
+
}
|
|
2229
|
+
get name() {
|
|
2230
|
+
return this._params.name;
|
|
2231
|
+
}
|
|
2232
|
+
get description() {
|
|
2233
|
+
return this._params.description;
|
|
2234
|
+
}
|
|
2235
|
+
get metadata() {
|
|
2236
|
+
return this._params.metadata;
|
|
2237
|
+
}
|
|
2238
|
+
get eventSchema() {
|
|
2239
|
+
return this._params.eventSchema ?? import_zod2.z.object({}).passthrough();
|
|
2240
|
+
}
|
|
2241
|
+
get source() {
|
|
2242
|
+
return this._params.source;
|
|
2243
|
+
}
|
|
2244
|
+
get polling() {
|
|
2245
|
+
return this._params.polling;
|
|
2246
|
+
}
|
|
2247
|
+
get webhook() {
|
|
2248
|
+
return this._params.webhook;
|
|
2249
|
+
}
|
|
2250
|
+
get gateway() {
|
|
2251
|
+
return this._params.gateway;
|
|
2252
|
+
}
|
|
2253
|
+
get routingMatchers() {
|
|
2254
|
+
return this._params.routingMatchers;
|
|
2255
|
+
}
|
|
1939
2256
|
};
|
|
1940
|
-
var
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
return SAFE_HEADER_PREFIXES.some((prefix) => normalized.startsWith(prefix));
|
|
2257
|
+
var SlateTriggerGroupBuilder = class {
|
|
2258
|
+
constructor(spec2, params, factory) {
|
|
2259
|
+
this.spec = spec2;
|
|
2260
|
+
this.params = params;
|
|
2261
|
+
this.factory = factory;
|
|
2262
|
+
}
|
|
2263
|
+
spec;
|
|
2264
|
+
params;
|
|
2265
|
+
factory;
|
|
2266
|
+
#source = null;
|
|
2267
|
+
#polling = null;
|
|
2268
|
+
#webhook = null;
|
|
2269
|
+
#gateway = null;
|
|
2270
|
+
#routingMatchers = null;
|
|
2271
|
+
polling(props) {
|
|
2272
|
+
if (this.#source) {
|
|
2273
|
+
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
2274
|
+
}
|
|
2275
|
+
this.#source = "polling";
|
|
2276
|
+
this.#polling = {
|
|
2277
|
+
intervalSeconds: props.intervalSeconds ?? SlateDefaultPollingIntervalSeconds,
|
|
2278
|
+
pollEvents: props.pollEvents
|
|
2279
|
+
};
|
|
2280
|
+
return this;
|
|
2281
|
+
}
|
|
2282
|
+
webhook(props) {
|
|
2283
|
+
if (this.#source) {
|
|
2284
|
+
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
2285
|
+
}
|
|
2286
|
+
if (!!props.autoRegistration === !!props.manualRegistration) {
|
|
2287
|
+
throw new SlateDeclarationError(
|
|
2288
|
+
"Webhook trigger groups require exactly one of autoRegistration or manualRegistration"
|
|
2289
|
+
);
|
|
2290
|
+
}
|
|
2291
|
+
this.#source = "webhook";
|
|
2292
|
+
this.#webhook = {
|
|
2293
|
+
autoRegistration: props.autoRegistration,
|
|
2294
|
+
manualRegistration: props.manualRegistration,
|
|
2295
|
+
process: props.process
|
|
2296
|
+
};
|
|
2297
|
+
return this;
|
|
2298
|
+
}
|
|
2299
|
+
/** Receive events over a platform-managed persistent connection (e.g. a WebSocket gateway). */
|
|
2300
|
+
gateway(props) {
|
|
2301
|
+
if (this.#source) {
|
|
2302
|
+
throw new SlateDeclarationError("Trigger group invocation is already defined");
|
|
2303
|
+
}
|
|
2304
|
+
this.#source = "gateway";
|
|
2305
|
+
this.#gateway = { connect: props.connect, receive: props.receive };
|
|
2306
|
+
return this;
|
|
2307
|
+
}
|
|
2308
|
+
routingMatchers(handler) {
|
|
2309
|
+
this.#routingMatchers = handler;
|
|
2310
|
+
return this;
|
|
2311
|
+
}
|
|
2312
|
+
build() {
|
|
2313
|
+
if (!this.#source) {
|
|
2314
|
+
throw new SlateDeclarationError(
|
|
2315
|
+
"Trigger group invocation (polling, webhook, or gateway) is not defined"
|
|
2316
|
+
);
|
|
2317
|
+
}
|
|
2318
|
+
if (!this.#routingMatchers) {
|
|
2319
|
+
throw new SlateDeclarationError("Trigger group routing matchers handler is not defined");
|
|
2320
|
+
}
|
|
2321
|
+
return this.factory({
|
|
2322
|
+
...this.params,
|
|
2323
|
+
source: this.#source,
|
|
2324
|
+
polling: this.#polling ?? void 0,
|
|
2325
|
+
webhook: this.#webhook ?? void 0,
|
|
2326
|
+
gateway: this.#gateway ?? void 0,
|
|
2327
|
+
routingMatchers: this.#routingMatchers
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2014
2330
|
};
|
|
2015
|
-
var
|
|
2016
|
-
|
|
2017
|
-
|
|
2331
|
+
var triggerGroup = (spec2, params) => SlateTriggerGroup.create(spec2, params);
|
|
2332
|
+
|
|
2333
|
+
// src/action/attachment.ts
|
|
2334
|
+
var createUrlAttachment = (url, opts = {}) => {
|
|
2335
|
+
if (opts.refreshReference !== void 0 && !opts.refreshAt) {
|
|
2336
|
+
throw new Error("createUrlAttachment: refreshAt is required when refreshReference is set");
|
|
2018
2337
|
}
|
|
2019
2338
|
return {
|
|
2020
|
-
|
|
2021
|
-
|
|
2339
|
+
mimeType: opts.mimeType,
|
|
2340
|
+
attachmentHash: opts.attachmentHash,
|
|
2341
|
+
content: {
|
|
2342
|
+
type: "url",
|
|
2343
|
+
url,
|
|
2344
|
+
...opts.headers ? { headers: opts.headers } : {},
|
|
2345
|
+
...opts.query ? { query: opts.query } : {},
|
|
2346
|
+
...opts.refreshReference !== void 0 ? { refreshReference: opts.refreshReference } : {},
|
|
2347
|
+
...opts.refreshAt ? { refreshAt: opts.refreshAt } : {}
|
|
2348
|
+
}
|
|
2022
2349
|
};
|
|
2023
2350
|
};
|
|
2024
|
-
var
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
for (let pattern of KNOWN_SECRET_VALUE_PATTERNS) {
|
|
2032
|
-
result = result.replace(pattern, REDACTED_VALUE);
|
|
2351
|
+
var createBase64Attachment = (content, mimeType, attachmentHash) => ({
|
|
2352
|
+
mimeType,
|
|
2353
|
+
attachmentHash,
|
|
2354
|
+
content: {
|
|
2355
|
+
type: "content",
|
|
2356
|
+
encoding: "base64",
|
|
2357
|
+
content
|
|
2033
2358
|
}
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
};
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
if (
|
|
2048
|
-
|
|
2049
|
-
|
|
2359
|
+
});
|
|
2360
|
+
var createTextAttachment = (content, mimeType, attachmentHash) => ({
|
|
2361
|
+
mimeType,
|
|
2362
|
+
attachmentHash,
|
|
2363
|
+
content: {
|
|
2364
|
+
type: "content",
|
|
2365
|
+
encoding: "utf-8",
|
|
2366
|
+
content
|
|
2367
|
+
}
|
|
2368
|
+
});
|
|
2369
|
+
|
|
2370
|
+
// src/action/directUpload.ts
|
|
2371
|
+
var bufferAttachmentBody = async (body, maxSizeBytes) => {
|
|
2372
|
+
if (body instanceof Uint8Array) {
|
|
2373
|
+
if (body.byteLength > maxSizeBytes) {
|
|
2374
|
+
throw new Error(`Attachment exceeds the maximum size of ${maxSizeBytes} bytes`);
|
|
2375
|
+
}
|
|
2376
|
+
let buffered2 = new ArrayBuffer(body.byteLength);
|
|
2377
|
+
new Uint8Array(buffered2).set(body);
|
|
2378
|
+
return buffered2;
|
|
2050
2379
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2380
|
+
let reader = body.getReader();
|
|
2381
|
+
let chunks = [];
|
|
2382
|
+
let sizeBytes = 0;
|
|
2383
|
+
while (true) {
|
|
2384
|
+
let { done, value } = await reader.read();
|
|
2385
|
+
if (done) break;
|
|
2386
|
+
if (!value) continue;
|
|
2387
|
+
sizeBytes += value.byteLength;
|
|
2388
|
+
if (sizeBytes > maxSizeBytes) {
|
|
2389
|
+
await reader.cancel();
|
|
2390
|
+
throw new Error(`Attachment exceeds the maximum size of ${maxSizeBytes} bytes`);
|
|
2391
|
+
}
|
|
2392
|
+
chunks.push(value);
|
|
2053
2393
|
}
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
);
|
|
2394
|
+
let buffered = new ArrayBuffer(sizeBytes);
|
|
2395
|
+
let bufferedView = new Uint8Array(buffered);
|
|
2396
|
+
let offset = 0;
|
|
2397
|
+
for (let chunk of chunks) {
|
|
2398
|
+
bufferedView.set(chunk, offset);
|
|
2399
|
+
offset += chunk.byteLength;
|
|
2061
2400
|
}
|
|
2062
|
-
return
|
|
2401
|
+
return buffered;
|
|
2063
2402
|
};
|
|
2064
|
-
var
|
|
2065
|
-
let
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2403
|
+
var uploadAttachmentDirect = async (d) => {
|
|
2404
|
+
let baseUrl = d.live.baseUrl.replace(/\/$/, "");
|
|
2405
|
+
let body = await bufferAttachmentBody(d.body, d.live.maxAttachmentSizeBytes);
|
|
2406
|
+
let registerRes = await fetch(`${baseUrl}/slates-hub/live-invocation/attachments`, {
|
|
2407
|
+
method: "POST",
|
|
2408
|
+
headers: {
|
|
2409
|
+
"content-type": "application/json",
|
|
2410
|
+
authorization: `Bearer ${d.live.token}`
|
|
2411
|
+
},
|
|
2412
|
+
body: JSON.stringify({
|
|
2413
|
+
attachments: [
|
|
2414
|
+
{
|
|
2415
|
+
mimeType: d.mimeType,
|
|
2416
|
+
filename: d.filename,
|
|
2417
|
+
sizeBytes: body.byteLength || void 0
|
|
2418
|
+
}
|
|
2419
|
+
]
|
|
2420
|
+
})
|
|
2421
|
+
});
|
|
2422
|
+
if (!registerRes.ok) {
|
|
2423
|
+
throw new Error(
|
|
2424
|
+
`Failed to register attachment for direct upload (status ${registerRes.status})`
|
|
2425
|
+
);
|
|
2069
2426
|
}
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2427
|
+
let { attachments } = await registerRes.json();
|
|
2428
|
+
let registration = attachments[0];
|
|
2429
|
+
if (!registration) {
|
|
2430
|
+
throw new Error("Live invocation API returned no attachment registrations");
|
|
2431
|
+
}
|
|
2432
|
+
let putRes = await fetch(registration.uploadUrl, {
|
|
2433
|
+
method: "PUT",
|
|
2434
|
+
headers: {
|
|
2435
|
+
...d.mimeType ? { "content-type": d.mimeType } : {},
|
|
2436
|
+
"content-length": String(body.byteLength)
|
|
2437
|
+
},
|
|
2438
|
+
body
|
|
2439
|
+
});
|
|
2440
|
+
if (!putRes.ok) {
|
|
2441
|
+
throw new Error(`Failed to upload attachment content (status ${putRes.status})`);
|
|
2074
2442
|
}
|
|
2075
|
-
};
|
|
2076
|
-
var sanitizeTextBody = (text, contentType, redactor) => {
|
|
2077
|
-
if (!text) return void 0;
|
|
2078
|
-
let normalizedContentType = normalizeContentType(contentType);
|
|
2079
|
-
let parsedJson = maybeParseJson(text, normalizedContentType);
|
|
2080
|
-
let normalizedText = parsedJson !== null ? JSON.stringify(redactStructuredValue(parsedJson, 0, redactor)) : sanitizeFreeText(text, redactor);
|
|
2081
|
-
let { text: truncatedText, truncated } = truncateText(normalizedText);
|
|
2082
2443
|
return {
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
...truncated ? { truncated: true } : {}
|
|
2444
|
+
mimeType: d.mimeType,
|
|
2445
|
+
content: { type: "upload_reference", referenceId: registration.referenceId }
|
|
2086
2446
|
};
|
|
2087
2447
|
};
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
};
|
|
2096
|
-
var serializeTextBody = (value, contentType, redactor) => {
|
|
2097
|
-
let normalizedContentType = normalizeContentType(contentType);
|
|
2098
|
-
if (value == null || isBinaryLike(value) || !isTextContentType(normalizedContentType)) {
|
|
2099
|
-
return void 0;
|
|
2448
|
+
|
|
2449
|
+
// src/adapter/adapter.ts
|
|
2450
|
+
var SlateAdapter = class {
|
|
2451
|
+
constructor(_spec, _tools, _triggers) {
|
|
2452
|
+
this._spec = _spec;
|
|
2453
|
+
this._tools = _tools;
|
|
2454
|
+
this._triggers = _triggers;
|
|
2100
2455
|
}
|
|
2101
|
-
|
|
2102
|
-
|
|
2456
|
+
_spec;
|
|
2457
|
+
_tools;
|
|
2458
|
+
_triggers;
|
|
2459
|
+
get spec() {
|
|
2460
|
+
return this._spec;
|
|
2103
2461
|
}
|
|
2104
|
-
|
|
2105
|
-
return
|
|
2462
|
+
get id() {
|
|
2463
|
+
return this._spec.id;
|
|
2106
2464
|
}
|
|
2107
|
-
|
|
2108
|
-
return
|
|
2465
|
+
get name() {
|
|
2466
|
+
return this._spec.name;
|
|
2109
2467
|
}
|
|
2110
|
-
|
|
2111
|
-
return
|
|
2112
|
-
JSON.stringify(redactStructuredValue(value, 0, redactor)),
|
|
2113
|
-
"application/json",
|
|
2114
|
-
redactor
|
|
2115
|
-
);
|
|
2468
|
+
get capabilities() {
|
|
2469
|
+
return this._spec.capabilities;
|
|
2116
2470
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
return url;
|
|
2471
|
+
get tools() {
|
|
2472
|
+
return this._tools;
|
|
2473
|
+
}
|
|
2474
|
+
get triggers() {
|
|
2475
|
+
return this._triggers;
|
|
2476
|
+
}
|
|
2477
|
+
get actions() {
|
|
2478
|
+
return [...this._triggers, ...this._tools];
|
|
2126
2479
|
}
|
|
2127
2480
|
};
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
var
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2481
|
+
|
|
2482
|
+
// src/adapter/spec.ts
|
|
2483
|
+
var SlateAdapterSpec = class _SlateAdapterSpec {
|
|
2484
|
+
constructor(_params) {
|
|
2485
|
+
this._params = _params;
|
|
2486
|
+
}
|
|
2487
|
+
_params;
|
|
2488
|
+
static create(params) {
|
|
2489
|
+
let id = params.id?.trim();
|
|
2490
|
+
let name = params.name?.trim();
|
|
2491
|
+
if (!id) {
|
|
2492
|
+
throw new SlateDeclarationError("Adapter id must be a non-empty string");
|
|
2139
2493
|
}
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
};
|
|
2143
|
-
var sanitizeUrl = (value, redactor) => {
|
|
2144
|
-
if (!value) return value;
|
|
2145
|
-
try {
|
|
2146
|
-
let url = new URL(value);
|
|
2147
|
-
if (url.username || url.password) {
|
|
2148
|
-
url.username = "";
|
|
2149
|
-
url.password = "";
|
|
2494
|
+
if (!name) {
|
|
2495
|
+
throw new SlateDeclarationError("Adapter name must be a non-empty string");
|
|
2150
2496
|
}
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2497
|
+
return new _SlateAdapterSpec({
|
|
2498
|
+
id,
|
|
2499
|
+
name,
|
|
2500
|
+
capabilities: validateCapabilities(params.capabilities ?? [])
|
|
2501
|
+
});
|
|
2502
|
+
}
|
|
2503
|
+
get id() {
|
|
2504
|
+
return this._params.id;
|
|
2505
|
+
}
|
|
2506
|
+
get name() {
|
|
2507
|
+
return this._params.name;
|
|
2508
|
+
}
|
|
2509
|
+
get capabilities() {
|
|
2510
|
+
return this._params.capabilities;
|
|
2511
|
+
}
|
|
2512
|
+
get parameters() {
|
|
2513
|
+
return this._params;
|
|
2514
|
+
}
|
|
2515
|
+
tool(spec2, params) {
|
|
2516
|
+
return SlateTool.create(spec2, this.linkAction(params));
|
|
2517
|
+
}
|
|
2518
|
+
publicTool(spec2, params) {
|
|
2519
|
+
return SlatePublicTool.create(spec2, this.linkAction(params));
|
|
2520
|
+
}
|
|
2521
|
+
trigger(spec2, params) {
|
|
2522
|
+
return SlateTrigger.create(spec2, this.linkAction(params));
|
|
2523
|
+
}
|
|
2524
|
+
register(params) {
|
|
2525
|
+
let actions = [...params.tools, ...params.triggers];
|
|
2526
|
+
let seenKeys = /* @__PURE__ */ new Set();
|
|
2527
|
+
for (let action of actions) {
|
|
2528
|
+
if (action.adapter && action.adapter !== this.id) {
|
|
2529
|
+
throw new SlateDeclarationError(
|
|
2530
|
+
`Action "${action.key}" is linked to adapter "${action.adapter}", not "${this.id}"`
|
|
2531
|
+
);
|
|
2155
2532
|
}
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2533
|
+
if (!action.adapter) {
|
|
2534
|
+
throw new SlateDeclarationError(
|
|
2535
|
+
`Action "${action.key}" must be created with this adapter's tool(), publicTool(), or trigger() helpers`
|
|
2536
|
+
);
|
|
2537
|
+
}
|
|
2538
|
+
if (seenKeys.has(action.key)) {
|
|
2539
|
+
throw new SlateDeclarationError(
|
|
2540
|
+
`Adapter "${this.id}" already has an action with key "${action.key}"`
|
|
2541
|
+
);
|
|
2542
|
+
}
|
|
2543
|
+
seenKeys.add(action.key);
|
|
2159
2544
|
}
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2545
|
+
return new SlateAdapter(this, params.tools, params.triggers);
|
|
2546
|
+
}
|
|
2547
|
+
linkAction(params) {
|
|
2548
|
+
if (params.adapter != null && params.adapter !== this.id) {
|
|
2549
|
+
throw new SlateDeclarationError(
|
|
2550
|
+
`Action "${params.key}" cannot be linked to adapter "${this.id}" because it is already linked to "${params.adapter}"`
|
|
2551
|
+
);
|
|
2552
|
+
}
|
|
2553
|
+
return {
|
|
2554
|
+
...params,
|
|
2555
|
+
adapter: this.id
|
|
2556
|
+
};
|
|
2168
2557
|
}
|
|
2169
2558
|
};
|
|
2170
|
-
var
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
let
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2559
|
+
var adapterSpec = (params) => SlateAdapterSpec.create(params);
|
|
2560
|
+
var validateCapabilities = (capabilities) => {
|
|
2561
|
+
let seenIds = /* @__PURE__ */ new Set();
|
|
2562
|
+
return capabilities.map((capability) => {
|
|
2563
|
+
let id = capability.id?.trim();
|
|
2564
|
+
if (!id) {
|
|
2565
|
+
throw new SlateDeclarationError("Adapter capability ids must be non-empty strings");
|
|
2566
|
+
}
|
|
2567
|
+
if (seenIds.has(id)) {
|
|
2568
|
+
throw new SlateDeclarationError(`Adapter capability "${id}" is defined more than once`);
|
|
2569
|
+
}
|
|
2570
|
+
seenIds.add(id);
|
|
2571
|
+
return {
|
|
2572
|
+
id,
|
|
2573
|
+
value: capability.value
|
|
2574
|
+
};
|
|
2575
|
+
});
|
|
2178
2576
|
};
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2577
|
+
|
|
2578
|
+
// src/auth/auth.ts
|
|
2579
|
+
var SlateAuth = class _SlateAuth {
|
|
2580
|
+
#outputSchema = null;
|
|
2581
|
+
#authStack = [];
|
|
2582
|
+
constructor() {
|
|
2583
|
+
}
|
|
2584
|
+
static create() {
|
|
2585
|
+
return new _SlateAuth();
|
|
2586
|
+
}
|
|
2587
|
+
output(schema) {
|
|
2588
|
+
this.#outputSchema = schema;
|
|
2589
|
+
return this;
|
|
2590
|
+
}
|
|
2591
|
+
addAuth(auth2) {
|
|
2592
|
+
let existingKeys = this.#authStack.map((a) => a.key);
|
|
2593
|
+
if (existingKeys.includes(auth2.key)) {
|
|
2594
|
+
throw new Error(`Auth with key "${auth2.key}" already exists in the auth stack`);
|
|
2188
2595
|
}
|
|
2596
|
+
this.#authStack.push(auth2);
|
|
2597
|
+
return this;
|
|
2189
2598
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
).map(([key, value]) => [key, value]);
|
|
2599
|
+
addOauth(auth2) {
|
|
2600
|
+
this.addAuth(auth2);
|
|
2601
|
+
return this;
|
|
2194
2602
|
}
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
return flattened ? [key, flattened] : null;
|
|
2199
|
-
}).filter((entry) => entry !== null);
|
|
2603
|
+
addTokenAuth(auth2) {
|
|
2604
|
+
this.addAuth(auth2);
|
|
2605
|
+
return this;
|
|
2200
2606
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
let entries = headerEntries(headers).map(
|
|
2205
|
-
([key, value]) => [key.toLowerCase(), sanitizeScalar(value, redactor).text]
|
|
2206
|
-
).filter(([key]) => isSafeHeaderName(key));
|
|
2207
|
-
if (entries.length === 0) return void 0;
|
|
2208
|
-
return Object.fromEntries(entries);
|
|
2209
|
-
};
|
|
2210
|
-
var getContentType = (headers) => headerEntries(headers).find(([key]) => key.toLowerCase() === "content-type")?.[1];
|
|
2211
|
-
var takeTraceDraft = (config2) => {
|
|
2212
|
-
if (!config2) return void 0;
|
|
2213
|
-
let draft = config2.__slatesHttpTraceDraft ?? (isObjectLike(config2) ? traceDraftsByConfig.get(config2) : void 0) ?? (isObjectLike(config2.headers) ? traceDraftsByHeaders.get(config2.headers) : void 0);
|
|
2214
|
-
if (!draft) return void 0;
|
|
2215
|
-
return draft;
|
|
2216
|
-
};
|
|
2217
|
-
var clearTraceDraft = (config2, draft) => {
|
|
2218
|
-
if (!config2) return;
|
|
2219
|
-
if (config2.__slatesHttpTraceDraft === draft) {
|
|
2220
|
-
config2.__slatesHttpTraceDraft = void 0;
|
|
2607
|
+
addServiceAccountAuth(auth2) {
|
|
2608
|
+
this.addAuth(auth2);
|
|
2609
|
+
return this;
|
|
2221
2610
|
}
|
|
2222
|
-
|
|
2223
|
-
|
|
2611
|
+
addCustomAuth(auth2) {
|
|
2612
|
+
this.addAuth(auth2);
|
|
2613
|
+
return this;
|
|
2224
2614
|
}
|
|
2225
|
-
|
|
2226
|
-
|
|
2615
|
+
addNone() {
|
|
2616
|
+
this.addAuth({
|
|
2617
|
+
type: "auth.none",
|
|
2618
|
+
name: "No Authentication",
|
|
2619
|
+
key: "none"
|
|
2620
|
+
});
|
|
2621
|
+
return this;
|
|
2622
|
+
}
|
|
2623
|
+
get authStack() {
|
|
2624
|
+
return this.#authStack.filter((a) => a.type !== "auth.none");
|
|
2625
|
+
}
|
|
2626
|
+
get outputSchema() {
|
|
2627
|
+
if (!this.#outputSchema) {
|
|
2628
|
+
throw new Error("Output schema is not defined for this auth");
|
|
2629
|
+
}
|
|
2630
|
+
return this.#outputSchema;
|
|
2227
2631
|
}
|
|
2228
2632
|
};
|
|
2229
|
-
var
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2633
|
+
var auth = () => SlateAuth.create();
|
|
2634
|
+
|
|
2635
|
+
// src/auth/oauth.ts
|
|
2636
|
+
var isOAuthTokenResponse = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2637
|
+
var formatOAuthTokenResponseMessage = (fieldLabel, providerLabel = "OAuth provider", operation = "token response") => `${providerLabel} OAuth ${operation} did not return ${fieldLabel}.`;
|
|
2638
|
+
var getOAuthExpiresAtFromExpiresIn = (expiresIn, options = {}) => {
|
|
2639
|
+
let {
|
|
2640
|
+
nowMs = Date.now(),
|
|
2641
|
+
providerLabel,
|
|
2642
|
+
operation,
|
|
2643
|
+
required = false,
|
|
2644
|
+
expiresInType = "numberLike",
|
|
2645
|
+
message
|
|
2646
|
+
} = options;
|
|
2647
|
+
if (expiresIn === void 0 || expiresIn === null || expiresIn === "") {
|
|
2648
|
+
if (required) {
|
|
2649
|
+
throw createApiServiceError(
|
|
2650
|
+
message ?? formatOAuthTokenResponseMessage(
|
|
2651
|
+
"a valid expires_in value",
|
|
2652
|
+
providerLabel,
|
|
2653
|
+
operation
|
|
2654
|
+
),
|
|
2655
|
+
{ reason: "oauth_token_response" }
|
|
2656
|
+
);
|
|
2242
2657
|
}
|
|
2243
|
-
|
|
2244
|
-
if (isObjectLike(traceAwareConfig)) {
|
|
2245
|
-
traceDraftsByConfig.set(traceAwareConfig, traceAwareConfig.__slatesHttpTraceDraft);
|
|
2658
|
+
return void 0;
|
|
2246
2659
|
}
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2660
|
+
let seconds = typeof expiresIn === "number" ? expiresIn : expiresInType === "numberLike" && typeof expiresIn === "string" ? Number(expiresIn) : Number.NaN;
|
|
2661
|
+
if (!Number.isFinite(seconds)) {
|
|
2662
|
+
throw createApiServiceError(
|
|
2663
|
+
message ?? formatOAuthTokenResponseMessage("a valid expires_in value", providerLabel, operation),
|
|
2664
|
+
{ reason: "oauth_token_response" }
|
|
2251
2665
|
);
|
|
2252
2666
|
}
|
|
2253
|
-
return
|
|
2667
|
+
return new Date(nowMs + seconds * 1e3).toISOString();
|
|
2254
2668
|
};
|
|
2255
|
-
var
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
clearTraceDraft(config2, draft);
|
|
2260
|
-
let redactor = new AuthConfigSecretRedactor(draft.context._getAuthConfigForRedaction());
|
|
2261
|
-
let contentType = getContentType(response.headers);
|
|
2262
|
-
draft.context.recordHttpTrace({
|
|
2263
|
-
startedAt: draft.startedAt,
|
|
2264
|
-
durationMs: Math.max(Date.now() - draft.startedAtMs, 0),
|
|
2265
|
-
request: draft.request,
|
|
2266
|
-
response: {
|
|
2267
|
-
status: response.status,
|
|
2268
|
-
...response.statusText ? { statusText: response.statusText } : {},
|
|
2269
|
-
...sanitizeHeaders(response.headers, redactor) ? { headers: sanitizeHeaders(response.headers, redactor) } : {},
|
|
2270
|
-
...serializeTextBody(response.data, contentType, redactor) ? { body: serializeTextBody(response.data, contentType, redactor) } : {}
|
|
2669
|
+
var getRefreshToken = (refreshToken, previousRefreshToken, fallbackMode) => {
|
|
2670
|
+
if (typeof refreshToken === "string") {
|
|
2671
|
+
if (fallbackMode === "falsy" && !refreshToken) {
|
|
2672
|
+
return previousRefreshToken;
|
|
2271
2673
|
}
|
|
2272
|
-
|
|
2273
|
-
|
|
2674
|
+
return refreshToken;
|
|
2675
|
+
}
|
|
2676
|
+
if (fallbackMode === "falsy" && !refreshToken) {
|
|
2677
|
+
return previousRefreshToken;
|
|
2678
|
+
}
|
|
2679
|
+
return refreshToken === void 0 || refreshToken === null ? previousRefreshToken : void 0;
|
|
2274
2680
|
};
|
|
2275
|
-
var
|
|
2276
|
-
let
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
response
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2681
|
+
var normalizeOAuthTokenResponse = (data, options = {}) => {
|
|
2682
|
+
let {
|
|
2683
|
+
providerLabel,
|
|
2684
|
+
operation,
|
|
2685
|
+
previousRefreshToken,
|
|
2686
|
+
refreshTokenFallbackMode = "nullish",
|
|
2687
|
+
accessTokenMessage,
|
|
2688
|
+
expiresInMessage,
|
|
2689
|
+
...expiresAtOptions
|
|
2690
|
+
} = options;
|
|
2691
|
+
if (!isOAuthTokenResponse(data)) {
|
|
2692
|
+
throw createApiServiceError(
|
|
2693
|
+
accessTokenMessage ?? formatOAuthTokenResponseMessage("a token response object", providerLabel, operation),
|
|
2694
|
+
{ reason: "oauth_token_response" }
|
|
2695
|
+
);
|
|
2696
|
+
}
|
|
2697
|
+
if (typeof data.access_token !== "string" || !data.access_token) {
|
|
2698
|
+
throw createApiServiceError(
|
|
2699
|
+
accessTokenMessage ?? formatOAuthTokenResponseMessage("an access token", providerLabel, operation),
|
|
2700
|
+
{ reason: "oauth_token_response" }
|
|
2701
|
+
);
|
|
2702
|
+
}
|
|
2703
|
+
return {
|
|
2704
|
+
token: data.access_token,
|
|
2705
|
+
refreshToken: getRefreshToken(
|
|
2706
|
+
data.refresh_token,
|
|
2707
|
+
previousRefreshToken,
|
|
2708
|
+
refreshTokenFallbackMode
|
|
2709
|
+
),
|
|
2710
|
+
expiresAt: getOAuthExpiresAtFromExpiresIn(data.expires_in, {
|
|
2711
|
+
...expiresAtOptions,
|
|
2712
|
+
providerLabel,
|
|
2713
|
+
operation,
|
|
2714
|
+
message: expiresInMessage
|
|
2715
|
+
})
|
|
2716
|
+
};
|
|
2299
2717
|
};
|
|
2300
2718
|
|
|
2301
2719
|
// src/axios/index.ts
|
|
2720
|
+
var import_axios3 = __toESM(require("axios"), 1);
|
|
2302
2721
|
var applySlateInterceptors = (instance, errorMapping) => {
|
|
2303
2722
|
instance.interceptors.request.use(
|
|
2304
2723
|
(request) => {
|
|
@@ -2956,6 +3375,9 @@ var skipWebhook = (reason, response) => ({
|
|
|
2956
3375
|
});
|
|
2957
3376
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2958
3377
|
0 && (module.exports = {
|
|
3378
|
+
API_ERROR_MAX_DETAILS,
|
|
3379
|
+
API_ERROR_MAX_MESSAGE_LENGTH,
|
|
3380
|
+
API_ERROR_TRUNCATED_PLACEHOLDER,
|
|
2959
3381
|
AUTH_CONFIG_SECRET_PLACEHOLDER_PREFIX,
|
|
2960
3382
|
AuthConfigSecretRedactor,
|
|
2961
3383
|
GET_FILE_URL_TOOL_ID,
|
|
@@ -2994,8 +3416,10 @@ var skipWebhook = (reason, response) => ({
|
|
|
2994
3416
|
createSlateError,
|
|
2995
3417
|
createTextAttachment,
|
|
2996
3418
|
createUrlAttachment,
|
|
3419
|
+
decodeApiErrorBody,
|
|
2997
3420
|
extractApiErrorMessage,
|
|
2998
3421
|
getApiErrorResponse,
|
|
3422
|
+
getApiErrorResponseWithBody,
|
|
2999
3423
|
getApiErrorStatus,
|
|
3000
3424
|
getBase64ByteLength,
|
|
3001
3425
|
getCurrentContext,
|
|
@@ -3012,6 +3436,8 @@ var skipWebhook = (reason, response) => ({
|
|
|
3012
3436
|
isApiErrorRecord,
|
|
3013
3437
|
isAxiosErrorLike,
|
|
3014
3438
|
isServiceErrorData,
|
|
3439
|
+
isUrlEmbeddedCredential,
|
|
3440
|
+
looksLikeHtmlErrorBody,
|
|
3015
3441
|
mapServiceErrorCode,
|
|
3016
3442
|
mapServiceErrorToSlateErrorInput,
|
|
3017
3443
|
mergeScopes,
|
|
@@ -3019,6 +3445,8 @@ var skipWebhook = (reason, response) => ({
|
|
|
3019
3445
|
normalizeOAuthTokenResponse,
|
|
3020
3446
|
pickDefined,
|
|
3021
3447
|
publicTool,
|
|
3448
|
+
pushBoundedApiErrorDetail,
|
|
3449
|
+
readApiErrorText,
|
|
3022
3450
|
redactUrlAttachmentSecrets,
|
|
3023
3451
|
requestAxios,
|
|
3024
3452
|
requestAxiosData,
|
|
@@ -3031,6 +3459,7 @@ var skipWebhook = (reason, response) => ({
|
|
|
3031
3459
|
tool,
|
|
3032
3460
|
trigger,
|
|
3033
3461
|
triggerGroup,
|
|
3462
|
+
truncateApiErrorMessage,
|
|
3034
3463
|
uploadAttachmentDirect,
|
|
3035
3464
|
validateScopes,
|
|
3036
3465
|
verifyHmacSignature
|