@mastra/inngest 0.0.0-redis-cloud-transporter-20250508203756 → 0.0.0-share-agent-metadata-with-cloud-20250718123411
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/CHANGELOG.md +595 -2
- package/LICENSE.md +11 -42
- package/dist/_tsup-dts-rollup.d.cts +179 -63
- package/dist/_tsup-dts-rollup.d.ts +179 -63
- package/dist/index.cjs +582 -59
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +579 -57
- package/docker-compose.yaml +3 -3
- package/package.json +23 -18
- package/src/index.test.ts +5809 -3549
- package/src/index.ts +884 -103
- package/vitest.config.ts +6 -0
package/src/index.ts
CHANGED
|
@@ -1,34 +1,49 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
+
import type { ReadableStream } from 'node:stream/web';
|
|
2
3
|
import { subscribe } from '@inngest/realtime';
|
|
3
|
-
import type { Mastra, WorkflowRun } from '@mastra/core';
|
|
4
|
+
import type { Agent, Mastra, ToolExecutionContext, WorkflowRun, WorkflowRuns } from '@mastra/core';
|
|
4
5
|
import { RuntimeContext } from '@mastra/core/di';
|
|
5
|
-
import {
|
|
6
|
+
import { Tool } from '@mastra/core/tools';
|
|
7
|
+
import { Workflow, Run, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
6
8
|
import type {
|
|
7
9
|
ExecuteFunction,
|
|
8
10
|
ExecutionContext,
|
|
9
11
|
ExecutionEngine,
|
|
10
12
|
ExecutionGraph,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
NewWorkflowConfig,
|
|
13
|
+
Step,
|
|
14
|
+
WorkflowConfig,
|
|
14
15
|
StepFlowEntry,
|
|
15
16
|
StepResult,
|
|
16
17
|
WorkflowResult,
|
|
17
|
-
|
|
18
|
+
SerializedStepFlowEntry,
|
|
19
|
+
StepFailure,
|
|
20
|
+
Emitter,
|
|
21
|
+
WatchEvent,
|
|
22
|
+
StreamEvent,
|
|
23
|
+
} from '@mastra/core/workflows';
|
|
24
|
+
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
18
25
|
import type { Span } from '@opentelemetry/api';
|
|
19
26
|
import type { Inngest, BaseContext } from 'inngest';
|
|
20
27
|
import { serve as inngestServe } from 'inngest/hono';
|
|
21
|
-
import
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
|
|
30
|
+
export type InngestEngineType = {
|
|
31
|
+
step: any;
|
|
32
|
+
};
|
|
22
33
|
|
|
23
34
|
export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest }): ReturnType<typeof inngestServe> {
|
|
24
|
-
const wfs = mastra.
|
|
25
|
-
const functions =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
const wfs = mastra.getWorkflows();
|
|
36
|
+
const functions = Array.from(
|
|
37
|
+
new Set(
|
|
38
|
+
Object.values(wfs).flatMap(wf => {
|
|
39
|
+
if (wf instanceof InngestWorkflow) {
|
|
40
|
+
wf.__registerMastra(mastra);
|
|
41
|
+
return wf.getFunctions();
|
|
42
|
+
}
|
|
43
|
+
return [];
|
|
44
|
+
}),
|
|
45
|
+
),
|
|
46
|
+
);
|
|
32
47
|
return inngestServe({
|
|
33
48
|
client: inngest,
|
|
34
49
|
functions,
|
|
@@ -36,11 +51,13 @@ export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest })
|
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
export class InngestRun<
|
|
39
|
-
|
|
54
|
+
TEngineType = InngestEngineType,
|
|
55
|
+
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
40
56
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
41
57
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
42
|
-
> extends Run<TSteps, TInput, TOutput> {
|
|
58
|
+
> extends Run<TEngineType, TSteps, TInput, TOutput> {
|
|
43
59
|
private inngest: Inngest;
|
|
60
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
44
61
|
#mastra: Mastra;
|
|
45
62
|
|
|
46
63
|
constructor(
|
|
@@ -49,6 +66,7 @@ export class InngestRun<
|
|
|
49
66
|
runId: string;
|
|
50
67
|
executionEngine: ExecutionEngine;
|
|
51
68
|
executionGraph: ExecutionGraph;
|
|
69
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
52
70
|
mastra?: Mastra;
|
|
53
71
|
retryConfig?: {
|
|
54
72
|
attempts?: number;
|
|
@@ -60,11 +78,12 @@ export class InngestRun<
|
|
|
60
78
|
) {
|
|
61
79
|
super(params);
|
|
62
80
|
this.inngest = inngest;
|
|
81
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
63
82
|
this.#mastra = params.mastra!;
|
|
64
83
|
}
|
|
65
84
|
|
|
66
85
|
async getRuns(eventId: string) {
|
|
67
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
86
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? 'https://api.inngest.com'}/v1/events/${eventId}/runs`, {
|
|
68
87
|
headers: {
|
|
69
88
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`,
|
|
70
89
|
},
|
|
@@ -75,16 +94,55 @@ export class InngestRun<
|
|
|
75
94
|
|
|
76
95
|
async getRunOutput(eventId: string) {
|
|
77
96
|
let runs = await this.getRuns(eventId);
|
|
78
|
-
|
|
97
|
+
|
|
98
|
+
while (runs?.[0]?.status !== 'Completed' || runs?.[0]?.event_id !== eventId) {
|
|
79
99
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
80
100
|
runs = await this.getRuns(eventId);
|
|
81
|
-
if (runs?.[0]?.status === 'Failed'
|
|
101
|
+
if (runs?.[0]?.status === 'Failed') {
|
|
102
|
+
console.log('run', runs?.[0]);
|
|
82
103
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
104
|
+
} else if (runs?.[0]?.status === 'Cancelled') {
|
|
105
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
106
|
+
workflowName: this.workflowId,
|
|
107
|
+
runId: this.runId,
|
|
108
|
+
});
|
|
109
|
+
return { output: { result: { steps: snapshot?.context, status: 'canceled' } } };
|
|
83
110
|
}
|
|
84
111
|
}
|
|
85
112
|
return runs?.[0];
|
|
86
113
|
}
|
|
87
114
|
|
|
115
|
+
async sendEvent(event: string, data: any) {
|
|
116
|
+
await this.inngest.send({
|
|
117
|
+
name: `user-event-${event}`,
|
|
118
|
+
data,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
async cancel() {
|
|
123
|
+
await this.inngest.send({
|
|
124
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
125
|
+
data: {
|
|
126
|
+
runId: this.runId,
|
|
127
|
+
},
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
131
|
+
workflowName: this.workflowId,
|
|
132
|
+
runId: this.runId,
|
|
133
|
+
});
|
|
134
|
+
if (snapshot) {
|
|
135
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
136
|
+
workflowName: this.workflowId,
|
|
137
|
+
runId: this.runId,
|
|
138
|
+
snapshot: {
|
|
139
|
+
...snapshot,
|
|
140
|
+
status: 'canceled' as any,
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
88
146
|
async start({
|
|
89
147
|
inputData,
|
|
90
148
|
}: {
|
|
@@ -96,11 +154,13 @@ export class InngestRun<
|
|
|
96
154
|
runId: this.runId,
|
|
97
155
|
snapshot: {
|
|
98
156
|
runId: this.runId,
|
|
157
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
99
158
|
value: {},
|
|
100
159
|
context: {} as any,
|
|
101
160
|
activePaths: [],
|
|
102
161
|
suspendedPaths: {},
|
|
103
162
|
timestamp: Date.now(),
|
|
163
|
+
status: 'running',
|
|
104
164
|
},
|
|
105
165
|
});
|
|
106
166
|
|
|
@@ -122,7 +182,9 @@ export class InngestRun<
|
|
|
122
182
|
result.error = new Error(result.error);
|
|
123
183
|
}
|
|
124
184
|
|
|
125
|
-
|
|
185
|
+
if (result.status !== 'suspended') {
|
|
186
|
+
this.cleanup?.();
|
|
187
|
+
}
|
|
126
188
|
return result;
|
|
127
189
|
}
|
|
128
190
|
|
|
@@ -134,6 +196,27 @@ export class InngestRun<
|
|
|
134
196
|
| string
|
|
135
197
|
| string[];
|
|
136
198
|
runtimeContext?: RuntimeContext;
|
|
199
|
+
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
200
|
+
const p = this._resume(params).then(result => {
|
|
201
|
+
if (result.status !== 'suspended') {
|
|
202
|
+
this.closeStreamAction?.().catch(() => {});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
this.executionResults = p;
|
|
209
|
+
return p;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
async _resume<TResumeSchema extends z.ZodType<any>>(params: {
|
|
213
|
+
resumeData?: z.infer<TResumeSchema>;
|
|
214
|
+
step:
|
|
215
|
+
| Step<string, any, any, TResumeSchema, any>
|
|
216
|
+
| [...Step<string, any, any, any, any>[], Step<string, any, any, TResumeSchema, any>]
|
|
217
|
+
| string
|
|
218
|
+
| string[];
|
|
219
|
+
runtimeContext?: RuntimeContext;
|
|
137
220
|
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
138
221
|
const steps: string[] = (Array.isArray(params.step) ? params.step : [params.step]).map(step =>
|
|
139
222
|
typeof step === 'string' ? step : step?.id,
|
|
@@ -171,43 +254,88 @@ export class InngestRun<
|
|
|
171
254
|
return result;
|
|
172
255
|
}
|
|
173
256
|
|
|
174
|
-
watch(cb: (event:
|
|
257
|
+
watch(cb: (event: WatchEvent) => void, type: 'watch' | 'watch-v2' = 'watch'): () => void {
|
|
258
|
+
let active = true;
|
|
175
259
|
const streamPromise = subscribe(
|
|
176
260
|
{
|
|
177
261
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
178
|
-
topics: [
|
|
262
|
+
topics: [type],
|
|
179
263
|
app: this.inngest,
|
|
180
264
|
},
|
|
181
265
|
(message: any) => {
|
|
182
|
-
|
|
266
|
+
if (active) {
|
|
267
|
+
cb(message.data);
|
|
268
|
+
}
|
|
183
269
|
},
|
|
184
270
|
);
|
|
185
271
|
|
|
186
272
|
return () => {
|
|
273
|
+
active = false;
|
|
187
274
|
streamPromise
|
|
188
|
-
.then((stream:
|
|
189
|
-
stream.cancel();
|
|
275
|
+
.then(async (stream: Awaited<typeof streamPromise>) => {
|
|
276
|
+
return stream.cancel();
|
|
190
277
|
})
|
|
191
278
|
.catch(err => {
|
|
192
279
|
console.error(err);
|
|
193
280
|
});
|
|
194
281
|
};
|
|
195
282
|
}
|
|
283
|
+
|
|
284
|
+
stream({ inputData, runtimeContext }: { inputData?: z.infer<TInput>; runtimeContext?: RuntimeContext } = {}): {
|
|
285
|
+
stream: ReadableStream<StreamEvent>;
|
|
286
|
+
getWorkflowState: () => Promise<WorkflowResult<TOutput, TSteps>>;
|
|
287
|
+
} {
|
|
288
|
+
const { readable, writable } = new TransformStream<StreamEvent, StreamEvent>();
|
|
289
|
+
|
|
290
|
+
const writer = writable.getWriter();
|
|
291
|
+
const unwatch = this.watch(async event => {
|
|
292
|
+
try {
|
|
293
|
+
// watch-v2 events are data stream events, so we need to cast them to the correct type
|
|
294
|
+
await writer.write(event as any);
|
|
295
|
+
} catch {}
|
|
296
|
+
}, 'watch-v2');
|
|
297
|
+
|
|
298
|
+
this.closeStreamAction = async () => {
|
|
299
|
+
unwatch();
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
await writer.close();
|
|
303
|
+
} catch (err) {
|
|
304
|
+
console.error('Error closing stream:', err);
|
|
305
|
+
} finally {
|
|
306
|
+
writer.releaseLock();
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then(result => {
|
|
311
|
+
if (result.status !== 'suspended') {
|
|
312
|
+
this.closeStreamAction?.().catch(() => {});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return result;
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
return {
|
|
319
|
+
stream: readable as ReadableStream<StreamEvent>,
|
|
320
|
+
getWorkflowState: () => this.executionResults!,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
196
323
|
}
|
|
197
324
|
|
|
198
325
|
export class InngestWorkflow<
|
|
199
|
-
|
|
326
|
+
TEngineType = InngestEngineType,
|
|
327
|
+
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
200
328
|
TWorkflowId extends string = string,
|
|
201
329
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
202
330
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
203
331
|
TPrevSchema extends z.ZodType<any> = TInput,
|
|
204
|
-
> extends
|
|
332
|
+
> extends Workflow<TEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
205
333
|
#mastra: Mastra;
|
|
206
334
|
public inngest: Inngest;
|
|
207
335
|
|
|
208
336
|
private function: ReturnType<Inngest['createFunction']> | undefined;
|
|
209
337
|
|
|
210
|
-
constructor(params:
|
|
338
|
+
constructor(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
|
|
211
339
|
super(params);
|
|
212
340
|
this.#mastra = params.mastra!;
|
|
213
341
|
this.inngest = inngest;
|
|
@@ -226,16 +354,19 @@ export class InngestWorkflow<
|
|
|
226
354
|
return { runs: [], total: 0 };
|
|
227
355
|
}
|
|
228
356
|
|
|
229
|
-
return storage.getWorkflowRuns({ workflowName: this.id, ...(args ?? {}) });
|
|
357
|
+
return storage.getWorkflowRuns({ workflowName: this.id, ...(args ?? {}) }) as unknown as WorkflowRuns;
|
|
230
358
|
}
|
|
231
359
|
|
|
232
360
|
async getWorkflowRunById(runId: string): Promise<WorkflowRun | null> {
|
|
233
361
|
const storage = this.#mastra?.getStorage();
|
|
234
362
|
if (!storage) {
|
|
235
363
|
this.logger.debug('Cannot get workflow runs. Mastra engine is not initialized');
|
|
236
|
-
|
|
364
|
+
//returning in memory run if no storage is initialized
|
|
365
|
+
return this.runs.get(runId)
|
|
366
|
+
? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as WorkflowRun)
|
|
367
|
+
: null;
|
|
237
368
|
}
|
|
238
|
-
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
369
|
+
const run = (await storage.getWorkflowRunById({ runId, workflowName: this.id })) as unknown as WorkflowRun;
|
|
239
370
|
|
|
240
371
|
return (
|
|
241
372
|
run ??
|
|
@@ -243,6 +374,32 @@ export class InngestWorkflow<
|
|
|
243
374
|
);
|
|
244
375
|
}
|
|
245
376
|
|
|
377
|
+
async getWorkflowRunExecutionResult(runId: string): Promise<WatchEvent['payload']['workflowState'] | null> {
|
|
378
|
+
const storage = this.#mastra?.getStorage();
|
|
379
|
+
if (!storage) {
|
|
380
|
+
this.logger.debug('Cannot get workflow run execution result. Mastra storage is not initialized');
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
385
|
+
|
|
386
|
+
if (!run?.snapshot) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (typeof run.snapshot === 'string') {
|
|
391
|
+
return null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return {
|
|
395
|
+
status: run.snapshot.status,
|
|
396
|
+
result: run.snapshot.result,
|
|
397
|
+
error: run.snapshot.error,
|
|
398
|
+
payload: run.snapshot.context?.input,
|
|
399
|
+
steps: run.snapshot.context as any,
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
|
|
246
403
|
__registerMastra(mastra: Mastra) {
|
|
247
404
|
this.#mastra = mastra;
|
|
248
405
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -266,11 +423,35 @@ export class InngestWorkflow<
|
|
|
266
423
|
}
|
|
267
424
|
}
|
|
268
425
|
|
|
269
|
-
createRun(options?: { runId?: string }): Run<TSteps, TInput, TOutput> {
|
|
426
|
+
createRun(options?: { runId?: string }): Run<TEngineType, TSteps, TInput, TOutput> {
|
|
427
|
+
const runIdToUse = options?.runId || randomUUID();
|
|
428
|
+
|
|
429
|
+
// Return a new Run instance with object parameters
|
|
430
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
431
|
+
this.runs.get(runIdToUse) ??
|
|
432
|
+
new InngestRun(
|
|
433
|
+
{
|
|
434
|
+
workflowId: this.id,
|
|
435
|
+
runId: runIdToUse,
|
|
436
|
+
executionEngine: this.executionEngine,
|
|
437
|
+
executionGraph: this.executionGraph,
|
|
438
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
439
|
+
mastra: this.#mastra,
|
|
440
|
+
retryConfig: this.retryConfig,
|
|
441
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
442
|
+
},
|
|
443
|
+
this.inngest,
|
|
444
|
+
);
|
|
445
|
+
|
|
446
|
+
this.runs.set(runIdToUse, run);
|
|
447
|
+
return run;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async createRunAsync(options?: { runId?: string }): Promise<Run<TEngineType, TSteps, TInput, TOutput>> {
|
|
270
451
|
const runIdToUse = options?.runId || randomUUID();
|
|
271
452
|
|
|
272
453
|
// Return a new Run instance with object parameters
|
|
273
|
-
const run: Run<TSteps, TInput, TOutput> =
|
|
454
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
274
455
|
this.runs.get(runIdToUse) ??
|
|
275
456
|
new InngestRun(
|
|
276
457
|
{
|
|
@@ -278,6 +459,7 @@ export class InngestWorkflow<
|
|
|
278
459
|
runId: runIdToUse,
|
|
279
460
|
executionEngine: this.executionEngine,
|
|
280
461
|
executionGraph: this.executionGraph,
|
|
462
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
281
463
|
mastra: this.#mastra,
|
|
282
464
|
retryConfig: this.retryConfig,
|
|
283
465
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
@@ -286,6 +468,29 @@ export class InngestWorkflow<
|
|
|
286
468
|
);
|
|
287
469
|
|
|
288
470
|
this.runs.set(runIdToUse, run);
|
|
471
|
+
|
|
472
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
|
|
473
|
+
|
|
474
|
+
if (!workflowSnapshotInStorage) {
|
|
475
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
476
|
+
workflowName: this.id,
|
|
477
|
+
runId: runIdToUse,
|
|
478
|
+
snapshot: {
|
|
479
|
+
runId: runIdToUse,
|
|
480
|
+
status: 'pending',
|
|
481
|
+
value: {},
|
|
482
|
+
context: {},
|
|
483
|
+
activePaths: [],
|
|
484
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
485
|
+
suspendedPaths: {},
|
|
486
|
+
result: undefined,
|
|
487
|
+
error: undefined,
|
|
488
|
+
// @ts-ignore
|
|
489
|
+
timestamp: Date.now(),
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
289
494
|
return run;
|
|
290
495
|
}
|
|
291
496
|
|
|
@@ -294,8 +499,12 @@ export class InngestWorkflow<
|
|
|
294
499
|
return this.function;
|
|
295
500
|
}
|
|
296
501
|
this.function = this.inngest.createFunction(
|
|
297
|
-
|
|
298
|
-
|
|
502
|
+
{
|
|
503
|
+
id: `workflow.${this.id}`,
|
|
504
|
+
// @ts-ignore
|
|
505
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
506
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
507
|
+
},
|
|
299
508
|
{ event: `workflow.${this.id}` },
|
|
300
509
|
async ({ event, step, attempt, publish }) => {
|
|
301
510
|
let { inputData, runId, resume } = event.data;
|
|
@@ -315,13 +524,22 @@ export class InngestWorkflow<
|
|
|
315
524
|
try {
|
|
316
525
|
await publish({
|
|
317
526
|
channel: `workflow:${this.id}:${runId}`,
|
|
318
|
-
topic:
|
|
527
|
+
topic: event,
|
|
319
528
|
data,
|
|
320
529
|
});
|
|
321
530
|
} catch (err: any) {
|
|
322
531
|
this.logger.error('Error emitting event: ' + (err?.stack ?? err?.message ?? err));
|
|
323
532
|
}
|
|
324
533
|
},
|
|
534
|
+
on: (_event: string, _callback: (data: any) => void) => {
|
|
535
|
+
// no-op
|
|
536
|
+
},
|
|
537
|
+
off: (_event: string, _callback: (data: any) => void) => {
|
|
538
|
+
// no-op
|
|
539
|
+
},
|
|
540
|
+
once: (_event: string, _callback: (data: any) => void) => {
|
|
541
|
+
// no-op
|
|
542
|
+
},
|
|
325
543
|
};
|
|
326
544
|
|
|
327
545
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -329,11 +547,13 @@ export class InngestWorkflow<
|
|
|
329
547
|
workflowId: this.id,
|
|
330
548
|
runId,
|
|
331
549
|
graph: this.executionGraph,
|
|
550
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
332
551
|
input: inputData,
|
|
333
552
|
emitter,
|
|
334
553
|
retryConfig: this.retryConfig,
|
|
335
554
|
runtimeContext: new RuntimeContext(), // TODO
|
|
336
555
|
resume,
|
|
556
|
+
abortController: new AbortController(),
|
|
337
557
|
});
|
|
338
558
|
|
|
339
559
|
return { result, runId };
|
|
@@ -362,29 +582,197 @@ export class InngestWorkflow<
|
|
|
362
582
|
}
|
|
363
583
|
}
|
|
364
584
|
|
|
365
|
-
function
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
585
|
+
function isAgent(params: any): params is Agent<any, any, any> {
|
|
586
|
+
return params?.component === 'AGENT';
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function isTool(params: any): params is Tool<any, any, any> {
|
|
590
|
+
return params instanceof Tool;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
export function createStep<
|
|
594
|
+
TStepId extends string,
|
|
595
|
+
TStepInput extends z.ZodType<any>,
|
|
596
|
+
TStepOutput extends z.ZodType<any>,
|
|
597
|
+
TResumeSchema extends z.ZodType<any>,
|
|
598
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
599
|
+
>(params: {
|
|
600
|
+
id: TStepId;
|
|
601
|
+
description?: string;
|
|
602
|
+
inputSchema: TStepInput;
|
|
603
|
+
outputSchema: TStepOutput;
|
|
604
|
+
resumeSchema?: TResumeSchema;
|
|
605
|
+
suspendSchema?: TSuspendSchema;
|
|
606
|
+
execute: ExecuteFunction<
|
|
607
|
+
z.infer<TStepInput>,
|
|
608
|
+
z.infer<TStepOutput>,
|
|
609
|
+
z.infer<TResumeSchema>,
|
|
610
|
+
z.infer<TSuspendSchema>,
|
|
611
|
+
InngestEngineType
|
|
612
|
+
>;
|
|
613
|
+
}): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
614
|
+
|
|
615
|
+
export function createStep<
|
|
616
|
+
TStepId extends string,
|
|
617
|
+
TStepInput extends z.ZodObject<{ prompt: z.ZodString }>,
|
|
618
|
+
TStepOutput extends z.ZodObject<{ text: z.ZodString }>,
|
|
619
|
+
TResumeSchema extends z.ZodType<any>,
|
|
620
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
370
621
|
>(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
622
|
+
agent: Agent<TStepId, any, any>,
|
|
623
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
624
|
+
|
|
625
|
+
export function createStep<
|
|
626
|
+
TSchemaIn extends z.ZodType<any>,
|
|
627
|
+
TSchemaOut extends z.ZodType<any>,
|
|
628
|
+
TContext extends ToolExecutionContext<TSchemaIn>,
|
|
629
|
+
>(
|
|
630
|
+
tool: Tool<TSchemaIn, TSchemaOut, TContext> & {
|
|
631
|
+
inputSchema: TSchemaIn;
|
|
632
|
+
outputSchema: TSchemaOut;
|
|
633
|
+
execute: (context: TContext) => Promise<any>;
|
|
634
|
+
},
|
|
635
|
+
): Step<string, TSchemaIn, TSchemaOut, z.ZodType<any>, z.ZodType<any>, InngestEngineType>;
|
|
636
|
+
export function createStep<
|
|
637
|
+
TStepId extends string,
|
|
638
|
+
TStepInput extends z.ZodType<any>,
|
|
639
|
+
TStepOutput extends z.ZodType<any>,
|
|
640
|
+
TResumeSchema extends z.ZodType<any>,
|
|
641
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
642
|
+
>(
|
|
643
|
+
params:
|
|
644
|
+
| {
|
|
645
|
+
id: TStepId;
|
|
646
|
+
description?: string;
|
|
647
|
+
inputSchema: TStepInput;
|
|
648
|
+
outputSchema: TStepOutput;
|
|
649
|
+
resumeSchema?: TResumeSchema;
|
|
650
|
+
suspendSchema?: TSuspendSchema;
|
|
651
|
+
execute: ExecuteFunction<
|
|
652
|
+
z.infer<TStepInput>,
|
|
653
|
+
z.infer<TStepOutput>,
|
|
654
|
+
z.infer<TResumeSchema>,
|
|
655
|
+
z.infer<TSuspendSchema>,
|
|
656
|
+
InngestEngineType
|
|
657
|
+
>;
|
|
658
|
+
}
|
|
659
|
+
| Agent<any, any, any>
|
|
660
|
+
| (Tool<TStepInput, TStepOutput, any> & {
|
|
661
|
+
inputSchema: TStepInput;
|
|
662
|
+
outputSchema: TStepOutput;
|
|
663
|
+
execute: (context: ToolExecutionContext<TStepInput>) => Promise<any>;
|
|
664
|
+
}),
|
|
665
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType> {
|
|
666
|
+
if (isAgent(params)) {
|
|
667
|
+
return {
|
|
668
|
+
id: params.name,
|
|
669
|
+
// @ts-ignore
|
|
670
|
+
inputSchema: z.object({
|
|
671
|
+
prompt: z.string(),
|
|
672
|
+
// resourceId: z.string().optional(),
|
|
673
|
+
// threadId: z.string().optional(),
|
|
674
|
+
}),
|
|
675
|
+
// @ts-ignore
|
|
676
|
+
outputSchema: z.object({
|
|
677
|
+
text: z.string(),
|
|
678
|
+
}),
|
|
679
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
680
|
+
let streamPromise = {} as {
|
|
681
|
+
promise: Promise<string>;
|
|
682
|
+
resolve: (value: string) => void;
|
|
683
|
+
reject: (reason?: any) => void;
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
687
|
+
streamPromise.resolve = resolve;
|
|
688
|
+
streamPromise.reject = reject;
|
|
689
|
+
});
|
|
690
|
+
const toolData = {
|
|
691
|
+
name: params.name,
|
|
692
|
+
args: inputData,
|
|
693
|
+
};
|
|
694
|
+
await emitter.emit('watch-v2', {
|
|
695
|
+
type: 'tool-call-streaming-start',
|
|
696
|
+
...toolData,
|
|
697
|
+
});
|
|
698
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
699
|
+
// resourceId: inputData.resourceId,
|
|
700
|
+
// threadId: inputData.threadId,
|
|
701
|
+
runtimeContext,
|
|
702
|
+
onFinish: result => {
|
|
703
|
+
streamPromise.resolve(result.text);
|
|
704
|
+
},
|
|
705
|
+
abortSignal,
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
if (abortSignal.aborted) {
|
|
709
|
+
return abort();
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
for await (const chunk of fullStream) {
|
|
713
|
+
switch (chunk.type) {
|
|
714
|
+
case 'text-delta':
|
|
715
|
+
await emitter.emit('watch-v2', {
|
|
716
|
+
type: 'tool-call-delta',
|
|
717
|
+
...toolData,
|
|
718
|
+
argsTextDelta: chunk.textDelta,
|
|
719
|
+
});
|
|
720
|
+
break;
|
|
721
|
+
|
|
722
|
+
case 'step-start':
|
|
723
|
+
case 'step-finish':
|
|
724
|
+
case 'finish':
|
|
725
|
+
break;
|
|
726
|
+
|
|
727
|
+
case 'tool-call':
|
|
728
|
+
case 'tool-result':
|
|
729
|
+
case 'tool-call-streaming-start':
|
|
730
|
+
case 'tool-call-delta':
|
|
731
|
+
case 'source':
|
|
732
|
+
case 'file':
|
|
733
|
+
default:
|
|
734
|
+
await emitter.emit('watch-v2', chunk);
|
|
735
|
+
break;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
384
738
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
739
|
+
return {
|
|
740
|
+
text: await streamPromise.promise,
|
|
741
|
+
};
|
|
742
|
+
},
|
|
743
|
+
};
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
if (isTool(params)) {
|
|
747
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
748
|
+
throw new Error('Tool must have input and output schemas defined');
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return {
|
|
752
|
+
// TODO: tool probably should have strong id type
|
|
753
|
+
// @ts-ignore
|
|
754
|
+
id: params.id,
|
|
755
|
+
inputSchema: params.inputSchema,
|
|
756
|
+
outputSchema: params.outputSchema,
|
|
757
|
+
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
758
|
+
return params.execute({
|
|
759
|
+
context: inputData,
|
|
760
|
+
mastra,
|
|
761
|
+
runtimeContext,
|
|
762
|
+
});
|
|
763
|
+
},
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
return {
|
|
768
|
+
id: params.id,
|
|
769
|
+
description: params.description,
|
|
770
|
+
inputSchema: params.inputSchema,
|
|
771
|
+
outputSchema: params.outputSchema,
|
|
772
|
+
resumeSchema: params.resumeSchema,
|
|
773
|
+
suspendSchema: params.suspendSchema,
|
|
774
|
+
execute: params.execute,
|
|
775
|
+
};
|
|
388
776
|
}
|
|
389
777
|
|
|
390
778
|
export function init(inngest: Inngest) {
|
|
@@ -393,13 +781,59 @@ export function init(inngest: Inngest) {
|
|
|
393
781
|
TWorkflowId extends string = string,
|
|
394
782
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
395
783
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
396
|
-
TSteps extends Step<string, any, any
|
|
397
|
-
|
|
398
|
-
|
|
784
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
785
|
+
string,
|
|
786
|
+
any,
|
|
787
|
+
any,
|
|
788
|
+
any,
|
|
789
|
+
any,
|
|
790
|
+
InngestEngineType
|
|
791
|
+
>[],
|
|
792
|
+
>(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
|
|
793
|
+
return new InngestWorkflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TInput>(params, inngest);
|
|
399
794
|
},
|
|
400
795
|
createStep,
|
|
401
|
-
cloneStep
|
|
402
|
-
|
|
796
|
+
cloneStep<TStepId extends string>(
|
|
797
|
+
step: Step<string, any, any, any, any, InngestEngineType>,
|
|
798
|
+
opts: { id: TStepId },
|
|
799
|
+
): Step<TStepId, any, any, any, any, InngestEngineType> {
|
|
800
|
+
return {
|
|
801
|
+
id: opts.id,
|
|
802
|
+
description: step.description,
|
|
803
|
+
inputSchema: step.inputSchema,
|
|
804
|
+
outputSchema: step.outputSchema,
|
|
805
|
+
execute: step.execute,
|
|
806
|
+
};
|
|
807
|
+
},
|
|
808
|
+
cloneWorkflow<
|
|
809
|
+
TWorkflowId extends string = string,
|
|
810
|
+
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
811
|
+
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
812
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
813
|
+
string,
|
|
814
|
+
any,
|
|
815
|
+
any,
|
|
816
|
+
any,
|
|
817
|
+
any,
|
|
818
|
+
InngestEngineType
|
|
819
|
+
>[],
|
|
820
|
+
TPrevSchema extends z.ZodType<any> = TInput,
|
|
821
|
+
>(
|
|
822
|
+
workflow: Workflow<InngestEngineType, TSteps, string, TInput, TOutput, TPrevSchema>,
|
|
823
|
+
opts: { id: TWorkflowId },
|
|
824
|
+
): Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
825
|
+
const wf: Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> = new Workflow({
|
|
826
|
+
id: opts.id,
|
|
827
|
+
inputSchema: workflow.inputSchema,
|
|
828
|
+
outputSchema: workflow.outputSchema,
|
|
829
|
+
steps: workflow.stepDefs,
|
|
830
|
+
mastra: workflow.mastra,
|
|
831
|
+
});
|
|
832
|
+
|
|
833
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
834
|
+
wf.commit();
|
|
835
|
+
return wf;
|
|
836
|
+
},
|
|
403
837
|
};
|
|
404
838
|
}
|
|
405
839
|
|
|
@@ -413,11 +847,47 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
413
847
|
this.inngestAttempts = inngestAttempts;
|
|
414
848
|
}
|
|
415
849
|
|
|
850
|
+
async execute<TInput, TOutput>(params: {
|
|
851
|
+
workflowId: string;
|
|
852
|
+
runId: string;
|
|
853
|
+
graph: ExecutionGraph;
|
|
854
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
855
|
+
input?: TInput;
|
|
856
|
+
resume?: {
|
|
857
|
+
// TODO: add execute path
|
|
858
|
+
steps: string[];
|
|
859
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
860
|
+
resumePayload: any;
|
|
861
|
+
resumePath: number[];
|
|
862
|
+
};
|
|
863
|
+
emitter: Emitter;
|
|
864
|
+
retryConfig?: {
|
|
865
|
+
attempts?: number;
|
|
866
|
+
delay?: number;
|
|
867
|
+
};
|
|
868
|
+
runtimeContext: RuntimeContext;
|
|
869
|
+
abortController: AbortController;
|
|
870
|
+
}): Promise<TOutput> {
|
|
871
|
+
await params.emitter.emit('watch-v2', {
|
|
872
|
+
type: 'start',
|
|
873
|
+
payload: { runId: params.runId },
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
const result = await super.execute<TInput, TOutput>(params);
|
|
877
|
+
|
|
878
|
+
await params.emitter.emit('watch-v2', {
|
|
879
|
+
type: 'finish',
|
|
880
|
+
payload: { runId: params.runId },
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
return result;
|
|
884
|
+
}
|
|
885
|
+
|
|
416
886
|
protected async fmtReturnValue<TOutput>(
|
|
417
887
|
executionSpan: Span | undefined,
|
|
418
|
-
emitter:
|
|
419
|
-
stepResults: Record<string, StepResult<any>>,
|
|
420
|
-
lastOutput: StepResult<any>,
|
|
888
|
+
emitter: Emitter,
|
|
889
|
+
stepResults: Record<string, StepResult<any, any, any, any>>,
|
|
890
|
+
lastOutput: StepResult<any, any, any, any>,
|
|
421
891
|
error?: Error | string,
|
|
422
892
|
): Promise<TOutput> {
|
|
423
893
|
const base: any = {
|
|
@@ -496,21 +966,23 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
496
966
|
resume,
|
|
497
967
|
prevOutput,
|
|
498
968
|
emitter,
|
|
969
|
+
abortController,
|
|
499
970
|
runtimeContext,
|
|
500
971
|
}: {
|
|
501
972
|
workflowId: string;
|
|
502
973
|
runId: string;
|
|
503
974
|
step: Step<string, any, any>;
|
|
504
|
-
stepResults: Record<string, StepResult<any>>;
|
|
975
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
505
976
|
executionContext: ExecutionContext;
|
|
506
977
|
resume?: {
|
|
507
978
|
steps: string[];
|
|
508
979
|
resumePayload: any;
|
|
509
980
|
};
|
|
510
981
|
prevOutput: any;
|
|
511
|
-
emitter:
|
|
982
|
+
emitter: Emitter;
|
|
983
|
+
abortController: AbortController;
|
|
512
984
|
runtimeContext: RuntimeContext;
|
|
513
|
-
}): Promise<StepResult<any>> {
|
|
985
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
514
986
|
return super.executeStep({
|
|
515
987
|
workflowId,
|
|
516
988
|
runId,
|
|
@@ -520,10 +992,178 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
520
992
|
resume,
|
|
521
993
|
prevOutput,
|
|
522
994
|
emitter,
|
|
995
|
+
abortController,
|
|
523
996
|
runtimeContext,
|
|
524
997
|
});
|
|
525
998
|
}
|
|
526
999
|
|
|
1000
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
1001
|
+
// await this.inngestStep.sleep(id, duration);
|
|
1002
|
+
// }
|
|
1003
|
+
|
|
1004
|
+
async executeSleep({
|
|
1005
|
+
workflowId,
|
|
1006
|
+
runId,
|
|
1007
|
+
entry,
|
|
1008
|
+
prevOutput,
|
|
1009
|
+
stepResults,
|
|
1010
|
+
emitter,
|
|
1011
|
+
abortController,
|
|
1012
|
+
runtimeContext,
|
|
1013
|
+
}: {
|
|
1014
|
+
workflowId: string;
|
|
1015
|
+
runId: string;
|
|
1016
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
1017
|
+
entry: {
|
|
1018
|
+
type: 'sleep';
|
|
1019
|
+
id: string;
|
|
1020
|
+
duration?: number;
|
|
1021
|
+
fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
|
|
1022
|
+
};
|
|
1023
|
+
prevStep: StepFlowEntry;
|
|
1024
|
+
prevOutput: any;
|
|
1025
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1026
|
+
resume?: {
|
|
1027
|
+
steps: string[];
|
|
1028
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1029
|
+
resumePayload: any;
|
|
1030
|
+
resumePath: number[];
|
|
1031
|
+
};
|
|
1032
|
+
executionContext: ExecutionContext;
|
|
1033
|
+
emitter: Emitter;
|
|
1034
|
+
abortController: AbortController;
|
|
1035
|
+
runtimeContext: RuntimeContext;
|
|
1036
|
+
}): Promise<void> {
|
|
1037
|
+
let { duration, fn } = entry;
|
|
1038
|
+
|
|
1039
|
+
if (fn) {
|
|
1040
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
1041
|
+
return await fn({
|
|
1042
|
+
runId,
|
|
1043
|
+
mastra: this.mastra!,
|
|
1044
|
+
runtimeContext,
|
|
1045
|
+
inputData: prevOutput,
|
|
1046
|
+
runCount: -1,
|
|
1047
|
+
getInitData: () => stepResults?.input as any,
|
|
1048
|
+
getStepResult: (step: any) => {
|
|
1049
|
+
if (!step?.id) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const result = stepResults[step.id];
|
|
1054
|
+
if (result?.status === 'success') {
|
|
1055
|
+
return result.output;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
return null;
|
|
1059
|
+
},
|
|
1060
|
+
|
|
1061
|
+
// TODO: this function shouldn't have suspend probably?
|
|
1062
|
+
suspend: async (_suspendPayload: any): Promise<any> => {},
|
|
1063
|
+
bail: () => {},
|
|
1064
|
+
abort: () => {
|
|
1065
|
+
abortController?.abort();
|
|
1066
|
+
},
|
|
1067
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1068
|
+
engine: { step: this.inngestStep },
|
|
1069
|
+
abortSignal: abortController?.signal,
|
|
1070
|
+
});
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
async executeSleepUntil({
|
|
1078
|
+
workflowId,
|
|
1079
|
+
runId,
|
|
1080
|
+
entry,
|
|
1081
|
+
prevOutput,
|
|
1082
|
+
stepResults,
|
|
1083
|
+
emitter,
|
|
1084
|
+
abortController,
|
|
1085
|
+
runtimeContext,
|
|
1086
|
+
}: {
|
|
1087
|
+
workflowId: string;
|
|
1088
|
+
runId: string;
|
|
1089
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
1090
|
+
entry: {
|
|
1091
|
+
type: 'sleepUntil';
|
|
1092
|
+
id: string;
|
|
1093
|
+
date?: Date;
|
|
1094
|
+
fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
|
|
1095
|
+
};
|
|
1096
|
+
prevStep: StepFlowEntry;
|
|
1097
|
+
prevOutput: any;
|
|
1098
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1099
|
+
resume?: {
|
|
1100
|
+
steps: string[];
|
|
1101
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1102
|
+
resumePayload: any;
|
|
1103
|
+
resumePath: number[];
|
|
1104
|
+
};
|
|
1105
|
+
executionContext: ExecutionContext;
|
|
1106
|
+
emitter: Emitter;
|
|
1107
|
+
abortController: AbortController;
|
|
1108
|
+
runtimeContext: RuntimeContext;
|
|
1109
|
+
}): Promise<void> {
|
|
1110
|
+
let { date, fn } = entry;
|
|
1111
|
+
|
|
1112
|
+
if (fn) {
|
|
1113
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
1114
|
+
return await fn({
|
|
1115
|
+
runId,
|
|
1116
|
+
mastra: this.mastra!,
|
|
1117
|
+
runtimeContext,
|
|
1118
|
+
inputData: prevOutput,
|
|
1119
|
+
runCount: -1,
|
|
1120
|
+
getInitData: () => stepResults?.input as any,
|
|
1121
|
+
getStepResult: (step: any) => {
|
|
1122
|
+
if (!step?.id) {
|
|
1123
|
+
return null;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
const result = stepResults[step.id];
|
|
1127
|
+
if (result?.status === 'success') {
|
|
1128
|
+
return result.output;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
return null;
|
|
1132
|
+
},
|
|
1133
|
+
|
|
1134
|
+
// TODO: this function shouldn't have suspend probably?
|
|
1135
|
+
suspend: async (_suspendPayload: any): Promise<any> => {},
|
|
1136
|
+
bail: () => {},
|
|
1137
|
+
abort: () => {
|
|
1138
|
+
abortController?.abort();
|
|
1139
|
+
},
|
|
1140
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1141
|
+
engine: { step: this.inngestStep },
|
|
1142
|
+
abortSignal: abortController?.signal,
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
if (!(date instanceof Date)) {
|
|
1148
|
+
return;
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
|
|
1155
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
1156
|
+
event: `user-event-${event}`,
|
|
1157
|
+
timeout: timeout ?? 5e3,
|
|
1158
|
+
});
|
|
1159
|
+
|
|
1160
|
+
if (eventData === null) {
|
|
1161
|
+
throw 'Timeout waiting for event';
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
return eventData?.data;
|
|
1165
|
+
}
|
|
1166
|
+
|
|
527
1167
|
async executeStep({
|
|
528
1168
|
step,
|
|
529
1169
|
stepResults,
|
|
@@ -531,29 +1171,26 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
531
1171
|
resume,
|
|
532
1172
|
prevOutput,
|
|
533
1173
|
emitter,
|
|
1174
|
+
abortController,
|
|
534
1175
|
runtimeContext,
|
|
535
1176
|
}: {
|
|
536
1177
|
step: Step<string, any, any>;
|
|
537
|
-
stepResults: Record<string, StepResult<any>>;
|
|
538
|
-
executionContext:
|
|
539
|
-
workflowId: string;
|
|
540
|
-
runId: string;
|
|
541
|
-
executionPath: number[];
|
|
542
|
-
suspendedPaths: Record<string, number[]>;
|
|
543
|
-
retryConfig: { attempts: number; delay: number };
|
|
544
|
-
};
|
|
1178
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1179
|
+
executionContext: ExecutionContext;
|
|
545
1180
|
resume?: {
|
|
546
1181
|
steps: string[];
|
|
547
1182
|
resumePayload: any;
|
|
548
1183
|
runId?: string;
|
|
549
1184
|
};
|
|
550
1185
|
prevOutput: any;
|
|
551
|
-
emitter:
|
|
1186
|
+
emitter: Emitter;
|
|
1187
|
+
abortController: AbortController;
|
|
552
1188
|
runtimeContext: RuntimeContext;
|
|
553
|
-
}): Promise<StepResult<any>> {
|
|
554
|
-
await this.inngestStep.run(
|
|
1189
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
1190
|
+
const startedAt = await this.inngestStep.run(
|
|
555
1191
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
556
1192
|
async () => {
|
|
1193
|
+
const startedAt = Date.now();
|
|
557
1194
|
await emitter.emit('watch', {
|
|
558
1195
|
type: 'watch',
|
|
559
1196
|
payload: {
|
|
@@ -575,6 +1212,18 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
575
1212
|
},
|
|
576
1213
|
eventTimestamp: Date.now(),
|
|
577
1214
|
});
|
|
1215
|
+
|
|
1216
|
+
await emitter.emit('watch-v2', {
|
|
1217
|
+
type: 'step-start',
|
|
1218
|
+
payload: {
|
|
1219
|
+
id: step.id,
|
|
1220
|
+
status: 'running',
|
|
1221
|
+
payload: prevOutput,
|
|
1222
|
+
startedAt,
|
|
1223
|
+
},
|
|
1224
|
+
});
|
|
1225
|
+
|
|
1226
|
+
return startedAt;
|
|
578
1227
|
},
|
|
579
1228
|
);
|
|
580
1229
|
|
|
@@ -641,10 +1290,20 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
641
1290
|
eventTimestamp: Date.now(),
|
|
642
1291
|
});
|
|
643
1292
|
|
|
1293
|
+
await emitter.emit('watch-v2', {
|
|
1294
|
+
type: 'step-result',
|
|
1295
|
+
payload: {
|
|
1296
|
+
id: step.id,
|
|
1297
|
+
status: 'failed',
|
|
1298
|
+
error: result?.error,
|
|
1299
|
+
payload: prevOutput,
|
|
1300
|
+
},
|
|
1301
|
+
});
|
|
1302
|
+
|
|
644
1303
|
return { executionContext, result: { status: 'failed', error: result?.error } };
|
|
645
1304
|
} else if (result.status === 'suspended') {
|
|
646
1305
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
647
|
-
const stepRes: StepResult<any> = stepResult as StepResult<any>;
|
|
1306
|
+
const stepRes: StepResult<any, any, any, any> = stepResult as StepResult<any, any, any, any>;
|
|
648
1307
|
return stepRes?.status === 'suspended';
|
|
649
1308
|
});
|
|
650
1309
|
|
|
@@ -671,6 +1330,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
671
1330
|
eventTimestamp: Date.now(),
|
|
672
1331
|
});
|
|
673
1332
|
|
|
1333
|
+
await emitter.emit('watch-v2', {
|
|
1334
|
+
type: 'step-suspended',
|
|
1335
|
+
payload: {
|
|
1336
|
+
id: step.id,
|
|
1337
|
+
status: 'suspended',
|
|
1338
|
+
},
|
|
1339
|
+
});
|
|
1340
|
+
|
|
674
1341
|
return {
|
|
675
1342
|
executionContext,
|
|
676
1343
|
result: {
|
|
@@ -727,19 +1394,39 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
727
1394
|
eventTimestamp: Date.now(),
|
|
728
1395
|
});
|
|
729
1396
|
|
|
1397
|
+
await emitter.emit('watch-v2', {
|
|
1398
|
+
type: 'step-result',
|
|
1399
|
+
payload: {
|
|
1400
|
+
id: step.id,
|
|
1401
|
+
status: 'success',
|
|
1402
|
+
output: result?.result,
|
|
1403
|
+
},
|
|
1404
|
+
});
|
|
1405
|
+
|
|
1406
|
+
await emitter.emit('watch-v2', {
|
|
1407
|
+
type: 'step-finish',
|
|
1408
|
+
payload: {
|
|
1409
|
+
id: step.id,
|
|
1410
|
+
metadata: {},
|
|
1411
|
+
},
|
|
1412
|
+
});
|
|
1413
|
+
|
|
730
1414
|
return { executionContext, result: { status: 'success', output: result?.result } };
|
|
731
1415
|
},
|
|
732
1416
|
);
|
|
733
1417
|
|
|
734
1418
|
Object.assign(executionContext, res.executionContext);
|
|
735
|
-
return res.result as StepResult<any>;
|
|
1419
|
+
return res.result as StepResult<any, any, any, any>;
|
|
736
1420
|
}
|
|
737
1421
|
|
|
738
1422
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
739
1423
|
let execResults: any;
|
|
740
1424
|
let suspended: { payload: any } | undefined;
|
|
1425
|
+
let bailed: { payload: any } | undefined;
|
|
1426
|
+
|
|
741
1427
|
try {
|
|
742
1428
|
const result = await step.execute({
|
|
1429
|
+
runId: executionContext.runId,
|
|
743
1430
|
mastra: this.mastra!,
|
|
744
1431
|
runtimeContext,
|
|
745
1432
|
inputData: prevOutput,
|
|
@@ -757,22 +1444,56 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
757
1444
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
758
1445
|
suspended = { payload: suspendPayload };
|
|
759
1446
|
},
|
|
1447
|
+
bail: (result: any) => {
|
|
1448
|
+
bailed = { payload: result };
|
|
1449
|
+
},
|
|
760
1450
|
resume: {
|
|
761
1451
|
steps: resume?.steps?.slice(1) || [],
|
|
762
1452
|
resumePayload: resume?.resumePayload,
|
|
763
1453
|
// @ts-ignore
|
|
764
1454
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId,
|
|
765
1455
|
},
|
|
766
|
-
emitter,
|
|
1456
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1457
|
+
engine: {
|
|
1458
|
+
step: this.inngestStep,
|
|
1459
|
+
},
|
|
1460
|
+
abortSignal: abortController.signal,
|
|
767
1461
|
});
|
|
768
|
-
|
|
769
|
-
|
|
1462
|
+
const endedAt = Date.now();
|
|
1463
|
+
|
|
1464
|
+
execResults = {
|
|
1465
|
+
status: 'success',
|
|
1466
|
+
output: result,
|
|
1467
|
+
startedAt,
|
|
1468
|
+
endedAt,
|
|
1469
|
+
payload: prevOutput,
|
|
1470
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1471
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1472
|
+
};
|
|
770
1473
|
} catch (e) {
|
|
771
|
-
execResults = {
|
|
1474
|
+
execResults = {
|
|
1475
|
+
status: 'failed',
|
|
1476
|
+
payload: prevOutput,
|
|
1477
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1478
|
+
endedAt: Date.now(),
|
|
1479
|
+
startedAt,
|
|
1480
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1481
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1482
|
+
};
|
|
772
1483
|
}
|
|
773
1484
|
|
|
774
1485
|
if (suspended) {
|
|
775
|
-
execResults = {
|
|
1486
|
+
execResults = {
|
|
1487
|
+
status: 'suspended',
|
|
1488
|
+
suspendedPayload: suspended.payload,
|
|
1489
|
+
payload: prevOutput,
|
|
1490
|
+
suspendedAt: Date.now(),
|
|
1491
|
+
startedAt,
|
|
1492
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1493
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1494
|
+
};
|
|
1495
|
+
} else if (bailed) {
|
|
1496
|
+
execResults = { status: 'bailed', output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
776
1497
|
}
|
|
777
1498
|
|
|
778
1499
|
if (execResults.status === 'failed') {
|
|
@@ -786,12 +1507,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
786
1507
|
payload: {
|
|
787
1508
|
currentStep: {
|
|
788
1509
|
id: step.id,
|
|
789
|
-
|
|
790
|
-
output: execResults.output,
|
|
1510
|
+
...execResults,
|
|
791
1511
|
},
|
|
792
1512
|
workflowState: {
|
|
793
1513
|
status: 'running',
|
|
794
|
-
steps: stepResults,
|
|
1514
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
795
1515
|
result: null,
|
|
796
1516
|
error: null,
|
|
797
1517
|
},
|
|
@@ -799,6 +1519,32 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
799
1519
|
eventTimestamp: Date.now(),
|
|
800
1520
|
});
|
|
801
1521
|
|
|
1522
|
+
if (execResults.status === 'suspended') {
|
|
1523
|
+
await emitter.emit('watch-v2', {
|
|
1524
|
+
type: 'step-suspended',
|
|
1525
|
+
payload: {
|
|
1526
|
+
id: step.id,
|
|
1527
|
+
...execResults,
|
|
1528
|
+
},
|
|
1529
|
+
});
|
|
1530
|
+
} else {
|
|
1531
|
+
await emitter.emit('watch-v2', {
|
|
1532
|
+
type: 'step-result',
|
|
1533
|
+
payload: {
|
|
1534
|
+
id: step.id,
|
|
1535
|
+
...execResults,
|
|
1536
|
+
},
|
|
1537
|
+
});
|
|
1538
|
+
|
|
1539
|
+
await emitter.emit('watch-v2', {
|
|
1540
|
+
type: 'step-finish',
|
|
1541
|
+
payload: {
|
|
1542
|
+
id: step.id,
|
|
1543
|
+
metadata: {},
|
|
1544
|
+
},
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
|
|
802
1548
|
return { result: execResults, executionContext, stepResults };
|
|
803
1549
|
});
|
|
804
1550
|
|
|
@@ -816,11 +1562,20 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
816
1562
|
runId,
|
|
817
1563
|
stepResults,
|
|
818
1564
|
executionContext,
|
|
1565
|
+
serializedStepGraph,
|
|
1566
|
+
workflowStatus,
|
|
1567
|
+
result,
|
|
1568
|
+
error,
|
|
819
1569
|
}: {
|
|
820
1570
|
workflowId: string;
|
|
821
1571
|
runId: string;
|
|
822
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1572
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1573
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
823
1574
|
executionContext: ExecutionContext;
|
|
1575
|
+
workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
|
|
1576
|
+
result?: Record<string, any>;
|
|
1577
|
+
error?: string | Error;
|
|
1578
|
+
runtimeContext: RuntimeContext;
|
|
824
1579
|
}) {
|
|
825
1580
|
await this.inngestStep.run(
|
|
826
1581
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -834,6 +1589,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
834
1589
|
context: stepResults as any,
|
|
835
1590
|
activePaths: [],
|
|
836
1591
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1592
|
+
serializedStepGraph,
|
|
1593
|
+
status: workflowStatus,
|
|
1594
|
+
result,
|
|
1595
|
+
error,
|
|
837
1596
|
// @ts-ignore
|
|
838
1597
|
timestamp: Date.now(),
|
|
839
1598
|
},
|
|
@@ -849,27 +1608,35 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
849
1608
|
prevOutput,
|
|
850
1609
|
prevStep,
|
|
851
1610
|
stepResults,
|
|
1611
|
+
serializedStepGraph,
|
|
852
1612
|
resume,
|
|
853
1613
|
executionContext,
|
|
854
1614
|
emitter,
|
|
1615
|
+
abortController,
|
|
855
1616
|
runtimeContext,
|
|
856
1617
|
}: {
|
|
857
1618
|
workflowId: string;
|
|
858
1619
|
runId: string;
|
|
859
|
-
entry: {
|
|
1620
|
+
entry: {
|
|
1621
|
+
type: 'conditional';
|
|
1622
|
+
steps: StepFlowEntry[];
|
|
1623
|
+
conditions: ExecuteFunction<any, any, any, any, InngestEngineType>[];
|
|
1624
|
+
};
|
|
860
1625
|
prevStep: StepFlowEntry;
|
|
1626
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
861
1627
|
prevOutput: any;
|
|
862
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1628
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
863
1629
|
resume?: {
|
|
864
1630
|
steps: string[];
|
|
865
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1631
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
866
1632
|
resumePayload: any;
|
|
867
1633
|
resumePath: number[];
|
|
868
1634
|
};
|
|
869
1635
|
executionContext: ExecutionContext;
|
|
870
|
-
emitter:
|
|
1636
|
+
emitter: Emitter;
|
|
1637
|
+
abortController: AbortController;
|
|
871
1638
|
runtimeContext: RuntimeContext;
|
|
872
|
-
}): Promise<StepResult<any>> {
|
|
1639
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
873
1640
|
let execResults: any;
|
|
874
1641
|
const truthyIndexes = (
|
|
875
1642
|
await Promise.all(
|
|
@@ -877,8 +1644,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
877
1644
|
this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
878
1645
|
try {
|
|
879
1646
|
const result = await cond({
|
|
1647
|
+
runId,
|
|
880
1648
|
mastra: this.mastra!,
|
|
881
1649
|
runtimeContext,
|
|
1650
|
+
runCount: -1,
|
|
882
1651
|
inputData: prevOutput,
|
|
883
1652
|
getInitData: () => stepResults?.input as any,
|
|
884
1653
|
getStepResult: (step: any) => {
|
|
@@ -896,7 +1665,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
896
1665
|
|
|
897
1666
|
// TODO: this function shouldn't have suspend probably?
|
|
898
1667
|
suspend: async (_suspendPayload: any) => {},
|
|
899
|
-
|
|
1668
|
+
bail: () => {},
|
|
1669
|
+
abort: () => {
|
|
1670
|
+
abortController.abort();
|
|
1671
|
+
},
|
|
1672
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1673
|
+
engine: {
|
|
1674
|
+
step: this.inngestStep,
|
|
1675
|
+
},
|
|
1676
|
+
abortSignal: abortController.signal,
|
|
900
1677
|
});
|
|
901
1678
|
return result ? index : null;
|
|
902
1679
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -909,7 +1686,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
909
1686
|
).filter((index: any): index is number => index !== null);
|
|
910
1687
|
|
|
911
1688
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
912
|
-
const results: StepResult<any>[] = await Promise.all(
|
|
1689
|
+
const results: { result: StepResult<any, any, any, any> }[] = await Promise.all(
|
|
913
1690
|
stepsToRun.map((step, index) =>
|
|
914
1691
|
this.executeEntry({
|
|
915
1692
|
workflowId,
|
|
@@ -918,6 +1695,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
918
1695
|
prevStep,
|
|
919
1696
|
stepResults,
|
|
920
1697
|
resume,
|
|
1698
|
+
serializedStepGraph,
|
|
921
1699
|
executionContext: {
|
|
922
1700
|
workflowId,
|
|
923
1701
|
runId,
|
|
@@ -927,21 +1705,24 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
927
1705
|
executionSpan: executionContext.executionSpan,
|
|
928
1706
|
},
|
|
929
1707
|
emitter,
|
|
1708
|
+
abortController,
|
|
930
1709
|
runtimeContext,
|
|
931
1710
|
}),
|
|
932
1711
|
),
|
|
933
1712
|
);
|
|
934
|
-
const hasFailed = results.find(result => result.status === 'failed')
|
|
935
|
-
|
|
1713
|
+
const hasFailed = results.find(result => result.result.status === 'failed') as {
|
|
1714
|
+
result: StepFailure<any, any, any>;
|
|
1715
|
+
};
|
|
1716
|
+
const hasSuspended = results.find(result => result.result.status === 'suspended');
|
|
936
1717
|
if (hasFailed) {
|
|
937
|
-
execResults = { status: 'failed', error: hasFailed.error };
|
|
1718
|
+
execResults = { status: 'failed', error: hasFailed.result.error };
|
|
938
1719
|
} else if (hasSuspended) {
|
|
939
|
-
execResults = { status: 'suspended', payload: hasSuspended.
|
|
1720
|
+
execResults = { status: 'suspended', payload: hasSuspended.result.suspendPayload };
|
|
940
1721
|
} else {
|
|
941
1722
|
execResults = {
|
|
942
1723
|
status: 'success',
|
|
943
1724
|
output: results.reduce((acc: Record<string, any>, result, index) => {
|
|
944
|
-
if (result.status === 'success') {
|
|
1725
|
+
if (result.result.status === 'success') {
|
|
945
1726
|
// @ts-ignore
|
|
946
1727
|
acc[stepsToRun[index]!.step.id] = result.output;
|
|
947
1728
|
}
|