@slates/provider-handler 1.0.0-rc.6 → 1.0.0-rc.7

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.
Files changed (65) hide show
  1. package/dist/index.cjs +954 -2
  2. package/dist/index.d.cts +8 -0
  3. package/dist/index.d.ts +6 -3
  4. package/dist/index.module.js +926 -2
  5. package/package.json +10 -9
  6. package/src/index.ts +480 -84
  7. package/src/spec.ts +9 -8
  8. package/src/validation.ts +1 -1
  9. package/dist/action/action.d.ts +0 -90
  10. package/dist/action/action.d.ts.map +0 -1
  11. package/dist/action/builder.d.ts +0 -27
  12. package/dist/action/builder.d.ts.map +0 -1
  13. package/dist/action/index.d.ts +0 -5
  14. package/dist/action/index.d.ts.map +0 -1
  15. package/dist/action/tool.d.ts +0 -11
  16. package/dist/action/tool.d.ts.map +0 -1
  17. package/dist/action/trigger.d.ts +0 -14
  18. package/dist/action/trigger.d.ts.map +0 -1
  19. package/dist/auth/auth.d.ts +0 -26
  20. package/dist/auth/auth.d.ts.map +0 -1
  21. package/dist/auth/index.d.ts +0 -3
  22. package/dist/auth/index.d.ts.map +0 -1
  23. package/dist/auth/types.d.ts +0 -148
  24. package/dist/auth/types.d.ts.map +0 -1
  25. package/dist/axios/index.d.ts +0 -4
  26. package/dist/axios/index.d.ts.map +0 -1
  27. package/dist/config/config.d.ts +0 -22
  28. package/dist/config/config.d.ts.map +0 -1
  29. package/dist/config/index.d.ts +0 -2
  30. package/dist/config/index.d.ts.map +0 -1
  31. package/dist/context/context.d.ts +0 -20
  32. package/dist/context/context.d.ts.map +0 -1
  33. package/dist/context/hook.d.ts +0 -4
  34. package/dist/context/hook.d.ts.map +0 -1
  35. package/dist/context/index.d.ts +0 -2
  36. package/dist/context/index.d.ts.map +0 -1
  37. package/dist/error/base.d.ts +0 -5
  38. package/dist/error/base.d.ts.map +0 -1
  39. package/dist/error/declaration.d.ts +0 -6
  40. package/dist/error/declaration.d.ts.map +0 -1
  41. package/dist/error/index.d.ts +0 -3
  42. package/dist/error/index.d.ts.map +0 -1
  43. package/dist/index.cjs.map +0 -1
  44. package/dist/index.d.ts.map +0 -1
  45. package/dist/index.modern.js +0 -2
  46. package/dist/index.modern.js.map +0 -1
  47. package/dist/index.module.js.map +0 -1
  48. package/dist/index.umd.js +0 -2
  49. package/dist/index.umd.js.map +0 -1
  50. package/dist/spec.d.ts +0 -14
  51. package/dist/spec.d.ts.map +0 -1
  52. package/dist/specification/index.d.ts +0 -3
  53. package/dist/specification/index.d.ts.map +0 -1
  54. package/dist/specification/slate.d.ts +0 -15
  55. package/dist/specification/slate.d.ts.map +0 -1
  56. package/dist/specification/specification.d.ts +0 -30
  57. package/dist/specification/specification.d.ts.map +0 -1
  58. package/dist/specification/zero.d.ts +0 -13
  59. package/dist/specification/zero.d.ts.map +0 -1
  60. package/dist/state.d.ts +0 -8
  61. package/dist/state.d.ts.map +0 -1
  62. package/dist/tokens.d.ts +0 -34
  63. package/dist/tokens.d.ts.map +0 -1
  64. package/dist/validation.d.ts +0 -5
  65. package/dist/validation.d.ts.map +0 -1
package/src/index.ts CHANGED
@@ -1,16 +1,46 @@
1
1
  import { badRequestError, preconditionFailedError, ServiceError } from '@lowerdeck/error';
