@mastra/inngest 0.0.0-generate-message-id-20250512171942 → 0.0.0-http-transporter-20250702160118

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/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 { NewWorkflow, createStep, Run, DefaultExecutionEngine, cloneStep } from '@mastra/core/workflows/vNext';
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
- NewStep,
12
- NewStep as Step,
13
- NewWorkflowConfig,
13
+ Step,
14
+ WorkflowConfig,
14
15
  StepFlowEntry,
15
16
  StepResult,
16
17
  WorkflowResult,
17
- } from '@mastra/core/workflows/vNext';
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 type { z } from 'zod';
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.vnext_getWorkflows();
25
- const functions = Object.values(wfs).flatMap(wf => {
26
- if (wf instanceof InngestWorkflow) {
27
- wf.__registerMastra(mastra);
28
- return wf.getFunctions();
29
- }
30
- return [];
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
- TSteps extends NewStep<string, any, any>[] = NewStep<string, any, any>[],
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
- while (runs?.[0]?.status !== 'Completed') {
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' || runs?.[0]?.status === 'Cancelled') {
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
- this.cleanup?.();
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: any) => void): () => void {
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: ['watch'],
262
+ topics: [type],
179
263
  app: this.inngest,
180
264
  },
181
265
  (message: any) => {
182
- cb(message.data);
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: any) => {
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
- TSteps extends NewStep<string, any, any>[] = NewStep<string, any, any>[],
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 NewWorkflow<TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
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: NewWorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
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
- return null;
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
- // @ts-ignore
298
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
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: 'watch',
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 cloneWorkflow<
366
- TWorkflowId extends string = string,
367
- TInput extends z.ZodType<any> = z.ZodType<any>,
368
- TOutput extends z.ZodType<any> = z.ZodType<any>,
369
- TSteps extends Step<string, any, any, any, any>[] = Step<string, any, any, any, any>[],
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
- workflow: InngestWorkflow<TSteps, string, TInput, TOutput>,
372
- opts: { id: TWorkflowId },
373
- ): InngestWorkflow<TSteps, TWorkflowId, TInput, TOutput> {
374
- const wf = new InngestWorkflow(
375
- {
376
- id: opts.id,
377
- inputSchema: workflow.inputSchema,
378
- outputSchema: workflow.outputSchema,
379
- steps: workflow.stepDefs,
380
- mastra: workflow.mastra,
381
- },
382
- workflow.inngest,
383
- );
622
+ agent: Agent<TStepId, any, any>,
623
+ ): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
384
624
 
385
- wf.setStepFlow(workflow.stepGraph);
386
- wf.commit();
387
- return wf;
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
+ }
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>[] = Step<string, any, any>[],
397
- >(params: NewWorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
398
- return new InngestWorkflow(params, inngest);
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
- cloneWorkflow,
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: { emit: (event: string, data: any) => Promise<void> },
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: { emit: (event: string, data: any) => Promise<void> };
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,28 @@ 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 executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
1005
+ const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
1006
+ event: `user-event-${event}`,
1007
+ timeout: timeout ?? 5e3,
1008
+ });
1009
+
1010
+ if (eventData === null) {
1011
+ throw 'Timeout waiting for event';
1012
+ }
1013
+
1014
+ return eventData?.data;
1015
+ }
1016
+
527
1017
  async executeStep({
528
1018
  step,
529
1019
  stepResults,
@@ -531,29 +1021,26 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
531
1021
  resume,
532
1022
  prevOutput,
533
1023
  emitter,
1024
+ abortController,
534
1025
  runtimeContext,
535
1026
  }: {
536
1027
  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
- };
1028
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1029
+ executionContext: ExecutionContext;
545
1030
  resume?: {
546
1031
  steps: string[];
547
1032
  resumePayload: any;
548
1033
  runId?: string;
549
1034
  };
550
1035
  prevOutput: any;
551
- emitter: { emit: (event: string, data: any) => Promise<void> };
1036
+ emitter: Emitter;
1037
+ abortController: AbortController;
552
1038
  runtimeContext: RuntimeContext;
553
- }): Promise<StepResult<any>> {
554
- await this.inngestStep.run(
1039
+ }): Promise<StepResult<any, any, any, any>> {
1040
+ const startedAt = await this.inngestStep.run(
555
1041
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
556
1042
  async () => {
1043
+ const startedAt = Date.now();
557
1044
  await emitter.emit('watch', {
558
1045
  type: 'watch',
559
1046
  payload: {
@@ -575,6 +1062,18 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
575
1062
  },
576
1063
  eventTimestamp: Date.now(),
577
1064
  });
1065
+
1066
+ await emitter.emit('watch-v2', {
1067
+ type: 'step-start',
1068
+ payload: {
1069
+ id: step.id,
1070
+ status: 'running',
1071
+ payload: prevOutput,
1072
+ startedAt,
1073
+ },
1074
+ });
1075
+
1076
+ return startedAt;
578
1077
  },
579
1078
  );
580
1079
 
@@ -641,10 +1140,20 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
641
1140
  eventTimestamp: Date.now(),
642
1141
  });
