@mastra/inngest 0.0.0-redis-cloud-transporter-20250508194049 → 0.0.0-remove-unused-import-20250909212718

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 DELETED
@@ -1,956 +0,0 @@
1
- import { randomUUID } from 'crypto';
2
- import { subscribe } from '@inngest/realtime';
3
- import type { Mastra, WorkflowRun } from '@mastra/core';
4
- import { RuntimeContext } from '@mastra/core/di';
5
- import { NewWorkflow, createStep, Run, DefaultExecutionEngine, cloneStep } from '@mastra/core/workflows/vNext';
6
- import type {
7
- ExecuteFunction,
8
- ExecutionContext,
9
- ExecutionEngine,
10
- ExecutionGraph,
11
- NewStep,
12
- NewStep as Step,
13
- NewWorkflowConfig,
14
- StepFlowEntry,
15
- StepResult,
16
- WorkflowResult,
17
- } from '@mastra/core/workflows/vNext';
18
- import type { Span } from '@opentelemetry/api';
19
- import type { Inngest, BaseContext } from 'inngest';
20
- import { serve as inngestServe } from 'inngest/hono';
21
- import type { z } from 'zod';
22
-
23
- 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
- });
32
- return inngestServe({
33
- client: inngest,
34
- functions,
35
- });
36
- }
37
-
38
- export class InngestRun<
39
- TSteps extends NewStep<string, any, any>[] = NewStep<string, any, any>[],
40
- TInput extends z.ZodType<any> = z.ZodType<any>,
41
- TOutput extends z.ZodType<any> = z.ZodType<any>,
42
- > extends Run<TSteps, TInput, TOutput> {
43
- private inngest: Inngest;
44
- #mastra: Mastra;
45
-
46
- constructor(
47
- params: {
48
- workflowId: string;
49
- runId: string;
50
- executionEngine: ExecutionEngine;
51
- executionGraph: ExecutionGraph;
52
- mastra?: Mastra;
53
- retryConfig?: {
54
- attempts?: number;
55
- delay?: number;
56
- };
57
- cleanup?: () => void;
58
- },
59
- inngest: Inngest,
60
- ) {
61
- super(params);
62
- this.inngest = inngest;
63
- this.#mastra = params.mastra!;
64
- }
65
-
66
- async getRuns(eventId: string) {
67
- const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
68
- headers: {
69
- Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`,
70
- },
71
- });
72
- const json = await response.json();
73
- return (json as any).data;
74
- }
75
-
76
- async getRunOutput(eventId: string) {
77
- let runs = await this.getRuns(eventId);
78
- while (runs?.[0]?.status !== 'Completed') {
79
- await new Promise(resolve => setTimeout(resolve, 1000));
80
- runs = await this.getRuns(eventId);
81
- if (runs?.[0]?.status === 'Failed' || runs?.[0]?.status === 'Cancelled') {
82
- throw new Error(`Function run ${runs?.[0]?.status}`);
83
- }
84
- }
85
- return runs?.[0];
86
- }
87
-
88
- async start({
89
- inputData,
90
- }: {
91
- inputData?: z.infer<TInput>;
92
- runtimeContext?: RuntimeContext;
93
- }): Promise<WorkflowResult<TOutput, TSteps>> {
94
- await this.#mastra.getStorage()?.persistWorkflowSnapshot({
95
- workflowName: this.workflowId,
96
- runId: this.runId,
97
- snapshot: {
98
- runId: this.runId,
99
- value: {},
100
- context: {} as any,
101
- activePaths: [],
102
- suspendedPaths: {},
103
- timestamp: Date.now(),
104
- },
105
- });
106
-
107
- const eventOutput = await this.inngest.send({
108
- name: `workflow.${this.workflowId}`,
109
- data: {
110
- inputData,
111
- runId: this.runId,
112
- },
113
- });
114
-
115
- const eventId = eventOutput.ids[0];
116
- if (!eventId) {
117
- throw new Error('Event ID is not set');
118
- }
119
- const runOutput = await this.getRunOutput(eventId);
120
- const result = runOutput?.output?.result;
121
- if (result.status === 'failed') {
122
- result.error = new Error(result.error);
123
- }
124
-
125
- this.cleanup?.();
126
- return result;
127
- }
128
-
129
- async resume<TResumeSchema extends z.ZodType<any>>(params: {
130
- resumeData?: z.infer<TResumeSchema>;
131
- step:
132
- | Step<string, any, any, TResumeSchema, any>
133
- | [...Step<string, any, any, any, any>[], Step<string, any, any, TResumeSchema, any>]
134
- | string
135
- | string[];
136
- runtimeContext?: RuntimeContext;
137
- }): Promise<WorkflowResult<TOutput, TSteps>> {
138
- const steps: string[] = (Array.isArray(params.step) ? params.step : [params.step]).map(step =>
139
- typeof step === 'string' ? step : step?.id,
140
- );
141
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
142
- workflowName: this.workflowId,
143
- runId: this.runId,
144
- });
145
-
146
- const eventOutput = await this.inngest.send({
147
- name: `workflow.${this.workflowId}`,
148
- data: {
149
- inputData: params.resumeData,
150
- runId: this.runId,
151
- stepResults: snapshot?.context as any,
152
- resume: {
153
- steps,
154
- stepResults: snapshot?.context as any,
155
- resumePayload: params.resumeData,
156
- // @ts-ignore
157
- resumePath: snapshot?.suspendedPaths?.[steps?.[0]] as any,
158
- },
159
- },
160
- });
161
-
162
- const eventId = eventOutput.ids[0];
163
- if (!eventId) {
164
- throw new Error('Event ID is not set');
165
- }
166
- const runOutput = await this.getRunOutput(eventId);
167
- const result = runOutput?.output?.result;
168
- if (result.status === 'failed') {
169
- result.error = new Error(result.error);
170
- }
171
- return result;
172
- }
173
-
174
- watch(cb: (event: any) => void): () => void {
175
- const streamPromise = subscribe(
176
- {
177
- channel: `workflow:${this.workflowId}:${this.runId}`,
178
- topics: ['watch'],
179
- app: this.inngest,
180
- },
181
- (message: any) => {
182
- cb(message.data);
183
- },
184
- );
185
-
186
- return () => {
187
- streamPromise
188
- .then((stream: any) => {
189
- stream.cancel();
190
- })
191
- .catch(err => {
192
- console.error(err);
193
- });
194
- };
195
- }
196
- }
197
-
198
- export class InngestWorkflow<
199
- TSteps extends NewStep<string, any, any>[] = NewStep<string, any, any>[],
200
- TWorkflowId extends string = string,
201
- TInput extends z.ZodType<any> = z.ZodType<any>,
202
- TOutput extends z.ZodType<any> = z.ZodType<any>,
203
- TPrevSchema extends z.ZodType<any> = TInput,
204
- > extends NewWorkflow<TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
205
- #mastra: Mastra;
206
- public inngest: Inngest;
207
-
208
- private function: ReturnType<Inngest['createFunction']> | undefined;
209
-
210
- constructor(params: NewWorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
211
- super(params);
212
- this.#mastra = params.mastra!;
213
- this.inngest = inngest;
214
- }
215
-
216
- async getWorkflowRuns(args?: {
217
- fromDate?: Date;
218
- toDate?: Date;
219
- limit?: number;
220
- offset?: number;
221
- resourceId?: string;
222
- }) {
223
- const storage = this.#mastra?.getStorage();
224
- if (!storage) {
225
- this.logger.debug('Cannot get workflow runs. Mastra engine is not initialized');
226
- return { runs: [], total: 0 };
227
- }
228
-
229
- return storage.getWorkflowRuns({ workflowName: this.id, ...(args ?? {}) });
230
- }
231
-
232
- async getWorkflowRunById(runId: string): Promise<WorkflowRun | null> {
233
- const storage = this.#mastra?.getStorage();
234
- if (!storage) {
235
- this.logger.debug('Cannot get workflow runs. Mastra engine is not initialized');
236
- return null;
237
- }
238
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
239
-
240
- return (
241
- run ??
242
- (this.runs.get(runId) ? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as WorkflowRun) : null)
243
- );
244
- }
245
-
246
- __registerMastra(mastra: Mastra) {
247
- this.#mastra = mastra;
248
- this.executionEngine.__registerMastra(mastra);
249
- const updateNested = (step: StepFlowEntry) => {
250
- if (
251
- (step.type === 'step' || step.type === 'loop' || step.type === 'foreach') &&
252
- step.step instanceof InngestWorkflow
253
- ) {
254
- step.step.__registerMastra(mastra);
255
- } else if (step.type === 'parallel' || step.type === 'conditional') {
256
- for (const subStep of step.steps) {
257
- updateNested(subStep);
258
- }
259
- }
260
- };
261
-
262
- if (this.executionGraph.steps.length) {
263
- for (const step of this.executionGraph.steps) {
264
- updateNested(step);
265
- }
266
- }
267
- }
268
-
269
- createRun(options?: { runId?: string }): Run<TSteps, TInput, TOutput> {
270
- const runIdToUse = options?.runId || randomUUID();
271
-
272
- // Return a new Run instance with object parameters
273
- const run: Run<TSteps, TInput, TOutput> =
274
- this.runs.get(runIdToUse) ??
275
- new InngestRun(
276
- {
277
- workflowId: this.id,
278
- runId: runIdToUse,
279
- executionEngine: this.executionEngine,
280
- executionGraph: this.executionGraph,
281
- mastra: this.#mastra,
282
- retryConfig: this.retryConfig,
283
- cleanup: () => this.runs.delete(runIdToUse),
284
- },
285
- this.inngest,
286
- );
287
-
288
- this.runs.set(runIdToUse, run);
289
- return run;
290
- }
291
-
292
- getFunction() {
293
- if (this.function) {
294
- return this.function;
295
- }
296
- this.function = this.inngest.createFunction(
297
- // @ts-ignore
298
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
299
- { event: `workflow.${this.id}` },
300
- async ({ event, step, attempt, publish }) => {
301
- let { inputData, runId, resume } = event.data;
302
-
303
- if (!runId) {
304
- runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
305
- return randomUUID();
306
- });
307
- }
308
-
309
- const emitter = {
310
- emit: async (event: string, data: any) => {
311
- if (!publish) {
312
- return;
313
- }
314
-
315
- try {
316
- await publish({
317
- channel: `workflow:${this.id}:${runId}`,
318
- topic: 'watch',
319
- data,
320
- });
321
- } catch (err: any) {
322
- this.logger.error('Error emitting event: ' + (err?.stack ?? err?.message ?? err));
323
- }
324
- },
325
- };
326
-
327
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
328
- const result = await engine.execute<z.infer<TInput>, WorkflowResult<TOutput, TSteps>>({
329
- workflowId: this.id,
330
- runId,
331
- graph: this.executionGraph,
332
- input: inputData,
333
- emitter,
334
- retryConfig: this.retryConfig,
335
- runtimeContext: new RuntimeContext(), // TODO
336
- resume,
337
- });
338
-
339
- return { result, runId };
340
- },
341
- );
342
- return this.function;
343
- }
344
-
345
- getNestedFunctions(steps: StepFlowEntry[]): ReturnType<Inngest['createFunction']>[] {
346
- return steps.flatMap(step => {
347
- if (step.type === 'step' || step.type === 'loop' || step.type === 'foreach') {
348
- if (step.step instanceof InngestWorkflow) {
349
- return [step.step.getFunction(), ...step.step.getNestedFunctions(step.step.executionGraph.steps)];
350
- }
351
- return [];
352
- } else if (step.type === 'parallel' || step.type === 'conditional') {
353
- return this.getNestedFunctions(step.steps);
354
- }
355
-
356
- return [];
357
- });
358
- }
359
-
360
- getFunctions() {
361
- return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
362
- }
363
- }
364
-
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>[],
370
- >(
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
- );
384
-
385
- wf.setStepFlow(workflow.stepGraph);
386
- wf.commit();
387
- return wf;
388
- }
389
-
390
- export function init(inngest: Inngest) {
391
- return {
392
- createWorkflow<
393
- TWorkflowId extends string = string,
394
- TInput extends z.ZodType<any> = z.ZodType<any>,
395
- 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);
399
- },
400
- createStep,
401
- cloneStep,
402
- cloneWorkflow,
403
- };
404
- }
405
-
406
- export class InngestExecutionEngine extends DefaultExecutionEngine {
407
- private inngestStep: BaseContext<Inngest>['step'];
408
- private inngestAttempts: number;
409
-
410
- constructor(mastra: Mastra, inngestStep: BaseContext<Inngest>['step'], inngestAttempts: number = 0) {
411
- super({ mastra });
412
- this.inngestStep = inngestStep;
413
- this.inngestAttempts = inngestAttempts;
414
- }
415
-
416
- protected async fmtReturnValue<TOutput>(
417
- executionSpan: Span | undefined,
418
- emitter: { emit: (event: string, data: any) => Promise<void> },
419
- stepResults: Record<string, StepResult<any>>,
420
- lastOutput: StepResult<any>,
421
- error?: Error | string,
422
- ): Promise<TOutput> {
423
- const base: any = {
424
- status: lastOutput.status,
425
- steps: stepResults,
426
- };
427
- if (lastOutput.status === 'success') {
428
- await emitter.emit('watch', {
429
- type: 'watch',
430
- payload: {
431
- workflowState: {
432
- status: lastOutput.status,
433
- steps: stepResults,
434
- result: lastOutput.output,
435
- },
436
- },
437
- eventTimestamp: Date.now(),
438
- });
439
-
440
- base.result = lastOutput.output;
441
- } else if (lastOutput.status === 'failed') {
442
- base.error =
443
- error instanceof Error
444
- ? (error?.stack ?? error.message)
445
- : lastOutput?.error instanceof Error
446
- ? lastOutput.error.message
447
- : (lastOutput.error ?? error ?? 'Unknown error');
448
-
449
- await emitter.emit('watch', {
450
- type: 'watch',
451
- payload: {
452
- workflowState: {
453
- status: lastOutput.status,
454
- steps: stepResults,
455
- result: null,
456
- error: base.error,
457
- },
458
- },
459
- eventTimestamp: Date.now(),
460
- });
461
- } else if (lastOutput.status === 'suspended') {
462
- await emitter.emit('watch', {
463
- type: 'watch',
464
- payload: {
465
- workflowState: {
466
- status: lastOutput.status,
467
- steps: stepResults,
468
- result: null,
469
- error: null,
470
- },
471
- },
472
- eventTimestamp: Date.now(),
473
- });
474
-
475
- const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
476
- if (stepResult?.status === 'suspended') {
477
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
478
- return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
479
- }
480
-
481
- return [];
482
- });
483
- base.suspended = suspendedStepIds;
484
- }
485
-
486
- executionSpan?.end();
487
- return base as TOutput;
488
- }
489
-
490
- async superExecuteStep({
491
- workflowId,
492
- runId,
493
- step,
494
- stepResults,
495
- executionContext,
496
- resume,
497
- prevOutput,
498
- emitter,
499
- runtimeContext,
500
- }: {
501
- workflowId: string;
502
- runId: string;
503
- step: Step<string, any, any>;
504
- stepResults: Record<string, StepResult<any>>;
505
- executionContext: ExecutionContext;
506
- resume?: {
507
- steps: string[];
508
- resumePayload: any;
509
- };
510
- prevOutput: any;
511
- emitter: { emit: (event: string, data: any) => Promise<void> };
512
- runtimeContext: RuntimeContext;
513
- }): Promise<StepResult<any>> {
514
- return super.executeStep({
515
- workflowId,
516
- runId,
517
- step,
518
- stepResults,
519
- executionContext,
520
- resume,
521
- prevOutput,
522
- emitter,
523
- runtimeContext,
524
- });
525
- }
526
-
527
- async executeStep({
528
- step,
529
- stepResults,
530
- executionContext,
531
- resume,
532
- prevOutput,
533
- emitter,
534
- runtimeContext,
535
- }: {
536
- 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
- };
545
- resume?: {
546
- steps: string[];
547
- resumePayload: any;
548
- runId?: string;
549
- };
550
- prevOutput: any;
551
- emitter: { emit: (event: string, data: any) => Promise<void> };
552
- runtimeContext: RuntimeContext;
553
- }): Promise<StepResult<any>> {
554
- await this.inngestStep.run(
555
- `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
556
- async () => {
557
- await emitter.emit('watch', {
558
- type: 'watch',
559
- payload: {
560
- currentStep: {
561
- id: step.id,
562
- status: 'running',
563
- },
564
- workflowState: {
565
- status: 'running',
566
- steps: {
567
- ...stepResults,
568
- [step.id]: {
569
- status: 'running',
570
- },
571
- },
572
- result: null,
573
- error: null,
574
- },
575
- },
576
- eventTimestamp: Date.now(),
577
- });
578
- },
579
- );
580
-
581
- if (step instanceof InngestWorkflow) {
582
- const isResume = !!resume?.steps?.length;
583
- let result: WorkflowResult<any, any>;
584
- let runId: string;
585
- if (isResume) {
586
- // @ts-ignore
587
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? randomUUID();
588
-
589
- const snapshot: any = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
590
- workflowName: step.id,
591
- runId: runId,
592
- });
593
-
594
- const invokeResp = (await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
595
- function: step.getFunction(),
596
- data: {
597
- inputData: prevOutput,
598
- runId: runId,
599
- resume: {
600
- runId: runId,
601
- steps: resume.steps.slice(1),
602
- stepResults: snapshot?.context as any,
603
- resumePayload: resume.resumePayload,
604
- // @ts-ignore
605
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]] as any,
606
- },
607
- },
608
- })) as any;
609
- result = invokeResp.result;
610
- runId = invokeResp.runId;
611
- } else {
612
- const invokeResp = (await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
613
- function: step.getFunction(),
614
- data: {
615
- inputData: prevOutput,
616
- },
617
- })) as any;
618
- result = invokeResp.result;
619
- runId = invokeResp.runId;
620
- }
621
-
622
- const res = await this.inngestStep.run(
623
- `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
624
- async () => {
625
- if (result.status === 'failed') {
626
- await emitter.emit('watch', {
627
- type: 'watch',
628
- payload: {
629
- currentStep: {
630
- id: step.id,
631
- status: 'failed',
632
- error: result?.error,
633
- },
634
- workflowState: {
635
- status: 'running',
636
- steps: stepResults,
637
- result: null,
638
- error: null,
639
- },
640
- },
641
- eventTimestamp: Date.now(),
642
- });
643
-
644
- return { executionContext, result: { status: 'failed', error: result?.error } };
645
- } else if (result.status === 'suspended') {
646
- const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
647
- const stepRes: StepResult<any> = stepResult as StepResult<any>;
648
- return stepRes?.status === 'suspended';
649
- });
650
-
651
- for (const [stepName, stepResult] of suspendedSteps) {
652
- // @ts-ignore
653
- const suspendPath: string[] = [stepName, ...(stepResult?.payload?.__workflow_meta?.path ?? [])];
654
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
655
-
656
- await emitter.emit('watch', {
657
- type: 'watch',
658
- payload: {
659
- currentStep: {
660
- id: step.id,
661
- status: 'suspended',
662
- payload: { ...(stepResult as any)?.payload, __workflow_meta: { runId: runId, path: suspendPath } },
663
- },
664
- workflowState: {
665
- status: 'running',
666
- steps: stepResults,
667
- result: null,
668
- error: null,
669
- },
670
- },
671
- eventTimestamp: Date.now(),
672
- });
673
-
674
- return {
675
- executionContext,
676
- result: {
677
- status: 'suspended',
678
- payload: { ...(stepResult as any)?.payload, __workflow_meta: { runId: runId, path: suspendPath } },
679
- },
680
- };
681
- }
682
-
683
- await emitter.emit('watch', {
684
- type: 'watch',
685
- payload: {
686
- currentStep: {
687
- id: step.id,
688
- status: 'suspended',
689
- payload: {},
690
- },
691
- workflowState: {
692
- status: 'running',
693
- steps: stepResults,
694
- result: null,
695
- error: null,
696
- },
697
- },
698
- eventTimestamp: Date.now(),
699
- });
700
-
701
- return {
702
- executionContext,
703
- result: {
704
- status: 'suspended',
705
- payload: {},
706
- },
707
- };
708
- }
709
-
710
- // is success
711
-
712
- await emitter.emit('watch', {
713
- type: 'watch',
714
- payload: {
715
- currentStep: {
716
- id: step.id,
717
- status: 'success',
718
- output: result?.result,
719
- },
720
- workflowState: {
721
- status: 'running',
722
- steps: stepResults,
723
- result: null,
724
- error: null,
725
- },
726
- },
727
- eventTimestamp: Date.now(),
728
- });
729
-
730
- return { executionContext, result: { status: 'success', output: result?.result } };
731
- },
732
- );
733
-
734
- Object.assign(executionContext, res.executionContext);
735
- return res.result as StepResult<any>;
736
- }
737
-
738
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
739
- let execResults: any;
740
- let suspended: { payload: any } | undefined;
741
- try {
742
- const result = await step.execute({
743
- mastra: this.mastra!,
744
- runtimeContext,
745
- inputData: prevOutput,
746
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
747
- getInitData: () => stepResults?.input as any,
748
- getStepResult: (step: any) => {
749
- const result = stepResults[step.id];
750
- if (result?.status === 'success') {
751
- return result.output;
752
- }
753
-
754
- return null;
755
- },
756
- suspend: async (suspendPayload: any) => {
757
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
758
- suspended = { payload: suspendPayload };
759
- },
760
- resume: {
761
- steps: resume?.steps?.slice(1) || [],
762
- resumePayload: resume?.resumePayload,
763
- // @ts-ignore
764
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId,
765
- },
766
- emitter,
767
- });
768
-
769
- execResults = { status: 'success', output: result };
770
- } catch (e) {
771
- execResults = { status: 'failed', error: e instanceof Error ? e.message : String(e) };
772
- }
773
-
774
- if (suspended) {
775
- execResults = { status: 'suspended', payload: suspended.payload };
776
- }
777
-
778
- if (execResults.status === 'failed') {
779
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
780
- throw execResults.error;
781
- }
782
- }
783
-
784
- await emitter.emit('watch', {
785
- type: 'watch',
786
- payload: {
787
- currentStep: {
788
- id: step.id,
789
- status: execResults.status,
790
- output: execResults.output,
791
- },
792
- workflowState: {
793
- status: 'running',
794
- steps: stepResults,
795
- result: null,
796
- error: null,
797
- },
798
- },
799
- eventTimestamp: Date.now(),
800
- });
801
-
802
- return { result: execResults, executionContext, stepResults };
803
- });
804
-
805
- // @ts-ignore
806
- Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
807
- // @ts-ignore
808
- Object.assign(stepResults, stepRes.stepResults);
809
-
810
- // @ts-ignore
811
- return stepRes.result;
812
- }
813
-
814
- async persistStepUpdate({
815
- workflowId,
816
- runId,
817
- stepResults,
818
- executionContext,
819
- }: {
820
- workflowId: string;
821
- runId: string;
822
- stepResults: Record<string, StepResult<any>>;
823
- executionContext: ExecutionContext;
824
- }) {
825
- await this.inngestStep.run(
826
- `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
827
- async () => {
828
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
829
- workflowName: workflowId,
830
- runId,
831
- snapshot: {
832
- runId,
833
- value: {},
834
- context: stepResults as any,
835
- activePaths: [],
836
- suspendedPaths: executionContext.suspendedPaths,
837
- // @ts-ignore
838
- timestamp: Date.now(),
839
- },
840
- });
841
- },
842
- );
843
- }
844
-
845
- async executeConditional({
846
- workflowId,
847
- runId,
848
- entry,
849
- prevOutput,
850
- prevStep,
851
- stepResults,
852
- resume,
853
- executionContext,
854
- emitter,
855
- runtimeContext,
856
- }: {
857
- workflowId: string;
858
- runId: string;
859
- entry: { type: 'conditional'; steps: StepFlowEntry[]; conditions: ExecuteFunction<any, any, any, any>[] };
860
- prevStep: StepFlowEntry;
861
- prevOutput: any;
862
- stepResults: Record<string, StepResult<any>>;
863
- resume?: {
864
- steps: string[];
865
- stepResults: Record<string, StepResult<any>>;
866
- resumePayload: any;
867
- resumePath: number[];
868
- };
869
- executionContext: ExecutionContext;
870
- emitter: { emit: (event: string, data: any) => Promise<void> };
871
- runtimeContext: RuntimeContext;
872
- }): Promise<StepResult<any>> {
873
- let execResults: any;
874
- const truthyIndexes = (
875
- await Promise.all(
876
- entry.conditions.map((cond, index) =>
877
- this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
878
- try {
879
- const result = await cond({
880
- mastra: this.mastra!,
881
- runtimeContext,
882
- inputData: prevOutput,
883
- getInitData: () => stepResults?.input as any,
884
- getStepResult: (step: any) => {
885
- if (!step?.id) {
886
- return null;
887
- }
888
-
889
- const result = stepResults[step.id];
890
- if (result?.status === 'success') {
891
- return result.output;
892
- }
893
-
894
- return null;
895
- },
896
-
897
- // TODO: this function shouldn't have suspend probably?
898
- suspend: async (_suspendPayload: any) => {},
899
- emitter,
900
- });
901
- return result ? index : null;
902
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
903
- } catch (e: unknown) {
904
- return null;
905
- }
906
- }),
907
- ),
908
- )
909
- ).filter((index: any): index is number => index !== null);
910
-
911
- const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
912
- const results: StepResult<any>[] = await Promise.all(
913
- stepsToRun.map((step, index) =>
914
- this.executeEntry({
915
- workflowId,
916
- runId,
917
- entry: step,
918
- prevStep,
919
- stepResults,
920
- resume,
921
- executionContext: {
922
- workflowId,
923
- runId,
924
- executionPath: [...executionContext.executionPath, index],
925
- suspendedPaths: executionContext.suspendedPaths,
926
- retryConfig: executionContext.retryConfig,
927
- executionSpan: executionContext.executionSpan,
928
- },
929
- emitter,
930
- runtimeContext,
931
- }),
932
- ),
933
- );
934
- const hasFailed = results.find(result => result.status === 'failed');
935
- const hasSuspended = results.find(result => result.status === 'suspended');
936
- if (hasFailed) {
937
- execResults = { status: 'failed', error: hasFailed.error };
938
- } else if (hasSuspended) {
939
- execResults = { status: 'suspended', payload: hasSuspended.payload };
940
- } else {
941
- execResults = {
942
- status: 'success',
943
- output: results.reduce((acc: Record<string, any>, result, index) => {
944
- if (result.status === 'success') {
945
- // @ts-ignore
946
- acc[stepsToRun[index]!.step.id] = result.output;
947
- }
948
-
949
- return acc;
950
- }, {}),
951
- };
952
- }
953
-
954
- return execResults;
955
- }
956
- }