2
- import { createSlatesProviderProtoHandler, SlatesParticipant } from '@slates/proto';
2
+ import {
3
+ createSlatesProviderProtoHandler,
4
+ SLATES_PROTOCOL_VERSION,
5
+ type SlatesParticipant
6
+ } from '@slates/proto';
3
7
  import {
4
8
  runWithContext,
5
- Slate,
9
+ type Slate,
6
10
  SlateContext,
7
11
  SlateLogger,
8
- SlateLogListener
12
+ type SlateLogListener
9
13
  } from '@slates/provider';
10
14
  import { getAction, getActionWithType, getAuthMethod, mapAction, mapAuthMethod } from './spec';
11
15
  import { State } from './state';
12
16
  import { toJsonSchema, validate } from './validation';
13
17
 
18
+ let isRecord = (value: unknown): value is Record<string, unknown> =>
19
+ typeof value === 'object' && value !== null && !Array.isArray(value);
20
+
21
+ let getObjectKeyCount = (value: unknown) =>
22
+ isRecord(value) ? Object.keys(value).length : undefined;
23
+
24
+ let toErrorMetadata = (error: unknown) => {
25
+ if (error instanceof Error) {
26
+ return {
27
+ errorName: error.name,
28
+ errorMessage: error.message,
29
+ errorStack: error.stack
30
+ };
31
+ }
32
+
33
+ return {
34
+ errorValue: String(error)
35
+ };
36
+ };
37
+
38
+ let formatEntityLabel = (name: string, key: string) => `"${name}" (${key})`;
39
+ let resolveTraceMessage = <ResultType>(
40
+ message: string | ((result: ResultType) => string),
41
+ result: ResultType
42
+ ) => (typeof message === 'function' ? message(result) : message);
43
+
14
44
  export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
15
45
  slate: Slate<ConfigType, AuthType>,
16
46
  listeners: SlateLogListener[]
@@ -21,10 +51,69 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
21
51
 
22
52
  let auth = new State<{ authenticationMethodId: string; output: AuthType } | null>(null);
23
53
  let config = new State<{ value: ConfigType } | null>(null);
24
-
25
54
  let session = new State<{ id: string; state: any } | null>(null);
26
55
 
27
56
  let logger = new SlateLogger(listeners);
57
+ let providerTrace = {
58
+ providerId: slate.spec.key,
59
+ providerName: slate.spec.name
60
+ };
61
+
62
+ let traceProviderCall = async <ResultType>(
63
+ trace: {
64
+ component: 'config' | 'auth' | 'action';
65
+ functionName: string;
66
+ message: string;
67
+ successMessage: string | ((result: ResultType) => string);
68
+ errorMessage?: string;
69
+ metadata?: Record<string, unknown>;
70
+ onSuccess?: (result: ResultType) => Record<string, unknown> | undefined;
71
+ },
72
+ handler: () => Promise<ResultType>
73
+ ): Promise<ResultType> => {
74
+ let startedAt = Date.now();
75
+
76
+ logger.info({
77
+ ...providerTrace,
78
+ ...trace.metadata,
79
+ component: trace.component,
80
+ functionName: trace.functionName,
81
+ phase: 'start',
82
+ message: trace.message
83
+ });
84
+
85
+ try {
86
+ let result = await handler();
87
+ let successMessage = resolveTraceMessage(trace.successMessage, result);
88
+
89
+ logger.info({
90
+ ...providerTrace,
91
+ ...trace.metadata,
92
+ ...(trace.onSuccess?.(result) ?? {}),
93
+ component: trace.component,
94
+ functionName: trace.functionName,
95
+ phase: 'success',
96
+ durationMs: Date.now() - startedAt,
97
+ message: successMessage
98
+ });
99
+
100
+ return result;
101
+ } catch (error) {
102
+ logger.error({
103
+ ...providerTrace,
104
+ ...trace.metadata,
105
+ ...toErrorMetadata(error),
106
+ component: trace.component,
107
+ functionName: trace.functionName,
108
+ phase: 'error',
109
+ durationMs: Date.now() - startedAt,
110
+ message:
111
+ trace.errorMessage ??
112
+ `${typeof trace.successMessage === 'string' ? trace.successMessage : trace.message} failed`
113
+ });
114
+ throw error;
115
+ }
116
+ };
28
117
 