643
1142
 
1143
+ await emitter.emit('watch-v2', {
1144
+ type: 'step-result',
1145
+ payload: {
1146
+ id: step.id,
1147
+ status: 'failed',
1148
+ error: result?.error,
1149
+ payload: prevOutput,
1150
+ },
1151
+ });
1152
+
644
1153
  return { executionContext, result: { status: 'failed', error: result?.error } };
645
1154
  } else if (result.status === 'suspended') {
646
1155
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
647
- const stepRes: StepResult<any> = stepResult as StepResult<any>;
1156
+ const stepRes: StepResult<any, any, any, any> = stepResult as StepResult<any, any, any, any>;
648
1157
  return stepRes?.status === 'suspended';
649
1158
  });
650
1159
 
@@ -671,6 +1180,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
671
1180
  eventTimestamp: Date.now(),
672
1181
  });
673
1182
 
1183
+ await emitter.emit('watch-v2', {
1184
+ type: 'step-suspended',
1185
+ payload: {
1186
+ id: step.id,
1187
+ status: 'suspended',
1188
+ },
1189
+ });
1190
+
674
1191
  return {
675
1192
  executionContext,
676
1193
  result: {
@@ -727,19 +1244,39 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
727
1244
  eventTimestamp: Date.now(),
728
1245
  });
729
1246
 
1247
+ await emitter.emit('watch-v2', {
1248
+ type: 'step-result',
1249
+ payload: {
1250
+ id: step.id,
1251
+ status: 'success',
1252
+ output: result?.result,
1253
+ },
1254
+ });
1255
+
1256
+ await emitter.emit('watch-v2', {
1257
+ type: 'step-finish',
1258
+ payload: {
1259
+ id: step.id,
1260
+ metadata: {},
1261
+ },
1262
+ });
1263
+
730
1264
  return { executionContext, result: { status: 'success', output: result?.result } };
731
1265
  },
732
1266
  );
733
1267
 
734
1268
  Object.assign(executionContext, res.executionContext);
735
- return res.result as StepResult<any>;
1269
+ return res.result as StepResult<any, any, any, any>;
736
1270
  }
737
1271
 
738
1272
  const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
739
1273
  let execResults: any;
740
1274
  let suspended: { payload: any } | undefined;
1275
+ let bailed: { payload: any } | undefined;
1276
+
741
1277
  try {
742
1278
  const result = await step.execute({
1279
+ runId: executionContext.runId,
743
1280
  mastra: this.mastra!,
744
1281
  runtimeContext,
745
1282
  inputData: prevOutput,
@@ -757,22 +1294,56 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
757
1294
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
758
1295
  suspended = { payload: suspendPayload };
759
1296
  },
1297
+ bail: (result: any) => {
1298
+ bailed = { payload: result };
1299
+ },
760
1300
  resume: {
761
1301
  steps: resume?.steps?.slice(1) || [],
762
1302
  resumePayload: resume?.resumePayload,
763
1303
  // @ts-ignore
764
1304
  runId: stepResults[step.id]?.payload?.__workflow_meta?.runId,
765
1305
  },
766
- emitter,
1306
+ [EMITTER_SYMBOL]: emitter,
1307
+ engine: {
1308
+ step: this.inngestStep,
1309
+ },
1310
+ abortSignal: abortController.signal,
767
1311
  });
