@mastra/inngest 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-transpile-packages-20250724123433

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