@mastra/inngest 0.0.0-fix-generate-title-20250616171351 → 0.0.0-fix-fetch-workflow-runs-20250624231457

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.test.ts CHANGED
@@ -5,10 +5,12 @@ import { openai } from '@ai-sdk/openai';
5
5
  import { serve } from '@hono/node-server';
6
6
  import { realtimeMiddleware } from '@inngest/realtime';
7
7
  import { createTool, Mastra, Telemetry } from '@mastra/core';
8
+ import type { StreamEvent } from '@mastra/core';
8
9
  import { Agent } from '@mastra/core/agent';
9
10
  import { RuntimeContext } from '@mastra/core/runtime-context';
10
11
  import { createHonoServer } from '@mastra/deployer/server';
11
12
  import { DefaultStorage } from '@mastra/libsql';
13
+ import { MockLanguageModelV1, simulateReadableStream } from 'ai/test';
12
14
  import { $ } from 'execa';
13
15
  import getPort from 'get-port';
14
16
  import { Inngest } from 'inngest';
@@ -33,13 +35,118 @@ describe('MastraInngestWorkflow', () => {
33
35
  ctx.inngestPort = inngestPort;
34
36
  ctx.handlerPort = handlerPort;
35
37
  ctx.containerName = containerName;
38
+
39
+ vi.restoreAllMocks();
36
40
  });
37
41
 
38
42
  afterEach<LocalTestContext>(async ctx => {
39
43
  await $`docker stop ${ctx.containerName}`;
40
44
  });
41
45
 