768
-
769
- execResults = { status: 'success', output: result };
1312
+ const endedAt = Date.now();
1313
+
1314
+ execResults = {
1315
+ status: 'success',
1316
+ output: result,
1317
+ startedAt,
1318
+ endedAt,
1319
+ payload: prevOutput,
1320
+ resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
1321
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
1322
+ };
770
1323
  } catch (e) {
771
- execResults = { status: 'failed', error: e instanceof Error ? e.message : String(e) };
1324
+ execResults = {
1325
+ status: 'failed',
1326
+ payload: prevOutput,
1327
+ error: e instanceof Error ? e.message : String(e),
1328
+ endedAt: Date.now(),
1329
+ startedAt,
1330
+ resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
1331
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
1332
+ };
772
1333
  }
773
1334
 
774
1335
  if (suspended) {
775
- execResults = { status: 'suspended', payload: suspended.payload };
1336
+ execResults = {
1337
+ status: 'suspended',
1338
+ suspendedPayload: suspended.payload,
1339
+ payload: prevOutput,
1340
+ suspendedAt: Date.now(),
1341
+ startedAt,
1342
+ resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
1343
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
1344
+ };
1345
+ } else if (bailed) {
1346
+ execResults = { status: 'bailed', output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
776
1347
  }
777
1348
 
778
1349
  if (execResults.status === 'failed') {
@@ -786,12 +1357,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
786
1357
  payload: {
787
1358
  currentStep: {
788
1359
  id: step.id,
789
- status: execResults.status,
790
- output: execResults.output,
1360
+ ...execResults,
791
1361
  },
792
1362
  workflowState: {
793
1363
  status: 'running',
794
- steps: stepResults,
1364
+ steps: { ...stepResults, [step.id]: execResults },
795
1365
  result: null,
796
1366
  error: null,
797
1367
  },
@@ -799,6 +1369,32 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
799
1369
  eventTimestamp: Date.now(),
800
1370
  });
801
1371
 
1372
+ if (execResults.status === 'suspended') {
1373
+ await emitter.emit('watch-v2', {
1374
+ type: 'step-suspended',
1375
+ payload: {
1376
+ id: step.id,
1377
+ ...execResults,
1378
+ },
1379
+ });
1380
+ } else {
1381
+ await emitter.emit('watch-v2', {
1382
+ type: 'step-result',
1383
+ payload: {
1384
+ id: step.id,
1385
+ ...execResults,
1386
+ },
1387
+ });
1388
+
1389
+ await emitter.emit('watch-v2', {
1390
+ type: 'step-finish',
1391
+ payload: {
1392
+ id: step.id,
1393
+ metadata: {},
1394
+ },
1395
+ });
1396
+ }
1397
+
802
1398
  return { result: execResults, executionContext, stepResults };
803
1399
  });
804
1400
 
@@ -816,11 +1412,19 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
816
1412
  runId,
817
1413
  stepResults,
818
1414
  executionContext,
