@slates/provider-handler 1.0.0-rc.4 → 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 +523 -109
  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,10 +1,46 @@
1
1
  import { badRequestError, preconditionFailedError, ServiceError } from '@lowerdeck/error';
2
- import { createSlatesProviderProtoHandler, SlatesParticipant } from '@slates/proto';
3
- import { Slate, SlateContext, SlateLogger, SlateLogListener } from '@slates/provider';
2
+ import {
3
+ createSlatesProviderProtoHandler,
4
+ SLATES_PROTOCOL_VERSION,
5
+ type SlatesParticipant
6
+ } from '@slates/proto';
7
+ import {
8
+ runWithContext,
9
+ type Slate,
10
+ SlateContext,
11
+ SlateLogger,
12
+ type SlateLogListener
13
+ } from '@slates/provider';
4
14
  import { getAction, getActionWithType, getAuthMethod, mapAction, mapAuthMethod } from './spec';
5
15
  import { State } from './state';
6
16
  import { toJsonSchema, validate } from './validation';
7
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
+
8
44
  export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
9
45
  slate: Slate<ConfigType, AuthType>,
10
46
  listeners: SlateLogListener[]
@@ -15,10 +51,69 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
15
51
 
16
52
  let auth = new State<{ authenticationMethodId: string; output: AuthType } | null>(null);
17
53
  let config = new State<{ value: ConfigType } | null>(null);
18
-
19
54
  let session = new State<{ id: string; state: any } | null>(null);
20
55
 
21
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
+ };
22
117
 
23
118
  let getContextBasic = () => {
24
119
  let currentProtocol = protocol.get();
@@ -65,6 +160,15 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
65
160
  };
66
161
  };
67
162
 
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
+ };
171
+
68
172
  manager.onNotification('slates/hello', async ({ params }) => {
69
173
  protocol.set(params.protocol);
70
174
  });
@@ -133,15 +237,37 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
133
237
  return { success: true, config: newConfig };
134
238
  }
135
239
 
136
- let updatedConfig = await configChanged({
137
- previousConfig: params.previousConfig as ConfigType | null,
138
- newConfig
139
- });
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
+ );
140
263
 
141
- return { success: true, config: updatedConfig?.config ?? newConfig };
264
+ return withRequestTraces(context, {
265
+ success: true,
266
+ config: (updatedConfig?.config ?? newConfig) as Record<string, any>
267
+ });
142
268
  });
143
269
 
144
- manager.onRequest('slates/config.get_default', async ({ params }) => {
270
+ manager.onRequest('slates/config.get_default', async () => {
145
271
  getContextBasic();
146
272
 
147
273
  let getDefaultConfig = slate.spec.config.handlers.getDefaultConfig;
@@ -149,21 +275,35 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
149
275
  return { config: null };
150
276
  }
151
277
 
152
- let defaultConfig = await getDefaultConfig();
153
- 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
+ });
154
294
  });
155
295
 
156
- manager.onRequest('slates/config.schema.get', async ({ params }) => {
296
+ manager.onRequest('slates/config.schema.get', async () => {
157
297
  getContextBasic();
158
298
 
159
299
  return { schema: toJsonSchema(slate.spec.configSchema) };
160
300
  });
161
301
 
162
- manager.onRequest('slates/provider.identify', async ({ params }) => {
302
+ manager.onRequest('slates/provider.identify', async () => {
163
303
  getContextBasic();
164
304
 
165
305
  return {
166
- protocol: 'slates@2026-01-01',
306
+ protocol: SLATES_PROTOCOL_VERSION,
167
307
  provider: {
168
308
  type: 'provider',
169
309
  id: slate.spec.key,
@@ -174,7 +314,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
174
314
  };
175
315
  });
176
316
 
177
- manager.onRequest('slates/auth.methods.list', async ({ params }) => {
317
+ manager.onRequest('slates/auth.methods.list', async () => {
178
318
  getContextBasic();
179
319
 
180
320
  return {
@@ -199,7 +339,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
199
339
  return { input: null };
200
340
  }
201
341
 
202
- return { input: await authMethod.getDefaultInput() };
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 });
203
361
  });
204
362
 
205
363
  manager.onRequest('slates/auth.input.changed', async ({ params }) => {
@@ -210,12 +368,36 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
210
368
  return { success: true, input: params.newInput };
211
369
  }
212
370
 
213
- let updatedInput = await authMethod.onInputChanged({
214
- previousInput: params.previousInput as any | null,
215
- newInput: params.newInput
216
- });
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
+ )
395
+ );
217
396
 
218
- return { success: true, input: updatedInput?.input ?? params.newInput };
397
+ return withRequestTraces(context, {
398
+ success: true,
399
+ input: updatedInput?.input ?? params.newInput
400
+ });
219
401
  });
220
402
 
221
403
  manager.onRequest('slates/auth.output.get', async ({ params }) => {
@@ -234,8 +416,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
234
416
  }
235
417
 
236
418
  if ('getOutput' in authMethod) {
237
- let outputRes = await authMethod.getOutput({ input });
238
- return { output: outputRes.output };
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 }))
436
+ );
437
+ return withRequestTraces(context, { output: outputRes.output });
239
438
  }