29
118
  let getContextBasic = () => {
30
119
  let currentProtocol = protocol.get();
@@ -72,6 +161,13 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
72
161
  };
73
162
 
74
163
  let getEmptyContext = () => new SlateContext({}, {}, {}, slate.spec as any, logger);
164
+ let withRequestTraces = <Result extends Record<string, any>>(
165
+ context: SlateContext<any, any, any>,
166
+ result: Result
167
+ ) => {
168
+ let requestTraces = context.getHttpTraces();
169
+ return requestTraces.length > 0 ? { ...result, requestTraces } : result;
170
+ };
75
171
 
76
172
  manager.onNotification('slates/hello', async ({ params }) => {
77
173
  protocol.set(params.protocol);
@@ -141,15 +237,37 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
141
237
  return { success: true, config: newConfig };
142
238
  }
143
239
 
144
- let updatedConfig = await configChanged({
145
- previousConfig: params.previousConfig as ConfigType | null,
146
- newConfig
147
- });
240
+ let context = getEmptyContext();
241
+ let updatedConfig = await traceProviderCall<{ config?: ConfigType } | undefined>(
242
+ {
243
+ component: 'config',
244
+ functionName: 'configChanged',
245
+ message: 'Running config change handler',
246
+ successMessage: 'Config change handler completed',
247
+ metadata: {
248
+ hasPreviousConfig: params.previousConfig !== null,
249
+ newConfigKeyCount: getObjectKeyCount(newConfig)
250
+ },
251
+ onSuccess: result => ({
252
+ returnedConfig: !!result?.config
253
+ })
254
+ },
255
+ () =>
256
+ runWithContext(context, async () =>
257
+ configChanged({
258
+ previousConfig: params.previousConfig as ConfigType | null,
259
+ newConfig
260
+ })
261
+ )
262
+ );
148
263
 
149
- return { success: true, config: updatedConfig?.config ?? newConfig };
264
+ return withRequestTraces(context, {
265
+ success: true,
266
+ config: (updatedConfig?.config ?? newConfig) as Record<string, any>
267
+ });
150
268
  });
151
269
 
