@mastra/inngest 0.0.0-http-transporter-20250702160118 → 0.0.0-memory-system-message-error-20250813233316
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +271 -2
- package/LICENSE.md +11 -42
- package/dist/index.cjs +146 -8
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +282 -7
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +147 -9
- package/dist/index.js.map +1 -0
- package/docker-compose.yaml +1 -1
- package/package.json +13 -12
- package/src/index.test.ts +703 -18
- package/src/index.ts +201 -3
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +17 -0
- package/dist/_tsup-dts-rollup.d.cts +0 -265
- package/dist/_tsup-dts-rollup.d.ts +0 -265
- package/dist/index.d.cts +0 -7
package/src/index.test.ts
CHANGED
|
@@ -367,7 +367,7 @@ describe('MastraInngestWorkflow', () => {
|
|
|
367
367
|
srv.close();
|
|
368
368
|
});
|
|
369
369
|
|
|
370
|
-
it('should execute a
|
|
370
|
+
it('should execute a sleep step', async ctx => {
|
|
371
371
|
const inngest = new Inngest({
|
|
372
372
|
id: 'mastra',
|
|
373
373
|
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
@@ -455,6 +455,100 @@ describe('MastraInngestWorkflow', () => {
|
|
|
455
455
|
srv.close();
|
|
456
456
|
});
|
|
457
457
|
|
|
458
|
+
it('should execute a sleep step with fn parameter', async ctx => {
|
|
459
|
+
const inngest = new Inngest({
|
|
460
|
+
id: 'mastra',
|
|
461
|
+
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
462
|
+
});
|
|
463
|
+
|
|
464
|
+
const { createWorkflow, createStep } = init(inngest);
|
|
465
|
+
|
|
466
|
+
const execute = vi.fn<any>().mockResolvedValue({ value: 1000 });
|
|
467
|
+
const step1 = createStep({
|
|
468
|
+
id: 'step1',
|
|
469
|
+
execute,
|
|
470
|
+
inputSchema: z.object({}),
|
|
471
|
+
outputSchema: z.object({ value: z.number() }),
|
|
472
|
+
});
|
|
473
|
+
const step2 = createStep({
|
|
474
|
+
id: 'step2',
|
|
475
|
+
execute: async ({ inputData }) => {
|
|
476
|
+
return { value: inputData.value + 1000 };
|
|
477
|
+
},
|
|
478
|
+
inputSchema: z.object({ value: z.number() }),
|
|
479
|
+
outputSchema: z.object({ value: z.number() }),
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
const workflow = createWorkflow({
|
|
483
|
+
id: 'test-workflow',
|
|
484
|
+
inputSchema: z.object({}),
|
|
485
|
+
outputSchema: z.object({
|
|
486
|
+
value: z.number(),
|
|
487
|
+
}),
|
|
488
|
+
steps: [step1],
|
|
489
|
+
});
|
|
490
|
+
|
|
491
|
+
workflow
|
|
492
|
+
.then(step1)
|
|
493
|
+
.sleep(async ({ inputData }) => {
|
|
494
|
+
return inputData.value;
|
|
495
|
+
})
|
|
496
|
+
.then(step2)
|
|
497
|
+
.commit();
|
|
498
|
+
|
|
499
|
+
const mastra = new Mastra({
|
|
500
|
+
storage: new DefaultStorage({
|
|
501
|
+
url: ':memory:',
|
|
502
|
+
}),
|
|
503
|
+
workflows: {
|
|
504
|
+
'test-workflow': workflow,
|
|
505
|
+
},
|
|
506
|
+
server: {
|
|
507
|
+
apiRoutes: [
|
|
508
|
+
{
|
|
509
|
+
path: '/inngest/api',
|
|
510
|
+
method: 'ALL',
|
|
511
|
+
createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
|
|
512
|
+
},
|
|
513
|
+
],
|
|
514
|
+
},
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
const app = await createHonoServer(mastra);
|
|
518
|
+
|
|
519
|
+
const srv = (globServer = serve({
|
|
520
|
+
fetch: app.fetch,
|
|
521
|
+
port: (ctx as any).handlerPort,
|
|
522
|
+
}));
|
|
523
|
+
await resetInngest();
|
|
524
|
+
|
|
525
|
+
const run = await workflow.createRunAsync();
|
|
526
|
+
const startTime = Date.now();
|
|
527
|
+
const result = await run.start({ inputData: {} });
|
|
528
|
+
const endTime = Date.now();
|
|
529
|
+
|
|
530
|
+
expect(execute).toHaveBeenCalled();
|
|
531
|
+
expect(result.steps['step1']).toMatchObject({
|
|
532
|
+
status: 'success',
|
|
533
|
+
output: { value: 1000 },
|
|
534
|
+
// payload: {},
|
|
535
|
+
// startedAt: expect.any(Number),
|
|
536
|
+
// endedAt: expect.any(Number),
|
|
537
|
+
});
|
|
538
|
+
|
|
539
|
+
expect(result.steps['step2']).toMatchObject({
|
|
540
|
+
status: 'success',
|
|
541
|
+
output: { value: 2000 },
|
|
542
|
+
// payload: { result: 'success' },
|
|
543
|
+
// startedAt: expect.any(Number),
|
|
544
|
+
// endedAt: expect.any(Number),
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
expect(endTime - startTime).toBeGreaterThan(1000);
|
|
548
|
+
|
|
549
|
+
srv.close();
|
|
550
|
+
});
|
|
551
|
+
|
|
458
552
|
it('should execute a a sleep until step', async ctx => {
|
|
459
553
|
const inngest = new Inngest({
|
|
460
554
|
id: 'mastra',
|
|
@@ -547,6 +641,100 @@ describe('MastraInngestWorkflow', () => {
|
|
|
547
641
|
srv.close();
|
|
548
642
|
});
|
|
549
643
|
|
|
644
|
+
it('should execute a sleep until step with fn parameter', 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({ value: 1000 });
|
|
653
|
+
const step1 = createStep({
|
|
654
|
+
id: 'step1',
|
|
655
|
+
execute,
|
|
656
|
+
inputSchema: z.object({}),
|
|
657
|
+
outputSchema: z.object({ value: z.number() }),
|
|
658
|
+
});
|
|
659
|
+
const step2 = createStep({
|
|
660
|
+
id: 'step2',
|
|
661
|
+
execute: async ({ inputData }) => {
|
|
662
|
+
return { value: inputData.value + 1000 };
|
|
663
|
+
},
|
|
664
|
+
inputSchema: z.object({ value: z.number() }),
|
|
665
|
+
outputSchema: z.object({ value: z.number() }),
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
const workflow = createWorkflow({
|
|
669
|
+
id: 'test-workflow',
|
|
670
|
+
inputSchema: z.object({}),
|
|
671
|
+
outputSchema: z.object({
|
|
672
|
+
value: z.number(),
|
|
673
|
+
}),
|
|
674
|
+
steps: [step1],
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
workflow
|
|
678
|
+
.then(step1)
|
|
679
|
+
.sleepUntil(async ({ inputData }) => {
|
|
680
|
+
return new Date(Date.now() + inputData.value);
|
|
681
|
+
})
|
|
682
|
+
.then(step2)
|
|
683
|
+
.commit();
|
|
684
|
+
|
|
685
|
+
const mastra = new Mastra({
|
|
686
|
+
storage: new DefaultStorage({
|
|
687
|
+
url: ':memory:',
|
|
688
|
+
}),
|
|
689
|
+
workflows: {
|
|
690
|
+
'test-workflow': workflow,
|
|
691
|
+
},
|
|
692
|
+
server: {
|
|
693
|
+
apiRoutes: [
|
|
694
|
+
{
|
|
695
|
+
path: '/inngest/api',
|
|
696
|
+
method: 'ALL',
|
|
697
|
+
createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
|
|
698
|
+
},
|
|
699
|
+
],
|
|
700
|
+
},
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
const app = await createHonoServer(mastra);
|
|
704
|
+
|
|
705
|
+
const srv = (globServer = serve({
|
|
706
|
+
fetch: app.fetch,
|
|
707
|
+
port: (ctx as any).handlerPort,
|
|
708
|
+
}));
|
|
709
|
+
await resetInngest();
|
|
710
|
+
|
|
711
|
+
const run = await workflow.createRunAsync();
|
|
712
|
+
const startTime = Date.now();
|
|
713
|
+
const result = await run.start({ inputData: {} });
|
|
714
|
+
const endTime = Date.now();
|
|
715
|
+
|
|
716
|
+
expect(execute).toHaveBeenCalled();
|
|
717
|
+
expect(result.steps['step1']).toMatchObject({
|
|
718
|
+
status: 'success',
|
|
719
|
+
output: { value: 1000 },
|
|
720
|
+
// payload: {},
|
|
721
|
+
// startedAt: expect.any(Number),
|
|
722
|
+
// endedAt: expect.any(Number),
|
|
723
|
+
});
|
|
724
|
+
|
|
725
|
+
expect(result.steps['step2']).toMatchObject({
|
|
726
|
+
status: 'success',
|
|
727
|
+
output: { value: 2000 },
|
|
728
|
+
// payload: { result: 'success' },
|
|
729
|
+
// startedAt: expect.any(Number),
|
|
730
|
+
// endedAt: expect.any(Number),
|
|
731
|
+
});
|
|
732
|
+
|
|
733
|
+
expect(endTime - startTime).toBeGreaterThan(1000);
|
|
734
|
+
|
|
735
|
+
srv.close();
|
|
736
|
+
});
|
|
737
|
+
|
|
550
738
|
it('should execute a a waitForEvent step', async ctx => {
|
|
551
739
|
const inngest = new Inngest({
|
|
552
740
|
id: 'mastra',
|
|
@@ -4070,6 +4258,124 @@ describe('MastraInngestWorkflow', () => {
|
|
|
4070
4258
|
|
|
4071
4259
|
expect(promptAgentAction).toHaveBeenCalledTimes(2);
|
|
4072
4260
|
});
|
|
4261
|
+
|
|
4262
|
+
it('should handle consecutive nested workflows with suspend/resume', async ctx => {
|
|
4263
|
+
const inngest = new Inngest({
|
|
4264
|
+
id: 'mastra',
|
|
4265
|
+
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
4266
|
+
middleware: [realtimeMiddleware()],
|
|
4267
|
+
});
|
|
4268
|
+
|
|
4269
|
+
const { createWorkflow, createStep } = init(inngest);
|
|
4270
|
+
|
|
4271
|
+
const step1 = vi.fn().mockImplementation(async ({ resumeData, suspend }) => {
|
|
4272
|
+
if (!resumeData?.suspect) {
|
|
4273
|
+
return await suspend({ message: 'What is the suspect?' });
|
|
4274
|
+
}
|
|
4275
|
+
return { suspect: resumeData.suspect };
|
|
4276
|
+
});
|
|
4277
|
+
const step1Definition = createStep({
|
|
4278
|
+
id: 'step-1',
|
|
4279
|
+
inputSchema: z.object({ suspect: z.string() }),
|
|
4280
|
+
outputSchema: z.object({ suspect: z.string() }),
|
|
4281
|
+
suspendSchema: z.object({ message: z.string() }),
|
|
4282
|
+
resumeSchema: z.object({ suspect: z.string() }),
|
|
4283
|
+
execute: step1,
|
|
4284
|
+
});
|
|
4285
|
+
|
|
4286
|
+
const step2 = vi.fn().mockImplementation(async ({ resumeData, suspend }) => {
|
|
4287
|
+
if (!resumeData?.suspect) {
|
|
4288
|
+
return await suspend({ message: 'What is the second suspect?' });
|
|
4289
|
+
}
|
|
4290
|
+
return { suspect: resumeData.suspect };
|
|
4291
|
+
});
|
|
4292
|
+
const step2Definition = createStep({
|
|
4293
|
+
id: 'step-2',
|
|
4294
|
+
inputSchema: z.object({ suspect: z.string() }),
|
|
4295
|
+
outputSchema: z.object({ suspect: z.string() }),
|
|
4296
|
+
suspendSchema: z.object({ message: z.string() }),
|
|
4297
|
+
resumeSchema: z.object({ suspect: z.string() }),
|
|
4298
|
+
execute: step2,
|
|
4299
|
+
});
|
|
4300
|
+
|
|
4301
|
+
const subWorkflow1 = createWorkflow({
|
|
4302
|
+
id: 'sub-workflow-1',
|
|
4303
|
+
inputSchema: z.object({ suspect: z.string() }),
|
|
4304
|
+
outputSchema: z.object({ suspect: z.string() }),
|
|
4305
|
+
})
|
|
4306
|
+
.then(step1Definition)
|
|
4307
|
+
.commit();
|
|
4308
|
+
|
|
4309
|
+
const subWorkflow2 = createWorkflow({
|
|
4310
|
+
id: 'sub-workflow-2',
|
|
4311
|
+
inputSchema: z.object({ suspect: z.string() }),
|
|
4312
|
+
outputSchema: z.object({ suspect: z.string() }),
|
|
4313
|
+
})
|
|
4314
|
+
.then(step2Definition)
|
|
4315
|
+
.commit();
|
|
4316
|
+
|
|
4317
|
+
const mainWorkflow = createWorkflow({
|
|
4318
|
+
id: 'main-workflow',
|
|
4319
|
+
inputSchema: z.object({ suspect: z.string() }),
|
|
4320
|
+
outputSchema: z.object({ suspect: z.string() }),
|
|
4321
|
+
})
|
|
4322
|
+
.then(subWorkflow1)
|
|
4323
|
+
.then(subWorkflow2)
|
|
4324
|
+
.commit();
|
|
4325
|
+
|
|
4326
|
+
const mastra = new Mastra({
|
|
4327
|
+
logger: false,
|
|
4328
|
+
storage: new DefaultStorage({
|
|
4329
|
+
url: ':memory:',
|
|
4330
|
+
}),
|
|
4331
|
+
workflows: { mainWorkflow },
|
|
4332
|
+
server: {
|
|
4333
|
+
apiRoutes: [
|
|
4334
|
+
{
|
|
4335
|
+
path: '/inngest/api',
|
|
4336
|
+
method: 'ALL',
|
|
4337
|
+
createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
|
|
4338
|
+
},
|
|
4339
|
+
],
|
|
4340
|
+
},
|
|
4341
|
+
});
|
|
4342
|
+
|
|
4343
|
+
const app = await createHonoServer(mastra);
|
|
4344
|
+
|
|
4345
|
+
const srv = (globServer = serve({
|
|
4346
|
+
fetch: app.fetch,
|
|
4347
|
+
port: (ctx as any).handlerPort,
|
|
4348
|
+
}));
|
|
4349
|
+
await resetInngest();
|
|
4350
|
+
|
|
4351
|
+
const run = await mainWorkflow.createRunAsync();
|
|
4352
|
+
|
|
4353
|
+
const initialResult = await run.start({ inputData: { suspect: 'initial-suspect' } });
|
|
4354
|
+
expect(initialResult.status).toBe('suspended');
|
|
4355
|
+
|
|
4356
|
+
const firstResumeResult = await run.resume({
|
|
4357
|
+
step: ['sub-workflow-1', 'step-1'],
|
|
4358
|
+
resumeData: { suspect: 'first-suspect' },
|
|
4359
|
+
});
|
|
4360
|
+
expect(firstResumeResult.status).toBe('suspended');
|
|
4361
|
+
|
|
4362
|
+
const secondResumeResult = await run.resume({
|
|
4363
|
+
step: ['sub-workflow-2', 'step-2'],
|
|
4364
|
+
resumeData: { suspect: 'second-suspect' },
|
|
4365
|
+
});
|
|
4366
|
+
|
|
4367
|
+
expect(step1).toHaveBeenCalledTimes(2);
|
|
4368
|
+
expect(step2).toHaveBeenCalledTimes(2);
|
|
4369
|
+
expect(secondResumeResult.status).toBe('success');
|
|
4370
|
+
expect(secondResumeResult.steps['sub-workflow-1']).toMatchObject({
|
|
4371
|
+
status: 'success',
|
|
4372
|
+
});
|
|
4373
|
+
expect(secondResumeResult.steps['sub-workflow-2']).toMatchObject({
|
|
4374
|
+
status: 'success',
|
|
4375
|
+
});
|
|
4376
|
+
|
|
4377
|
+
srv.close();
|
|
4378
|
+
});
|
|
4073
4379
|
});
|
|
4074
4380
|
|
|
4075
4381
|
describe('Accessing Mastra', () => {
|
|
@@ -6031,10 +6337,8 @@ describe('MastraInngestWorkflow', () => {
|
|
|
6031
6337
|
// @ts-ignore
|
|
6032
6338
|
expect(result?.steps.step1.output.injectedValue).toBe(testValue + '2');
|
|
6033
6339
|
});
|
|
6034
|
-
});
|
|
6035
6340
|
|
|
6036
|
-
|
|
6037
|
-
it('should inject inngest step primitives into steps during run', async ctx => {
|
|
6341
|
+
it('should have access to runtimeContext from before suspension during workflow resume', async ctx => {
|
|
6038
6342
|
const inngest = new Inngest({
|
|
6039
6343
|
id: 'mastra',
|
|
6040
6344
|
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
@@ -6042,22 +6346,194 @@ describe('MastraInngestWorkflow', () => {
|
|
|
6042
6346
|
|
|
6043
6347
|
const { createWorkflow, createStep } = init(inngest);
|
|
6044
6348
|
|
|
6045
|
-
const
|
|
6046
|
-
|
|
6047
|
-
|
|
6048
|
-
|
|
6049
|
-
|
|
6050
|
-
|
|
6349
|
+
const testValue = 'test-dependency';
|
|
6350
|
+
const resumeStep = createStep({
|
|
6351
|
+
id: 'resume',
|
|
6352
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6353
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6354
|
+
resumeSchema: z.object({ value: z.number() }),
|
|
6355
|
+
suspendSchema: z.object({ message: z.string() }),
|
|
6356
|
+
execute: async ({ inputData, resumeData, suspend }) => {
|
|
6357
|
+
const finalValue = (resumeData?.value ?? 0) + inputData.value;
|
|
6358
|
+
|
|
6359
|
+
if (!resumeData?.value || finalValue < 10) {
|
|
6360
|
+
return await suspend({
|
|
6361
|
+
message: `Please provide additional information. now value is ${inputData.value}`,
|
|
6362
|
+
});
|
|
6363
|
+
}
|
|
6364
|
+
|
|
6365
|
+
return { value: finalValue };
|
|
6051
6366
|
},
|
|
6052
|
-
inputSchema: z.object({}),
|
|
6053
|
-
outputSchema: z.object({}),
|
|
6054
6367
|
});
|
|
6055
|
-
|
|
6056
|
-
|
|
6057
|
-
|
|
6058
|
-
|
|
6059
|
-
|
|
6060
|
-
}),
|
|
6368
|
+
|
|
6369
|
+
const incrementStep = createStep({
|
|
6370
|
+
id: 'increment',
|
|
6371
|
+
inputSchema: z.object({
|
|
6372
|
+
value: z.number(),
|
|
6373
|
+
}),
|
|
6374
|
+
outputSchema: z.object({
|
|
6375
|
+
value: z.number(),
|
|
6376
|
+
}),
|
|
6377
|
+
execute: async ({ inputData, runtimeContext }) => {
|
|
6378
|
+
runtimeContext.set('testKey', testValue);
|
|
6379
|
+
return {
|
|
6380
|
+
value: inputData.value + 1,
|
|
6381
|
+
};
|
|
6382
|
+
},
|
|
6383
|
+
});
|
|
6384
|
+
|
|
6385
|
+
const incrementWorkflow = createWorkflow({
|
|
6386
|
+
id: 'increment-workflow',
|
|
6387
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6388
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6389
|
+
})
|
|
6390
|
+
.then(incrementStep)
|
|
6391
|
+
.then(resumeStep)
|
|
6392
|
+
.then(
|
|
6393
|
+
createStep({
|
|
6394
|
+
id: 'final',
|
|
6395
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6396
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6397
|
+
execute: async ({ inputData, runtimeContext }) => {
|
|
6398
|
+
const testKey = runtimeContext.get('testKey');
|
|
6399
|
+
expect(testKey).toBe(testValue);
|
|
6400
|
+
return { value: inputData.value };
|
|
6401
|
+
},
|
|
6402
|
+
}),
|
|
6403
|
+
)
|
|
6404
|
+
.commit();
|
|
6405
|
+
|
|
6406
|
+
new Mastra({
|
|
6407
|
+
logger: false,
|
|
6408
|
+
storage: testStorage,
|
|
6409
|
+
workflows: { incrementWorkflow },
|
|
6410
|
+
});
|
|
6411
|
+
|
|
6412
|
+
const run = await incrementWorkflow.createRunAsync();
|
|
6413
|
+
const result = await run.start({ inputData: { value: 0 } });
|
|
6414
|
+
expect(result.status).toBe('suspended');
|
|
6415
|
+
|
|
6416
|
+
const resumeResult = await run.resume({
|
|
6417
|
+
resumeData: { value: 21 },
|
|
6418
|
+
step: ['resume'],
|
|
6419
|
+
});
|
|
6420
|
+
|
|
6421
|
+
expect(resumeResult.status).toBe('success');
|
|
6422
|
+
});
|
|
6423
|
+
|
|
6424
|
+
it('should not show removed runtimeContext values in subsequent steps', async ctx => {
|
|
6425
|
+
const inngest = new Inngest({
|
|
6426
|
+
id: 'mastra',
|
|
6427
|
+
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
6428
|
+
});
|
|
6429
|
+
|
|
6430
|
+
const { createWorkflow, createStep } = init(inngest);
|
|
6431
|
+
const testValue = 'test-dependency';
|
|
6432
|
+
const resumeStep = createStep({
|
|
6433
|
+
id: 'resume',
|
|
6434
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6435
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6436
|
+
resumeSchema: z.object({ value: z.number() }),
|
|
6437
|
+
suspendSchema: z.object({ message: z.string() }),
|
|
6438
|
+
execute: async ({ inputData, resumeData, suspend, runtimeContext }) => {
|
|
6439
|
+
const finalValue = (resumeData?.value ?? 0) + inputData.value;
|
|
6440
|
+
|
|
6441
|
+
if (!resumeData?.value || finalValue < 10) {
|
|
6442
|
+
return await suspend({
|
|
6443
|
+
message: `Please provide additional information. now value is ${inputData.value}`,
|
|
6444
|
+
});
|
|
6445
|
+
}
|
|
6446
|
+
|
|
6447
|
+
const testKey = runtimeContext.get('testKey');
|
|
6448
|
+
expect(testKey).toBe(testValue);
|
|
6449
|
+
|
|
6450
|
+
runtimeContext.delete('testKey');
|
|
6451
|
+
|
|
6452
|
+
return { value: finalValue };
|
|
6453
|
+
},
|
|
6454
|
+
});
|
|
6455
|
+
|
|
6456
|
+
const incrementStep = createStep({
|
|
6457
|
+
id: 'increment',
|
|
6458
|
+
inputSchema: z.object({
|
|
6459
|
+
value: z.number(),
|
|
6460
|
+
}),
|
|
6461
|
+
outputSchema: z.object({
|
|
6462
|
+
value: z.number(),
|
|
6463
|
+
}),
|
|
6464
|
+
execute: async ({ inputData, runtimeContext }) => {
|
|
6465
|
+
runtimeContext.set('testKey', testValue);
|
|
6466
|
+
return {
|
|
6467
|
+
value: inputData.value + 1,
|
|
6468
|
+
};
|
|
6469
|
+
},
|
|
6470
|
+
});
|
|
6471
|
+
|
|
6472
|
+
const incrementWorkflow = createWorkflow({
|
|
6473
|
+
id: 'increment-workflow',
|
|
6474
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6475
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6476
|
+
})
|
|
6477
|
+
.then(incrementStep)
|
|
6478
|
+
.then(resumeStep)
|
|
6479
|
+
.then(
|
|
6480
|
+
createStep({
|
|
6481
|
+
id: 'final',
|
|
6482
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6483
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6484
|
+
execute: async ({ inputData, runtimeContext }) => {
|
|
6485
|
+
const testKey = runtimeContext.get('testKey');
|
|
6486
|
+
expect(testKey).toBeUndefined();
|
|
6487
|
+
return { value: inputData.value };
|
|
6488
|
+
},
|
|
6489
|
+
}),
|
|
6490
|
+
)
|
|
6491
|
+
.commit();
|
|
6492
|
+
|
|
6493
|
+
new Mastra({
|
|
6494
|
+
logger: false,
|
|
6495
|
+
storage: testStorage,
|
|
6496
|
+
workflows: { incrementWorkflow },
|
|
6497
|
+
});
|
|
6498
|
+
|
|
6499
|
+
const run = await incrementWorkflow.createRunAsync();
|
|
6500
|
+
const result = await run.start({ inputData: { value: 0 } });
|
|
6501
|
+
expect(result.status).toBe('suspended');
|
|
6502
|
+
|
|
6503
|
+
const resumeResult = await run.resume({
|
|
6504
|
+
resumeData: { value: 21 },
|
|
6505
|
+
step: ['resume'],
|
|
6506
|
+
});
|
|
6507
|
+
|
|
6508
|
+
expect(resumeResult.status).toBe('success');
|
|
6509
|
+
});
|
|
6510
|
+
});
|
|
6511
|
+
|
|
6512
|
+
describe('Access to inngest step primitives', () => {
|
|
6513
|
+
it('should inject inngest step primitives into steps during run', async ctx => {
|
|
6514
|
+
const inngest = new Inngest({
|
|
6515
|
+
id: 'mastra',
|
|
6516
|
+
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
6517
|
+
});
|
|
6518
|
+
|
|
6519
|
+
const { createWorkflow, createStep } = init(inngest);
|
|
6520
|
+
|
|
6521
|
+
const step = createStep({
|
|
6522
|
+
id: 'step1',
|
|
6523
|
+
execute: async ({ engine }) => {
|
|
6524
|
+
return {
|
|
6525
|
+
hasEngine: !!engine.step,
|
|
6526
|
+
};
|
|
6527
|
+
},
|
|
6528
|
+
inputSchema: z.object({}),
|
|
6529
|
+
outputSchema: z.object({}),
|
|
6530
|
+
});
|
|
6531
|
+
const workflow = createWorkflow({
|
|
6532
|
+
id: 'test-workflow',
|
|
6533
|
+
inputSchema: z.object({}),
|
|
6534
|
+
outputSchema: z.object({
|
|
6535
|
+
hasEngine: z.boolean(),
|
|
6536
|
+
}),
|
|
6061
6537
|
});
|
|
6062
6538
|
workflow.then(step).commit();
|
|
6063
6539
|
|
|
@@ -6473,6 +6949,215 @@ describe('MastraInngestWorkflow', () => {
|
|
|
6473
6949
|
});
|
|
6474
6950
|
});
|
|
6475
6951
|
|
|
6952
|
+
it('should handle basic sleep waiting flow with fn parameter', async ctx => {
|
|
6953
|
+
const inngest = new Inngest({
|
|
6954
|
+
id: 'mastra',
|
|
6955
|
+
baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
|
|
6956
|
+
middleware: [realtimeMiddleware()],
|
|
6957
|
+
});
|
|
6958
|
+
|
|
6959
|
+
const { createWorkflow, createStep } = init(inngest);
|
|
6960
|
+
|
|
6961
|
+
const step1Action = vi.fn<any>().mockResolvedValue({ value: 1000 });
|
|
6962
|
+
const step2Action = vi.fn<any>().mockResolvedValue({ value: 2000 });
|
|
6963
|
+
|
|
6964
|
+
const step1 = createStep({
|
|
6965
|
+
id: 'step1',
|
|
6966
|
+
execute: step1Action,
|
|
6967
|
+
inputSchema: z.object({}),
|
|
6968
|
+
outputSchema: z.object({ value: z.number() }),
|
|
6969
|
+
});
|
|
6970
|
+
const step2 = createStep({
|
|
6971
|
+
id: 'step2',
|
|
6972
|
+
execute: step2Action,
|
|
6973
|
+
inputSchema: z.object({ value: z.number() }),
|
|
6974
|
+
outputSchema: z.object({}),
|
|
6975
|
+
});
|
|
6976
|
+
|
|
6977
|
+
const workflow = createWorkflow({
|
|
6978
|
+
id: 'test-workflow',
|
|
6979
|
+
inputSchema: z.object({}),
|
|
6980
|
+
outputSchema: z.object({}),
|
|
6981
|
+
steps: [step1, step2],
|
|
6982
|
+
});
|
|
6983
|
+
workflow
|
|
6984
|
+
.then(step1)
|
|
6985
|
+
.sleep(async ({ inputData }) => {
|
|
6986
|
+
return inputData.value;
|
|
6987
|
+
})
|
|
6988
|
+
.then(step2)
|
|
6989
|
+
.commit();
|
|
6990
|
+
|
|
6991
|
+
const mastra = new Mastra({
|
|
6992
|
+
storage: new DefaultStorage({
|
|
6993
|
+
url: ':memory:',
|
|
6994
|
+
}),
|
|
6995
|
+
workflows: {
|
|
6996
|
+
'test-workflow': workflow,
|
|
6997
|
+
},
|
|
6998
|
+
server: {
|
|
6999
|
+
apiRoutes: [
|
|
7000
|
+
{
|
|
7001
|
+
path: '/inngest/api',
|
|
7002
|
+
method: 'ALL',
|
|
7003
|
+
createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
|
|
7004
|
+
},
|
|
7005
|
+
],
|
|
7006
|
+
},
|
|
7007
|
+
});
|
|
7008
|
+
|
|
7009
|
+
const app = await createHonoServer(mastra);
|
|
7010
|
+
|
|
7011
|
+
const srv = (globServer = serve({
|
|
7012
|
+
fetch: app.fetch,
|
|
7013
|
+
port: (ctx as any).handlerPort,
|
|
7014
|
+
}));
|
|
7015
|
+
await resetInngest();
|
|
7016
|
+
|
|
7017
|
+
const runId = 'test-run-id';
|
|
7018
|
+
let watchData: StreamEvent[] = [];
|
|
7019
|
+
const run = await workflow.createRunAsync({
|
|
7020
|
+
runId,
|
|
7021
|
+
});
|
|
7022
|
+
|
|
7023
|
+
await resetInngest();
|
|
7024
|
+
|
|
7025
|
+
const { stream, getWorkflowState } = run.stream({ inputData: {} });
|
|
7026
|
+
|
|
7027
|
+
// Start watching the workflow
|
|
7028
|
+
const collectedStreamData: StreamEvent[] = [];
|
|
7029
|
+
for await (const data of stream) {
|
|
7030
|
+
collectedStreamData.push(JSON.parse(JSON.stringify(data)));
|
|
7031
|
+
}
|
|
7032
|
+
watchData = collectedStreamData;
|
|
7033
|
+
|
|
7034
|
+
const executionResult = await getWorkflowState();
|
|
7035
|
+
|
|
7036
|
+
await resetInngest();
|
|
7037
|
+
|
|
7038
|
+
srv.close();
|
|
7039
|
+
|
|
7040
|
+
expect(watchData.length).toBe(11);
|
|
7041
|
+
expect(watchData).toMatchObject([
|
|
7042
|
+
{
|
|
7043
|
+
payload: {
|
|
7044
|
+
runId: 'test-run-id',
|
|
7045
|
+
},
|
|
7046
|
+
type: 'start',
|
|
7047
|
+
},
|
|
7048
|
+
{
|
|
7049
|
+
payload: {
|
|
7050
|
+
id: 'step1',
|
|
7051
|
+
startedAt: expect.any(Number),
|
|
7052
|
+
status: 'running',
|
|
7053
|
+
payload: {},
|
|
7054
|
+
},
|
|
7055
|
+
type: 'step-start',
|
|
7056
|
+
},
|
|
7057
|
+
{
|
|
7058
|
+
payload: {
|
|
7059
|
+
id: 'step1',
|
|
7060
|
+
output: {
|
|
7061
|
+
value: 1000,
|
|
7062
|
+
},
|
|
7063
|
+
endedAt: expect.any(Number),
|
|
7064
|
+
status: 'success',
|
|
7065
|
+
},
|
|
7066
|
+
type: 'step-result',
|
|
7067
|
+
},
|
|
7068
|
+
{
|
|
7069
|
+
payload: {
|
|
7070
|
+
id: 'step1',
|
|
7071
|
+
metadata: {},
|
|
7072
|
+
},
|
|
7073
|
+
type: 'step-finish',
|
|
7074
|
+
},
|
|
7075
|
+
{
|
|
7076
|
+
payload: {
|
|
7077
|
+
id: expect.any(String),
|
|
7078
|
+
startedAt: expect.any(Number),
|
|
7079
|
+
status: 'waiting',
|
|
7080
|
+
payload: {
|
|
7081
|
+
value: 1000,
|
|
7082
|
+
},
|
|
7083
|
+
},
|
|
7084
|
+
type: 'step-waiting',
|
|
7085
|
+
},
|
|
7086
|
+
{
|
|
7087
|
+
payload: {
|
|
7088
|
+
id: expect.any(String),
|
|
7089
|
+
endedAt: expect.any(Number),
|
|
7090
|
+
startedAt: expect.any(Number),
|
|
7091
|
+
status: 'success',
|
|
7092
|
+
output: {
|
|
7093
|
+
value: 1000,
|
|
7094
|
+
},
|
|
7095
|
+
},
|
|
7096
|
+
type: 'step-result',
|
|
7097
|
+
},
|
|
7098
|
+
{
|
|
7099
|
+
type: 'step-finish',
|
|
7100
|
+
payload: {
|
|
7101
|
+
id: expect.any(String),
|
|
7102
|
+
metadata: {},
|
|
7103
|
+
},
|
|
7104
|
+
},
|
|
7105
|
+
{
|
|
7106
|
+
payload: {
|
|
7107
|
+
id: 'step2',
|
|
7108
|
+
payload: {
|
|
7109
|
+
value: 1000,
|
|
7110
|
+
},
|
|
7111
|
+
startedAt: expect.any(Number),
|
|
7112
|
+
status: 'running',
|
|
7113
|
+
},
|
|
7114
|
+
type: 'step-start',
|
|
7115
|
+
},
|
|
7116
|
+
{
|
|
7117
|
+
payload: {
|
|
7118
|
+
id: 'step2',
|
|
7119
|
+
output: {
|
|
7120
|
+
value: 2000,
|
|
7121
|
+
},
|
|
7122
|
+
endedAt: expect.any(Number),
|
|
7123
|
+
status: 'success',
|
|
7124
|
+
},
|
|
7125
|
+
type: 'step-result',
|
|
7126
|
+
},
|
|
7127
|
+
{
|
|
7128
|
+
payload: {
|
|
7129
|
+
id: 'step2',
|
|
7130
|
+
metadata: {},
|
|
7131
|
+
},
|
|
7132
|
+
type: 'step-finish',
|
|
7133
|
+
},
|
|
7134
|
+
{
|
|
7135
|
+
payload: {
|
|
7136
|
+
runId: 'test-run-id',
|
|
7137
|
+
},
|
|
7138
|
+
type: 'finish',
|
|
7139
|
+
},
|
|
7140
|
+
]);
|
|
7141
|
+
|
|
7142
|
+
// Verify execution completed successfully
|
|
7143
|
+
expect(executionResult.steps.step1).toMatchObject({
|
|
7144
|
+
status: 'success',
|
|
7145
|
+
output: { value: 1000 },
|
|
7146
|
+
payload: {},
|
|
7147
|
+
startedAt: expect.any(Number),
|
|
7148
|
+
endedAt: expect.any(Number),
|
|
7149
|
+
});
|
|
7150
|
+
expect(executionResult.steps.step2).toMatchObject({
|
|
7151
|
+
status: 'success',
|
|
7152
|
+
output: { value: 2000 },
|
|
7153
|
+
payload: {
|
|
7154
|
+
value: 1000,
|
|
7155
|
+
},
|
|
7156
|
+
startedAt: expect.any(Number),
|
|
7157
|
+
endedAt: expect.any(Number),
|
|
7158
|
+
});
|
|
7159
|
+
});
|
|
7160
|
+
|
|
6476
7161
|
it('should handle waitForEvent waiting flow', async ctx => {
|
|
6477
7162
|
const inngest = new Inngest({
|
|
6478
7163
|
id: 'mastra',
|