240
439
 
241
440
  return { output: input as any };
@@ -246,20 +445,45 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
246
445
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
247
446
 
248
447
  if ('handleCallback' in authMethod) {
249
- let callbackRes = await authMethod.handleCallback({
250
- code: params.code,
251
- state: params.state,
252
- redirectUri: params.redirectUri,
253
- input: params.input,
254
- clientId: params.clientId,
255
- clientSecret: params.clientSecret,
256
- scopes: params.scopes
257
- });
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
+ )
480
+ );
258
481
 
259
- return {
482
+ return withRequestTraces(context, {
260
483
  output: callbackRes.output,
261
- input: callbackRes.input
262
- };
484
+ input: callbackRes.input,
485
+ scopes: callbackRes.scopes
486
+ });
263
487
  }
264
488
 
265
489
  throw new ServiceError(
@@ -274,19 +498,42 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
274
498
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
275
499
 
276
500
  if ('getAuthorizationUrl' in authMethod) {
277
- let urlRes = await authMethod.getAuthorizationUrl({
278
- redirectUri: params.redirectUri,
279
- state: params.state,
280
- input: params.input,
281
- clientId: params.clientId,
282
- clientSecret: params.clientSecret,
283
- scopes: params.scopes
284
- });
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
+ )
530
+ );
285
531
 
286
- return {
532
+ return withRequestTraces(context, {
287
533
  authorizationUrl: urlRes.url,
288
- input: urlRes.input
289
- };
534
+ input: urlRes.input,
535
+ callbackState: urlRes.callbackState
536
+ });
290
537
  }
291
538
 
292
539
  throw new ServiceError(
@@ -301,15 +548,39 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
301
548
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
302
549
 
303
550
  if (authMethod.getProfile) {
304
- let profileRes = await authMethod.getProfile({
305
- output: params.output as any,
306
- input: params.input,
307
- scopes: params.scopes
308
- });
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
+ )
579
+ );
309
580
 
310
- return {
581
+ return withRequestTraces(context, {
311
582
  profile: profileRes.profile
312
- };
583
+ });
313
584
  }
314
585
 
315
586
  throw new ServiceError(
@@ -324,18 +595,41 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
324
595
  let authMethod = getAuthMethod(slate, params.authenticationMethodId);
325
596
 
326
597
  if ('handleTokenRefresh' in authMethod && authMethod.handleTokenRefresh) {
327
- let refreshRes = await authMethod.handleTokenRefresh({
328
- output: params.output as any,
329
- input: params.input,
330
- clientId: params.clientId,
331
- clientSecret: params.clientSecret,
332
- scopes: params.scopes
333
- });
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
+ )
627
+ );
334
628
 
335
- return {
629
+ return withRequestTraces(context, {
336
630
  output: refreshRes.output,
337
631
  input: refreshRes.input
338
- };
632
+ });
339
633
  }
340
634
 
341
635
  throw new ServiceError(
@@ -345,7 +639,7 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
345
639
  );
346
640
  });
347
641
 
348
- manager.onRequest('slates/actions.list', async ({ params }) => {
642
+ manager.onRequest('slates/actions.list', async () => {
349
643
  getContextBasic();
350
644
 
351
645
  return {
@@ -373,11 +667,30 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
373
667
  `Invalid input for tool ID: ${params.actionId}`
374
668
  );
375
669
 
376
- let res = await action.handleInvocation(
377
- new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger)
670
+ let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
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))
378
691
  );
379
692
 
380
- return { output: res.output, message: res.message };
693
+ return withRequestTraces(context, { output: res.output, message: res.message });
381
694
  });