152
- manager.onRequest('slates/config.get_default', async ({ params }) => {
270
+ manager.onRequest('slates/config.get_default', async () => {
153
271
  getContextBasic();
154
272
 
155
273
  let getDefaultConfig = slate.spec.config.handlers.getDefaultConfig;
@@ -157,21 +275,35 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
157
275
  return { config: null };
158
276
  }
159
277
 
160
- let defaultConfig = await getDefaultConfig();
161
- return { config: defaultConfig };
278
+ let context = getEmptyContext();
279
+ let defaultConfig = await traceProviderCall<ConfigType>(
280
+ {
281
+ component: 'config',
282
+ functionName: 'getDefaultConfig',
283
+ message: 'Getting default config',
284
+ successMessage: 'Default config retrieved',
285
+ onSuccess: result => ({
286
+ configKeyCount: getObjectKeyCount(result)
287
+ })
288
+ },
289
+ () => runWithContext(context, async () => getDefaultConfig())
290
+ );
291
+ return withRequestTraces(context, {
292
+ config: (defaultConfig ?? null) as Record<string, any> | null
293
+ });
162
294
  });
163
295
 
164
- manager.onRequest('slates/config.schema.get', async ({ params }) => {
296
+ manager.onRequest('slates/config.schema.get', async () => {
165
297
  getContextBasic();
166
298
 
167
299
  return { schema: toJsonSchema(slate.spec.configSchema) };
168
300
  });
169
301
 
170
- manager.onRequest('slates/provider.identify', async ({ params }) => {
302
+ manager.onRequest('slates/provider.identify', async () => {
171
303
  getContextBasic();
172
304
 
173
305
  return {
174
- protocol: 'slates@2026-01-01',
306
+ protocol: SLATES_PROTOCOL_VERSION,
175
307
  provider: {
176
308
  type: 'provider',
177
309
  id: slate.spec.key,
@@ -182,7 +314,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
182
314
  };
183
315
  });
184
316
 
185
- manager.onRequest('slates/auth.methods.list', async ({ params }) => {
317
+ manager.onRequest('slates/auth.methods.list', async () => {
186
318
  getContextBasic();
187
319
 
188
320
  return {
@@ -207,9 +339,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
207
339
  return { input: null };
208
340
  }
209
341
 
210
- return {
211
- input: await runWithContext(getEmptyContext(), () => authMethod.getDefaultInput!())
212
- };
342
+ let context = getEmptyContext();
343
+ let input = await traceProviderCall(
344
+ {
345
+ component: 'auth',
346
+ functionName: 'getDefaultInput',
347
+ message: 'Getting default authentication input',
348
+ successMessage: 'Default authentication input retrieved',
349
+ metadata: {
350
+ authenticationMethodId: params.authenticationMethodId,
351
+ authenticationMethodName: authMethod.name
352
+ },
353
+ onSuccess: result => ({
354
+ inputKeyCount: getObjectKeyCount(result)
355
+ })
356
+ },
357
+ () => runWithContext(context, () => authMethod.getDefaultInput!())
358
+ );
359
+
360
+ return withRequestTraces(context, { input });
213
361
  });
214
362
 
215
363
  manager.onRequest('slates/auth.input.changed', async ({ params }) => {
@@ -220,14 +368,36 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
220
368
  return { success: true, input: params.newInput };
221
369
  }
222
370
 
223
- let updatedInput = await runWithContext(getEmptyContext(), () =>
224
- authMethod.onInputChanged!({
225
- previousInput: params.previousInput as any | null,
226
- newInput: params.newInput
227
- })
371
+ let context = getEmptyContext();
372
+ let updatedInput = await traceProviderCall(
373
+ {
374
+ component: 'auth',
375
+ functionName: 'onInputChanged',
376
+ message: 'Running authentication input change handler',
377
+ successMessage: 'Authentication input change handler completed',
378
+ metadata: {
379
+ authenticationMethodId: params.authenticationMethodId,
380
+ authenticationMethodName: authMethod.name,
381
+ hasPreviousInput: params.previousInput !== null,
382
+ newInputKeyCount: getObjectKeyCount(params.newInput)
383
+ },
384
+ onSuccess: result => ({
385
+ returnedInput: !!result?.input
386
+ })
387
+ },
388
+ () =>
389
+ runWithContext(context, () =>
390
+ authMethod.onInputChanged!({
391
+ previousInput: params.previousInput as any | null,
392
+ newInput: params.newInput
393
+ })
394
+ )
228
395
  );
229
396
 
230
- return { success: true, input: updatedInput?.input ?? params.newInput };
397
+ return withRequestTraces(context, {
398
+ success: true,
399
+ input: updatedInput?.input ?? params.newInput
400
+ });
231
401
  });
232
402
 
233
403
  manager.onRequest('slates/auth.output.get', async ({ params }) => {
@@ -246,10 +416,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
246
416
  }
247
417
 
248
418
  if ('getOutput' in authMethod) {
249
- let outputRes = await runWithContext(getEmptyContext(), () =>
250
- authMethod.getOutput({ input })
419
+ let context = getEmptyContext();
420
+ let outputRes = await traceProviderCall(
421
+ {
422
+ component: 'auth',
423
+ functionName: 'getOutput',
424
+ message: 'Getting authentication output',
425
+ successMessage: 'Authentication output retrieved',
426
+ metadata: {
427
+ authenticationMethodId: params.authenticationMethodId,
428
+ authenticationMethodName: authMethod.name,
429
+ inputKeyCount: getObjectKeyCount(input)
430
+ },
431
+ onSuccess: result => ({
432
+ outputKeyCount: getObjectKeyCount(result.output)
433
+ })
434
+ },
435
+ () => runWithContext(context, () => authMethod.getOutput({ input }))
251
436
  );
252
- return { output: outputRes.output };
437
+ return withRequestTraces(context, { output: outputRes.output });
253
438
  }
254
439
 
255
440
  return { output: input as any };
@@ -260,23 +445,45 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
260
445
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
261
446
 
262
447
  if ('handleCallback' in authMethod) {
263
- let callbackRes = await runWithContext(getEmptyContext(), () =>
264
- authMethod.handleCallback({
265
- code: params.code,
266
- state: params.state,
267
- redirectUri: params.redirectUri,
268
- input: params.input,
269
- clientId: params.clientId,
270
- clientSecret: params.clientSecret,
271
- scopes: params.scopes,
272
- callbackState: params.callbackState || {}
273
- })
448
+ let context = getEmptyContext();
449
+ let callbackRes = await traceProviderCall(
450
+ {
451
+ component: 'auth',
452
+ functionName: 'handleCallback',
453
+ message: 'Handling authentication callback',
454
+ successMessage: 'Authentication callback handled',
455
+ metadata: {
456
+ authenticationMethodId: params.authenticationMethodId,
457
+ authenticationMethodName: authMethod.name,
458
+ scopeCount: params.scopes.length,
459
+ hasCallbackState: !!params.callbackState
460
+ },
461
+ onSuccess: result => ({
462
+ outputKeyCount: getObjectKeyCount(result.output),
463
+ returnedInput: !!result.input,
464
+ returnedScopeCount: result.scopes?.length
465
+ })
466
+ },
467
+ () =>
468
+ runWithContext(context, () =>
469
+ authMethod.handleCallback({
470
+ code: params.code,
471
+ state: params.state,
472
+ redirectUri: params.redirectUri,
473
+ input: params.input,
474
+ clientId: params.clientId,
475
+ clientSecret: params.clientSecret,
476
+ scopes: params.scopes,
477
+ callbackState: params.callbackState || {}
478
+ })
479
+ )
274
480
  );
275
481
 
276
- return {
482
+ return withRequestTraces(context, {
277
483
  output: callbackRes.output,
278
- input: callbackRes.input
279
- };
484
+ input: callbackRes.input,
485
+ scopes: callbackRes.scopes
486
+ });
280
487
  }
281
488
 
282
489
  throw new ServiceError(
@@ -291,22 +498,42 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
291
498
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
292
499
 
293
500
  if ('getAuthorizationUrl' in authMethod) {
294
- let urlRes = await runWithContext(getEmptyContext(), () =>
295
- authMethod.getAuthorizationUrl({
296
- redirectUri: params.redirectUri,
297
- state: params.state,
298
- input: params.input,
299
- clientId: params.clientId,
300
- clientSecret: params.clientSecret,
301
- scopes: params.scopes
302
- })
501
+ let context = getEmptyContext();
502
+ let urlRes = await traceProviderCall(
503
+ {
504
+ component: 'auth',
505
+ functionName: 'getAuthorizationUrl',
506
+ message: 'Getting authentication authorization URL',
507
+ successMessage: 'Authentication authorization URL retrieved',
508
+ metadata: {
509
+ authenticationMethodId: params.authenticationMethodId,
510
+ authenticationMethodName: authMethod.name,
511
+ scopeCount: params.scopes.length,
512
+ inputKeyCount: getObjectKeyCount(params.input)
513
+ },
514
+ onSuccess: result => ({
515
+ returnedInput: !!result.input,
516
+ hasCallbackState: !!result.callbackState
517
+ })
518
+ },
519
+ () =>
520
+ runWithContext(context, () =>
521
+ authMethod.getAuthorizationUrl({
522
+ redirectUri: params.redirectUri,
523
+ state: params.state,
524
+ input: params.input,
525
+ clientId: params.clientId,
526
+ clientSecret: params.clientSecret,
527
+ scopes: params.scopes
528
+ })
529
+ )
303
530
  );
304
531
 
305
- return {
532
+ return withRequestTraces(context, {
306
533
  authorizationUrl: urlRes.url,
307
534
  input: urlRes.input,
308
535
  callbackState: urlRes.callbackState
309
- };
536
+ });
310
537
  }
311
538
 
312
539
  throw new ServiceError(
@@ -321,17 +548,39 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
321
548
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
322
549
 
323
550
  if (authMethod.getProfile) {
324
- let profileRes = await runWithContext(getEmptyContext(), () =>
325
- authMethod.getProfile!({
326
- output: params.output as any,
327
- input: params.input,
328
- scopes: params.scopes
329
- })
551
+ let context = getEmptyContext();
552
+ let profileRes = await traceProviderCall(
553
+ {
554
+ component: 'auth',
555
+ functionName: 'getProfile',
556
+ message: 'Getting authentication profile',
557
+ successMessage: 'Authentication profile retrieved',
558
+ metadata: {
559
+ authenticationMethodId: params.authenticationMethodId,
560
+ authenticationMethodName: authMethod.name,
561
+ scopeCount: params.scopes.length,
562
+ inputKeyCount: getObjectKeyCount(params.input),
563
+ outputKeyCount: getObjectKeyCount(params.output)
564
+ },
565
+ onSuccess: result => ({
566
+ profileKeyCount: getObjectKeyCount(result.profile)
567
+ })
568
+ },
569
+ () =>
570
+ runWithContext(
571
+ context,
572
+ () =>
573
+ authMethod.getProfile!({
574
+ output: params.output as any,
575
+ input: params.input,
576
+ scopes: params.scopes
577
+ })!
578
+ )
330
579
  );
331
580
 
332
- return {
581
+ return withRequestTraces(context, {
333
582
  profile: profileRes.profile
334
- };
583
+ });
335
584
  }
336
585
 
337
586
  throw new ServiceError(
@@ -346,20 +595,41 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
346
595
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
347
596
 
348
597
  if ('handleTokenRefresh' in authMethod && authMethod.handleTokenRefresh) {
349
- let refreshRes = await runWithContext(getEmptyContext(), () =>
350
- authMethod.handleTokenRefresh!({
351
- output: params.output as any,
352
- input: params.input,
353
- clientId: params.clientId,
354
- clientSecret: params.clientSecret,
355
- scopes: params.scopes
356
- })
598
+ let context = getEmptyContext();
599
+ let refreshRes = await traceProviderCall(
600
+ {
601
+ component: 'auth',
602
+ functionName: 'handleTokenRefresh',
603
+ message: 'Refreshing authentication token',
604
+ successMessage: 'Authentication token refreshed',
605
+ metadata: {
606
+ authenticationMethodId: params.authenticationMethodId,
607
+ authenticationMethodName: authMethod.name,
608
+ scopeCount: params.scopes.length,
609
+ inputKeyCount: getObjectKeyCount(params.input),
610
+ outputKeyCount: getObjectKeyCount(params.output)
611
+ },
612
+ onSuccess: result => ({
613
+ refreshedOutputKeyCount: getObjectKeyCount(result.output),
614
+ returnedInput: !!result.input
615
+ })
616
+ },
617
+ () =>
618
+ runWithContext(context, () =>
619
+ authMethod.handleTokenRefresh!({
620
+ output: params.output as any,
621
+ input: params.input,
622
+ clientId: params.clientId,
623
+ clientSecret: params.clientSecret,
624
+ scopes: params.scopes
625
+ })
626
+ )
357
627
  );
358
628
 
359
- return {
629
+ return withRequestTraces(context, {
360
630
  output: refreshRes.output,
361
631
  input: refreshRes.input
362
- };
632
+ });
363
633
  }
364
634
 
365
635
  throw new ServiceError(
@@ -369,7 +639,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
369
639
  );
370
640
  });
371
641
 
372
- manager.onRequest('slates/actions.list', async ({ params }) => {
642
+ manager.onRequest('slates/actions.list', async () => {
373
643
  getContextBasic();
374
644
 
375
645
  return {
@@ -398,9 +668,29 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
398
668
  );
399
669
 
400
670
  let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
401
- let res = await runWithContext(context, () => action.handleInvocation(context));
671
+ let res = await traceProviderCall(
672
+ {
673
+ component: 'action',
674
+ functionName: 'handleInvocation',
675
+ message: `Starting tool ${formatEntityLabel(action.name, action.key)}`,
676
+ successMessage: `Completed tool ${formatEntityLabel(action.name, action.key)}`,
677
+ errorMessage: `Tool ${formatEntityLabel(action.name, action.key)} failed`,
678
+ metadata: {
679
+ actionId: action.key,
680
+ actionName: action.name,
681
+ actionType: action.type,
682
+ inputKeyCount: getObjectKeyCount(input)
683
+ },
684
+ onSuccess: result => ({
685
+ hasMessage: !!result.message,
686
+ actionResultMessage: result.message,
687
+ outputKeyCount: getObjectKeyCount(result.output)
688
+ })
689
+ },
690
+ () => runWithContext(context, () => action.handleInvocation(context))
691
+ );
402
692
 
403
- return { output: res.output, message: res.message };
693
+ return withRequestTraces(context, { output: res.output, message: res.message });
404
694
  });
405
695
 
406
696
  manager.onRequest('slates/action.trigger.map_event', async ({ params }) => {
@@ -415,9 +705,30 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
415
705
  );
416
706
 
417
707
  let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
418
- let res = await runWithContext(context, () => action.handleEvent(context));
708
+ let res = await traceProviderCall(
709
+ {
710
+ component: 'action',
711
+ functionName: 'handleEvent',
712
+ message: `Mapping event for trigger ${formatEntityLabel(action.name, action.key)}`,
713
+ successMessage: result =>
714
+ `Mapped trigger event "${result.type}" for ${formatEntityLabel(action.name, action.key)}`,
715
+ errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while mapping an event`,
716
+ metadata: {
717
+ actionId: action.key,
718
+ actionName: action.name,
719
+ actionType: action.type,
720
+ inputKeyCount: getObjectKeyCount(input)
721
+ },
722
+ onSuccess: result => ({
723
+ eventType: result.type,
724
+ hasEventId: !!result.id,
725
+ outputKeyCount: getObjectKeyCount(result.output)
726
+ })
727
+ },
728
+ () => runWithContext(context, () => action.handleEvent(context))
729
+ );
419
730
 
420
- return { id: res.id, type: res.type, output: res.output };
731
+ return withRequestTraces(context, { id: res.id, type: res.type, output: res.output });
421
732
  });
422
733
 
423
734
  manager.onRequest('slates/action.trigger.poll_events', async ({ params }) => {
@@ -439,9 +750,32 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
439
750
  slate.spec,
440
751
  logger
441
752
  );
442
- let res = await runWithContext(context, () => action.pollEvents!(context));
753
+ let res = await traceProviderCall(
754
+ {
755
+ component: 'action',
756
+ functionName: 'pollEvents',
757
+ message: `Polling events for trigger ${formatEntityLabel(action.name, action.key)}`,
758
+ successMessage: result =>
759
+ `Polled ${result.inputs.length} event(s) for trigger ${formatEntityLabel(action.name, action.key)}`,
760
+ errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while polling events`,
761
+ metadata: {
762
+ actionId: action.key,
763
+ actionName: action.name,
764
+ actionType: action.type,
765
+ hasPreviousState: params.state !== null
766
+ },
767
+ onSuccess: result => ({
768
+ inputCount: result.inputs.length,
769
+ hasUpdatedState: result.updatedState !== undefined
770
+ })
771
+ },
772
+ () => runWithContext(context, () => action.pollEvents!(context))
773
+ );
443
774
 
444
- return { inputs: res.inputs, updatedState: res.updatedState };
775
+ return withRequestTraces(context, {
776
+ inputs: res.inputs,
777
+ updatedState: res.updatedState
778
+ });
445
779
  });
446
780
 
447
781
  manager.onRequest('slates/action.trigger.webhook_handle', async ({ params }) => {
@@ -471,9 +805,34 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
471
805
  slate.spec,
472
806
  logger
473
807
  );
474
- let res = await runWithContext(context, () => action.handleRequest!(context));
808
+ let res = await traceProviderCall(
809
+ {
810
+ component: 'action',
811
+ functionName: 'handleRequest',
812
+ message: `Handling webhook request for trigger ${formatEntityLabel(action.name, action.key)}`,
813
+ successMessage: result =>
814
+ `Received ${result.inputs.length} webhook event(s) for trigger ${formatEntityLabel(action.name, action.key)}`,
815
+ errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while handling a webhook request`,
816
+ metadata: {
817
+ actionId: action.key,
818
+ actionName: action.name,
819
+ actionType: action.type,
820
+ requestMethod: params.method,
821
+ hasRequestBody: !!params.body,
822
+ hasPreviousState: params.state !== null
823
+ },
824
+ onSuccess: result => ({
825
+ inputCount: result.inputs.length,
826
+ hasUpdatedState: result.updatedState !== undefined
827
+ })
828
+ },
829
+ () => runWithContext(context, () => action.handleRequest!(context))
830
+ );
475
831
 
476
- return { inputs: res.inputs, updatedState: res.updatedState };
832
+ return withRequestTraces(context, {
833
+ inputs: res.inputs,
834
+ updatedState: res.updatedState
835
+ });
477
836
  });
478
837
 
479
838
  manager.onRequest('slates/action.trigger.webhook_register', async ({ params }) => {
@@ -495,9 +854,30 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
495
854
  slate.spec,
496
855
  logger
497
856
  );
498
- let res = await runWithContext(context, () => action.autoRegisterWebhook!(context));
857
+ let res = await traceProviderCall(
858
+ {
859
+ component: 'action',
860
+ functionName: 'autoRegisterWebhook',
861
+ message: `Registering webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
862
+ successMessage: `Registered webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
863
+ errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while registering a webhook`,
864
+ metadata: {
865
+ actionId: action.key,
866
+ actionName: action.name,
867
+ actionType: action.type
868
+ },
869
+ onSuccess: result => ({
870
+ hasRegistrationDetails: result.registrationDetails !== undefined,
871
+ hasState: result.state !== undefined
872
+ })
873
+ },
874
+ () => runWithContext(context, () => action.autoRegisterWebhook!(context))
875
+ );
499
876
 
500
- return { registrationDetails: res.registrationDetails, state: res.state };
877
+ return withRequestTraces(context, {
878
+ registrationDetails: res.registrationDetails,
879
+ state: res.state
880
+ });
501
881
  });
502
882
 
503
883
  manager.onRequest('slates/action.trigger.webhook_unregister', async ({ params }) => {
@@ -523,8 +903,24 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
523
903
  slate.spec,
524
904
  logger
525
905
  );
526
- await runWithContext(context, () => action.autoUnregisterWebhook!(context));
906
+ await traceProviderCall(
907
+ {
908
+ component: 'action',
909
+ functionName: 'autoUnregisterWebhook',
910
+ message: `Unregistering webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
911
+ successMessage: `Unregistered webhook for trigger ${formatEntityLabel(action.name, action.key)}`,
912
+ errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while unregistering a webhook`,
913
+ metadata: {
914
+ actionId: action.key,
915
+ actionName: action.name,
916
+ actionType: action.type,
917
+ hasRegistrationDetails: params.registrationDetails !== null,
918
+ hasPreviousState: params.state !== null
919
+ }
920
+ },
921
+ () => runWithContext(context, () => action.autoUnregisterWebhook!(context))
922
+ );
527
923
 
528
- return {};
924
+ return withRequestTraces(context, {});
529
925
  });
530
926
  });