@mastra/inngest 0.10.4 → 0.10.5-alpha.1

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/dist/index.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import { subscribe } from '@inngest/realtime';
3
+ import { Agent, Tool } from '@mastra/core';
3
4
  import { RuntimeContext } from '@mastra/core/di';
4
- import { Run, Workflow, cloneStep, createStep, DefaultExecutionEngine } from '@mastra/core/workflows';
5
+ import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
5
6
  import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
6
7
  import { serve as serve$1 } from 'inngest/hono';
8
+ import { z } from 'zod';
7
9
 
8
10
  // src/index.ts
9
11
  function serve({ mastra, inngest }) {
@@ -161,11 +163,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
161
163
  const storage = this.#mastra?.getStorage();
162
164
  if (!storage) {
163
165
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
164
- return null;
166
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
165
167
  }
166
168
  const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
167
169
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
168
170
  }
171
+ async getWorkflowRunExecutionResult(runId) {
172
+ const storage = this.#mastra?.getStorage();
173
+ if (!storage) {
174
+ this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
175
+ return null;
176
+ }
177
+ const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
178
+ if (!run?.snapshot) {
179
+ return null;
180
+ }
181
+ if (typeof run.snapshot === "string") {
182
+ return null;
183
+ }
184
+ return {
185
+ status: run.snapshot.status,
186
+ result: run.snapshot.result,
187
+ error: run.snapshot.error,
188
+ payload: run.snapshot.context?.input,
189
+ steps: run.snapshot.context
190
+ };
191
+ }
169
192
  __registerMastra(mastra) {
170
193
  this.#mastra = mastra;
171
194
  this.executionEngine.__registerMastra(mastra);
@@ -268,31 +291,128 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
268
291
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
269
292
  }
270
293
  };
271
- function cloneWorkflow(workflow, opts) {
272
- const wf = new InngestWorkflow(
273
- {
274
- id: opts.id,
275
- inputSchema: workflow.inputSchema,
276
- outputSchema: workflow.outputSchema,
277
- steps: workflow.stepDefs,
278
- mastra: workflow.mastra
279
- },
280
- workflow.inngest
281
- );
282
- wf.setStepFlow(workflow.stepGraph);
283
- wf.commit();
284
- return wf;
294
+ function createStep(params) {
295
+ if (params instanceof Agent) {
296
+ return {
297
+ id: params.name,
298
+ // @ts-ignore
299
+ inputSchema: z.object({
300
+ prompt: z.string()
301
+ // resourceId: z.string().optional(),
302
+ // threadId: z.string().optional(),
303
+ }),
304
+ // @ts-ignore
305
+ outputSchema: z.object({
306
+ text: z.string()
307
+ }),
308
+ execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
309
+ let streamPromise = {};
310
+ streamPromise.promise = new Promise((resolve, reject) => {
311
+ streamPromise.resolve = resolve;
312
+ streamPromise.reject = reject;
313
+ });
314
+ const toolData = {
315
+ name: params.name,
316
+ args: inputData
317
+ };
318
+ await emitter.emit("watch-v2", {
319
+ type: "tool-call-streaming-start",
320
+ ...toolData
321
+ });
322
+ const { fullStream } = await params.stream(inputData.prompt, {
323
+ // resourceId: inputData.resourceId,
324
+ // threadId: inputData.threadId,
325
+ runtimeContext,
326
+ onFinish: (result) => {
327
+ streamPromise.resolve(result.text);
328
+ }
329
+ });
330
+ for await (const chunk of fullStream) {
331
+ switch (chunk.type) {
332
+ case "text-delta":
333
+ await emitter.emit("watch-v2", {
334
+ type: "tool-call-delta",
335
+ ...toolData,
336
+ argsTextDelta: chunk.textDelta
337
+ });
338
+ break;
339
+ case "step-start":
340
+ case "step-finish":
341
+ case "finish":
342
+ break;
343
+ case "tool-call":
344
+ case "tool-result":
345
+ case "tool-call-streaming-start":
346
+ case "tool-call-delta":
347
+ case "source":
348
+ case "file":
349
+ default:
350
+ await emitter.emit("watch-v2", chunk);
351
+ break;
352
+ }
353
+ }
354
+ return {
355
+ text: await streamPromise.promise
356
+ };
357
+ }
358
+ };
359
+ }
360
+ if (params instanceof Tool) {
361
+ if (!params.inputSchema || !params.outputSchema) {
362
+ throw new Error("Tool must have input and output schemas defined");
363
+ }
364
+ return {
365
+ // TODO: tool probably should have strong id type
366
+ // @ts-ignore
367
+ id: params.id,
368
+ inputSchema: params.inputSchema,
369
+ outputSchema: params.outputSchema,
370
+ execute: async ({ inputData, mastra, runtimeContext }) => {
371
+ return params.execute({
372
+ context: inputData,
373
+ mastra,
374
+ runtimeContext
375
+ });
376
+ }
377
+ };
378
+ }
379
+ return {
380
+ id: params.id,
381
+ description: params.description,
382
+ inputSchema: params.inputSchema,
383
+ outputSchema: params.outputSchema,
384
+ resumeSchema: params.resumeSchema,
385
+ suspendSchema: params.suspendSchema,
386
+ execute: params.execute
387
+ };
285
388
  }