382
695
 
383
696
  manager.onRequest('slates/action.trigger.map_event', async ({ params }) => {
@@ -391,11 +704,31 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
391
704
  `Invalid event for trigger ID: ${params.actionId}`
392
705
  );
393
706
 
394
- let res = await action.handleEvent(
395
- new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger)
707
+ let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
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))
396
729
  );
397
730
 
398
- return { id: res.id, type: res.type, output: res.output };
731
+ return withRequestTraces(context, { id: res.id, type: res.type, output: res.output });
399
732
  });
400
733
 
401
734
  manager.onRequest('slates/action.trigger.poll_events', async ({ params }) => {
@@ -410,17 +743,39 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
410
743
  );
411
744
  }
412
745
 
413
- let res = await action.pollEvents(
414
- new SlateContext(
415
- ctx.config,
416
- { state: params.state },
417
- ctx.auth?.output!,
418
- slate.spec,
419
- logger
420
- )
746
+ let context = new SlateContext(
747
+ ctx.config,
748
+ { state: params.state },
749
+ ctx.auth?.output!,
750
+ slate.spec,
751
+ logger
752
+ );
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))
421
773
  );
422
774
 
423
- return { inputs: res.inputs, updatedState: res.updatedState };
775
+ return withRequestTraces(context, {
776
+ inputs: res.inputs,
777
+ updatedState: res.updatedState
778
+ });
424
779
  });
425
780
 
426
781
  manager.onRequest('slates/action.trigger.webhook_handle', async ({ params }) => {
@@ -443,17 +798,41 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
443
798
  : null
444
799
  });
445
800
 
446
- let res = await action.handleRequest(
447
- new SlateContext(
448
- ctx.config,
449
- { request: req, state: params.state },
450
- ctx.auth?.output!,
451
- slate.spec,
452
- logger
453
- )
801
+ let context = new SlateContext(
802
+ ctx.config,
803
+ { request: req, state: params.state },
804
+ ctx.auth?.output!,
805
+ slate.spec,
806
+ logger
807
+ );
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))
454
830
  );
455
831
 
456
- return { inputs: res.inputs, updatedState: res.updatedState };
832
+ return withRequestTraces(context, {
833
+ inputs: res.inputs,
834
+ updatedState: res.updatedState
835
+ });
457
836
  });
458
837
 
459
838
  manager.onRequest('slates/action.trigger.webhook_register', async ({ params }) => {
@@ -468,17 +847,37 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
468
847
  );
469
848
  }
470
849
 
471
- let res = await action.autoRegisterWebhook(
472
- new SlateContext(
473
- ctx.config,
474
- { webhookBaseUrl: params.webhookBaseUrl },
475
- ctx.auth?.output!,
476
- slate.spec,
477
- logger
478
- )
850
+ let context = new SlateContext(
851
+ ctx.config,
852
+ { webhookBaseUrl: params.webhookBaseUrl },
853
+ ctx.auth?.output!,
854
+ slate.spec,
855
+ logger
856
+ );
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))
479
875
  );
480
876
 
481
- return { registrationDetails: res.registrationDetails, state: res.state };
877
+ return withRequestTraces(context, {
878
+ registrationDetails: res.registrationDetails,
879
+ state: res.state
880
+ });
482
881
  });
483
882
 
484
883
  manager.onRequest('slates/action.trigger.webhook_unregister', async ({ params }) => {
@@ -493,20 +892,35 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
493
892
  );
494
893
  }
495
894
 
496
- await action.autoUnregisterWebhook(
497
- new SlateContext(
498
- ctx.config,
499
- {
500
- webhookBaseUrl: params.webhookBaseUrl,
501
- registrationDetails: params.registrationDetails,
502
- state: params.state
503
- },
504
- ctx.auth?.output!,
505
- slate.spec,
506
- logger
507
- )
895
+ let context = new SlateContext(
896
+ ctx.config,
897
+ {
898
+ webhookBaseUrl: params.webhookBaseUrl,
899
+ registrationDetails: params.registrationDetails,
900
+ state: params.state
901
+ },
902
+ ctx.auth?.output!,
903
+ slate.spec,
904
+ logger
905
+ );
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))
508
922
  );
509
923
 
510
- return {};
924
+ return withRequestTraces(context, {});
511
925
  });
512
926
  });