1415
+ serializedStepGraph,
1416
+ workflowStatus,
1417
+ result,
1418
+ error,
819
1419
  }: {
820
1420
  workflowId: string;
821
1421
  runId: string;
822
- stepResults: Record<string, StepResult<any>>;
1422
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1423
+ serializedStepGraph: SerializedStepFlowEntry[];
823
1424
  executionContext: ExecutionContext;
1425
+ workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
1426
+ result?: Record<string, any>;
1427
+ error?: string | Error;
824
1428
  }) {
825
1429
  await this.inngestStep.run(
826
1430
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -834,6 +1438,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
834
1438
  context: stepResults as any,
835
1439
  activePaths: [],
836
1440
  suspendedPaths: executionContext.suspendedPaths,
1441
+ serializedStepGraph,
1442
+ status: workflowStatus,
1443
+ result,
1444
+ error,
837
1445
  // @ts-ignore
838
1446
  timestamp: Date.now(),
839
1447
  },
@@ -849,27 +1457,35 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
849
1457
  prevOutput,
850
1458
  prevStep,
851
1459
  stepResults,
1460
+ serializedStepGraph,
852
1461
  resume,
853
1462
  executionContext,
854
1463
  emitter,
1464
+ abortController,
855
1465
  runtimeContext,
856
1466
  }: {
857
1467
  workflowId: string;
858
1468
  runId: string;
859
- entry: { type: 'conditional'; steps: StepFlowEntry[]; conditions: ExecuteFunction<any, any, any, any>[] };
1469
+ entry: {
1470
+ type: 'conditional';
1471
+ steps: StepFlowEntry[];
1472
+ conditions: ExecuteFunction<any, any, any, any, InngestEngineType>[];
1473
+ };
860
1474
  prevStep: StepFlowEntry;
1475
+ serializedStepGraph: SerializedStepFlowEntry[];
861
1476
  prevOutput: any;
862
- stepResults: Record<string, StepResult<any>>;
1477
+ stepResults: Record<string, StepResult<any, any, any, any>>;
863
1478
  resume?: {
864
1479
  steps: string[];
865
- stepResults: Record<string, StepResult<any>>;
1480
+ stepResults: Record<string, StepResult<any, any, any, any>>;
866
1481
  resumePayload: any;
867
1482
  resumePath: number[];
868
1483
  };
869
1484
  executionContext: ExecutionContext;
870
- emitter: { emit: (event: string, data: any) => Promise<void> };
1485
+ emitter: Emitter;
1486
+ abortController: AbortController;
871
1487
  runtimeContext: RuntimeContext;
872
- }): Promise<StepResult<any>> {
1488
+ }): Promise<StepResult<any, any, any, any>> {
873
1489
  let execResults: any;
874
1490
  const truthyIndexes = (
875
1491
  await Promise.all(
@@ -877,8 +1493,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
877
1493
  this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
878
1494
  try {
879
1495
  const result = await cond({
1496
+ runId,
880
1497
  mastra: this.mastra!,
881
1498
  runtimeContext,
1499
+ runCount: -1,
882
1500
  inputData: prevOutput,
883
1501
  getInitData: () => stepResults?.input as any,
884
1502
  getStepResult: (step: any) => {
@@ -896,7 +1514,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
896
1514
 
897
1515
  // TODO: this function shouldn't have suspend probably?
898
1516
  suspend: async (_suspendPayload: any) => {},
899
- emitter,
1517
+ bail: () => {},
1518
+ abort: () => {
1519
+ abortController.abort();
1520
+ },
1521
+ [EMITTER_SYMBOL]: emitter,
1522
+ engine: {
1523
+ step: this.inngestStep,
1524
+ },
1525
+ abortSignal: abortController.signal,
900
1526
  });
901
1527
  return result ? index : null;
902
1528
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -909,7 +1535,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
909
1535
  ).filter((index: any): index is number => index !== null);
910
1536
 
911
1537
  const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
912
- const results: StepResult<any>[] = await Promise.all(
1538
+ const results: { result: StepResult<any, any, any, any> }[] = await Promise.all(
913
1539
  stepsToRun.map((step, index) =>
914
1540
  this.executeEntry({
915
1541
  workflowId,
@@ -918,6 +1544,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
918
1544
  prevStep,
919
1545
  stepResults,
920
1546
  resume,
1547
+ serializedStepGraph,
921
1548
  executionContext: {
922
1549
  workflowId,
923
1550
  runId,
@@ -927,21 +1554,24 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
927
1554
  executionSpan: executionContext.executionSpan,
928
1555
  },
929
1556
  emitter,
1557
+ abortController,
930
1558
  runtimeContext,
931
1559
  }),
932
1560
  ),
933
1561
  );
934
- const hasFailed = results.find(result => result.status === 'failed');
935
- const hasSuspended = results.find(result => result.status === 'suspended');
1562
+ const hasFailed = results.find(result => result.result.status === 'failed') as {
1563
+ result: StepFailure<any, any, any>;
1564
+ };
1565
+ const hasSuspended = results.find(result => result.result.status === 'suspended');
936
1566
  if (hasFailed) {
937
- execResults = { status: 'failed', error: hasFailed.error };
1567
+ execResults = { status: 'failed', error: hasFailed.result.error };
938
1568
  } else if (hasSuspended) {
939
- execResults = { status: 'suspended', payload: hasSuspended.payload };
1569
+ execResults = { status: 'suspended', payload: hasSuspended.result.suspendPayload };
940
1570
  } else {
941
1571
  execResults = {
942
1572
  status: 'success',
943
1573
  output: results.reduce((acc: Record<string, any>, result, index) => {
944
- if (result.status === 'success') {
1574
+ if (result.result.status === 'success') {
945
1575
  // @ts-ignore
946
1576
  acc[stepsToRun[index]!.step.id] = result.output;
947
1577
  }