286
389
  function init(inngest) {
287
390
  return {
288
391
  createWorkflow(params) {
289
392
  return new InngestWorkflow(params, inngest);
290
393
  },
291
- createStep(params) {
292
- return createStep(params);
394
+ createStep,
395
+ cloneStep(step, opts) {
396
+ return {
397
+ id: opts.id,
398
+ description: step.description,
399
+ inputSchema: step.inputSchema,
400
+ outputSchema: step.outputSchema,
401
+ execute: step.execute
402
+ };
293
403
  },
294
- cloneStep,
295
- cloneWorkflow
404
+ cloneWorkflow(workflow, opts) {
405
+ const wf = new Workflow({
406
+ id: opts.id,
407
+ inputSchema: workflow.inputSchema,
408
+ outputSchema: workflow.outputSchema,
409
+ steps: workflow.stepDefs,
410
+ mastra: workflow.mastra
411
+ });
412
+ wf.setStepFlow(workflow.stepGraph);
413
+ wf.commit();
414
+ return wf;
415
+ }
296
416
  };
297
417
  }
298
418
  var InngestExecutionEngine = class extends DefaultExecutionEngine {
@@ -383,6 +503,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
383
503
  runtimeContext
384
504
  });
385
505
  }
506
+ async executeSleep({ id, duration }) {
507
+ await this.inngestStep.sleep(id, duration);
508
+ }
386
509
  async executeStep({
387
510
  step,
388
511
  stepResults,
@@ -753,4 +876,4 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
753
876
  }
754
877
  };
755
878
 
756
- export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
879
+ export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/inngest",
3
- "version": "0.10.4",
3
+ "version": "0.10.5-alpha.1",
4
4
  "description": "Mastra Inngest integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,27 +20,27 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@inngest/realtime": "^0.3.1",
23
- "inngest": "^3.35.1",
24
- "zod": "^3.25.56",
25
- "@opentelemetry/api": "^1.9.0"
23
+ "@opentelemetry/api": "^1.9.0",
24
+ "inngest": "^3.39.1",
25
+ "zod": "^3.25.57"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@ai-sdk/openai": "^1.3.22",
29
- "@hono/node-server": "^1.14.3",
29
+ "@hono/node-server": "^1.14.4",
30
30
  "@microsoft/api-extractor": "^7.52.8",
31
- "@types/node": "^20.17.57",
32
- "ai": "^4.3.15",
31
+ "@types/node": "^20.19.0",
32
+ "ai": "^4.3.16",
33
33
  "eslint": "^9.28.0",
34
34
  "execa": "^9.6.0",
35
35
  "get-port": "7.1.0",
36
- "hono": "^4.7.7",
36
+ "hono": "^4.7.11",
37
37
  "tsup": "^8.5.0",
38
- "typescript": "^5.8.2",
38
+ "typescript": "^5.8.3",
39
39
  "vitest": "^2.1.9",
40
40
  "@internal/lint": "0.0.12",
41
- "@mastra/deployer": "0.10.5",
42
- "@mastra/core": "0.10.5",
43
- "@mastra/libsql": "0.10.2"
41
+ "@mastra/core": "0.10.6-alpha.1",
42
+ "@mastra/deployer": "0.10.6-alpha.1",
43
+ "@mastra/libsql": "0.10.3-alpha.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@mastra/core": "^0.10.2-alpha.0"
package/src/index.test.ts CHANGED
@@ -259,6 +259,186 @@ describe('MastraInngestWorkflow', () => {
259
259
 
260
260
  srv.close();
261
261
  });