42
- describe('Basic Workflow Execution', () => {
46
+ describe.sequential('Basic Workflow Execution', () => {
47
+ it('should be able to bail workflow execution', async ctx => {
48
+ const inngest = new Inngest({
49
+ id: 'mastra',
50
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
51
+ middleware: [realtimeMiddleware()],
52
+ });
53
+
54
+ const { createWorkflow, createStep } = init(inngest);
55
+
56
+ const step1 = createStep({
57
+ id: 'step1',
58
+ execute: async ({ bail, inputData }) => {
59
+ if (inputData.value === 'bail') {
60
+ return bail({ result: 'bailed' });
61
+ }
62
+
63
+ return { result: 'step1: ' + inputData.value };
64
+ },
65
+ inputSchema: z.object({ value: z.string() }),
66
+ outputSchema: z.object({ result: z.string() }),
67
+ });
68
+ const step2 = createStep({
69
+ id: 'step2',
70
+ execute: async ({ inputData }) => {
71
+ return { result: 'step2: ' + inputData.result };
72
+ },
73
+ inputSchema: z.object({ result: z.string() }),
74
+ outputSchema: z.object({ result: z.string() }),
75
+ });
76
+
77
+ const workflow = createWorkflow({
78
+ id: 'test-workflow',
79
+ inputSchema: z.object({ value: z.string() }),
80
+ outputSchema: z.object({
81
+ result: z.string(),
82
+ }),
83
+ steps: [step1, step2],
84
+ });
85
+
86
+ workflow.then(step1).then(step2).commit();
87
+
88
+ const mastra = new Mastra({
89
+ storage: new DefaultStorage({
90
+ url: ':memory:',
91
+ }),
92
+ workflows: {
93
+ 'test-workflow': workflow,
94
+ },
95
+ server: {
96
+ apiRoutes: [
97
+ {
98
+ path: '/inngest/api',
99
+ method: 'ALL',
100
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
101
+ },
102
+ ],
103
+ },
104
+ });
105
+
106
+ const app = await createHonoServer(mastra);
107
+
108
+ const srv = serve({
109
+ fetch: app.fetch,
110
+ port: (ctx as any).handlerPort,
111
+ });
112
+
113
+ const run = await workflow.createRunAsync();
114
+ const result = await run.start({ inputData: { value: 'bail' } });
115
+
116
+ await new Promise(resolve => setTimeout(resolve, 2000));
117
+
118
+ expect(result.steps['step1']).toEqual({
119
+ status: 'success',
120
+ output: { result: 'bailed' },
121
+ payload: { value: 'bail' },
122
+ startedAt: expect.any(Number),
123
+ endedAt: expect.any(Number),
124
+ });
125
+
126
+ expect(result.steps['step2']).toBeUndefined();
127
+
128
+ const run2 = await workflow.createRunAsync();
129
+ const result2 = await run2.start({ inputData: { value: 'no-bail' } });
130
+
131
+ srv.close();
132
+
133
+ expect(result2.steps['step1']).toEqual({
134
+ status: 'success',
135
+ output: { result: 'step1: no-bail' },
136
+ payload: { value: 'no-bail' },
137
+ startedAt: expect.any(Number),
138
+ endedAt: expect.any(Number),
139
+ });
140
+
141
+ expect(result2.steps['step2']).toEqual({
142
+ status: 'success',
143
+ output: { result: 'step2: step1: no-bail' },
144
+ payload: { result: 'step1: no-bail' },
145
+ startedAt: expect.any(Number),
146
+ endedAt: expect.any(Number),
147
+ });
148
+ });
149
+
43
150
  it('should execute a single step workflow successfully', async ctx => {
44
151
  const inngest = new Inngest({
45
152
  id: 'mastra',
@@ -91,11 +198,11 @@ describe('MastraInngestWorkflow', () => {
91
198
  });
92
199
  await new Promise(resolve => setTimeout(resolve, 2000));
93
200
 
94
- const run = workflow.createRun();
201
+ const run = await workflow.createRunAsync();
95
202
  const result = await run.start({ inputData: {} });
96
203
 
97
204
  expect(execute).toHaveBeenCalled();
98
- expect(result.steps['step1']).toEqual({
205
+ expect(result.steps['step1']).toMatchObject({
99
206
  status: 'success',
100
207
  output: { result: 'success' },
101
208
  });
@@ -166,12 +273,12 @@ describe('MastraInngestWorkflow', () => {
166
273
  });
167
274
  await new Promise(resolve => setTimeout(resolve, 2000));
168
275
 
169
- const run = workflow.createRun();
276
+ const run = await workflow.createRunAsync();
170
277
  const result = await run.start({ inputData: {} });
171
278
 
172
279
  expect(step1Action).toHaveBeenCalled();
173
280
  expect(step2Action).toHaveBeenCalled();
174
- expect(result.steps).toEqual({
281
+ expect(result.steps).toMatchObject({
175
282
  input: {},
176
283
  step1: { status: 'success', output: { value: 'step1' } },
177
284
  step2: { status: 'success', output: { value: 'step2' } },
@@ -247,11 +354,11 @@ describe('MastraInngestWorkflow', () => {
247
354
  });
248
355
  await new Promise(resolve => setTimeout(resolve, 2000));
249
356
 
250
- const run = workflow.createRun();
357
+ const run = await workflow.createRunAsync();
251
358
  const result = await run.start({ inputData: {} });
252
359
 
253
- expect(executionOrder).toEqual(['step1', 'step2']);
254
- expect(result.steps).toEqual({
360
+ expect(executionOrder).toMatchObject(['step1', 'step2']);
361
+ expect(result.steps).toMatchObject({
255
362
  input: {},
256
363
  step1: { status: 'success', output: { value: 'step1' } },
257
364
  step2: { status: 'success', output: { value: 'step2' } },
@@ -321,13 +428,13 @@ describe('MastraInngestWorkflow', () => {
321
428
  });
322
429
  await new Promise(resolve => setTimeout(resolve, 2000));
323
430
 
324
- const run = workflow.createRun();
431
+ const run = await workflow.createRunAsync();
325
432
  const startTime = Date.now();
326
433
  const result = await run.start({ inputData: {} });
327
434
  const endTime = Date.now();
328
435
 
329
436
  expect(execute).toHaveBeenCalled();
330
- expect(result.steps['step1']).toEqual({
437
+ expect(result.steps['step1']).toMatchObject({
331
438
  status: 'success',
332
439
  output: { result: 'success' },
333
440
  // payload: {},
@@ -335,7 +442,7 @@ describe('MastraInngestWorkflow', () => {
335
442
  // endedAt: expect.any(Number),
336
443
  });
337
444
 
338
- expect(result.steps['step2']).toEqual({
445
+ expect(result.steps['step2']).toMatchObject({
339
446
  status: 'success',
340
447
  output: { result: 'slept successfully: success' },
341
448
  // payload: { result: 'success' },
@@ -413,13 +520,13 @@ describe('MastraInngestWorkflow', () => {
413
520
  });
414
521
  await new Promise(resolve => setTimeout(resolve, 2000));
415
522
 
416
- const run = workflow.createRun();
523
+ const run = await workflow.createRunAsync();
417
524
  const startTime = Date.now();
418
525
  const result = await run.start({ inputData: {} });
419
526
  const endTime = Date.now();
420
527
 
421
528
  expect(execute).toHaveBeenCalled();
422
- expect(result.steps['step1']).toEqual({
529
+ expect(result.steps['step1']).toMatchObject({
423
530
  status: 'success',
424
531
  output: { result: 'success' },
425
532
  // payload: {},
@@ -427,7 +534,7 @@ describe('MastraInngestWorkflow', () => {
427
534
  // endedAt: expect.any(Number),
428
535
  });
429
536
 
430
- expect(result.steps['step2']).toEqual({
537
+ expect(result.steps['step2']).toMatchObject({
431
538
  status: 'success',
432
539
  output: { result: 'slept successfully: success' },
433
540
  // payload: { result: 'success' },
@@ -439,6 +546,190 @@ describe('MastraInngestWorkflow', () => {
439
546
 
440
547
  srv.close();
441
548
  });
549
+
550
+ it('should execute a a waitForEvent step', async ctx => {
551
+ const inngest = new Inngest({
552
+ id: 'mastra',
553
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
554
+ });
555
+
556
+ const { createWorkflow, createStep } = init(inngest);
557
+
558
+ const execute = vi.fn<any>().mockResolvedValue({ result: 'success' });
559
+ const step1 = createStep({
560
+ id: 'step1',
561
+ execute,
562
+ inputSchema: z.object({}),
563
+ outputSchema: z.object({ result: z.string() }),
564
+ });
565
+ const step2 = createStep({
566
+ id: 'step2',
567
+ execute: async ({ inputData, resumeData }) => {
568
+ return { result: inputData.result, resumed: resumeData };
569
+ },
570
+ inputSchema: z.object({ result: z.string() }),
571
+ outputSchema: z.object({ result: z.string(), resumed: z.any() }),
572
+ resumeSchema: z.any(),
573
+ });
574
+
575
+ const workflow = createWorkflow({
576
+ id: 'test-workflow',
577
+ inputSchema: z.object({}),
578
+ outputSchema: z.object({
579
+ result: z.string(),
580
+ resumed: z.any(),
581
+ }),
582
+ steps: [step1],
583
+ });
584
+
585
+ workflow.then(step1).waitForEvent('hello-event', step2).commit();
586
+
587
+ const mastra = new Mastra({
588
+ storage: new DefaultStorage({
589
+ url: ':memory:',
590
+ }),
591
+ workflows: {
592
+ 'test-workflow': workflow,
593
+ },
594
+ server: {
595
+ apiRoutes: [
596
+ {
597
+ path: '/inngest/api',
598
+ method: 'ALL',
599
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
600
+ },
601
+ ],
602
+ },
603
+ });
604
+
605
+ const app = await createHonoServer(mastra);
606
+
607
+ const srv = serve({
608
+ fetch: app.fetch,
609
+ port: (ctx as any).handlerPort,
610
+ });
611
+ await new Promise(resolve => setTimeout(resolve, 2000));
612
+
613
+ const run = await workflow.createRunAsync();
614
+ const startTime = Date.now();
615
+ setTimeout(() => {
616
+ run.sendEvent('hello-event', { data: 'hello' });
617
+ }, 1000);
618
+ const result = await run.start({ inputData: {} });
619
+ const endTime = Date.now();
620
+
621
+ expect(execute).toHaveBeenCalled();
622
+ expect(result.steps['step1']).toMatchObject({
623
+ status: 'success',
624
+ output: { result: 'success' },
625
+ // payload: {},
626
+ // startedAt: expect.any(Number),
627
+ // endedAt: expect.any(Number),
628
+ });
629
+
630
+ expect(result.steps['step2']).toMatchObject({
631
+ status: 'success',
632
+ output: { result: 'success', resumed: { data: 'hello' } },
633
+ payload: { result: 'success' },
634
+ // resumePayload: { data: 'hello' },
635
+ startedAt: expect.any(Number),
636
+ endedAt: expect.any(Number),
637
+ });
638
+
639
+ expect(endTime - startTime).toBeGreaterThan(1000);
640
+
641
+ srv.close();
642
+ });
643
+
644
+ it('should execute a a waitForEvent step after timeout', async ctx => {
645
+ const inngest = new Inngest({
646
+ id: 'mastra',
647
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
648
+ });
649
+
650
+ const { createWorkflow, createStep } = init(inngest);
651
+
652
+ const execute = vi.fn<any>().mockResolvedValue({ result: 'success' });
653
+ const step1 = createStep({
654
+ id: 'step1',
655
+ execute,
656
+ inputSchema: z.object({}),
657
+ outputSchema: z.object({ result: z.string() }),
658
+ });
659
+ const step2 = createStep({
660
+ id: 'step2',
661
+ execute: async ({ inputData, resumeData }) => {
662
+ return { result: inputData.result, resumed: resumeData };
663
+ },
664
+ inputSchema: z.object({ result: z.string() }),
665
+ outputSchema: z.object({ result: z.string(), resumed: z.any() }),
666
+ resumeSchema: z.any(),
667
+ });
668
+
669
+ const workflow = createWorkflow({
670
+ id: 'test-workflow',
671
+ inputSchema: z.object({}),
672
+ outputSchema: z.object({
673
+ result: z.string(),
674
+ resumed: z.any(),
675
+ }),
676
+ steps: [step1],
677
+ });
678
+
679
+ workflow.then(step1).waitForEvent('hello-event', step2, { timeout: 1000 }).commit();
680
+
681
+ const mastra = new Mastra({
682
+ storage: new DefaultStorage({
683
+ url: ':memory:',
684
+ }),
685
+ workflows: {
686
+ 'test-workflow': workflow,
687
+ },
688
+ server: {
689
+ apiRoutes: [
690
+ {
691
+ path: '/inngest/api',
692
+ method: 'ALL',
693
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
694
+ },
695
+ ],
696
+ },
697
+ });
698
+
699
+ const app = await createHonoServer(mastra);
700
+
701
+ const srv = serve({
702
+ fetch: app.fetch,
703
+ port: (ctx as any).handlerPort,
704
+ });
705
+ await new Promise(resolve => setTimeout(resolve, 2000));
706
+
707
+ const run = await workflow.createRunAsync();
708
+ const startTime = Date.now();
709
+ const result = await run.start({ inputData: {} });
710
+ const endTime = Date.now();
711
+
712
+ expect(execute).toHaveBeenCalled();
713
+ expect(result.steps['step1']).toMatchObject({
714
+ status: 'success',
715
+ output: { result: 'success' },
716
+ // payload: {},
717
+ // startedAt: expect.any(Number),
718
+ // endedAt: expect.any(Number),
719
+ });
720
+
721
+ expect(result.steps['step2']).toMatchObject({
722
+ status: 'failed',
723
+ error: expect.any(String),
724
+ payload: { result: 'success' },
725
+ startedAt: expect.any(Number),
726
+ endedAt: expect.any(Number),
727
+ });
728
+
729
+ expect(endTime - startTime).toBeGreaterThan(1000);
730
+
731
+ srv.close();
732
+ });
442
733
  });
443
734
 
444
735
  describe('Variable Resolution', () => {
@@ -498,11 +789,11 @@ describe('MastraInngestWorkflow', () => {
498
789
  port: (ctx as any).handlerPort,
499
790
  });
500
791
 
501
- const run = workflow.createRun();
792
+ const run = await workflow.createRunAsync();
502
793
  const result = await run.start({ inputData: { inputData: 'test-input' } });
503
794
 
504
- expect(result.steps.step1).toEqual({ status: 'success', output: { result: 'success' } });
505
- expect(result.steps.step2).toEqual({ status: 'success', output: { result: 'success' } });
795
+ expect(result.steps.step1).toMatchObject({ status: 'success', output: { result: 'success' } });
796
+ expect(result.steps.step2).toMatchObject({ status: 'success', output: { result: 'success' } });
506
797
 
507
798
  srv.close();
508
799
  });
@@ -517,14 +808,14 @@ describe('MastraInngestWorkflow', () => {
517
808
 
518
809
  const step1Action = vi.fn().mockImplementation(async ({ inputData }) => {
519
810
  // Test accessing trigger data with correct type
520
- expect(inputData).toEqual({ inputValue: 'test-input' });
811
+ expect(inputData).toMatchObject({ inputValue: 'test-input' });
521
812
  return { value: 'step1-result' };
522
813
  });
523
814
 
524
815
  const step2Action = vi.fn().mockImplementation(async ({ getStepResult }) => {
525
816
  // Test accessing previous step result with type
526
817
  const step1Result = getStepResult(step1);
527
- expect(step1Result).toEqual({ value: 'step1-result' });
818
+ expect(step1Result).toMatchObject({ value: 'step1-result' });
528
819
 
529
820
  const failedStep = getStepResult(nonExecutedStep);
530
821
  expect(failedStep).toBe(null);
@@ -585,12 +876,12 @@ describe('MastraInngestWorkflow', () => {
585
876
  port: (ctx as any).handlerPort,
586
877
  });
587
878
 
588
- const run = workflow.createRun();
879
+ const run = await workflow.createRunAsync();
589
880
  const result = await run.start({ inputData: { inputValue: 'test-input' } });
590
881
 
591
882
  expect(step1Action).toHaveBeenCalled();
592
883
  expect(step2Action).toHaveBeenCalled();
593
- expect(result.steps).toEqual({
884
+ expect(result.steps).toMatchObject({
594
885
  input: { inputValue: 'test-input' },
595
886
  step1: { status: 'success', output: { value: 'step1-result' } },
596
887
  step2: { status: 'success', output: { value: 'step2-result' } },
@@ -652,7 +943,7 @@ describe('MastraInngestWorkflow', () => {
652
943
  port: (ctx as any).handlerPort,
653
944
  });
654
945
 
655
- const run = workflow.createRun();
946
+ const run = await workflow.createRunAsync();
656
947
  await run.start({ inputData: { inputData: 'test-input' } });
657
948
 
658
949
  expect(execute).toHaveBeenCalledWith(
@@ -727,7 +1018,7 @@ describe('MastraInngestWorkflow', () => {
727
1018
  port: (ctx as any).handlerPort,
728
1019
  });
729
1020
 
730
- const run = workflow.createRun();
1021
+ const run = await workflow.createRunAsync();
731
1022
  const result = await run.start({ inputData: { cool: 'test-input' } });
732
1023
 
733
1024
  expect(execute).toHaveBeenCalledWith(
@@ -736,7 +1027,7 @@ describe('MastraInngestWorkflow', () => {
736
1027
  }),
737
1028
  );
738
1029
 
739
- expect(result.steps.step2).toEqual({ status: 'success', output: { result: { cool: 'test-input' } } });
1030
+ expect(result.steps.step2).toMatchObject({ status: 'success', output: { result: { cool: 'test-input' } } });
740
1031
 
741
1032
  srv.close();
742
1033
  });
@@ -809,7 +1100,7 @@ describe('MastraInngestWorkflow', () => {
809
1100
  port: (ctx as any).handlerPort,
810
1101
  });
811
1102
 
812
- const run = workflow.createRun();
1103
+ const run = await workflow.createRunAsync();
813
1104
  await run.start({ inputData: {} });
814
1105
 
815
1106
  expect(step2Action).toHaveBeenCalledWith(
@@ -912,14 +1203,14 @@ describe('MastraInngestWorkflow', () => {
912
1203
  port: (ctx as any).handlerPort,
913
1204
  });
914
1205
 
915
- const run = workflow.createRun();
1206
+ const run = await workflow.createRunAsync();
916
1207
  const result = await run.start({ inputData: { status: 'success' } });
917
1208
  srv.close();
918
1209
 
919
1210
  expect(step1Action).toHaveBeenCalled();
920
1211
  expect(step2Action).toHaveBeenCalled();
921
1212
  expect(step3Action).not.toHaveBeenCalled();
922
- expect(result.steps).toEqual({
1213
+ expect(result.steps).toMatchObject({
923
1214
  input: { status: 'success' },
924
1215
  step1: { status: 'success', output: { status: 'success' } },
925
1216
  step2: { status: 'success', output: { result: 'step2' } },
@@ -988,7 +1279,7 @@ describe('MastraInngestWorkflow', () => {
988
1279
  port: (ctx as any).handlerPort,
989
1280
  });
990
1281
 
991
- const run = workflow.createRun();
1282
+ const run = await workflow.createRunAsync();
992
1283
  let result: Awaited<ReturnType<typeof run.start>> | undefined = undefined;
993
1284
  try {
994
1285
  result = await run.start({ inputData: {} });
@@ -1000,7 +1291,7 @@ describe('MastraInngestWorkflow', () => {
1000
1291
 
1001
1292
  expect(step1Action).toHaveBeenCalled();
1002
1293
  expect(step2Action).not.toHaveBeenCalled();
1003
- expect(result?.steps).toEqual({
1294
+ expect(result?.steps).toMatchObject({
1004
1295
  input: {},
1005
1296
  step1: { status: 'failed', error: 'Failed' },
1006
1297
  });
@@ -1093,7 +1384,7 @@ describe('MastraInngestWorkflow', () => {
1093
1384
  port: (ctx as any).handlerPort,
1094
1385
  });
1095
1386
 
1096
- const run = workflow.createRun();
1387
+ const run = await workflow.createRunAsync();
1097
1388
  const result = await run.start({ inputData: { status: 'success' } });
1098
1389
  srv.close();
1099
1390
 
@@ -1176,18 +1467,17 @@ describe('MastraInngestWorkflow', () => {
1176
1467
  port: (ctx as any).handlerPort,
1177
1468
  });
1178
1469
 
1179
- const run = workflow.createRun();
1470
+ const run = await workflow.createRunAsync();
1180
1471
  const result = await run.start({ inputData: { count: 5 } });
1181
1472
  srv.close();
1182
1473
 
1183
1474
  expect(step2Action).toHaveBeenCalled();
1184
- expect(result.steps.step1).toEqual({
1475
+ expect(result.steps.step1).toMatchObject({
1185
1476
  status: 'success',
1186
1477
  output: { count: 5 },
1187
1478
  });
1188
- expect(result.steps.step2).toEqual({
1479
+ expect(result.steps.step2).toMatchObject({
1189
1480
  status: 'success',
1190
- output: undefined,
1191
1481
  });
1192
1482
  });
1193
1483
  });
@@ -1245,7 +1535,7 @@ describe('MastraInngestWorkflow', () => {
1245
1535
  });
1246
1536
  await new Promise(resolve => setTimeout(resolve, 2000));
1247
1537
 
1248
- const run = workflow.createRun();
1538
+ const run = await workflow.createRunAsync();
1249
1539
 
1250
1540
  await expect(run.start({ inputData: {} })).resolves.toMatchObject({
1251
1541
  steps: {
@@ -1329,7 +1619,7 @@ describe('MastraInngestWorkflow', () => {
1329
1619
  });
1330
1620
  await new Promise(resolve => setTimeout(resolve, 2000));
1331
1621
 
1332
- const run = workflow.createRun();
1622
+ const run = await workflow.createRunAsync();
1333
1623
  const result = await run.start({ inputData: {} });
1334
1624
 
1335
1625
  expect(result.steps).toMatchObject({
@@ -1423,7 +1713,7 @@ describe('MastraInngestWorkflow', () => {
1423
1713
  });
1424
1714
  await new Promise(resolve => setTimeout(resolve, 2000));
1425
1715
 
1426
- const run = mainWorkflow.createRun();
1716
+ const run = await mainWorkflow.createRunAsync();
1427
1717
  const result = await run.start({ inputData: {} });
1428
1718
 
1429
1719
  expect(result.steps).toMatchObject({
@@ -1551,12 +1841,12 @@ describe('MastraInngestWorkflow', () => {
1551
1841
  });
1552
1842
  await new Promise(resolve => setTimeout(resolve, 2000));
1553
1843
 
1554
- const run = workflow.createRun();
1844
+ const run = await workflow.createRunAsync();
1555
1845
  const result = await run.start({ inputData: {} });
1556
1846
 
1557
1847
  expect(step2Action).toHaveBeenCalled();
1558
1848
  expect(step3Action).not.toHaveBeenCalled();
1559
- expect(result.steps.step2).toEqual({ status: 'success', output: { result: 'step2' } });
1849
+ expect(result.steps.step2).toMatchObject({ status: 'success', output: { result: 'step2' } });
1560
1850
 
1561
1851
  srv.close();
1562
1852
  });
@@ -1653,15 +1943,15 @@ describe('MastraInngestWorkflow', () => {
1653
1943
  });
1654
1944
  await new Promise(resolve => setTimeout(resolve, 2000));
1655
1945
 
1656
- const run = counterWorkflow.createRun();
1946
+ const run = await counterWorkflow.createRunAsync();
1657
1947
  const result = await run.start({ inputData: { target: 10, value: 0 } });
1658
1948
 
1659
1949
  expect(increment).toHaveBeenCalledTimes(12);
1660
1950
  expect(final).toHaveBeenCalledTimes(1);
1661
1951
  // @ts-ignore
1662
- expect(result.result).toEqual({ finalValue: 12 });
1952
+ expect(result.result).toMatchObject({ finalValue: 12 });
1663
1953
  // @ts-ignore
1664
- expect(result.steps.increment.output).toEqual({ value: 12 });
1954
+ expect(result.steps.increment.output).toMatchObject({ value: 12 });
1665
1955
 
1666
1956
  srv.close();
1667
1957
  });
@@ -1756,15 +2046,15 @@ describe('MastraInngestWorkflow', () => {
1756
2046
  });
1757
2047
  await new Promise(resolve => setTimeout(resolve, 2000));
1758
2048
 
1759
- const run = counterWorkflow.createRun();
2049
+ const run = await counterWorkflow.createRunAsync();
1760
2050
  const result = await run.start({ inputData: { target: 10, value: 0 } });
1761
2051
 
1762
2052
  expect(increment).toHaveBeenCalledTimes(12);
1763
2053
  expect(final).toHaveBeenCalledTimes(1);
1764
2054
  // @ts-ignore
1765
- expect(result.result).toEqual({ finalValue: 12 });
2055
+ expect(result.result).toMatchObject({ finalValue: 12 });
1766
2056
  // @ts-ignore
1767
- expect(result.steps.increment.output).toEqual({ value: 12 });
2057
+ expect(result.steps.increment.output).toMatchObject({ value: 12 });
1768
2058
 
1769
2059
  srv.close();
1770
2060
  });
@@ -1845,7 +2135,7 @@ describe('MastraInngestWorkflow', () => {
1845
2135
  });
1846
2136
  await new Promise(resolve => setTimeout(resolve, 2000));
1847
2137
 
1848
- const run = counterWorkflow.createRun();
2138
+ const run = await counterWorkflow.createRunAsync();
1849
2139
  const result = await run.start({ inputData: [{ value: 1 }, { value: 22 }, { value: 333 }] });
1850
2140
 
1851
2141
  const endTime = Date.now();
@@ -1853,7 +2143,7 @@ describe('MastraInngestWorkflow', () => {
1853
2143
  expect(duration).toBeGreaterThan(1e3 * 3);
1854
2144
 
1855
2145
  expect(map).toHaveBeenCalledTimes(3);
1856
- expect(result.steps).toEqual({
2146
+ expect(result.steps).toMatchObject({
1857
2147
  input: [{ value: 1 }, { value: 22 }, { value: 333 }],
1858
2148
  map: { status: 'success', output: [{ value: 12 }, { value: 33 }, { value: 344 }] },
1859
2149
  final: { status: 'success', output: { finalValue: 1 + 11 + (22 + 11) + (333 + 11) } },
@@ -1998,16 +2288,16 @@ describe('MastraInngestWorkflow', () => {
1998
2288
  });
1999
2289
  await new Promise(resolve => setTimeout(resolve, 2000));
2000
2290
 
2001
- const run = counterWorkflow.createRun();
2291
+ const run = await counterWorkflow.createRunAsync();
2002
2292
  const result = await run.start({ inputData: { startValue: 1 } });
2003
2293
 
2004
2294
  expect(start).toHaveBeenCalledTimes(1);
2005
2295
  expect(other).toHaveBeenCalledTimes(0);
2006
2296
  expect(final).toHaveBeenCalledTimes(1);
2007
2297
  // @ts-ignore
2008
- expect(result.steps.finalIf.output).toEqual({ finalValue: 2 });
2298
+ expect(result.steps.finalIf.output).toMatchObject({ finalValue: 2 });
2009
2299
  // @ts-ignore
2010
- expect(result.steps.start.output).toEqual({ newValue: 2 });
2300
+ expect(result.steps.start.output).toMatchObject({ newValue: 2 });
2011
2301
 
2012
2302
  srv.close();
2013
2303
  });
@@ -2147,16 +2437,16 @@ describe('MastraInngestWorkflow', () => {
2147
2437
  });
2148
2438
  await new Promise(resolve => setTimeout(resolve, 2000));
2149
2439
 
2150
- const run = counterWorkflow.createRun();
2440
+ const run = await counterWorkflow.createRunAsync();
2151
2441
  const result = await run.start({ inputData: { startValue: 6 } });
2152
2442
 
2153
2443
  expect(start).toHaveBeenCalledTimes(1);
2154
2444
  expect(other).toHaveBeenCalledTimes(1);
2155
2445
  expect(final).toHaveBeenCalledTimes(1);
2156
2446
  // @ts-ignore
2157
- expect(result.steps['else-branch'].output).toEqual({ finalValue: 26 + 6 + 1 });
2447
+ expect(result.steps['else-branch'].output).toMatchObject({ finalValue: 26 + 6 + 1 });
2158
2448
  // @ts-ignore
2159
- expect(result.steps.start.output).toEqual({ newValue: 7 });
2449
+ expect(result.steps.start.output).toMatchObject({ newValue: 7 });
2160
2450
 
2161
2451
  srv.close();
2162
2452
  });
@@ -2213,7 +2503,7 @@ describe('MastraInngestWorkflow', () => {
2213
2503
  ).rejects.toThrow();
2214
2504
 
2215
2505
  // Should pass validation
2216
- const run = workflow.createRun();
2506
+ const run = await workflow.createRunAsync();
2217
2507
  await run.start({
2218
2508
  inputData: {
2219
2509
  required: 'test',
@@ -2319,11 +2609,11 @@ describe('MastraInngestWorkflow', () => {
2319
2609
  });
2320
2610
  await new Promise(resolve => setTimeout(resolve, 2000));
2321
2611
 
2322
- const run = workflow.createRun();
2612
+ const run = await workflow.createRunAsync();
2323
2613
  const result = await run.start({ inputData: {} });
2324
2614
 
2325
- expect(result.steps['nested-a']).toEqual({ status: 'success', output: { result: 'success3' } });
2326
- expect(result.steps['nested-b']).toEqual({ status: 'success', output: { result: 'success5' } });
2615
+ expect(result.steps['nested-a']).toMatchObject({ status: 'success', output: { result: 'success3' } });
2616
+ expect(result.steps['nested-b']).toMatchObject({ status: 'success', output: { result: 'success5' } });
2327
2617
 
2328
2618
  srv.close();
2329
2619
  });
@@ -2385,11 +2675,11 @@ describe('MastraInngestWorkflow', () => {
2385
2675
  });
2386
2676
  await new Promise(resolve => setTimeout(resolve, 2000));
2387
2677
 
2388
- const run = workflow.createRun();
2678
+ const run = await workflow.createRunAsync();
2389
2679
  const result = await run.start({ inputData: {} });
2390
2680
 
2391
- expect(result.steps.step1).toEqual({ status: 'success', output: { result: 'success' } });
2392
- expect(result.steps.step2).toEqual({ status: 'failed', error: 'Step failed' });
2681
+ expect(result.steps.step1).toMatchObject({ status: 'success', output: { result: 'success' } });
2682
+ expect(result.steps.step2).toMatchObject({ status: 'failed', error: 'Step failed' });
2393
2683
  expect(step1.execute).toHaveBeenCalledTimes(1);
2394
2684
  expect(step2.execute).toHaveBeenCalledTimes(1); // 0 retries + 1 initial call
2395
2685
 
@@ -2442,11 +2732,11 @@ describe('MastraInngestWorkflow', () => {
2442
2732
 
2443
2733
  workflow.then(step1).then(step2).commit();
2444
2734
 
2445
- const run = workflow.createRun();
2735
+ const run = await workflow.createRunAsync();
2446
2736
  const result = await run.start({ inputData: {} });
2447
2737
 
2448
- expect(result.steps.step1).toEqual({ status: 'success', output: { result: 'success' } });
2449
- expect(result.steps.step2).toEqual({ status: 'failed', error: 'Step failed' });
2738
+ expect(result.steps.step1).toMatchObject({ status: 'success', output: { result: 'success' } });
2739
+ expect(result.steps.step2).toMatchObject({ status: 'failed', error: 'Step failed' });
2450
2740
  expect(step1.execute).toHaveBeenCalledTimes(1);
2451
2741
  expect(step2.execute).toHaveBeenCalledTimes(6); // 5 retries + 1 initial call
2452
2742
  });
@@ -2517,14 +2807,15 @@ describe('MastraInngestWorkflow', () => {
2517
2807
  });
2518
2808
  await new Promise(resolve => setTimeout(resolve, 2000));
2519
2809
 
2520
- const result = await workflow.createRun().start({ inputData: {} });
2810
+ const run = await workflow.createRunAsync();
2811
+ const result = await run.start({ inputData: {} });
2521
2812
 
2522
2813
  srv.close();
2523
2814
 
2524
2815
  expect(step1Action).toHaveBeenCalled();
2525
2816
  expect(toolAction).toHaveBeenCalled();
2526
- expect(result.steps.step1).toEqual({ status: 'success', output: { name: 'step1' } });
2527
- expect(result.steps['random-tool']).toEqual({ status: 'success', output: { name: 'step1' } });
2817
+ expect(result.steps.step1).toMatchObject({ status: 'success', output: { name: 'step1' } });
2818
+ expect(result.steps['random-tool']).toMatchObject({ status: 'success', output: { name: 'step1' } });
2528
2819
  }, 10000);
2529
2820
  });
2530
2821
 
@@ -2588,7 +2879,7 @@ describe('MastraInngestWorkflow', () => {
2588
2879
  });
2589
2880
  await new Promise(resolve => setTimeout(resolve, 2000));
2590
2881
 
2591
- const run = workflow.createRun();
2882
+ const run = await workflow.createRunAsync();
2592
2883
 
2593
2884
  // Start watching the workflow
2594
2885
  let cnt = 0;
@@ -2703,11 +2994,11 @@ describe('MastraInngestWorkflow', () => {
2703
2994
  });
2704
2995
 
2705
2996
  // Verify execution completed successfully
2706
- expect(executionResult.steps.step1).toEqual({
2997
+ expect(executionResult.steps.step1).toMatchObject({
2707
2998
  status: 'success',
2708
2999
  output: { result: 'success1' },
2709
3000
  });
2710
- expect(executionResult.steps.step2).toEqual({
3001
+ expect(executionResult.steps.step2).toMatchObject({
2711
3002
  status: 'success',
2712
3003
  output: { result: 'success2' },
2713
3004
  });
@@ -2777,7 +3068,7 @@ describe('MastraInngestWorkflow', () => {
2777
3068
  const onTransition = vi.fn();
2778
3069
  const onTransition2 = vi.fn();
2779
3070
 
2780
- const run = workflow.createRun();
3071
+ const run = await workflow.createRunAsync();
2781
3072
 
2782
3073
  run.watch(onTransition);
2783
3074
  run.watch(onTransition2);
@@ -2787,7 +3078,7 @@ describe('MastraInngestWorkflow', () => {
2787
3078
  expect(onTransition).toHaveBeenCalledTimes(5);
2788
3079
  expect(onTransition2).toHaveBeenCalledTimes(5);
2789
3080
 
2790
- const run2 = workflow.createRun();
3081
+ const run2 = await workflow.createRunAsync();
2791
3082
 
2792
3083
  run2.watch(onTransition2);
2793
3084
 
@@ -2796,7 +3087,7 @@ describe('MastraInngestWorkflow', () => {
2796
3087
  expect(onTransition).toHaveBeenCalledTimes(5);
2797
3088
  expect(onTransition2).toHaveBeenCalledTimes(10);
2798
3089
 
2799
- const run3 = workflow.createRun();
3090
+ const run3 = await workflow.createRunAsync();
2800
3091
 
2801
3092
  run3.watch(onTransition);
2802
3093
 
@@ -2831,8 +3122,8 @@ describe('MastraInngestWorkflow', () => {
2831
3122
  outputSchema: z.object({}),
2832
3123
  steps: [],
2833
3124
  });
2834
- const run = workflow.createRun();
2835
- const run2 = workflow.createRun({ runId: run.runId });
3125
+ const run = await workflow.createRunAsync();
3126
+ const run2 = await workflow.createRunAsync({ runId: run.runId });
2836
3127
 
2837
3128
  expect(run.runId).toBeDefined();
2838
3129
  expect(run2.runId).toBeDefined();
@@ -2946,7 +3237,7 @@ describe('MastraInngestWorkflow', () => {
2946
3237
  });
2947
3238
  await new Promise(resolve => setTimeout(resolve, 2000));
2948
3239
 
2949
- const run = promptEvalWorkflow.createRun();
3240
+ const run = await promptEvalWorkflow.createRunAsync();
2950
3241
 
2951
3242
  // Create a promise to track when the workflow is ready to resume
2952
3243
  let resolveWorkflowSuspended: (value: unknown) => void;
@@ -2976,7 +3267,7 @@ describe('MastraInngestWorkflow', () => {
2976
3267
  throw new Error('Resume failed to return a result');
2977
3268
  }
2978
3269
 
2979
- expect(resumeResult.steps).toEqual({
3270
+ expect(resumeResult.steps).toMatchObject({
2980
3271
  input: { input: 'test' },
2981
3272
  getUserInput: { status: 'success', output: { userInput: 'test input' } },
2982
3273
  promptAgent: { status: 'success', output: { modelOutput: 'test output' } },
@@ -3096,7 +3387,7 @@ describe('MastraInngestWorkflow', () => {
3096
3387
  });
3097
3388
  await new Promise(resolve => setTimeout(resolve, 2000));
3098
3389
 
3099
- const run = workflow.createRun();
3390
+ const run = await workflow.createRunAsync();
3100
3391
 
3101
3392
  const started = run.start({ inputData: { input: 'test' } });
3102
3393
 
@@ -3139,7 +3430,7 @@ describe('MastraInngestWorkflow', () => {
3139
3430
  throw new Error('Resume failed to return a result');
3140
3431
  }
3141
3432
 
3142
- expect(result.steps).toEqual({
3433
+ expect(result.steps).toMatchObject({
3143
3434
  input: { input: 'test' },
3144
3435
  getUserInput: { status: 'success', output: { userInput: 'test input' } },
3145
3436
  promptAgent: { status: 'success', output: { modelOutput: 'test output' } },
@@ -3298,7 +3589,7 @@ describe('MastraInngestWorkflow', () => {
3298
3589
  });
3299
3590
  await new Promise(resolve => setTimeout(resolve, 2000));
3300
3591
 
3301
- const run = workflow.createRun();
3592
+ const run = await workflow.createRunAsync();
3302
3593
  const started = run.start({ inputData: { input: 'test' } });
3303
3594
  let improvedResponseResultPromise: Promise<any | undefined>;
3304
3595
 
@@ -3492,18 +3783,22 @@ describe('MastraInngestWorkflow', () => {
3492
3783
  });
3493
3784
  await new Promise(resolve => setTimeout(resolve, 2000));
3494
3785
 
3495
- const run = promptEvalWorkflow.createRun();
3786
+ const run = await promptEvalWorkflow.createRunAsync();
3496
3787
 
3497
3788
  const initialResult = await run.start({ inputData: { input: 'test' } });
3498
3789
  expect(initialResult.steps.promptAgent.status).toBe('suspended');
3499
3790
  expect(promptAgentAction).toHaveBeenCalledTimes(1);
3500
3791
  // expect(initialResult.activePaths.size).toBe(1);
3501
3792
  // expect(initialResult.activePaths.get('promptAgent')?.status).toBe('suspended');
3502
- // expect(initialResult.activePaths.get('promptAgent')?.suspendPayload).toEqual({ testPayload: 'hello' });
3503
- expect(initialResult.steps).toEqual({
3793
+ // expect(initialResult.activePaths.get('promptAgent')?.suspendPayload).toMatchObject({ testPayload: 'hello' });
3794
+ expect(initialResult.steps).toMatchObject({
3504
3795
  input: { input: 'test' },
3505
3796
  getUserInput: { status: 'success', output: { userInput: 'test input' } },
3506
- promptAgent: { status: 'suspended', payload: { testPayload: 'hello' } },
3797
+ promptAgent: {
3798
+ status: 'suspended',
3799
+ suspendedPayload: { testPayload: 'hello' },
3800
+ payload: { userInput: 'test input' },
3801
+ },
3507
3802
  });
3508
3803
 
3509
3804
  const newCtx = {
@@ -3520,7 +3815,7 @@ describe('MastraInngestWorkflow', () => {
3520
3815
 
3521
3816
  // expect(firstResumeResult.activePaths.size).toBe(1);
3522
3817
  // expect(firstResumeResult.activePaths.get('improveResponse')?.status).toBe('suspended');
3523
- expect(firstResumeResult.steps).toEqual({
3818
+ expect(firstResumeResult.steps).toMatchObject({
3524
3819
  input: { input: 'test' },
3525
3820
  getUserInput: { status: 'success', output: { userInput: 'test input' } },
3526
3821
  promptAgent: { status: 'success', output: { modelOutput: 'test output' } },
@@ -3547,7 +3842,7 @@ describe('MastraInngestWorkflow', () => {
3547
3842
 
3548
3843
  expect(promptAgentAction).toHaveBeenCalledTimes(2);
3549
3844
 
3550
- expect(secondResumeResult.steps).toEqual({
3845
+ expect(secondResumeResult.steps).toMatchObject({
3551
3846
  input: { input: 'test' },
3552
3847
  getUserInput: { status: 'success', output: { userInput: 'test input' } },
3553
3848
  promptAgent: { status: 'success', output: { modelOutput: 'test output' } },
@@ -3617,7 +3912,7 @@ describe('MastraInngestWorkflow', () => {
3617
3912
  await new Promise(resolve => setTimeout(resolve, 2000));
3618
3913
 
3619
3914
  // Access new instance properties directly - should work without warning
3620
- const run = workflow.createRun();
3915
+ const run = await workflow.createRunAsync();
3621
3916
  await run.start({ inputData: {} });
3622
3917
 
3623
3918
  expect(telemetry).toBeDefined();
@@ -3632,6 +3927,7 @@ describe('MastraInngestWorkflow', () => {
3632
3927
  const inngest = new Inngest({
3633
3928
  id: 'mastra',
3634
3929
  baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
3930
+ middleware: [realtimeMiddleware()],
3635
3931
  });
3636
3932
 
3637
3933
  const { createWorkflow, createStep } = init(inngest);
@@ -3719,28 +4015,29 @@ describe('MastraInngestWorkflow', () => {
3719
4015
  });
3720
4016
  await new Promise(resolve => setTimeout(resolve, 2000));
3721
4017
 
3722
- const run = workflow.createRun();
4018
+ const run = await workflow.createRunAsync();
3723
4019
  const result = await run.start({
3724
4020
  inputData: { prompt1: 'Capital of France, just the name', prompt2: 'Capital of UK, just the name' },
3725
4021
  });
3726
4022
 
3727
- expect(result.steps['test-agent-1']).toEqual({
4023
+ srv.close();
4024
+
4025
+ expect(result.steps['test-agent-1']).toMatchObject({
3728
4026
  status: 'success',
3729
4027
  output: { text: 'Paris' },
3730
4028
  });
3731
4029
 
3732
- expect(result.steps['test-agent-2']).toEqual({
4030
+ expect(result.steps['test-agent-2']).toMatchObject({
3733
4031
  status: 'success',
3734
4032
  output: { text: 'London' },
3735
4033
  });
3736
-
3737
- srv.close();
3738
4034
  });
3739
4035
 
3740
4036
  it('should be able to use an agent in parallel', async ctx => {
3741
4037
  const inngest = new Inngest({
3742
4038
  id: 'mastra',
3743
4039
  baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
4040
+ middleware: [realtimeMiddleware()],
3744
4041
  });
3745
4042
 
3746
4043
  const { createWorkflow, createStep } = init(inngest);
@@ -3855,23 +4152,23 @@ describe('MastraInngestWorkflow', () => {
3855
4152
  });
3856
4153
  await new Promise(resolve => setTimeout(resolve, 2000));
3857
4154
 
3858
- const run = workflow.createRun();
4155
+ const run = await workflow.createRunAsync();
3859
4156
  const result = await run.start({
3860
4157
  inputData: { prompt1: 'Capital of France, just the name', prompt2: 'Capital of UK, just the name' },
3861
4158
  });
3862
4159
 
3863
4160
  expect(execute).toHaveBeenCalledTimes(1);
3864
- expect(result.steps['finalStep']).toEqual({
4161
+ expect(result.steps['finalStep']).toMatchObject({
3865
4162
  status: 'success',
3866
4163
  output: { result: 'success' },
3867
4164
  });
3868
4165
 
3869
- expect(result.steps['nested-workflow']).toEqual({
4166
+ expect(result.steps['nested-workflow']).toMatchObject({
3870
4167
  status: 'success',
3871
4168
  output: { text: 'Paris' },
3872
4169
  });
3873
4170
 
3874
- expect(result.steps['nested-workflow-2']).toEqual({
4171
+ expect(result.steps['nested-workflow-2']).toMatchObject({
3875
4172
  status: 'success',
3876
4173
  output: { text: 'London' },
3877
4174
  });
@@ -3998,7 +4295,7 @@ describe('MastraInngestWorkflow', () => {
3998
4295
  });
3999
4296
  await new Promise(resolve => setTimeout(resolve, 2000));
4000
4297
 
4001
- const run = counterWorkflow.createRun();
4298
+ const run = await counterWorkflow.createRunAsync();
4002
4299
  const result = await run.start({ inputData: { startValue: 0 } });
4003
4300
 
4004
4301
  srv.close();
@@ -4008,16 +4305,16 @@ describe('MastraInngestWorkflow', () => {
4008
4305
  expect(final).toHaveBeenCalledTimes(2);
4009
4306
  expect(last).toHaveBeenCalledTimes(1);
4010
4307
  // @ts-ignore
4011
- expect(result.steps['nested-workflow-a'].output).toEqual({
4308
+ expect(result.steps['nested-workflow-a'].output).toMatchObject({
4012
4309
  finalValue: 26 + 1,
4013
4310
  });
4014
4311
 
4015
4312
  // @ts-ignore
4016
- expect(result.steps['nested-workflow-b'].output).toEqual({
4313
+ expect(result.steps['nested-workflow-b'].output).toMatchObject({
4017
4314
  finalValue: 1,
4018
4315
  });
4019
4316
 
4020
- expect(result.steps['last-step']).toEqual({
4317
+ expect(result.steps['last-step']).toMatchObject({
4021
4318
  output: { success: true },
4022
4319
  status: 'success',
4023
4320
  });
@@ -4150,7 +4447,7 @@ describe('MastraInngestWorkflow', () => {
4150
4447
  });
4151
4448
  await new Promise(resolve => setTimeout(resolve, 2000));
4152
4449
 
4153
- const run = counterWorkflow.createRun();
4450
+ const run = await counterWorkflow.createRunAsync();
4154
4451
  const result = await run.start({ inputData: { startValue: 0 } });
4155
4452
 
4156
4453
  srv.close();
@@ -4160,16 +4457,16 @@ describe('MastraInngestWorkflow', () => {
4160
4457
  expect(final).toHaveBeenCalledTimes(2);
4161
4458
  expect(last).toHaveBeenCalledTimes(1);
4162
4459
  // @ts-ignore
4163
- expect(result.steps['nested-workflow-a'].output).toEqual({
4460
+ expect(result.steps['nested-workflow-a'].output).toMatchObject({
4164
4461
  finalValue: 26 + 1,
4165
4462
  });
4166
4463
 
4167
4464
  // @ts-ignore
4168
- expect(result.steps['nested-workflow-b'].output).toEqual({
4465
+ expect(result.steps['nested-workflow-b'].output).toMatchObject({
4169
4466
  finalValue: 1,
4170
4467
  });
4171
4468
 
4172
- expect(result.steps['last-step']).toEqual({
4469
+ expect(result.steps['last-step']).toMatchObject({
4173
4470
  output: { success: true },
4174
4471
  status: 'success',
4175
4472
  });
@@ -4309,7 +4606,7 @@ describe('MastraInngestWorkflow', () => {
4309
4606
  port: (ctx as any).handlerPort,
4310
4607
  });
4311
4608
 
4312
- const run = counterWorkflow.createRun();
4609
+ const run = await counterWorkflow.createRunAsync();
4313
4610
  const result = await run.start({ inputData: { startValue: 0 } });
4314
4611
 
4315
4612
  srv.close();
@@ -4320,16 +4617,16 @@ describe('MastraInngestWorkflow', () => {
4320
4617
  expect(first).toHaveBeenCalledTimes(1);
4321
4618
  expect(last).toHaveBeenCalledTimes(1);
4322
4619
  // @ts-ignore
4323
- expect(result.steps['nested-workflow-a'].output).toEqual({
4620
+ expect(result.steps['nested-workflow-a'].output).toMatchObject({
4324
4621
  finalValue: 26 + 1,
4325
4622
  });
4326
4623
 
4327
- expect(result.steps['first-step']).toEqual({
4624
+ expect(result.steps['first-step']).toMatchObject({
4328
4625
  output: { success: true },
4329
4626
  status: 'success',
4330
4627
  });
4331
4628
 
4332
- expect(result.steps['last-step']).toEqual({
4629
+ expect(result.steps['last-step']).toMatchObject({
4333
4630
  output: { success: true },
4334
4631
  status: 'success',
4335
4632
  });
@@ -4468,7 +4765,7 @@ describe('MastraInngestWorkflow', () => {
4468
4765
  port: (ctx as any).handlerPort,
4469
4766
  });
4470
4767
 
4471
- const run = counterWorkflow.createRun();
4768
+ const run = await counterWorkflow.createRunAsync();
4472
4769
  const result = await run.start({ inputData: { startValue: 0 } });
4473
4770
 
4474
4771
  srv.close();
@@ -4480,16 +4777,16 @@ describe('MastraInngestWorkflow', () => {
4480
4777
  expect(last).toHaveBeenCalledTimes(1);
4481
4778
 
4482
4779
  // @ts-ignore
4483
- expect(result.steps['nested-workflow-b'].output).toEqual({
4780
+ expect(result.steps['nested-workflow-b'].output).toMatchObject({
4484
4781
  finalValue: 1,
4485
4782
  });
4486
4783
 
4487
- expect(result.steps['first-step']).toEqual({
4784
+ expect(result.steps['first-step']).toMatchObject({
4488
4785
  output: { success: true },
4489
4786
  status: 'success',
4490
4787
  });
4491
4788
 
4492
- expect(result.steps['last-step']).toEqual({
4789
+ expect(result.steps['last-step']).toMatchObject({
4493
4790
  output: { success: true },
4494
4791
  status: 'success',
4495
4792
  });
@@ -4665,7 +4962,7 @@ describe('MastraInngestWorkflow', () => {
4665
4962
  port: (ctx as any).handlerPort,
4666
4963
  });
4667
4964
 
4668
- const run = counterWorkflow.createRun();
4965
+ const run = await counterWorkflow.createRunAsync();
4669
4966
  const result = await run.start({ inputData: { startValue: 1 } });
4670
4967
 
4671
4968
  srv.close();
@@ -4677,16 +4974,16 @@ describe('MastraInngestWorkflow', () => {
4677
4974
  // expect(last).toHaveBeenCalledTimes(1);
4678
4975
 
4679
4976
  // @ts-ignore
4680
- expect(result.steps['nested-workflow-b'].output).toEqual({
4977
+ expect(result.steps['nested-workflow-b'].output).toMatchObject({
4681
4978
  finalValue: 1,
4682
4979
  });
4683
4980
 
4684
- expect(result.steps['first-step']).toEqual({
4981
+ expect(result.steps['first-step']).toMatchObject({
4685
4982
  output: { success: true },
4686
4983
  status: 'success',
4687
4984
  });
4688
4985
 
4689
- expect(result.steps['last-step']).toEqual({
4986
+ expect(result.steps['last-step']).toMatchObject({
4690
4987
  output: { success: true },
4691
4988
  status: 'success',
4692
4989
  });
@@ -4819,7 +5116,7 @@ describe('MastraInngestWorkflow', () => {
4819
5116
  });
4820
5117
  await new Promise(resolve => setTimeout(resolve, 2000));
4821
5118
 
4822
- const run = counterWorkflow.createRun();
5119
+ const run = await counterWorkflow.createRunAsync();
4823
5120
  const result = await run.start({ inputData: { startValue: 0 } });
4824
5121
 
4825
5122
  expect(begin).toHaveBeenCalledTimes(1);
@@ -4832,12 +5129,12 @@ describe('MastraInngestWorkflow', () => {
4832
5129
  });
4833
5130
 
4834
5131
  // @ts-ignore
4835
- expect(result.steps['last-step']).toEqual(undefined);
5132
+ expect(result.steps['last-step']).toMatchObject(undefined);
4836
5133
 
4837
5134
  const resumedResults = await run.resume({ step: [wfA, otherStep], resumeData: { newValue: 0 } });
4838
5135
 
4839
5136
  // @ts-ignore
4840
- expect(resumedResults.steps['nested-workflow-a'].output).toEqual({
5137
+ expect(resumedResults.steps['nested-workflow-a'].output).toMatchObject({
4841
5138
  finalValue: 26 + 1,
4842
5139
  });
4843
5140
 
@@ -4969,7 +5266,7 @@ describe('MastraInngestWorkflow', () => {
4969
5266
  port: (ctx as any).handlerPort,
4970
5267
  });
4971
5268
 
4972
- const run = counterWorkflow.createRun();
5269
+ const run = await counterWorkflow.createRunAsync();
4973
5270
  const result = await run.start({ inputData: { startValue: 0 } });
4974
5271
  const results = result.steps;
4975
5272
 
@@ -4988,7 +5285,7 @@ describe('MastraInngestWorkflow', () => {
4988
5285
  },
4989
5286
  });
4990
5287
 
4991
- expect(result.steps['last-step']).toEqual({
5288
+ expect(result.steps['last-step']).toMatchObject({
4992
5289
  status: 'success',
4993
5290
  output: { success: true },
4994
5291
  });
@@ -5151,7 +5448,7 @@ describe('MastraInngestWorkflow', () => {
5151
5448
  });
5152
5449
  await new Promise(resolve => setTimeout(resolve, 2000));
5153
5450
 
5154
- const run = counterWorkflow.createRun();
5451
+ const run = await counterWorkflow.createRunAsync();
5155
5452
  const result = await run.start({ inputData: { startValue: 0 } });
5156
5453
 
5157
5454
  expect(passthroughStep.execute).toHaveBeenCalledTimes(2);
@@ -5165,18 +5462,23 @@ describe('MastraInngestWorkflow', () => {
5165
5462
  });
5166
5463
 
5167
5464
  // @ts-ignore
5168
- expect(result.steps['last-step']).toEqual(undefined);
5465
+ expect(result.steps['last-step']).toMatchObject(undefined);
5169
5466
 
5170
5467
  if (result.status !== 'suspended') {
5171
5468
  expect.fail('Workflow should be suspended');
5172
5469
  }
5173
- expect(result.suspended[0]).toEqual(['nested-workflow-c', 'nested-workflow-b', 'nested-workflow-a', 'other']);
5470
+ expect(result.suspended[0]).toMatchObject([
5471
+ 'nested-workflow-c',
5472
+ 'nested-workflow-b',
5473
+ 'nested-workflow-a',
5474
+ 'other',
5475
+ ]);
5174
5476
  const resumedResults = await run.resume({ step: result.suspended[0], resumeData: { newValue: 0 } });
5175
5477
 
5176
5478
  srv.close();
5177
5479
 
5178
5480
  // @ts-ignore
5179
- expect(resumedResults.steps['nested-workflow-c'].output).toEqual({
5481
+ expect(resumedResults.steps['nested-workflow-c'].output).toMatchObject({
5180
5482
  finalValue: 26 + 1,
5181
5483
  });
5182
5484
 
@@ -5308,7 +5610,7 @@ describe('MastraInngestWorkflow', () => {
5308
5610
  });
5309
5611
  await new Promise(resolve => setTimeout(resolve, 2000));
5310
5612
 
5311
- const run = counterWorkflow.createRun();
5613
+ const run = await counterWorkflow.createRunAsync();
5312
5614
  const result = await run.start({ inputData: { startValue: 0 } });
5313
5615
 
5314
5616
  srv.close();
@@ -5318,16 +5620,16 @@ describe('MastraInngestWorkflow', () => {
5318
5620
  expect(final).toHaveBeenCalledTimes(2);
5319
5621
  expect(last).toHaveBeenCalledTimes(1);
5320
5622
  // @ts-ignore
5321
- expect(result.steps['nested-workflow-a-clone'].output).toEqual({
5623
+ expect(result.steps['nested-workflow-a-clone'].output).toMatchObject({
5322
5624
  finalValue: 26 + 1,
5323
5625
  });
5324
5626
 
5325
5627
  // @ts-ignore
5326
- expect(result.steps['nested-workflow-b'].output).toEqual({
5628
+ expect(result.steps['nested-workflow-b'].output).toMatchObject({
5327
5629
  finalValue: 1,
5328
5630
  });
5329
5631
 
5330
- expect(result.steps['last-step']).toEqual({
5632
+ expect(result.steps['last-step']).toMatchObject({
5331
5633
  output: { success: true },
5332
5634
  status: 'success',
5333
5635
  });
@@ -5384,7 +5686,7 @@ describe('MastraInngestWorkflow', () => {
5384
5686
  await new Promise(resolve => setTimeout(resolve, 2000));
5385
5687
 
5386
5688
  // Access new instance properties directly - should work without warning
5387
- const run = workflow.createRun();
5689
+ const run = await workflow.createRunAsync();
5388
5690
  await run.start({ inputData: {} });
5389
5691
 
5390
5692
  srv.close();
@@ -5445,7 +5747,7 @@ describe('MastraInngestWorkflow', () => {
5445
5747
  port: (ctx as any).handlerPort,
5446
5748
  });
5447
5749
 
5448
- const run = workflow.createRun();
5750
+ const run = await workflow.createRunAsync();
5449
5751
  const result = await run.start({ runtimeContext });
5450
5752
 
5451
5753
  srv.close();
@@ -5498,7 +5800,7 @@ describe('MastraInngestWorkflow', () => {
5498
5800
  });
5499
5801
  workflow.then(step).commit();
5500
5802
 
5501
- const run = workflow.createRun();
5803
+ const run = await workflow.createRunAsync();
5502
5804
  await run.start({ runtimeContext });
5503
5805
 
5504
5806
  const resumeruntimeContext = new RuntimeContext();
@@ -5517,5 +5819,1049 @@ describe('MastraInngestWorkflow', () => {
5517
5819
  });
5518
5820
  });
5519
5821
 
5520
- describe('Access to inngest step primitives', () => {});
5822
+ describe('Access to inngest step primitives', () => {
5823
+ it('should inject inngest step primitives into steps during run', async ctx => {
5824
+ const inngest = new Inngest({
5825
+ id: 'mastra',
5826
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
5827
+ });
5828
+
5829
+ const { createWorkflow, createStep } = init(inngest);
5830
+
5831
+ const step = createStep({
5832
+ id: 'step1',
5833
+ execute: async ({ engine }) => {
5834
+ return {
5835
+ hasEngine: !!engine.step,
5836
+ };
5837
+ },
5838
+ inputSchema: z.object({}),
5839
+ outputSchema: z.object({}),
5840
+ });
5841
+ const workflow = createWorkflow({
5842
+ id: 'test-workflow',
5843
+ inputSchema: z.object({}),
5844
+ outputSchema: z.object({
5845
+ hasEngine: z.boolean(),
5846
+ }),
5847
+ });
5848
+ workflow.then(step).commit();
5849
+
5850
+ const mastra = new Mastra({
5851
+ storage: new DefaultStorage({
5852
+ url: ':memory:',
5853
+ }),
5854
+ workflows: {
5855
+ 'test-workflow': workflow,
5856
+ },
5857
+ server: {
5858
+ apiRoutes: [
5859
+ {
5860
+ path: '/inngest/api',
5861
+ method: 'ALL',
5862
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
5863
+ },
5864
+ ],
5865
+ },
5866
+ });
5867
+
5868
+ const app = await createHonoServer(mastra);
5869
+
5870
+ const srv = serve({
5871
+ fetch: app.fetch,
5872
+ port: (ctx as any).handlerPort,
5873
+ });
5874
+
5875
+ const run = await workflow.createRunAsync();
5876
+ const result = await run.start({});
5877
+
5878
+ srv.close();
5879
+
5880
+ // @ts-ignore
5881
+ expect(result?.steps.step1.output.hasEngine).toBe(true);
5882
+ });
5883
+ });
5884
+
5885
+ describe('Streaming', () => {
5886
+ it('should generate a stream', async ctx => {
5887
+ const inngest = new Inngest({
5888
+ id: 'mastra',
5889
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
5890
+ middleware: [realtimeMiddleware()],
5891
+ });
5892
+
5893
+ const { createWorkflow, createStep } = init(inngest);
5894
+
5895
+ const step1Action = vi.fn<any>().mockResolvedValue({ result: 'success1' });
5896
+ const step2Action = vi.fn<any>().mockResolvedValue({ result: 'success2' });
5897
+
5898
+ const step1 = createStep({
5899
+ id: 'step1',
5900
+ execute: step1Action,
5901
+ inputSchema: z.object({}),
5902
+ outputSchema: z.object({ value: z.string() }),
5903
+ });
5904
+ const step2 = createStep({
5905
+ id: 'step2',
5906
+ execute: step2Action,
5907
+ inputSchema: z.object({ value: z.string() }),
5908
+ outputSchema: z.object({}),
5909
+ });
5910
+
5911
+ const workflow = createWorkflow({
5912
+ id: 'test-workflow',
5913
+ inputSchema: z.object({}),
5914
+ outputSchema: z.object({}),
5915
+ steps: [step1, step2],
5916
+ });
5917
+ workflow.then(step1).then(step2).commit();
5918
+
5919
+ const mastra = new Mastra({
5920
+ storage: new DefaultStorage({
5921
+ url: ':memory:',
5922
+ }),
5923
+ workflows: {
5924
+ 'test-workflow': workflow,
5925
+ },
5926
+ server: {
5927
+ apiRoutes: [
5928
+ {
5929
+ path: '/inngest/api',
5930
+ method: 'ALL',
5931
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
5932
+ },
5933
+ ],
5934
+ },
5935
+ });
5936
+
5937
+ const app = await createHonoServer(mastra);
5938
+
5939
+ const srv = serve({
5940
+ fetch: app.fetch,
5941
+ port: (ctx as any).handlerPort,
5942
+ });
5943
+
5944
+ const runId = 'test-run-id';
5945
+ let watchData: StreamEvent[] = [];
5946
+ const run = await workflow.createRunAsync({
5947
+ runId,
5948
+ });
5949
+
5950
+ await new Promise(resolve => setTimeout(resolve, 1000));
5951
+
5952
+ const { stream, getWorkflowState } = run.stream({ inputData: {} });
5953
+
5954
+ // Start watching the workflow
5955
+ const collectedStreamData: StreamEvent[] = [];
5956
+ for await (const data of stream) {
5957
+ collectedStreamData.push(JSON.parse(JSON.stringify(data)));
5958
+ }
5959
+ watchData = collectedStreamData;
5960
+
5961
+ const executionResult = await getWorkflowState();
5962
+
5963
+ await new Promise(resolve => setTimeout(resolve, 1000));
5964
+
5965
+ srv.close();
5966
+
5967
+ expect(watchData.length).toBe(8);
5968
+ expect(watchData).toMatchInlineSnapshot(`
5969
+ [
5970
+ {
5971
+ "payload": {
5972
+ "runId": "test-run-id",
5973
+ },
5974
+ "type": "start",
5975
+ },
5976
+ {
5977
+ "payload": {
5978
+ "id": "step1",
5979
+ },
5980
+ "type": "step-start",
5981
+ },
5982
+ {
5983
+ "payload": {
5984
+ "id": "step1",
5985
+ "output": {
5986
+ "result": "success1",
5987
+ },
5988
+ "status": "success",
5989
+ },
5990
+ "type": "step-result",
5991
+ },
5992
+ {
5993
+ "payload": {
5994
+ "id": "step1",
5995
+ "metadata": {},
5996
+ },
5997
+ "type": "step-finish",
5998
+ },
5999
+ {
6000
+ "payload": {
6001
+ "id": "step2",
6002
+ },
6003
+ "type": "step-start",
6004
+ },
6005
+ {
6006
+ "payload": {
6007
+ "id": "step2",
6008
+ "output": {
6009
+ "result": "success2",
6010
+ },
6011
+ "status": "success",
6012
+ },
6013
+ "type": "step-result",
6014
+ },
6015
+ {
6016
+ "payload": {
6017
+ "id": "step2",
6018
+ "metadata": {},
6019
+ },
6020
+ "type": "step-finish",
6021
+ },
6022
+ {
6023
+ "payload": {
6024
+ "runId": "test-run-id",
6025
+ },
6026
+ "type": "finish",
6027
+ },
6028
+ ]
6029
+ `);
6030
+ // Verify execution completed successfully
6031
+ expect(executionResult.steps.step1).toMatchObject({
6032
+ status: 'success',
6033
+ output: { result: 'success1' },
6034
+ payload: {},
6035
+ startedAt: expect.any(Number),
6036
+ endedAt: expect.any(Number),
6037
+ });
6038
+ expect(executionResult.steps.step2).toMatchObject({
6039
+ status: 'success',
6040
+ output: { result: 'success2' },
6041
+ payload: {
6042
+ result: 'success1',
6043
+ },
6044
+ startedAt: expect.any(Number),
6045
+ endedAt: expect.any(Number),
6046
+ });
6047
+ });
6048
+
6049
+ it('should handle basic sleep waiting flow', async ctx => {
6050
+ const inngest = new Inngest({
6051
+ id: 'mastra',
6052
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
6053
+ middleware: [realtimeMiddleware()],
6054
+ });
6055
+
6056
+ const { createWorkflow, createStep } = init(inngest);
6057
+
6058
+ const step1Action = vi.fn<any>().mockResolvedValue({ result: 'success1' });
6059
+ const step2Action = vi.fn<any>().mockResolvedValue({ result: 'success2' });
6060
+
6061
+ const step1 = createStep({
6062
+ id: 'step1',
6063
+ execute: step1Action,
6064
+ inputSchema: z.object({}),
6065
+ outputSchema: z.object({ value: z.string() }),
6066
+ });
6067
+ const step2 = createStep({
6068
+ id: 'step2',
6069
+ execute: step2Action,
6070
+ inputSchema: z.object({ value: z.string() }),
6071
+ outputSchema: z.object({}),
6072
+ });
6073
+
6074
+ const workflow = createWorkflow({
6075
+ id: 'test-workflow',
6076
+ inputSchema: z.object({}),
6077
+ outputSchema: z.object({}),
6078
+ steps: [step1, step2],
6079
+ });
6080
+ workflow.then(step1).sleep(1000).then(step2).commit();
6081
+
6082
+ const mastra = new Mastra({
6083
+ storage: new DefaultStorage({
6084
+ url: ':memory:',
6085
+ }),
6086
+ workflows: {
6087
+ 'test-workflow': workflow,
6088
+ },
6089
+ server: {
6090
+ apiRoutes: [
6091
+ {
6092
+ path: '/inngest/api',
6093
+ method: 'ALL',
6094
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
6095
+ },
6096
+ ],
6097
+ },
6098
+ });
6099
+
6100
+ const app = await createHonoServer(mastra);
6101
+
6102
+ const srv = serve({
6103
+ fetch: app.fetch,
6104
+ port: (ctx as any).handlerPort,
6105
+ });
6106
+
6107
+ const runId = 'test-run-id';
6108
+ let watchData: StreamEvent[] = [];
6109
+ const run = await workflow.createRunAsync({
6110
+ runId,
6111
+ });
6112
+
6113
+ await new Promise(resolve => setTimeout(resolve, 1000));
6114
+
6115
+ const { stream, getWorkflowState } = run.stream({ inputData: {} });
6116
+
6117
+ // Start watching the workflow
6118
+ const collectedStreamData: StreamEvent[] = [];
6119
+ for await (const data of stream) {
6120
+ collectedStreamData.push(JSON.parse(JSON.stringify(data)));
6121
+ }
6122
+ watchData = collectedStreamData;
6123
+
6124
+ const executionResult = await getWorkflowState();
6125
+
6126
+ await new Promise(resolve => setTimeout(resolve, 1000));
6127
+
6128
+ srv.close();
6129
+
6130
+ expect(watchData.length).toBe(9);
6131
+ expect(watchData).toMatchObject([
6132
+ {
6133
+ payload: {
6134
+ runId: 'test-run-id',
6135
+ },
6136
+ type: 'start',
6137
+ },
6138
+ {
6139
+ payload: {
6140
+ id: 'step1',
6141
+ },
6142
+ type: 'step-start',
6143
+ },
6144
+ {
6145
+ payload: {
6146
+ id: 'step1',
6147
+ output: {
6148
+ result: 'success1',
6149
+ },
6150
+ status: 'success',
6151
+ },
6152
+ type: 'step-result',
6153
+ },
6154
+ {
6155
+ payload: {
6156
+ id: 'step1',
6157
+ metadata: {},
6158
+ },
6159
+ type: 'step-finish',
6160
+ },
6161
+ {
6162
+ payload: {},
6163
+ type: 'step-waiting',
6164
+ },
6165
+ {
6166
+ payload: {
6167
+ id: 'step2',
6168
+ },
6169
+ type: 'step-start',
6170
+ },
6171
+ {
6172
+ payload: {
6173
+ id: 'step2',
6174
+ output: {
6175
+ result: 'success2',
6176
+ },
6177
+ status: 'success',
6178
+ },
6179
+ type: 'step-result',
6180
+ },
6181
+ {
6182
+ payload: {
6183
+ id: 'step2',
6184
+ metadata: {},
6185
+ },
6186
+ type: 'step-finish',
6187
+ },
6188
+ {
6189
+ payload: {
6190
+ runId: 'test-run-id',
6191
+ },
6192
+ type: 'finish',
6193
+ },
6194
+ ]);
6195
+ // Verify execution completed successfully
6196
+ expect(executionResult.steps.step1).toMatchObject({
6197
+ status: 'success',
6198
+ output: { result: 'success1' },
6199
+ payload: {},
6200
+ startedAt: expect.any(Number),
6201
+ endedAt: expect.any(Number),
6202
+ });
6203
+ expect(executionResult.steps.step2).toMatchObject({
6204
+ status: 'success',
6205
+ output: { result: 'success2' },
6206
+ payload: {
6207
+ result: 'success1',
6208
+ },
6209
+ startedAt: expect.any(Number),
6210
+ endedAt: expect.any(Number),
6211
+ });
6212
+ });
6213
+
6214
+ it('should handle waitForEvent waiting flow', async ctx => {
6215
+ const inngest = new Inngest({
6216
+ id: 'mastra',
6217
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
6218
+ middleware: [realtimeMiddleware()],
6219
+ });
6220
+
6221
+ const { createWorkflow, createStep } = init(inngest);
6222
+
6223
+ const step1Action = vi.fn<any>().mockResolvedValue({ result: 'success1' });
6224
+ const step2Action = vi.fn<any>().mockResolvedValue({ result: 'success2' });
6225
+
6226
+ const step1 = createStep({
6227
+ id: 'step1',
6228
+ execute: step1Action,
6229
+ inputSchema: z.object({}),
6230
+ outputSchema: z.object({ value: z.string() }),
6231
+ });
6232
+ const step2 = createStep({
6233
+ id: 'step2',
6234
+ execute: step2Action,
6235
+ inputSchema: z.object({ value: z.string() }),
6236
+ outputSchema: z.object({}),
6237
+ });
6238
+
6239
+ const workflow = createWorkflow({
6240
+ id: 'test-workflow',
6241
+ inputSchema: z.object({}),
6242
+ outputSchema: z.object({}),
6243
+ steps: [step1, step2],
6244
+ });
6245
+ workflow.then(step1).waitForEvent('user-event-test', step2).commit();
6246
+
6247
+ const mastra = new Mastra({
6248
+ storage: new DefaultStorage({
6249
+ url: ':memory:',
6250
+ }),
6251
+ workflows: {
6252
+ 'test-workflow': workflow,
6253
+ },
6254
+ server: {
6255
+ apiRoutes: [
6256
+ {
6257
+ path: '/inngest/api',
6258
+ method: 'ALL',
6259
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
6260
+ },
6261
+ ],
6262
+ },
6263
+ });
6264
+
6265
+ const app = await createHonoServer(mastra);
6266
+
6267
+ const srv = serve({
6268
+ fetch: app.fetch,
6269
+ port: (ctx as any).handlerPort,
6270
+ });
6271
+
6272
+ const runId = 'test-run-id';
6273
+ let watchData: StreamEvent[] = [];
6274
+ const run = await workflow.createRunAsync({
6275
+ runId,
6276
+ });
6277
+
6278
+ await new Promise(resolve => setTimeout(resolve, 1000));
6279
+
6280
+ const { stream, getWorkflowState } = run.stream({ inputData: {} });
6281
+
6282
+ setTimeout(() => {
6283
+ run.sendEvent('user-event-test', {
6284
+ value: 'eventdata',
6285
+ });
6286
+ }, 3000);
6287
+
6288
+ // Start watching the workflow
6289
+ const collectedStreamData: StreamEvent[] = [];
6290
+ for await (const data of stream) {
6291
+ collectedStreamData.push(JSON.parse(JSON.stringify(data)));
6292
+ }
6293
+ watchData = collectedStreamData;
6294
+ console.dir({ watchData }, { depth: null });
6295
+
6296
+ const executionResult = await getWorkflowState();
6297
+
6298
+ await new Promise(resolve => setTimeout(resolve, 1000));
6299
+
6300
+ srv.close();
6301
+
6302
+ expect(watchData.length).toBe(9);
6303
+ expect(watchData).toMatchObject([
6304
+ {
6305
+ payload: {
6306
+ runId: 'test-run-id',
6307
+ },
6308
+ type: 'start',
6309
+ },
6310
+ {
6311
+ payload: {
6312
+ id: 'step1',
6313
+ },
6314
+ type: 'step-start',
6315
+ },
6316
+ {
6317
+ payload: {
6318
+ id: 'step1',
6319
+ output: {
6320
+ result: 'success1',
6321
+ },
6322
+ status: 'success',
6323
+ },
6324
+ type: 'step-result',
6325
+ },
6326
+ {
6327
+ payload: {
6328
+ id: 'step1',
6329
+ metadata: {},
6330
+ },
6331
+ type: 'step-finish',
6332
+ },
6333
+ {
6334
+ payload: {
6335
+ id: 'step2',
6336
+ },
6337
+ type: 'step-waiting',
6338
+ },
6339
+ {
6340
+ payload: {
6341
+ id: 'step2',
6342
+ },
6343
+ type: 'step-start',
6344
+ },
6345
+ {
6346
+ payload: {
6347
+ id: 'step2',
6348
+ output: {
6349
+ result: 'success2',
6350
+ },
6351
+ status: 'success',
6352
+ },
6353
+ type: 'step-result',
6354
+ },
6355
+ {
6356
+ payload: {
6357
+ id: 'step2',
6358
+ metadata: {},
6359
+ },
6360
+ type: 'step-finish',
6361
+ },
6362
+ {
6363
+ payload: {
6364
+ runId: 'test-run-id',
6365
+ },
6366
+ type: 'finish',
6367
+ },
6368
+ ]);
6369
+ // Verify execution completed successfully
6370
+ expect(executionResult.steps.step1).toMatchObject({
6371
+ status: 'success',
6372
+ output: { result: 'success1' },
6373
+ payload: {},
6374
+ startedAt: expect.any(Number),
6375
+ endedAt: expect.any(Number),
6376
+ });
6377
+ expect(executionResult.steps.step2).toMatchObject({
6378
+ status: 'success',
6379
+ output: { result: 'success2' },
6380
+ payload: {
6381
+ result: 'success1',
6382
+ },
6383
+ resumePayload: {
6384
+ value: 'eventdata',
6385
+ },
6386
+ startedAt: expect.any(Number),
6387
+ resumedAt: expect.any(Number),
6388
+ endedAt: expect.any(Number),
6389
+ });
6390
+ });
6391
+
6392
+ it('should handle basic suspend and resume flow', async ctx => {
6393
+ const inngest = new Inngest({
6394
+ id: 'mastra',
6395
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
6396
+ middleware: [realtimeMiddleware()],
6397
+ });
6398
+
6399
+ const { createWorkflow, createStep } = init(inngest);
6400
+
6401
+ const getUserInputAction = vi.fn().mockResolvedValue({ userInput: 'test input' });
6402
+ const promptAgentAction = vi
6403
+ .fn()
6404
+ .mockImplementationOnce(async ({ suspend }) => {
6405
+ console.log('suspend');
6406
+ await suspend();
6407
+ return undefined;
6408
+ })
6409
+ .mockImplementationOnce(() => ({ modelOutput: 'test output' }));
6410
+ const evaluateToneAction = vi.fn().mockResolvedValue({
6411
+ toneScore: { score: 0.8 },
6412
+ completenessScore: { score: 0.7 },
6413
+ });
6414
+ const improveResponseAction = vi.fn().mockResolvedValue({ improvedOutput: 'improved output' });
6415
+ const evaluateImprovedAction = vi.fn().mockResolvedValue({
6416
+ toneScore: { score: 0.9 },
6417
+ completenessScore: { score: 0.8 },
6418
+ });
6419
+
6420
+ const getUserInput = createStep({
6421
+ id: 'getUserInput',
6422
+ execute: getUserInputAction,
6423
+ inputSchema: z.object({ input: z.string() }),
6424
+ outputSchema: z.object({ userInput: z.string() }),
6425
+ });
6426
+ const promptAgent = createStep({
6427
+ id: 'promptAgent',
6428
+ execute: promptAgentAction,
6429
+ inputSchema: z.object({ userInput: z.string() }),
6430
+ outputSchema: z.object({ modelOutput: z.string() }),
6431
+ });
6432
+ const evaluateTone = createStep({
6433
+ id: 'evaluateToneConsistency',
6434
+ execute: evaluateToneAction,
6435
+ inputSchema: z.object({ modelOutput: z.string() }),
6436
+ outputSchema: z.object({
6437
+ toneScore: z.any(),
6438
+ completenessScore: z.any(),
6439
+ }),
6440
+ });
6441
+ const improveResponse = createStep({
6442
+ id: 'improveResponse',
6443
+ execute: improveResponseAction,
6444
+ inputSchema: z.object({ toneScore: z.any(), completenessScore: z.any() }),
6445
+ outputSchema: z.object({ improvedOutput: z.string() }),
6446
+ });
6447
+ const evaluateImproved = createStep({
6448
+ id: 'evaluateImprovedResponse',
6449
+ execute: evaluateImprovedAction,
6450
+ inputSchema: z.object({ improvedOutput: z.string() }),
6451
+ outputSchema: z.object({
6452
+ toneScore: z.any(),
6453
+ completenessScore: z.any(),
6454
+ }),
6455
+ });
6456
+
6457
+ const promptEvalWorkflow = createWorkflow({
6458
+ id: 'test-workflow',
6459
+ inputSchema: z.object({ input: z.string() }),
6460
+ outputSchema: z.object({}),
6461
+ steps: [getUserInput, promptAgent, evaluateTone, improveResponse, evaluateImproved],
6462
+ });
6463
+
6464
+ promptEvalWorkflow
6465
+ .then(getUserInput)
6466
+ .then(promptAgent)
6467
+ .then(evaluateTone)
6468
+ .then(improveResponse)
6469
+ .then(evaluateImproved)
6470
+ .commit();
6471
+
6472
+ const mastra = new Mastra({
6473
+ storage: new DefaultStorage({
6474
+ url: ':memory:',
6475
+ }),
6476
+ workflows: {
6477
+ 'test-workflow': promptEvalWorkflow,
6478
+ },
6479
+ server: {
6480
+ apiRoutes: [
6481
+ {
6482
+ path: '/inngest/api',
6483
+ method: 'ALL',
6484
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
6485
+ },
6486
+ ],
6487
+ },
6488
+ });
6489
+
6490
+ const app = await createHonoServer(mastra);
6491
+
6492
+ const srv = serve({
6493
+ fetch: app.fetch,
6494
+ port: (ctx as any).handlerPort,
6495
+ });
6496
+
6497
+ await new Promise(resolve => setTimeout(resolve, 1000));
6498
+
6499
+ const run = await promptEvalWorkflow.createRunAsync();
6500
+
6501
+ const { stream, getWorkflowState } = run.stream({ inputData: { input: 'test' } });
6502
+
6503
+ for await (const data of stream) {
6504
+ if (data.type === 'step-suspended') {
6505
+ expect(promptAgentAction).toHaveBeenCalledTimes(1);
6506
+
6507
+ // make it async to show that execution is not blocked
6508
+ setImmediate(() => {
6509
+ const resumeData = { stepId: 'promptAgent', context: { userInput: 'test input for resumption' } };
6510
+ run.resume({ resumeData: resumeData as any, step: promptAgent });
6511
+ });
6512
+ expect(evaluateToneAction).not.toHaveBeenCalledTimes(1);
6513
+ }
6514
+ }
6515
+
6516
+ await new Promise(resolve => setTimeout(resolve, 5000));
6517
+ const resumeResult = await getWorkflowState();
6518
+
6519
+ srv.close();
6520
+
6521
+ expect(evaluateToneAction).toHaveBeenCalledTimes(1);
6522
+ expect(resumeResult.steps).toMatchObject({
6523
+ input: { input: 'test' },
6524
+ getUserInput: {
6525
+ status: 'success',
6526
+ output: { userInput: 'test input' },
6527
+ payload: { input: 'test' },
6528
+ startedAt: expect.any(Number),
6529
+ endedAt: expect.any(Number),
6530
+ },
6531
+ promptAgent: {
6532
+ status: 'success',
6533
+ output: { modelOutput: 'test output' },
6534
+ payload: { userInput: 'test input' },
6535
+ startedAt: expect.any(Number),
6536
+ endedAt: expect.any(Number),
6537
+ resumePayload: { stepId: 'promptAgent', context: { userInput: 'test input for resumption' } },
6538
+ resumedAt: expect.any(Number),
6539
+ // suspendedAt: expect.any(Number),
6540
+ },
6541
+ evaluateToneConsistency: {
6542
+ status: 'success',
6543
+ output: { toneScore: { score: 0.8 }, completenessScore: { score: 0.7 } },
6544
+ payload: { modelOutput: 'test output' },
6545
+ startedAt: expect.any(Number),
6546
+ endedAt: expect.any(Number),
6547
+ },
6548
+ improveResponse: {
6549
+ status: 'success',
6550
+ output: { improvedOutput: 'improved output' },
6551
+ payload: { toneScore: { score: 0.8 }, completenessScore: { score: 0.7 } },
6552
+ startedAt: expect.any(Number),
6553
+ endedAt: expect.any(Number),
6554
+ },
6555
+ evaluateImprovedResponse: {
6556
+ status: 'success',
6557
+ output: { toneScore: { score: 0.9 }, completenessScore: { score: 0.8 } },
6558
+ payload: { improvedOutput: 'improved output' },
6559
+ startedAt: expect.any(Number),
6560
+ endedAt: expect.any(Number),
6561
+ },
6562
+ });
6563
+ });
6564
+
6565
+ it('should be able to use an agent as a step', async ctx => {
6566
+ const inngest = new Inngest({
6567
+ id: 'mastra',
6568
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
6569
+ middleware: [realtimeMiddleware()],
6570
+ });
6571
+
6572
+ const { createWorkflow, createStep } = init(inngest);
6573
+
6574
+ const workflow = createWorkflow({
6575
+ id: 'test-workflow',
6576
+ inputSchema: z.object({
6577
+ prompt1: z.string(),
6578
+ prompt2: z.string(),
6579
+ }),
6580
+ outputSchema: z.object({}),
6581
+ });
6582
+
6583
+ const agent = new Agent({
6584
+ name: 'test-agent-1',
6585
+ instructions: 'test agent instructions"',
6586
+ model: new MockLanguageModelV1({
6587
+ doStream: async () => ({
6588
+ stream: simulateReadableStream({
6589
+ chunks: [
6590
+ { type: 'text-delta', textDelta: 'Paris' },
6591
+ {
6592
+ type: 'finish',
6593
+ finishReason: 'stop',
6594
+ logprobs: undefined,
6595
+ usage: { completionTokens: 10, promptTokens: 3 },
6596
+ },
6597
+ ],
6598
+ }),
6599
+ rawCall: { rawPrompt: null, rawSettings: {} },
6600
+ }),
6601
+ }),
6602
+ });
6603
+
6604
+ const agent2 = new Agent({
6605
+ name: 'test-agent-2',
6606
+ instructions: 'test agent instructions',
6607
+ model: new MockLanguageModelV1({
6608
+ doStream: async () => ({
6609
+ stream: simulateReadableStream({
6610
+ chunks: [
6611
+ { type: 'text-delta', textDelta: 'London' },
6612
+ {
6613
+ type: 'finish',
6614
+ finishReason: 'stop',
6615
+ logprobs: undefined,
6616
+ usage: { completionTokens: 10, promptTokens: 3 },
6617
+ },
6618
+ ],
6619
+ }),
6620
+ rawCall: { rawPrompt: null, rawSettings: {} },
6621
+ }),
6622
+ }),
6623
+ });
6624
+
6625
+ const startStep = createStep({
6626
+ id: 'start',
6627
+ inputSchema: z.object({
6628
+ prompt1: z.string(),
6629
+ prompt2: z.string(),
6630
+ }),
6631
+ outputSchema: z.object({ prompt1: z.string(), prompt2: z.string() }),
6632
+ execute: async ({ inputData }) => {
6633
+ return {
6634
+ prompt1: inputData.prompt1,
6635
+ prompt2: inputData.prompt2,
6636
+ };
6637
+ },
6638
+ });
6639
+
6640
+ const agentStep1 = createStep(agent);
6641
+ const agentStep2 = createStep(agent2);
6642
+
6643
+ workflow
6644
+ .then(startStep)
6645
+ .map({
6646
+ prompt: {
6647
+ step: startStep,
6648
+ path: 'prompt1',
6649
+ },
6650
+ })
6651
+ .then(agentStep1)
6652
+ .map({
6653
+ prompt: {
6654
+ step: startStep,
6655
+ path: 'prompt2',
6656
+ },
6657
+ })
6658
+ .then(agentStep2)
6659
+ .commit();
6660
+
6661
+ const mastra = new Mastra({
6662
+ storage: new DefaultStorage({
6663
+ url: ':memory:',
6664
+ }),
6665
+ workflows: {
6666
+ 'test-workflow': workflow,
6667
+ },
6668
+ server: {
6669
+ apiRoutes: [
6670
+ {
6671
+ path: '/inngest/api',
6672
+ method: 'ALL',
6673
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
6674
+ },
6675
+ ],
6676
+ },
6677
+ });
6678
+
6679
+ const app = await createHonoServer(mastra);
6680
+
6681
+ const srv = serve({
6682
+ fetch: app.fetch,
6683
+ port: (ctx as any).handlerPort,
6684
+ });
6685
+
6686
+ await new Promise(resolve => setTimeout(resolve, 1000));
6687
+
6688
+ const run = await workflow.createRunAsync({
6689
+ runId: 'test-run-id',
6690
+ });
6691
+ const { stream } = run.stream({
6692
+ inputData: {
6693
+ prompt1: 'Capital of France, just the name',
6694
+ prompt2: 'Capital of UK, just the name',
6695
+ },
6696
+ });
6697
+
6698
+ const values: StreamEvent[] = [];
6699
+ for await (const value of stream.values()) {
6700
+ values.push(value);
6701
+ }
6702
+
6703
+ srv.close();
6704
+
6705
+ expect(values).toMatchObject([
6706
+ {
6707
+ payload: {
6708
+ runId: 'test-run-id',
6709
+ },
6710
+ type: 'start',
6711
+ },
6712
+ {
6713
+ payload: {
6714
+ id: 'start',
6715
+ },
6716
+ type: 'step-start',
6717
+ },
6718
+ {
6719
+ payload: {
6720
+ id: 'start',
6721
+ output: {
6722
+ prompt1: 'Capital of France, just the name',
6723
+ prompt2: 'Capital of UK, just the name',
6724
+ },
6725
+ status: 'success',
6726
+ },
6727
+ type: 'step-result',
6728
+ },
6729
+ {
6730
+ payload: {
6731
+ id: 'start',
6732
+ metadata: {},
6733
+ },
6734
+ type: 'step-finish',
6735
+ },
6736
+ {
6737
+ payload: {
6738
+ id: expect.any(String),
6739
+ },
6740
+ type: 'step-start',
6741
+ },
6742
+ {
6743
+ payload: {
6744
+ id: expect.any(String),
6745
+ output: {
6746
+ prompt: 'Capital of France, just the name',
6747
+ },
6748
+ status: 'success',
6749
+ },
6750
+ type: 'step-result',
6751
+ },
6752
+ {
6753
+ payload: {
6754
+ id: expect.any(String),
6755
+ metadata: {},
6756
+ },
6757
+ type: 'step-finish',
6758
+ },
6759
+ {
6760
+ payload: {
6761
+ id: 'test-agent-1',
6762
+ },
6763
+ type: 'step-start',
6764
+ },
6765
+ {
6766
+ args: {
6767
+ prompt: 'Capital of France, just the name',
6768
+ },
6769
+ name: 'test-agent-1',
6770
+ type: 'tool-call-streaming-start',
6771
+ },
6772
+ {
6773
+ args: {
6774
+ prompt: 'Capital of France, just the name',
6775
+ },
6776
+ argsTextDelta: 'Paris',
6777
+ name: 'test-agent-1',
6778
+ type: 'tool-call-delta',
6779
+ },
6780
+ {
6781
+ payload: {
6782
+ id: 'test-agent-1',
6783
+ output: {
6784
+ text: 'Paris',
6785
+ },
6786
+ status: 'success',
6787
+ },
6788
+ type: 'step-result',
6789
+ },
6790
+ {
6791
+ payload: {
6792
+ id: expect.any(String),
6793
+ metadata: {},
6794
+ },
6795
+ type: 'step-finish',
6796
+ },
6797
+ {
6798
+ payload: {
6799
+ id: expect.any(String),
6800
+ },
6801
+ type: 'step-start',
6802
+ },
6803
+ {
6804
+ payload: {
6805
+ id: expect.any(String),
6806
+ output: {
6807
+ prompt: 'Capital of UK, just the name',
6808
+ },
6809
+ status: 'success',
6810
+ },
6811
+ type: 'step-result',
6812
+ },
6813
+ {
6814
+ payload: {
6815
+ id: expect.any(String),
6816
+ metadata: {},
6817
+ },
6818
+ type: 'step-finish',
6819
+ },
6820
+ {
6821
+ payload: {
6822
+ id: expect.any(String),
6823
+ },
6824
+ type: 'step-start',
6825
+ },
6826
+ {
6827
+ args: {
6828
+ prompt: 'Capital of UK, just the name',
6829
+ },
6830
+ name: 'test-agent-2',
6831
+ type: 'tool-call-streaming-start',
6832
+ },
6833
+ {
6834
+ args: {
6835
+ prompt: 'Capital of UK, just the name',
6836
+ },
6837
+ argsTextDelta: 'London',
6838
+ name: 'test-agent-2',
6839
+ type: 'tool-call-delta',
6840
+ },
6841
+ {
6842
+ payload: {
6843
+ id: expect.any(String),
6844
+ output: {
6845
+ text: 'London',
6846
+ },
6847
+ status: 'success',
6848
+ },
6849
+ type: 'step-result',
6850
+ },
6851
+ {
6852
+ payload: {
6853
+ id: expect.any(String),
6854
+ metadata: {},
6855
+ },
6856
+ type: 'step-finish',
6857
+ },
6858
+ {
6859
+ payload: {
6860
+ runId: 'test-run-id',
6861
+ },
6862
+ type: 'finish',
6863
+ },
6864
+ ]);
6865
+ });
6866
+ });
5521
6867
  }, 40e3);