@mastra/inngest 0.0.0-generate-message-id-20250512171942 → 0.0.0-mcp-changeset-20250707162621
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 +468 -3
- package/dist/_tsup-dts-rollup.d.cts +178 -63
- package/dist/_tsup-dts-rollup.d.ts +178 -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 +22 -17
- package/src/index.test.ts +5602 -3512
- package/src/index.ts +883 -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,11 @@ 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> {
|
|
270
427
|
const runIdToUse = options?.runId || randomUUID();
|
|
271
428
|
|
|
272
429
|
// Return a new Run instance with object parameters
|
|
273
|
-
const run: Run<TSteps, TInput, TOutput> =
|
|
430
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
274
431
|
this.runs.get(runIdToUse) ??
|
|
275
432
|
new InngestRun(
|
|
276
433
|
{
|
|
@@ -278,6 +435,7 @@ export class InngestWorkflow<
|
|
|
278
435
|
runId: runIdToUse,
|
|
279
436
|
executionEngine: this.executionEngine,
|
|
280
437
|
executionGraph: this.executionGraph,
|
|
438
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
281
439
|
mastra: this.#mastra,
|
|
282
440
|
retryConfig: this.retryConfig,
|
|
283
441
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
@@ -289,13 +447,64 @@ export class InngestWorkflow<
|
|
|
289
447
|
return run;
|
|
290
448
|
}
|
|
291
449
|
|
|
450
|
+
async createRunAsync(options?: { runId?: string }): Promise<Run<TEngineType, TSteps, TInput, TOutput>> {
|
|
451
|
+
const runIdToUse = options?.runId || randomUUID();
|
|
452
|
+
|
|
453
|
+
// Return a new Run instance with object parameters
|
|
454
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
455
|
+
this.runs.get(runIdToUse) ??
|
|
456
|
+
new InngestRun(
|
|
457
|
+
{
|
|
458
|
+
workflowId: this.id,
|
|
459
|
+
runId: runIdToUse,
|
|
460
|
+
executionEngine: this.executionEngine,
|
|
461
|
+
executionGraph: this.executionGraph,
|
|
462
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
463
|
+
mastra: this.#mastra,
|
|
464
|
+
retryConfig: this.retryConfig,
|
|
465
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
466
|
+
},
|
|
467
|
+
this.inngest,
|
|
468
|
+
);
|
|
469
|
+
|
|
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
|
+
|
|
494
|
+
return run;
|
|
495
|
+
}
|
|
496
|
+
|
|
292
497
|
getFunction() {
|
|
293
498
|
if (this.function) {
|
|
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
|
+
};
|
|
384
685
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
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
|
+
}
|
|
738
|
+
|
|
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,19 @@ 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;
|
|
824
1578
|
}) {
|
|
825
1579
|
await this.inngestStep.run(
|
|
826
1580
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -834,6 +1588,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
834
1588
|
context: stepResults as any,
|
|
835
1589
|
activePaths: [],
|
|
836
1590
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1591
|
+
serializedStepGraph,
|
|
1592
|
+
status: workflowStatus,
|
|
1593
|
+
result,
|
|
1594
|
+
error,
|
|
837
1595
|
// @ts-ignore
|
|
838
1596
|
timestamp: Date.now(),
|
|
839
1597
|
},
|
|
@@ -849,27 +1607,35 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
849
1607
|
prevOutput,
|
|
850
1608
|
prevStep,
|
|
851
1609
|
stepResults,
|
|
1610
|
+
serializedStepGraph,
|
|
852
1611
|
resume,
|
|
853
1612
|
executionContext,
|
|
854
1613
|
emitter,
|
|
1614
|
+
abortController,
|
|
855
1615
|
runtimeContext,
|
|
856
1616
|
}: {
|
|
857
1617
|
workflowId: string;
|
|
858
1618
|
runId: string;
|
|
859
|
-
entry: {
|
|
1619
|
+
entry: {
|
|
1620
|
+
type: 'conditional';
|
|
1621
|
+
steps: StepFlowEntry[];
|
|
1622
|
+
conditions: ExecuteFunction<any, any, any, any, InngestEngineType>[];
|
|
1623
|
+
};
|
|
860
1624
|
prevStep: StepFlowEntry;
|
|
1625
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
861
1626
|
prevOutput: any;
|
|
862
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1627
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
863
1628
|
resume?: {
|
|
864
1629
|
steps: string[];
|
|
865
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1630
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
866
1631
|
resumePayload: any;
|
|
867
1632
|
resumePath: number[];
|
|
868
1633
|
};
|
|
869
1634
|
executionContext: ExecutionContext;
|
|
870
|
-
emitter:
|
|
1635
|
+
emitter: Emitter;
|
|
1636
|
+
abortController: AbortController;
|
|
871
1637
|
runtimeContext: RuntimeContext;
|
|
872
|
-
}): Promise<StepResult<any>> {
|
|
1638
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
873
1639
|
let execResults: any;
|
|
874
1640
|
const truthyIndexes = (
|
|
875
1641
|
await Promise.all(
|
|
@@ -877,8 +1643,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
877
1643
|
this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
878
1644
|
try {
|
|
879
1645
|
const result = await cond({
|
|
1646
|
+
runId,
|
|
880
1647
|
mastra: this.mastra!,
|
|
881
1648
|
runtimeContext,
|
|
1649
|
+
runCount: -1,
|
|
882
1650
|
inputData: prevOutput,
|
|
883
1651
|
getInitData: () => stepResults?.input as any,
|
|
884
1652
|
getStepResult: (step: any) => {
|
|
@@ -896,7 +1664,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
896
1664
|
|
|
897
1665
|
// TODO: this function shouldn't have suspend probably?
|
|
898
1666
|
suspend: async (_suspendPayload: any) => {},
|
|
899
|
-
|
|
1667
|
+
bail: () => {},
|
|
1668
|
+
abort: () => {
|
|
1669
|
+
abortController.abort();
|
|
1670
|
+
},
|
|
1671
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1672
|
+
engine: {
|
|
1673
|
+
step: this.inngestStep,
|
|
1674
|
+
},
|
|
1675
|
+
abortSignal: abortController.signal,
|
|
900
1676
|
});
|
|
901
1677
|
return result ? index : null;
|
|
902
1678
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -909,7 +1685,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
909
1685
|
).filter((index: any): index is number => index !== null);
|
|
910
1686
|
|
|
911
1687
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
912
|
-
const results: StepResult<any>[] = await Promise.all(
|
|
1688
|
+
const results: { result: StepResult<any, any, any, any> }[] = await Promise.all(
|
|
913
1689
|
stepsToRun.map((step, index) =>
|
|
914
1690
|
this.executeEntry({
|
|
915
1691
|
workflowId,
|
|
@@ -918,6 +1694,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
918
1694
|
prevStep,
|
|
919
1695
|
stepResults,
|
|
920
1696
|
resume,
|
|
1697
|
+
serializedStepGraph,
|
|
921
1698
|
executionContext: {
|
|
922
1699
|
workflowId,
|
|
923
1700
|
runId,
|
|
@@ -927,21 +1704,24 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
927
1704
|
executionSpan: executionContext.executionSpan,
|
|
928
1705
|
},
|
|
929
1706
|
emitter,
|
|
1707
|
+
abortController,
|
|
930
1708
|
runtimeContext,
|
|
931
1709
|
}),
|
|
932
1710
|
),
|
|
933
1711
|
);
|
|
934
|
-
const hasFailed = results.find(result => result.status === 'failed')
|
|
935
|
-
|
|
1712
|
+
const hasFailed = results.find(result => result.result.status === 'failed') as {
|
|
1713
|
+
result: StepFailure<any, any, any>;
|
|
1714
|
+
};
|
|
1715
|
+
const hasSuspended = results.find(result => result.result.status === 'suspended');
|
|
936
1716
|
if (hasFailed) {
|
|
937
|
-
execResults = { status: 'failed', error: hasFailed.error };
|
|
1717
|
+
execResults = { status: 'failed', error: hasFailed.result.error };
|
|
938
1718
|
} else if (hasSuspended) {
|
|
939
|
-
execResults = { status: 'suspended', payload: hasSuspended.
|
|
1719
|
+
execResults = { status: 'suspended', payload: hasSuspended.result.suspendPayload };
|
|
940
1720
|
} else {
|
|
941
1721
|
execResults = {
|
|
942
1722
|
status: 'success',
|
|
943
1723
|
output: results.reduce((acc: Record<string, any>, result, index) => {
|
|
944
|
-
if (result.status === 'success') {
|
|
1724
|
+
if (result.result.status === 'success') {
|
|
945
1725
|
// @ts-ignore
|
|
946
1726
|
acc[stepsToRun[index]!.step.id] = result.output;
|
|
947
1727
|
}
|