@slates/provider-handler 1.0.0-rc.3 → 1.0.0-rc.32
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 +1475 -2
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.module.js +1452 -2
- package/package.json +11 -10
- package/src/attachments.test.ts +171 -0
- package/src/index.ts +1060 -137
- package/src/pQueue.test.ts +18 -0
- package/src/pQueue.ts +18 -0
- package/src/spec.test.ts +83 -0
- package/src/spec.ts +150 -21
- package/src/validation.ts +1 -1
- package/src/webhook.test.ts +65 -0
- package/src/webhook.ts +69 -0
- package/dist/action/action.d.ts +0 -90
- package/dist/action/action.d.ts.map +0 -1
- package/dist/action/builder.d.ts +0 -27
- package/dist/action/builder.d.ts.map +0 -1
- package/dist/action/index.d.ts +0 -5
- package/dist/action/index.d.ts.map +0 -1
- package/dist/action/tool.d.ts +0 -11
- package/dist/action/tool.d.ts.map +0 -1
- package/dist/action/trigger.d.ts +0 -14
- package/dist/action/trigger.d.ts.map +0 -1
- package/dist/auth/auth.d.ts +0 -26
- package/dist/auth/auth.d.ts.map +0 -1
- package/dist/auth/index.d.ts +0 -3
- package/dist/auth/index.d.ts.map +0 -1
- package/dist/auth/types.d.ts +0 -148
- package/dist/auth/types.d.ts.map +0 -1
- package/dist/axios/index.d.ts +0 -4
- package/dist/axios/index.d.ts.map +0 -1
- package/dist/config/config.d.ts +0 -22
- package/dist/config/config.d.ts.map +0 -1
- package/dist/config/index.d.ts +0 -2
- package/dist/config/index.d.ts.map +0 -1
- package/dist/context/context.d.ts +0 -20
- package/dist/context/context.d.ts.map +0 -1
- package/dist/context/hook.d.ts +0 -4
- package/dist/context/hook.d.ts.map +0 -1
- package/dist/context/index.d.ts +0 -2
- package/dist/context/index.d.ts.map +0 -1
- package/dist/error/base.d.ts +0 -5
- package/dist/error/base.d.ts.map +0 -1
- package/dist/error/declaration.d.ts +0 -6
- package/dist/error/declaration.d.ts.map +0 -1
- package/dist/error/index.d.ts +0 -3
- package/dist/error/index.d.ts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.modern.js +0 -2
- package/dist/index.modern.js.map +0 -1
- package/dist/index.module.js.map +0 -1
- package/dist/index.umd.js +0 -2
- package/dist/index.umd.js.map +0 -1
- package/dist/spec.d.ts +0 -14
- package/dist/spec.d.ts.map +0 -1
- package/dist/specification/index.d.ts +0 -3
- package/dist/specification/index.d.ts.map +0 -1
- package/dist/specification/slate.d.ts +0 -15
- package/dist/specification/slate.d.ts.map +0 -1
- package/dist/specification/specification.d.ts +0 -30
- package/dist/specification/specification.d.ts.map +0 -1
- package/dist/specification/zero.d.ts +0 -13
- package/dist/specification/zero.d.ts.map +0 -1
- package/dist/state.d.ts +0 -8
- package/dist/state.d.ts.map +0 -1
- package/dist/tokens.d.ts +0 -34
- package/dist/tokens.d.ts.map +0 -1
- package/dist/validation.d.ts +0 -5
- package/dist/validation.d.ts.map +0 -1
package/src/index.ts
CHANGED
|
@@ -1,9 +1,181 @@
|
|
|
1
1
|
import { badRequestError, preconditionFailedError, ServiceError } from '@lowerdeck/error';
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import {
|
|
3
|
+
createSlatesProviderProtoHandler,
|
|
4
|
+
SLATES_PROTOCOL_VERSION,
|
|
5
|
+
type SlatesParticipant
|
|
6
|
+
} from '@slates/proto';
|
|
7
|
+
import {
|
|
8
|
+
redactUrlAttachmentSecrets,
|
|
9
|
+
runWithContext,
|
|
10
|
+
type Slate,
|
|
11
|
+
type SlateAttachment,
|
|
12
|
+
SlateContext,
|
|
13
|
+
type SlateLiveInvocationInfo,
|
|
14
|
+
SlateLogger,
|
|
15
|
+
type SlateLogListener,
|
|
16
|
+
SlatePublicContext,
|
|
17
|
+
uploadAttachmentDirect
|
|
18
|
+
} from '@slates/provider';
|
|
19
|
+
import { PQueue } from './pQueue';
|
|
20
|
+
import {
|
|
21
|
+
evaluateTriggerMatches,
|
|
22
|
+
getActionWithType,
|
|
23
|
+
getAdapter,
|
|
24
|
+
getAuthMethod,
|
|
25
|
+
getMappableAction,
|
|
26
|
+
getTriggerGroup,
|
|
27
|
+
getWebhookAutoRegistration,
|
|
28
|
+
getWebhookManualRegistration,
|
|
29
|
+
isMappableTrigger,
|
|
30
|
+
mapAction,
|
|
31
|
+
mapAdapter,
|
|
32
|
+
mapAuthMethod,
|
|
33
|
+
mapTriggerGroup
|
|
34
|
+
} from './spec';
|
|
5
35
|
import { State } from './state';
|
|
6
36
|
import { toJsonSchema, validate } from './validation';
|
|
37
|
+
import { serializeWebhookHttpResponse } from './webhook';
|
|
38
|
+
|
|
39
|
+
let DEFAULT_MAX_ATTACHMENT_SIZE_BYTES = 100_000_000;
|
|
40
|
+
|
|
41
|
+
let routeAttachmentsThroughDirectUpload = async (
|
|
42
|
+
attachments: SlateAttachment[] | undefined,
|
|
43
|
+
live: SlateLiveInvocationInfo | null
|
|
44
|
+
): Promise<SlateAttachment[] | undefined> => {
|
|
45
|
+
if (!attachments || attachments.length === 0 || !live) return attachments;
|
|
46
|
+
|
|
47
|
+
let contentEntries = attachments
|
|
48
|
+
.map((attachment, index) => ({ attachment, index }))
|
|
49
|
+
.filter(entry => entry.attachment.content.type === 'content');
|
|
50
|
+
if (contentEntries.length === 0) return attachments;
|
|
51
|
+
|
|
52
|
+
let queue = new PQueue({ concurrency: 10 });
|
|
53
|
+
let replacements = new Map<number, SlateAttachment | null>();
|
|
54
|
+
|
|
55
|
+
await Promise.all(
|
|
56
|
+
contentEntries.map(entry =>
|
|
57
|
+
queue.add(async () => {
|
|
58
|
+
try {
|
|
59
|
+
let body =
|
|
60
|
+
entry.attachment.content.type === 'content'
|
|
61
|
+
? entry.attachment.content.encoding === 'base64'
|
|
62
|
+
? Buffer.from(entry.attachment.content.content, 'base64')
|
|
63
|
+
: Buffer.from(entry.attachment.content.content, 'utf-8')
|
|
64
|
+
: Buffer.alloc(0);
|
|
65
|
+
|
|
66
|
+
replacements.set(
|
|
67
|
+
entry.index,
|
|
68
|
+
await uploadAttachmentDirect({
|
|
69
|
+
live,
|
|
70
|
+
mimeType: entry.attachment.mimeType,
|
|
71
|
+
body
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
} catch {
|
|
75
|
+
// Upload failed or was interrupted -- we simply don't have this attachment, not a
|
|
76
|
+
// failed tool call.
|
|
77
|
+
replacements.set(entry.index, null);
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
)
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
return attachments
|
|
84
|
+
.map((attachment, index) =>
|
|
85
|
+
replacements.has(index) ? replacements.get(index) : attachment
|
|
86
|
+
)
|
|
87
|
+
.filter((a): a is SlateAttachment => a != null);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
let isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
91
|
+
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
92
|
+
|
|
93
|
+
let getObjectKeyCount = (value: unknown) =>
|
|
94
|
+
isRecord(value) ? Object.keys(value).length : undefined;
|
|
95
|
+
|
|
96
|
+
let DOWNLOAD_ATTACHMENT_URL_KEYS = new Set([
|
|
97
|
+
'downloadUrl',
|
|
98
|
+
'fileUrl',
|
|
99
|
+
'temporaryDownloadUrl',
|
|
100
|
+
'webContentLink'
|
|
101
|
+
]);
|
|
102
|
+
|
|
103
|
+
let isAttachmentUrl = (value: string) => /^[a-z][a-z0-9+.-]*:\/\//i.test(value);
|
|
104
|
+
|
|
105
|
+
let collectOutputUrlAttachments = (
|
|
106
|
+
value: unknown,
|
|
107
|
+
seen = new Set<string>()
|
|
108
|
+
): SlateAttachment[] => {
|
|
109
|
+
if (Array.isArray(value)) {
|
|
110
|
+
return value.flatMap(item => collectOutputUrlAttachments(item, seen));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (!isRecord(value)) {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let attachments: SlateAttachment[] = [];
|
|
118
|
+
|
|
119
|
+
for (let [key, nestedValue] of Object.entries(value)) {
|
|
120
|
+
if (
|
|
121
|
+
DOWNLOAD_ATTACHMENT_URL_KEYS.has(key) &&
|
|
122
|
+
typeof nestedValue === 'string' &&
|
|
123
|
+
nestedValue.length > 0 &&
|
|
124
|
+
isAttachmentUrl(nestedValue) &&
|
|
125
|
+
!seen.has(nestedValue)
|
|
126
|
+
) {
|
|
127
|
+
seen.add(nestedValue);
|
|
128
|
+
attachments.push({
|
|
129
|
+
content: {
|
|
130
|
+
type: 'url',
|
|
131
|
+
url: nestedValue
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
attachments.push(...collectOutputUrlAttachments(nestedValue, seen));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return attachments;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
let mergeAttachments = (
|
|
144
|
+
explicitAttachments: SlateAttachment[] | undefined,
|
|
145
|
+
output: unknown
|
|
146
|
+
): SlateAttachment[] | undefined => {
|
|
147
|
+
let attachments = [...(explicitAttachments ?? [])];
|
|
148
|
+
let seen = new Set(attachments.map(attachment => JSON.stringify(attachment)));
|
|
149
|
+
|
|
150
|
+
for (let attachment of collectOutputUrlAttachments(output)) {
|
|
151
|
+
let key = JSON.stringify(attachment);
|
|
152
|
+
if (seen.has(key)) continue;
|
|
153
|
+
seen.add(key);
|
|
154
|
+
attachments.push(attachment);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return attachments.length > 0 ? attachments : undefined;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
let toErrorMetadata = (error: unknown) => {
|
|
161
|
+
if (error instanceof Error) {
|
|
162
|
+
return {
|
|
163
|
+
errorName: error.name,
|
|
164
|
+
errorMessage: error.message,
|
|
165
|
+
errorStack: error.stack
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {
|
|
170
|
+
errorValue: String(error)
|
|
171
|
+
};
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
let formatEntityLabel = (name: string, key: string) => `"${name}" (${key})`;
|
|
175
|
+
let resolveTraceMessage = <ResultType>(
|
|
176
|
+
message: string | ((result: ResultType) => string),
|
|
177
|
+
result: ResultType
|
|
178
|
+
) => (typeof message === 'function' ? message(result) : message);
|
|
7
179
|
|
|
8
180
|
export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
9
181
|
slate: Slate<ConfigType, AuthType>,
|
|
@@ -15,10 +187,92 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
15
187
|
|
|
16
188
|
let auth = new State<{ authenticationMethodId: string; output: AuthType } | null>(null);
|
|
17
189
|
let config = new State<{ value: ConfigType } | null>(null);
|
|
18
|
-
|
|
19
190
|
let session = new State<{ id: string; state: any } | null>(null);
|
|
20
191
|
|
|
192
|
+
let hubCapabilities = new State<{
|
|
193
|
+
attachments?: { directUpload?: { enabled: boolean; maxAttachmentSizeBytes?: number } };
|
|
194
|
+
triggers?: boolean;
|
|
195
|
+
} | null>(null);
|
|
196
|
+
let liveInvocation = new State<Pick<SlateLiveInvocationInfo, 'token' | 'baseUrl'> | null>(
|
|
197
|
+
null
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
let getLiveInvocation = (): SlateLiveInvocationInfo | null => {
|
|
201
|
+
let directUpload = hubCapabilities.get()?.attachments?.directUpload;
|
|
202
|
+
let live = liveInvocation.get();
|
|
203
|
+
|
|
204
|
+
if (!directUpload?.enabled || !live) return null;
|
|
205
|
+
|
|
206
|
+
return {
|
|
207
|
+
...live,
|
|
208
|
+
maxAttachmentSizeBytes:
|
|
209
|
+
directUpload.maxAttachmentSizeBytes ?? DEFAULT_MAX_ATTACHMENT_SIZE_BYTES
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
let supportsTriggerGroups = () => !!hubCapabilities.get()?.triggers;
|
|
214
|
+
|
|
21
215
|
let logger = new SlateLogger(listeners);
|
|
216
|
+
let providerTrace = {
|
|
217
|
+
providerId: slate.spec.key,
|
|
218
|
+
providerName: slate.spec.name
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
let traceProviderCall = async <ResultType>(
|
|
222
|
+
trace: {
|
|
223
|
+
component: 'config' | 'auth' | 'action';
|
|
224
|
+
functionName: string;
|
|
225
|
+
message: string;
|
|
226
|
+
successMessage: string | ((result: ResultType) => string);
|
|
227
|
+
errorMessage?: string;
|
|
228
|
+
metadata?: Record<string, unknown>;
|
|
229
|
+
onSuccess?: (result: ResultType) => Record<string, unknown> | undefined;
|
|
230
|
+
},
|
|
231
|
+
handler: () => Promise<ResultType>
|
|
232
|
+
): Promise<ResultType> => {
|
|
233
|
+
let startedAt = Date.now();
|
|
234
|
+
|
|
235
|
+
logger.info({
|
|
236
|
+
...providerTrace,
|
|
237
|
+
...trace.metadata,
|
|
238
|
+
component: trace.component,
|
|
239
|
+
functionName: trace.functionName,
|
|
240
|
+
phase: 'start',
|
|
241
|
+
message: trace.message
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
let result = await handler();
|
|
246
|
+
let successMessage = resolveTraceMessage(trace.successMessage, result);
|
|
247
|
+
|
|
248
|
+
logger.info({
|
|
249
|
+
...providerTrace,
|
|
250
|
+
...trace.metadata,
|
|
251
|
+
...(trace.onSuccess?.(result) ?? {}),
|
|
252
|
+
component: trace.component,
|
|
253
|
+
functionName: trace.functionName,
|
|
254
|
+
phase: 'success',
|
|
255
|
+
durationMs: Date.now() - startedAt,
|
|
256
|
+
message: successMessage
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
return result;
|
|
260
|
+
} catch (error) {
|
|
261
|
+
logger.error({
|
|
262
|
+
...providerTrace,
|
|
263
|
+
...trace.metadata,
|
|
264
|
+
...toErrorMetadata(error),
|
|
265
|
+
component: trace.component,
|
|
266
|
+
functionName: trace.functionName,
|
|
267
|
+
phase: 'error',
|
|
268
|
+
durationMs: Date.now() - startedAt,
|
|
269
|
+
message:
|
|
270
|
+
trace.errorMessage ??
|
|
271
|
+
`${typeof trace.successMessage === 'string' ? trace.successMessage : trace.message} failed`
|
|
272
|
+
});
|
|
273
|
+
throw error;
|
|
274
|
+
}
|
|
275
|
+
};
|
|
22
276
|
|
|
23
277
|
let getContextBasic = () => {
|
|
24
278
|
let currentProtocol = protocol.get();
|
|
@@ -65,6 +319,19 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
65
319
|
};
|
|
66
320
|
};
|
|
67
321
|
|
|
322
|
+
let getAuthConfig = (): Record<string, any> => config.get()?.value ?? {};
|
|
323
|
+
|
|
324
|
+
let getEmptyContext = () => new SlateContext({}, {}, {}, slate.spec as any, logger);
|
|
325
|
+
let getAuthContext = () =>
|
|
326
|
+
new SlateContext(getAuthConfig(), {}, {}, slate.spec as any, logger);
|
|
327
|
+
let withRequestTraces = <Result extends Record<string, any>>(
|
|
328
|
+
context: SlatePublicContext<any>,
|
|
329
|
+
result: Result
|
|
330
|
+
) => {
|
|
331
|
+
let requestTraces = context.getHttpTraces();
|
|
332
|
+
return requestTraces.length > 0 ? { ...result, requestTraces } : result;
|
|
333
|
+
};
|
|
334
|
+
|
|
68
335
|
manager.onNotification('slates/hello', async ({ params }) => {
|
|
69
336
|
protocol.set(params.protocol);
|
|
70
337
|
});
|
|
@@ -118,6 +385,31 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
118
385
|
});
|
|
119
386
|
});
|
|
120
387
|
|
|
388
|
+
manager.onNotification('slates/hub.capabilities.set', async ({ params }) => {
|
|
389
|
+
hubCapabilities.set(params.capabilities);
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
manager.onNotification('slates/hub.live_invocation.set', async ({ params }) => {
|
|
393
|
+
liveInvocation.set({
|
|
394
|
+
token: params.token,
|
|
395
|
+
baseUrl: params.baseUrl
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
manager.onRequest('slates/provider.capabilities.get', async () => ({
|
|
400
|
+
capabilities: {
|
|
401
|
+
hub: {
|
|
402
|
+
capabilitiesNotification: true,
|
|
403
|
+
liveInvocation: true
|
|
404
|
+
},
|
|
405
|
+
provider: {
|
|
406
|
+
triggerGroups:
|
|
407
|
+
(slate.triggerGroups?.length ?? 0) > 0 &&
|
|
408
|
+
(slate.actions ?? []).every(isMappableTrigger)
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}));
|
|
412
|
+
|
|
121
413
|
manager.onRequest('slates/config.changed', async ({ params }) => {
|
|
122
414
|
getContextBasic();
|
|
123
415
|
|
|
@@ -133,15 +425,37 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
133
425
|
return { success: true, config: newConfig };
|
|
134
426
|
}
|
|
135
427
|
|
|
136
|
-
let
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
428
|
+
let context = getEmptyContext();
|
|
429
|
+
let updatedConfig = await traceProviderCall<{ config?: ConfigType } | undefined>(
|
|
430
|
+
{
|
|
431
|
+
component: 'config',
|
|
432
|
+
functionName: 'configChanged',
|
|
433
|
+
message: 'Running config change handler',
|
|
434
|
+
successMessage: 'Config change handler completed',
|
|
435
|
+
metadata: {
|
|
436
|
+
hasPreviousConfig: params.previousConfig !== null,
|
|
437
|
+
newConfigKeyCount: getObjectKeyCount(newConfig)
|
|
438
|
+
},
|
|
439
|
+
onSuccess: result => ({
|
|
440
|
+
returnedConfig: !!result?.config
|
|
441
|
+
})
|
|
442
|
+
},
|
|
443
|
+
() =>
|
|
444
|
+
runWithContext(context, async () =>
|
|
445
|
+
configChanged({
|
|
446
|
+
previousConfig: params.previousConfig as ConfigType | null,
|
|
447
|
+
newConfig
|
|
448
|
+
})
|
|
449
|
+
)
|
|
450
|
+
);
|
|
140
451
|
|
|
141
|
-
return
|
|
452
|
+
return withRequestTraces(context, {
|
|
453
|
+
success: true,
|
|
454
|
+
config: (updatedConfig?.config ?? newConfig) as Record<string, any>
|
|
455
|
+
});
|
|
142
456
|
});
|
|
143
457
|
|
|
144
|
-
manager.onRequest('slates/config.get_default', async (
|
|
458
|
+
manager.onRequest('slates/config.get_default', async () => {
|
|
145
459
|
getContextBasic();
|
|
146
460
|
|
|
147
461
|
let getDefaultConfig = slate.spec.config.handlers.getDefaultConfig;
|
|
@@ -149,32 +463,50 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
149
463
|
return { config: null };
|
|
150
464
|
}
|
|
151
465
|
|
|
152
|
-
let
|
|
153
|
-
|
|
466
|
+
let context = getEmptyContext();
|
|
467
|
+
let defaultConfig = await traceProviderCall<ConfigType>(
|
|
468
|
+
{
|
|
469
|
+
component: 'config',
|
|
470
|
+
functionName: 'getDefaultConfig',
|
|
471
|
+
message: 'Getting default config',
|
|
472
|
+
successMessage: 'Default config retrieved',
|
|
473
|
+
onSuccess: result => ({
|
|
474
|
+
configKeyCount: getObjectKeyCount(result)
|
|
475
|
+
})
|
|
476
|
+
},
|
|
477
|
+
() => runWithContext(context, async () => getDefaultConfig())
|
|
478
|
+
);
|
|
479
|
+
return withRequestTraces(context, {
|
|
480
|
+
config: (defaultConfig ?? null) as Record<string, any> | null
|
|
481
|
+
});
|
|
154
482
|
});
|
|
155
483
|
|
|
156
|
-
manager.onRequest('slates/config.schema.get', async (
|
|
484
|
+
manager.onRequest('slates/config.schema.get', async () => {
|
|
157
485
|
getContextBasic();
|
|
158
486
|
|
|
159
|
-
return {
|
|
487
|
+
return {
|
|
488
|
+
schema: toJsonSchema(slate.spec.configSchema),
|
|
489
|
+
docs: slate.spec.config.docsReferences ?? []
|
|
490
|
+
};
|
|
160
491
|
});
|
|
161
492
|
|
|
162
|
-
manager.onRequest('slates/provider.identify', async (
|
|
493
|
+
manager.onRequest('slates/provider.identify', async () => {
|
|
163
494
|
getContextBasic();
|
|
164
495
|
|
|
165
496
|
return {
|
|
166
|
-
protocol:
|
|
497
|
+
protocol: SLATES_PROTOCOL_VERSION,
|
|
167
498
|
provider: {
|
|
168
499
|
type: 'provider',
|
|
169
500
|
id: slate.spec.key,
|
|
170
501
|
name: slate.spec.name,
|
|
171
502
|
description: slate.spec.description,
|
|
172
503
|
metadata: slate.spec.parameters.metadata
|
|
173
|
-
}
|
|
504
|
+
},
|
|
505
|
+
docs: slate.spec.docs ?? []
|
|
174
506
|
};
|
|
175
507
|
});
|
|
176
508
|
|
|
177
|
-
manager.onRequest('slates/auth.methods.list', async (
|
|
509
|
+
manager.onRequest('slates/auth.methods.list', async () => {
|
|
178
510
|
getContextBasic();
|
|
179
511
|
|
|
180
512
|
return {
|
|
@@ -199,7 +531,25 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
199
531
|
return { input: null };
|
|
200
532
|
}
|
|
201
533
|
|
|
202
|
-
|
|
534
|
+
let context = getEmptyContext();
|
|
535
|
+
let input = await traceProviderCall(
|
|
536
|
+
{
|
|
537
|
+
component: 'auth',
|
|
538
|
+
functionName: 'getDefaultInput',
|
|
539
|
+
message: 'Getting default authentication input',
|
|
540
|
+
successMessage: 'Default authentication input retrieved',
|
|
541
|
+
metadata: {
|
|
542
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
543
|
+
authenticationMethodName: authMethod.name
|
|
544
|
+
},
|
|
545
|
+
onSuccess: result => ({
|
|
546
|
+
inputKeyCount: getObjectKeyCount(result)
|
|
547
|
+
})
|
|
548
|
+
},
|
|
549
|
+
() => runWithContext(context, () => authMethod.getDefaultInput!())
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
return withRequestTraces(context, { input });
|
|
203
553
|
});
|
|
204
554
|
|
|
205
555
|
manager.onRequest('slates/auth.input.changed', async ({ params }) => {
|
|
@@ -210,12 +560,36 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
210
560
|
return { success: true, input: params.newInput };
|
|
211
561
|
}
|
|
212
562
|
|
|
213
|
-
let
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
563
|
+
let context = getEmptyContext();
|
|
564
|
+
let updatedInput = await traceProviderCall(
|
|
565
|
+
{
|
|
566
|
+
component: 'auth',
|
|
567
|
+
functionName: 'onInputChanged',
|
|
568
|
+
message: 'Running authentication input change handler',
|
|
569
|
+
successMessage: 'Authentication input change handler completed',
|
|
570
|
+
metadata: {
|
|
571
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
572
|
+
authenticationMethodName: authMethod.name,
|
|
573
|
+
hasPreviousInput: params.previousInput !== null,
|
|
574
|
+
newInputKeyCount: getObjectKeyCount(params.newInput)
|
|
575
|
+
},
|
|
576
|
+
onSuccess: result => ({
|
|
577
|
+
returnedInput: !!result?.input
|
|
578
|
+
})
|
|
579
|
+
},
|
|
580
|
+
() =>
|
|
581
|
+
runWithContext(context, () =>
|
|
582
|
+
authMethod.onInputChanged!({
|
|
583
|
+
previousInput: params.previousInput as any | null,
|
|
584
|
+
newInput: params.newInput
|
|
585
|
+
})
|
|
586
|
+
)
|
|
587
|
+
);
|
|
217
588
|
|
|
218
|
-
return
|
|
589
|
+
return withRequestTraces(context, {
|
|
590
|
+
success: true,
|
|
591
|
+
input: updatedInput?.input ?? params.newInput
|
|
592
|
+
});
|
|
219
593
|
});
|
|
220
594
|
|
|
221
595
|
manager.onRequest('slates/auth.output.get', async ({ params }) => {
|
|
@@ -234,8 +608,35 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
234
608
|
}
|
|
235
609
|
|
|
236
610
|
if ('getOutput' in authMethod) {
|
|
237
|
-
let
|
|
238
|
-
|
|
611
|
+
let context = getAuthContext();
|
|
612
|
+
let outputRes = await traceProviderCall(
|
|
613
|
+
{
|
|
614
|
+
component: 'auth',
|
|
615
|
+
functionName: 'getOutput',
|
|
616
|
+
message: 'Getting authentication output',
|
|
617
|
+
successMessage: 'Authentication output retrieved',
|
|
618
|
+
metadata: {
|
|
619
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
620
|
+
authenticationMethodName: authMethod.name,
|
|
621
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
622
|
+
},
|
|
623
|
+
onSuccess: result => ({
|
|
624
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
625
|
+
scopeCount: result.scopes?.length ?? 0
|
|
626
|
+
})
|
|
627
|
+
},
|
|
628
|
+
() =>
|
|
629
|
+
runWithContext(context, () =>
|
|
630
|
+
authMethod.getOutput({
|
|
631
|
+
input,
|
|
632
|
+
config: getAuthConfig()
|
|
633
|
+
})
|
|
634
|
+
)
|
|
635
|
+
);
|
|
636
|
+
return withRequestTraces(context, {
|
|
637
|
+
output: outputRes.output,
|
|
638
|
+
scopes: outputRes.scopes
|
|
639
|
+
});
|
|
239
640
|
}
|
|
240
641
|
|
|
241
642
|
return { output: input as any };
|
|
@@ -246,20 +647,47 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
246
647
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
247
648
|
|
|
248
649
|
if ('handleCallback' in authMethod) {
|
|
249
|
-
let
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
650
|
+
let context = getEmptyContext();
|
|
651
|
+
let callbackRes = await traceProviderCall(
|
|
652
|
+
{
|
|
653
|
+
component: 'auth',
|
|
654
|
+
functionName: 'handleCallback',
|
|
655
|
+
message: 'Handling authentication callback',
|
|
656
|
+
successMessage: 'Authentication callback handled',
|
|
657
|
+
metadata: {
|
|
658
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
659
|
+
authenticationMethodName: authMethod.name,
|
|
660
|
+
scopeCount: params.scopes.length,
|
|
661
|
+
hasCallbackState: !!params.callbackState
|
|
662
|
+
},
|
|
663
|
+
onSuccess: result => ({
|
|
664
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
665
|
+
returnedInput: !!result.input,
|
|
666
|
+
returnedScopeCount: result.scopes?.length
|
|
667
|
+
})
|
|
668
|
+
},
|
|
669
|
+
() =>
|
|
670
|
+
runWithContext(context, () =>
|
|
671
|
+
authMethod.handleCallback({
|
|
672
|
+
code: params.code,
|
|
673
|
+
state: params.state,
|
|
674
|
+
redirectUri: params.redirectUri,
|
|
675
|
+
input: params.input,
|
|
676
|
+
clientId: params.clientId,
|
|
677
|
+
clientSecret: params.clientSecret,
|
|
678
|
+
scopes: params.scopes,
|
|
679
|
+
callbackParams: params.callbackParams || {},
|
|
680
|
+
callbackState: params.callbackState || {},
|
|
681
|
+
config: getAuthConfig()
|
|
682
|
+
})
|
|
683
|
+
)
|
|
684
|
+
);
|
|
258
685
|
|
|
259
|
-
return {
|
|
686
|
+
return withRequestTraces(context, {
|
|
260
687
|
output: callbackRes.output,
|
|
261
|
-
input: callbackRes.input
|
|
262
|
-
|
|
688
|
+
input: callbackRes.input,
|
|
689
|
+
scopes: callbackRes.scopes
|
|
690
|
+
});
|
|
263
691
|
}
|
|
264
692
|
|
|
265
693
|
throw new ServiceError(
|
|
@@ -274,19 +702,43 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
274
702
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
275
703
|
|
|
276
704
|
if ('getAuthorizationUrl' in authMethod) {
|
|
277
|
-
let
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
705
|
+
let context = getEmptyContext();
|
|
706
|
+
let urlRes = await traceProviderCall(
|
|
707
|
+
{
|
|
708
|
+
component: 'auth',
|
|
709
|
+
functionName: 'getAuthorizationUrl',
|
|
710
|
+
message: 'Getting authentication authorization URL',
|
|
711
|
+
successMessage: 'Authentication authorization URL retrieved',
|
|
712
|
+
metadata: {
|
|
713
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
714
|
+
authenticationMethodName: authMethod.name,
|
|
715
|
+
scopeCount: params.scopes.length,
|
|
716
|
+
inputKeyCount: getObjectKeyCount(params.input)
|
|
717
|
+
},
|
|
718
|
+
onSuccess: result => ({
|
|
719
|
+
returnedInput: !!result.input,
|
|
720
|
+
hasCallbackState: !!result.callbackState
|
|
721
|
+
})
|
|
722
|
+
},
|
|
723
|
+
() =>
|
|
724
|
+
runWithContext(context, () =>
|
|
725
|
+
authMethod.getAuthorizationUrl({
|
|
726
|
+
redirectUri: params.redirectUri,
|
|
727
|
+
state: params.state,
|
|
728
|
+
input: params.input,
|
|
729
|
+
clientId: params.clientId,
|
|
730
|
+
clientSecret: params.clientSecret,
|
|
731
|
+
scopes: params.scopes,
|
|
732
|
+
config: getAuthConfig()
|
|
733
|
+
})
|
|
734
|
+
)
|
|
735
|
+
);
|
|
285
736
|
|
|
286
|
-
return {
|
|
737
|
+
return withRequestTraces(context, {
|
|
287
738
|
authorizationUrl: urlRes.url,
|
|
288
|
-
input: urlRes.input
|
|
289
|
-
|
|
739
|
+
input: urlRes.input,
|
|
740
|
+
callbackState: urlRes.callbackState
|
|
741
|
+
});
|
|
290
742
|
}
|
|
291
743
|
|
|
292
744
|
throw new ServiceError(
|
|
@@ -301,15 +753,47 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
301
753
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
302
754
|
|
|
303
755
|
if (authMethod.getProfile) {
|
|
304
|
-
let
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
756
|
+
let context = getAuthContext();
|
|
757
|
+
let profileRes = await traceProviderCall(
|
|
758
|
+
{
|
|
759
|
+
component: 'auth',
|
|
760
|
+
functionName: 'getProfile',
|
|
761
|
+
message: 'Getting authentication profile',
|
|
762
|
+
successMessage: 'Authentication profile retrieved',
|
|
763
|
+
metadata: {
|
|
764
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
765
|
+
authenticationMethodName: authMethod.name,
|
|
766
|
+
scopeCount: params.scopes.length,
|
|
767
|
+
inputKeyCount: getObjectKeyCount(params.input),
|
|
768
|
+
outputKeyCount: getObjectKeyCount(params.output)
|
|
769
|
+
},
|
|
770
|
+
onSuccess: result => ({
|
|
771
|
+
profileKeyCount: getObjectKeyCount(result.profile)
|
|
772
|
+
})
|
|
773
|
+
},
|
|
774
|
+
() =>
|
|
775
|
+
runWithContext(context, () => {
|
|
776
|
+
if (authMethod.type === 'auth.oauth') {
|
|
777
|
+
return authMethod.getProfile!({
|
|
778
|
+
output: params.output as any,
|
|
779
|
+
input: params.input,
|
|
780
|
+
scopes: params.scopes,
|
|
781
|
+
config: getAuthConfig()
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
return authMethod.getProfile!({
|
|
786
|
+
output: params.output as any,
|
|
787
|
+
input: params.input,
|
|
788
|
+
scopes: params.scopes,
|
|
789
|
+
config: getAuthConfig()
|
|
790
|
+
})!;
|
|
791
|
+
})
|
|
792
|
+
);
|
|
309
793
|
|
|
310
|
-
return {
|
|
794
|
+
return withRequestTraces(context, {
|
|
311
795
|
profile: profileRes.profile
|
|
312
|
-
};
|
|
796
|
+
});
|
|
313
797
|
}
|
|
314
798
|
|
|
315
799
|
throw new ServiceError(
|
|
@@ -324,18 +808,53 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
324
808
|
let authMethod = getAuthMethod(slate, params.authenticationMethodId);
|
|
325
809
|
|
|
326
810
|
if ('handleTokenRefresh' in authMethod && authMethod.handleTokenRefresh) {
|
|
327
|
-
let
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
811
|
+
let context = getAuthContext();
|
|
812
|
+
let refreshRes = await traceProviderCall(
|
|
813
|
+
{
|
|
814
|
+
component: 'auth',
|
|
815
|
+
functionName: 'handleTokenRefresh',
|
|
816
|
+
message: 'Refreshing authentication token',
|
|
817
|
+
successMessage: 'Authentication token refreshed',
|
|
818
|
+
metadata: {
|
|
819
|
+
authenticationMethodId: params.authenticationMethodId,
|
|
820
|
+
authenticationMethodName: authMethod.name,
|
|
821
|
+
scopeCount: params.scopes.length,
|
|
822
|
+
inputKeyCount: getObjectKeyCount(params.input),
|
|
823
|
+
outputKeyCount: getObjectKeyCount(params.output)
|
|
824
|
+
},
|
|
825
|
+
onSuccess: result => ({
|
|
826
|
+
refreshedOutputKeyCount: getObjectKeyCount(result.output),
|
|
827
|
+
returnedInput: !!result.input
|
|
828
|
+
})
|
|
829
|
+
},
|
|
830
|
+
() =>
|
|
831
|
+
runWithContext(context, () => {
|
|
832
|
+
if (authMethod.type === 'auth.oauth') {
|
|
833
|
+
return authMethod.handleTokenRefresh!({
|
|
834
|
+
output: params.output as any,
|
|
835
|
+
input: params.input,
|
|
836
|
+
clientId: params.clientId,
|
|
837
|
+
clientSecret: params.clientSecret,
|
|
838
|
+
scopes: params.scopes,
|
|
839
|
+
config: getAuthConfig()
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
return authMethod.handleTokenRefresh!({
|
|
844
|
+
output: params.output as any,
|
|
845
|
+
input: params.input,
|
|
846
|
+
clientId: params.clientId,
|
|
847
|
+
clientSecret: params.clientSecret,
|
|
848
|
+
scopes: params.scopes,
|
|
849
|
+
config: getAuthConfig()
|
|
850
|
+
});
|
|
851
|
+
})
|
|
852
|
+
);
|
|
334
853
|
|
|
335
|
-
return {
|
|
854
|
+
return withRequestTraces(context, {
|
|
336
855
|
output: refreshRes.output,
|
|
337
856
|
input: refreshRes.input
|
|
338
|
-
};
|
|
857
|
+
});
|
|
339
858
|
}
|
|
340
859
|
|
|
341
860
|
throw new ServiceError(
|
|
@@ -348,22 +867,65 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
348
867
|
manager.onRequest('slates/actions.list', async ({ params }) => {
|
|
349
868
|
getContextBasic();
|
|
350
869
|
|
|
870
|
+
let actions = params.includeAdapterActions
|
|
871
|
+
? slate.actions
|
|
872
|
+
: slate.actions.filter(action => !action.adapter);
|
|
873
|
+
|
|
874
|
+
actions = actions.filter(isMappableTrigger);
|
|
875
|
+
|
|
876
|
+
if (!supportsTriggerGroups()) {
|
|
877
|
+
actions = actions.filter(action => action.type !== 'trigger');
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
return {
|
|
881
|
+
actions: actions.map(a => mapAction(slate, a))
|
|
882
|
+
};
|
|
883
|
+
});
|
|
884
|
+
|
|
885
|
+
manager.onRequest('slates/adapters.list', async () => {
|
|
886
|
+
getContextBasic();
|
|
887
|
+
|
|
888
|
+
return {
|
|
889
|
+
adapters: slate.adapters.map(mapAdapter)
|
|
890
|
+
};
|
|
891
|
+
});
|
|
892
|
+
|
|
893
|
+
manager.onRequest('slates/adapter.get', async ({ params }) => {
|
|
894
|
+
getContextBasic();
|
|
895
|
+
let adapter = getAdapter(slate, params.adapterId);
|
|
896
|
+
|
|
351
897
|
return {
|
|
352
|
-
|
|
898
|
+
adapter: mapAdapter(adapter)
|
|
353
899
|
};
|
|
354
900
|
});
|
|
355
901
|
|
|
356
902
|
manager.onRequest('slates/action.get', async ({ params }) => {
|
|
357
903
|
getContextBasic();
|
|
358
|
-
let action =
|
|
904
|
+
let action = getMappableAction(slate, params.actionId);
|
|
359
905
|
|
|
360
906
|
return {
|
|
361
907
|
action: mapAction(slate, action)
|
|
362
908
|
};
|
|
363
909
|
});
|
|
364
910
|
|
|
911
|
+
manager.onRequest('slates/trigger_groups.list', async () => {
|
|
912
|
+
getContextBasic();
|
|
913
|
+
|
|
914
|
+
return {
|
|
915
|
+
triggerGroups: slate.triggerGroups.map(mapTriggerGroup)
|
|
916
|
+
};
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
manager.onRequest('slates/trigger_group.get', async ({ params }) => {
|
|
920
|
+
getContextBasic();
|
|
921
|
+
let triggerGroup = getTriggerGroup(slate, params.triggerGroupId);
|
|
922
|
+
|
|
923
|
+
return {
|
|
924
|
+
triggerGroup: mapTriggerGroup(triggerGroup)
|
|
925
|
+
};
|
|
926
|
+
});
|
|
927
|
+
|
|
365
928
|
manager.onRequest('slates/action.tool.invoke', async ({ params }) => {
|
|
366
|
-
let ctx = getContextFull();
|
|
367
929
|
let action = getActionWithType(slate, 'tool', params.actionId);
|
|
368
930
|
|
|
369
931
|
let input = validate(
|
|
@@ -373,11 +935,69 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
373
935
|
`Invalid input for tool ID: ${params.actionId}`
|
|
374
936
|
);
|
|
375
937
|
|
|
376
|
-
let
|
|
377
|
-
|
|
378
|
-
|
|
938
|
+
let invoke = async (context: SlatePublicContext<any>) => {
|
|
939
|
+
let res = await traceProviderCall(
|
|
940
|
+
{
|
|
941
|
+
component: 'action',
|
|
942
|
+
functionName: 'handleInvocation',
|
|
943
|
+
message: `Starting tool ${formatEntityLabel(action.name, action.key)}`,
|
|
944
|
+
successMessage: `Completed tool ${formatEntityLabel(action.name, action.key)}`,
|
|
945
|
+
errorMessage: `Tool ${formatEntityLabel(action.name, action.key)} failed`,
|
|
946
|
+
metadata: {
|
|
947
|
+
actionId: action.key,
|
|
948
|
+
actionName: action.name,
|
|
949
|
+
actionType: action.type,
|
|
950
|
+
isPublic: action.isPublic,
|
|
951
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
952
|
+
},
|
|
953
|
+
onSuccess: result => ({
|
|
954
|
+
hasMessage: !!result.message,
|
|
955
|
+
actionResultMessage: result.message,
|
|
956
|
+
outputKeyCount: getObjectKeyCount(result.output),
|
|
957
|
+
attachmentCount: result.attachments?.length
|
|
958
|
+
})
|
|
959
|
+
},
|
|
960
|
+
() => runWithContext(context, () => action.handleInvocation(context as any))
|
|
961
|
+
);
|
|
379
962
|
|
|
380
|
-
|
|
963
|
+
let contextAttachments = await context._finalizeAttachments();
|
|
964
|
+
let merged = mergeAttachments(
|
|
965
|
+
[...(res.attachments ?? []), ...contextAttachments],
|
|
966
|
+
res.output
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
let redacted = redactUrlAttachmentSecrets(
|
|
970
|
+
merged,
|
|
971
|
+
context._getAuthConfigForRedaction()
|
|
972
|
+
);
|
|
973
|
+
let finalAttachments = await routeAttachmentsThroughDirectUpload(
|
|
974
|
+
redacted,
|
|
975
|
+
getLiveInvocation()
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
return withRequestTraces(context, {
|
|
979
|
+
output: res.output,
|
|
980
|
+
message: res.message,
|
|
981
|
+
attachments: finalAttachments
|
|
982
|
+
});
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
if (action.isPublic) {
|
|
986
|
+
getContextBasic();
|
|
987
|
+
return invoke(new SlatePublicContext(input, slate.spec, logger, getLiveInvocation()));
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
let ctx = getContextFull();
|
|
991
|
+
return invoke(
|
|
992
|
+
new SlateContext(
|
|
993
|
+
ctx.config,
|
|
994
|
+
input,
|
|
995
|
+
ctx.auth?.output!,
|
|
996
|
+
slate.spec,
|
|
997
|
+
logger,
|
|
998
|
+
getLiveInvocation()
|
|
999
|
+
)
|
|
1000
|
+
);
|
|
381
1001
|
});
|
|
382
1002
|
|
|
383
1003
|
manager.onRequest('slates/action.trigger.map_event', async ({ params }) => {
|
|
@@ -391,46 +1011,282 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
391
1011
|
`Invalid event for trigger ID: ${params.actionId}`
|
|
392
1012
|
);
|
|
393
1013
|
|
|
394
|
-
let
|
|
395
|
-
|
|
1014
|
+
let context = new SlateContext(ctx.config, input, ctx.auth?.output!, slate.spec, logger);
|
|
1015
|
+
let res = await traceProviderCall(
|
|
1016
|
+
{
|
|
1017
|
+
component: 'action',
|
|
1018
|
+
functionName: 'handleEvent',
|
|
1019
|
+
message: `Mapping event for trigger ${formatEntityLabel(action.name, action.key)}`,
|
|
1020
|
+
successMessage: result =>
|
|
1021
|
+
`Mapped trigger event "${result.type}" for ${formatEntityLabel(action.name, action.key)}`,
|
|
1022
|
+
errorMessage: `Trigger ${formatEntityLabel(action.name, action.key)} failed while mapping an event`,
|
|
1023
|
+
metadata: {
|
|
1024
|
+
actionId: action.key,
|
|
1025
|
+
actionName: action.name,
|
|
1026
|
+
actionType: action.type,
|
|
1027
|
+
inputKeyCount: getObjectKeyCount(input)
|
|
1028
|
+
},
|
|
1029
|
+
onSuccess: result => ({
|
|
1030
|
+
eventType: result.type,
|
|
1031
|
+
hasEventId: !!result.id,
|
|
1032
|
+
outputKeyCount: getObjectKeyCount(result.output)
|
|
1033
|
+
})
|
|
1034
|
+
},
|
|
1035
|
+
() => runWithContext(context, () => action.map(context))
|
|
396
1036
|
);
|
|
397
1037
|
|
|
398
|
-
return { id: res.id, type: res.type, output: res.output };
|
|
1038
|
+
return withRequestTraces(context, { id: res.id, type: res.type, output: res.output });
|
|
399
1039
|
});
|
|
400
1040
|
|
|
401
1041
|
manager.onRequest('slates/action.trigger.poll_events', async ({ params }) => {
|
|
402
|
-
|
|
403
|
-
let action = getActionWithType(slate, 'trigger', params.actionId);
|
|
1042
|
+
getContextBasic();
|
|
404
1043
|
|
|
405
|
-
if (
|
|
1044
|
+
if (supportsTriggerGroups()) {
|
|
406
1045
|
throw new ServiceError(
|
|
407
1046
|
badRequestError({
|
|
408
|
-
message: `
|
|
1047
|
+
message: `Legacy trigger polling is disabled once trigger_group support is announced: ${params.actionId}`
|
|
409
1048
|
})
|
|
410
1049
|
);
|
|
411
1050
|
}
|
|
412
1051
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
1052
|
+
return { inputs: [], updatedState: params.state };
|
|
1053
|
+
});
|
|
1054
|
+
|
|
1055
|
+
manager.onRequest('slates/action.trigger.webhook_handle', async ({ params }) => {
|
|
1056
|
+
getContextBasic();
|
|
1057
|
+
|
|
1058
|
+
if (supportsTriggerGroups()) {
|
|
1059
|
+
throw new ServiceError(
|
|
1060
|
+
badRequestError({
|
|
1061
|
+
message: `Legacy trigger webhook handling is disabled once trigger_group support is announced: ${params.actionId}`
|
|
1062
|
+
})
|
|
1063
|
+
);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
return { inputs: [], updatedState: params.state, response: null };
|
|
1067
|
+
});
|
|
1068
|
+
|
|
1069
|
+
manager.onRequest('slates/action.trigger.webhook_register', async ({ params }) => {
|
|
1070
|
+
getContextBasic();
|
|
1071
|
+
|
|
1072
|
+
if (supportsTriggerGroups()) {
|
|
1073
|
+
throw new ServiceError(
|
|
1074
|
+
badRequestError({
|
|
1075
|
+
message: `Legacy trigger webhook registration is disabled once trigger_group support is announced: ${params.actionId}`
|
|
1076
|
+
})
|
|
1077
|
+
);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
return { registrationDetails: null };
|
|
1081
|
+
});
|
|
1082
|
+
|
|
1083
|
+
manager.onRequest('slates/action.trigger.webhook_unregister', async ({ params }) => {
|
|
1084
|
+
getContextBasic();
|
|
1085
|
+
|
|
1086
|
+
if (supportsTriggerGroups()) {
|
|
1087
|
+
throw new ServiceError(
|
|
1088
|
+
badRequestError({
|
|
1089
|
+
message: `Legacy trigger webhook unregistration is disabled once trigger_group support is announced: ${params.actionId}`
|
|
1090
|
+
})
|
|
1091
|
+
);
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
return {};
|
|
1095
|
+
});
|
|
1096
|
+
|
|
1097
|
+
manager.onRequest('slates/trigger_group.webhook.targets_list', async ({ params }) => {
|
|
1098
|
+
let ctx = getContextFull();
|
|
1099
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1100
|
+
let autoRegistration = getWebhookAutoRegistration(group);
|
|
1101
|
+
|
|
1102
|
+
let context = new SlateContext(
|
|
1103
|
+
ctx.config,
|
|
1104
|
+
{ pageToken: params.pageToken ?? null },
|
|
1105
|
+
ctx.auth?.output!,
|
|
1106
|
+
slate.spec,
|
|
1107
|
+
logger
|
|
1108
|
+
);
|
|
1109
|
+
let res = await traceProviderCall(
|
|
1110
|
+
{
|
|
1111
|
+
component: 'action',
|
|
1112
|
+
functionName: 'webhookTargetList',
|
|
1113
|
+
message: `Listing webhook targets for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1114
|
+
successMessage: result =>
|
|
1115
|
+
`Listed ${result.targets.length} webhook target(s) for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1116
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while listing webhook targets`,
|
|
1117
|
+
metadata: {
|
|
1118
|
+
triggerGroupId: group.key,
|
|
1119
|
+
triggerGroupName: group.name
|
|
1120
|
+
},
|
|
1121
|
+
onSuccess: result => ({
|
|
1122
|
+
targetCount: result.targets.length,
|
|
1123
|
+
hasNextPageToken: result.nextPageToken !== null
|
|
1124
|
+
})
|
|
1125
|
+
},
|
|
1126
|
+
() => runWithContext(context, () => autoRegistration.webhookTargetList(context))
|
|
421
1127
|
);
|
|
422
1128
|
|
|
423
|
-
return
|
|
1129
|
+
return withRequestTraces(context, {
|
|
1130
|
+
targets: res.targets,
|
|
1131
|
+
nextPageToken: res.nextPageToken ?? null
|
|
1132
|
+
});
|
|
424
1133
|
});
|
|
425
1134
|
|
|
426
|
-
manager.onRequest('slates/
|
|
1135
|
+
manager.onRequest('slates/trigger_group.webhook.register', async ({ params }) => {
|
|
427
1136
|
let ctx = getContextFull();
|
|
428
|
-
let
|
|
1137
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1138
|
+
let autoRegistration = getWebhookAutoRegistration(group);
|
|
1139
|
+
|
|
1140
|
+
let context = new SlateContext(
|
|
1141
|
+
ctx.config,
|
|
1142
|
+
{
|
|
1143
|
+
webhookTargetIdentifier: params.webhookTargetIdentifier,
|
|
1144
|
+
webhookTargetPayload: params.webhookTargetPayload,
|
|
1145
|
+
webhookUrl: params.webhookUrl
|
|
1146
|
+
},
|
|
1147
|
+
ctx.auth?.output!,
|
|
1148
|
+
slate.spec,
|
|
1149
|
+
logger
|
|
1150
|
+
);
|
|
1151
|
+
let res = await traceProviderCall(
|
|
1152
|
+
{
|
|
1153
|
+
component: 'action',
|
|
1154
|
+
functionName: 'webhookRegister',
|
|
1155
|
+
message: `Registering webhook for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1156
|
+
successMessage: `Registered webhook for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1157
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while registering a webhook`,
|
|
1158
|
+
metadata: {
|
|
1159
|
+
triggerGroupId: group.key,
|
|
1160
|
+
triggerGroupName: group.name,
|
|
1161
|
+
webhookTargetIdentifier: params.webhookTargetIdentifier
|
|
1162
|
+
}
|
|
1163
|
+
},
|
|
1164
|
+
() => runWithContext(context, () => autoRegistration.webhookRegister(context))
|
|
1165
|
+
);
|
|
1166
|
+
|
|
1167
|
+
return withRequestTraces(context, {
|
|
1168
|
+
webhookRegistrationIdentifier: res.webhookRegistrationIdentifier,
|
|
1169
|
+
webhookRegistrationPayload: res.webhookRegistrationPayload
|
|
1170
|
+
});
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
manager.onRequest('slates/trigger_group.webhook.unregister', async ({ params }) => {
|
|
1174
|
+
let ctx = getContextFull();
|
|
1175
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1176
|
+
let autoRegistration = getWebhookAutoRegistration(group);
|
|
1177
|
+
|
|
1178
|
+
let context = new SlateContext(
|
|
1179
|
+
ctx.config,
|
|
1180
|
+
{
|
|
1181
|
+
webhookRegistrationIdentifier: params.webhookRegistrationIdentifier,
|
|
1182
|
+
webhookRegistrationPayload: params.webhookRegistrationPayload
|
|
1183
|
+
},
|
|
1184
|
+
ctx.auth?.output!,
|
|
1185
|
+
slate.spec,
|
|
1186
|
+
logger
|
|
1187
|
+
);
|
|
1188
|
+
await traceProviderCall(
|
|
1189
|
+
{
|
|
1190
|
+
component: 'action',
|
|
1191
|
+
functionName: 'webhookUnregister',
|
|
1192
|
+
message: `Unregistering webhook for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1193
|
+
successMessage: `Unregistered webhook for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1194
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while unregistering a webhook`,
|
|
1195
|
+
metadata: {
|
|
1196
|
+
triggerGroupId: group.key,
|
|
1197
|
+
triggerGroupName: group.name,
|
|
1198
|
+
webhookRegistrationIdentifier: params.webhookRegistrationIdentifier
|
|
1199
|
+
}
|
|
1200
|
+
},
|
|
1201
|
+
() => runWithContext(context, () => autoRegistration.webhookUnregister(context))
|
|
1202
|
+
);
|
|
429
1203
|
|
|
430
|
-
|
|
1204
|
+
return withRequestTraces(context, {});
|
|
1205
|
+
});
|
|
1206
|
+
|
|
1207
|
+
manager.onRequest('slates/trigger_group.webhook.manual_setup', async ({ params }) => {
|
|
1208
|
+
getContextBasic();
|
|
1209
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1210
|
+
let manualRegistration = getWebhookManualRegistration(group);
|
|
1211
|
+
|
|
1212
|
+
let context = new SlateContext(
|
|
1213
|
+
{},
|
|
1214
|
+
{ webhookUrl: params.webhookUrl },
|
|
1215
|
+
{},
|
|
1216
|
+
slate.spec as any,
|
|
1217
|
+
logger
|
|
1218
|
+
);
|
|
1219
|
+
let res = await traceProviderCall(
|
|
1220
|
+
{
|
|
1221
|
+
component: 'action',
|
|
1222
|
+
functionName: 'webhookManualSetup',
|
|
1223
|
+
message: `Building manual webhook setup for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1224
|
+
successMessage: `Built manual webhook setup for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1225
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while building a manual webhook setup`,
|
|
1226
|
+
metadata: {
|
|
1227
|
+
triggerGroupId: group.key,
|
|
1228
|
+
triggerGroupName: group.name
|
|
1229
|
+
}
|
|
1230
|
+
},
|
|
1231
|
+
() => runWithContext(context, () => manualRegistration.setup(context))
|
|
1232
|
+
);
|
|
1233
|
+
|
|
1234
|
+
return {
|
|
1235
|
+
webhookSetupDocument: res.webhookSetupDocument,
|
|
1236
|
+
partialWebhookRegistrationPayload: res.partialWebhookRegistrationPayload
|
|
1237
|
+
};
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1240
|
+
manager.onRequest('slates/trigger_group.webhook.manual_finish', async ({ params }) => {
|
|
1241
|
+
getContextBasic();
|
|
1242
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1243
|
+
let manualRegistration = getWebhookManualRegistration(group);
|
|
1244
|
+
|
|
1245
|
+
if (!manualRegistration.finish) {
|
|
1246
|
+
throw new ServiceError(
|
|
1247
|
+
badRequestError({
|
|
1248
|
+
message: `Trigger group does not support manual webhook finish: ${params.triggerGroupId}`
|
|
1249
|
+
})
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
let context = new SlateContext(
|
|
1254
|
+
{},
|
|
1255
|
+
{
|
|
1256
|
+
webhookUrl: params.webhookUrl,
|
|
1257
|
+
partialWebhookRegistrationPayload: params.partialWebhookRegistrationPayload,
|
|
1258
|
+
userWebhookRegistrationPayload: params.userWebhookRegistrationPayload
|
|
1259
|
+
},
|
|
1260
|
+
{},
|
|
1261
|
+
slate.spec as any,
|
|
1262
|
+
logger
|
|
1263
|
+
);
|
|
1264
|
+
let res = await traceProviderCall(
|
|
1265
|
+
{
|
|
1266
|
+
component: 'action',
|
|
1267
|
+
functionName: 'webhookManualFinish',
|
|
1268
|
+
message: `Finishing manual webhook setup for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1269
|
+
successMessage: `Finished manual webhook setup for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1270
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while finishing a manual webhook setup`,
|
|
1271
|
+
metadata: {
|
|
1272
|
+
triggerGroupId: group.key,
|
|
1273
|
+
triggerGroupName: group.name
|
|
1274
|
+
}
|
|
1275
|
+
},
|
|
1276
|
+
() => runWithContext(context, () => manualRegistration.finish!(context))
|
|
1277
|
+
);
|
|
1278
|
+
|
|
1279
|
+
return withRequestTraces(context, {
|
|
1280
|
+
webhookRegistrationPayload: res.webhookRegistrationPayload
|
|
1281
|
+
});
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
manager.onRequest('slates/trigger_group.webhook.process', async ({ params }) => {
|
|
1285
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1286
|
+
if (group.source !== 'webhook' || !group.webhook) {
|
|
431
1287
|
throw new ServiceError(
|
|
432
1288
|
badRequestError({
|
|
433
|
-
message: `Trigger
|
|
1289
|
+
message: `Trigger group does not support webhook processing: ${params.triggerGroupId}`
|
|
434
1290
|
})
|
|
435
1291
|
);
|
|
436
1292
|
}
|
|
@@ -443,70 +1299,137 @@ export let createProviderHandler = <ConfigType extends {}, AuthType extends {}>(
|
|
|
443
1299
|
: null
|
|
444
1300
|
});
|
|
445
1301
|
|
|
446
|
-
let
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
1302
|
+
let context = new SlateContext(
|
|
1303
|
+
{},
|
|
1304
|
+
{
|
|
1305
|
+
request: req,
|
|
1306
|
+
webhookRegistrationPayload: params.webhookRegistrationPayload
|
|
1307
|
+
},
|
|
1308
|
+
{},
|
|
1309
|
+
slate.spec as any,
|
|
1310
|
+
logger
|
|
1311
|
+
);
|
|
1312
|
+
let res = await traceProviderCall(
|
|
1313
|
+
{
|
|
1314
|
+
component: 'action',
|
|
1315
|
+
functionName: 'webhookProcess',
|
|
1316
|
+
message: `Processing webhook request for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1317
|
+
successMessage: result =>
|
|
1318
|
+
`Extracted ${result.events.length} event(s) from webhook request for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1319
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while processing a webhook request`,
|
|
1320
|
+
metadata: {
|
|
1321
|
+
triggerGroupId: group.key,
|
|
1322
|
+
triggerGroupName: group.name,
|
|
1323
|
+
requestMethod: params.method,
|
|
1324
|
+
hasRequestBody: !!params.body
|
|
1325
|
+
},
|
|
1326
|
+
onSuccess: result => ({
|
|
1327
|
+
eventCount: result.events.length,
|
|
1328
|
+
hasResponse: result.response !== undefined
|
|
1329
|
+
})
|
|
1330
|
+
},
|
|
1331
|
+
() => runWithContext(context, () => group.webhook!.process(context))
|
|
454
1332
|
);
|
|
455
1333
|
|
|
456
|
-
|
|
1334
|
+
for (let event of res.events) {
|
|
1335
|
+
if (!event.matchers) {
|
|
1336
|
+
throw new ServiceError(
|
|
1337
|
+
preconditionFailedError({
|
|
1338
|
+
message: `Trigger group "${group.key}" process handler must return matchers for every event (return [] if there is nothing to assert)`
|
|
1339
|
+
})
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1344
|
+
let response =
|
|
1345
|
+
res.response === undefined
|
|
1346
|
+
? undefined
|
|
1347
|
+
: await serializeWebhookHttpResponse(res.response);
|
|
1348
|
+
|
|
1349
|
+
return withRequestTraces(context, {
|
|
1350
|
+
events: res.events.map(event => ({
|
|
1351
|
+
matchers: event.matchers,
|
|
1352
|
+
payload: event.payload,
|
|
1353
|
+
idempotencyKey: event.idempotencyKey,
|
|
1354
|
+
triggerIds: evaluateTriggerMatches(slate, group.key, event.payload)
|
|
1355
|
+
})),
|
|
1356
|
+
response
|
|
1357
|
+
});
|
|
457
1358
|
});
|
|
458
1359
|
|
|
459
|
-
manager.onRequest('slates/
|
|
1360
|
+
manager.onRequest('slates/trigger_group.routing_matchers.get', async ({ params }) => {
|
|
460
1361
|
let ctx = getContextFull();
|
|
461
|
-
let
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
1362
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1363
|
+
|
|
1364
|
+
let context = new SlateContext(ctx.config, {}, ctx.auth?.output!, slate.spec, logger);
|
|
1365
|
+
let matchers = await traceProviderCall(
|
|
1366
|
+
{
|
|
1367
|
+
component: 'action',
|
|
1368
|
+
functionName: 'routingMatchers',
|
|
1369
|
+
message: `Getting routing matchers for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1370
|
+
successMessage: result =>
|
|
1371
|
+
`Retrieved ${result.length} routing matcher(s) for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1372
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while getting routing matchers`,
|
|
1373
|
+
metadata: {
|
|
1374
|
+
triggerGroupId: group.key,
|
|
1375
|
+
triggerGroupName: group.name
|
|
1376
|
+
},
|
|
1377
|
+
onSuccess: result => ({
|
|
1378
|
+
matcherCount: result.length
|
|
467
1379
|
})
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
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
|
-
)
|
|
1380
|
+
},
|
|
1381
|
+
() => runWithContext(context, () => group.routingMatchers(context))
|
|
479
1382
|
);
|
|
480
1383
|
|
|
481
|
-
return
|
|
1384
|
+
return withRequestTraces(context, { matchers });
|
|
482
1385
|
});
|
|
483
1386
|
|
|
484
|
-
manager.onRequest('slates/
|
|
1387
|
+
manager.onRequest('slates/trigger_group.polling.poll', async ({ params }) => {
|
|
485
1388
|
let ctx = getContextFull();
|
|
486
|
-
let
|
|
487
|
-
|
|
488
|
-
if (!action.autoUnregisterWebhook) {
|
|
1389
|
+
let group = getTriggerGroup(slate, params.triggerGroupId);
|
|
1390
|
+
if (group.source !== 'polling' || !group.polling) {
|
|
489
1391
|
throw new ServiceError(
|
|
490
1392
|
badRequestError({
|
|
491
|
-
message: `Trigger
|
|
1393
|
+
message: `Trigger group does not support polling: ${params.triggerGroupId}`
|
|
492
1394
|
})
|
|
493
1395
|
);
|
|
494
1396
|
}
|
|
495
1397
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
1398
|
+
let context = new SlateContext(
|
|
1399
|
+
ctx.config,
|
|
1400
|
+
{ state: params.state },
|
|
1401
|
+
ctx.auth?.output!,
|
|
1402
|
+
slate.spec,
|
|
1403
|
+
logger
|
|
1404
|
+
);
|
|
1405
|
+
let res = await traceProviderCall(
|
|
1406
|
+
{
|
|
1407
|
+
component: 'action',
|
|
1408
|
+
functionName: 'pollEvents',
|
|
1409
|
+
message: `Polling events for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1410
|
+
successMessage: result =>
|
|
1411
|
+
`Polled ${result.events.length} event(s) for trigger group ${formatEntityLabel(group.name, group.key)}`,
|
|
1412
|
+
errorMessage: `Trigger group ${formatEntityLabel(group.name, group.key)} failed while polling events`,
|
|
1413
|
+
metadata: {
|
|
1414
|
+
triggerGroupId: group.key,
|
|
1415
|
+
triggerGroupName: group.name,
|
|
1416
|
+
hasPreviousState: params.state !== null
|
|
503
1417
|
},
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
1418
|
+
onSuccess: result => ({
|
|
1419
|
+
eventCount: result.events.length,
|
|
1420
|
+
hasUpdatedState: result.updatedState !== undefined
|
|
1421
|
+
})
|
|
1422
|
+
},
|
|
1423
|
+
() => runWithContext(context, () => group.polling!.pollEvents(context))
|
|
508
1424
|
);
|
|
509
1425
|
|
|
510
|
-
return {
|
|
1426
|
+
return withRequestTraces(context, {
|
|
1427
|
+
updatedState: res.updatedState,
|
|
1428
|
+
events: res.events.map(event => ({
|
|
1429
|
+
payload: event.payload,
|
|
1430
|
+
idempotencyKey: event.idempotencyKey,
|
|
1431
|
+
triggerIds: evaluateTriggerMatches(slate, group.key, event.payload)
|
|
1432
|
+
}))
|
|
1433
|
+
});
|
|
511
1434
|
});
|
|
512
1435
|
});
|