262
+
263
+ it('should execute a a sleep step', async ctx => {
264
+ const inngest = new Inngest({
265
+ id: 'mastra',
266
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
267
+ });
268
+
269
+ const { createWorkflow, createStep } = init(inngest);
270
+
271
+ const execute = vi.fn<any>().mockResolvedValue({ result: 'success' });
272
+ const step1 = createStep({
273
+ id: 'step1',
274
+ execute,
275
+ inputSchema: z.object({}),
276
+ outputSchema: z.object({ result: z.string() }),
277
+ });
278
+ const step2 = createStep({
279
+ id: 'step2',
280
+ execute: async ({ inputData }) => {
281
+ return { result: 'slept successfully: ' + inputData.result };
282
+ },
283
+ inputSchema: z.object({ result: z.string() }),
284
+ outputSchema: z.object({ result: z.string() }),
285
+ });
286
+
287
+ const workflow = createWorkflow({
288
+ id: 'test-workflow',
289
+ inputSchema: z.object({}),
290
+ outputSchema: z.object({
291
+ result: z.string(),
292
+ }),
293
+ steps: [step1],
294
+ });
295
+
296
+ workflow.then(step1).sleep(1000).then(step2).commit();
297
+
298
+ const mastra = new Mastra({
299
+ storage: new DefaultStorage({
300
+ url: ':memory:',
301
+ }),
302
+ workflows: {
303
+ 'test-workflow': workflow,
304
+ },
305
+ server: {
306
+ apiRoutes: [
307
+ {
308
+ path: '/inngest/api',
309
+ method: 'ALL',
310
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
311
+ },
312
+ ],
313
+ },
314
+ });
315
+
316
+ const app = await createHonoServer(mastra);
317
+
318
+ const srv = serve({
319
+ fetch: app.fetch,
320
+ port: (ctx as any).handlerPort,
321
+ });
322
+ await new Promise(resolve => setTimeout(resolve, 2000));
323
+
324
+ const run = workflow.createRun();
325
+ const startTime = Date.now();
326
+ const result = await run.start({ inputData: {} });
327
+ const endTime = Date.now();
328
+
329
+ expect(execute).toHaveBeenCalled();
330
+ expect(result.steps['step1']).toEqual({
331
+ status: 'success',
332
+ output: { result: 'success' },
333
+ // payload: {},
334
+ // startedAt: expect.any(Number),
335
+ // endedAt: expect.any(Number),
336
+ });
337
+
338
+ expect(result.steps['step2']).toEqual({
339
+ status: 'success',
340
+ output: { result: 'slept successfully: success' },
341
+ // payload: { result: 'success' },
342
+ // startedAt: expect.any(Number),
343
+ // endedAt: expect.any(Number),
344
+ });
345
+
346
+ expect(endTime - startTime).toBeGreaterThan(1000);
347
+
348
+ srv.close();
349
+ });
350
+
351
+ it('should execute a a sleep until step', async ctx => {
352
+ const inngest = new Inngest({
353
+ id: 'mastra',
354
+ baseUrl: `http://localhost:${(ctx as any).inngestPort}`,
355
+ });
356
+
357
+ const { createWorkflow, createStep } = init(inngest);
358
+
359
+ const execute = vi.fn<any>().mockResolvedValue({ result: 'success' });
360
+ const step1 = createStep({
361
+ id: 'step1',
362
+ execute,
363
+ inputSchema: z.object({}),
364
+ outputSchema: z.object({ result: z.string() }),
365
+ });
366
+ const step2 = createStep({
367
+ id: 'step2',
368
+ execute: async ({ inputData }) => {
369
+ return { result: 'slept successfully: ' + inputData.result };
370
+ },
371
+ inputSchema: z.object({ result: z.string() }),
372
+ outputSchema: z.object({ result: z.string() }),
373
+ });
374
+
375
+ const workflow = createWorkflow({
376
+ id: 'test-workflow',
377
+ inputSchema: z.object({}),
378
+ outputSchema: z.object({
379
+ result: z.string(),
380
+ }),
381
+ steps: [step1],
382
+ });
383
+
384
+ workflow
385
+ .then(step1)
386
+ .sleepUntil(new Date(Date.now() + 1000))
387
+ .then(step2)
388
+ .commit();
389
+
390
+ const mastra = new Mastra({
391
+ storage: new DefaultStorage({
392
+ url: ':memory:',
393
+ }),
394
+ workflows: {
395
+ 'test-workflow': workflow,
396
+ },
397
+ server: {
398
+ apiRoutes: [
399
+ {
400
+ path: '/inngest/api',
401
+ method: 'ALL',
402
+ createHandler: async ({ mastra }) => inngestServe({ mastra, inngest }),
403
+ },
404
+ ],
405
+ },
406
+ });
407
+
408
+ const app = await createHonoServer(mastra);
409
+
410
+ const srv = serve({
411
+ fetch: app.fetch,
412
+ port: (ctx as any).handlerPort,
413
+ });
414
+ await new Promise(resolve => setTimeout(resolve, 2000));
415
+
416
+ const run = workflow.createRun();
417
+ const startTime = Date.now();
418
+ const result = await run.start({ inputData: {} });
419
+ const endTime = Date.now();
420
+
421
+ expect(execute).toHaveBeenCalled();
422
+ expect(result.steps['step1']).toEqual({
423
+ status: 'success',
424
+ output: { result: 'success' },
425
+ // payload: {},
426
+ // startedAt: expect.any(Number),
427
+ // endedAt: expect.any(Number),
428
+ });
429
+
430
+ expect(result.steps['step2']).toEqual({
431
+ status: 'success',
432
+ output: { result: 'slept successfully: success' },
433
+ // payload: { result: 'success' },
434
+ // startedAt: expect.any(Number),
435
+ // endedAt: expect.any(Number),
436
+ });
437
+
438
+ expect(endTime - startTime).toBeGreaterThan(1000);
439
+
440
+ srv.close();
441
+ });
262
442
  });
263
443
 
264
444
  describe('Variable Resolution', () => {
@@ -4781,7 +4961,6 @@ describe('MastraInngestWorkflow', () => {
4781
4961
 
4782
4962
  const app = await createHonoServer(mastra);
4783
4963
  app.use('*', async (ctx, next) => {
4784
- 'middleware', ctx.req.method, ctx.req.url;
4785
4964
  await next();
4786
4965
  });
4787
4966