@mastra/inngest 0.0.0-generate-message-id-20250512171942 → 0.0.0-mcp-changeset-20250707162621

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.cjs CHANGED
@@ -3,34 +3,43 @@
3
3
  var crypto = require('crypto');
4
4
  var realtime = require('@inngest/realtime');
5
5
  var di = require('@mastra/core/di');
6
- var vNext = require('@mastra/core/workflows/vNext');
6
+ var tools = require('@mastra/core/tools');
7
+ var workflows = require('@mastra/core/workflows');
8
+ var _constants = require('@mastra/core/workflows/_constants');
7
9
  var hono = require('inngest/hono');
10
+ var zod = require('zod');
8
11
 
9
12
  // src/index.ts
10
13
  function serve({ mastra, inngest }) {
11
- const wfs = mastra.vnext_getWorkflows();
12
- const functions = Object.values(wfs).flatMap((wf) => {
13
- if (wf instanceof InngestWorkflow) {
14
- wf.__registerMastra(mastra);
15
- return wf.getFunctions();
16
- }
17
- return [];
18
- });
14
+ const wfs = mastra.getWorkflows();
15
+ const functions = Array.from(
16
+ new Set(
17
+ Object.values(wfs).flatMap((wf) => {
18
+ if (wf instanceof InngestWorkflow) {
19
+ wf.__registerMastra(mastra);
20
+ return wf.getFunctions();
21
+ }
22
+ return [];
23
+ })
24
+ )
25
+ );
19
26
  return hono.serve({
20
27
  client: inngest,
21
28
  functions
22
29
  });
23
30
  }
24
- var InngestRun = class extends vNext.Run {
31
+ var InngestRun = class extends workflows.Run {
25
32
  inngest;
33
+ serializedStepGraph;
26
34
  #mastra;
27
35
  constructor(params, inngest) {
28
36
  super(params);
29
37
  this.inngest = inngest;
38
+ this.serializedStepGraph = params.serializedStepGraph;
30
39
  this.#mastra = params.mastra;
31
40
  }
32
41
  async getRuns(eventId) {
33
- const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
42
+ const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
34
43
  headers: {
35
44
  Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
36
45
  }
@@ -40,15 +49,50 @@ var InngestRun = class extends vNext.Run {
40
49
  }
41
50
  async getRunOutput(eventId) {
42
51
  let runs = await this.getRuns(eventId);
43
- while (runs?.[0]?.status !== "Completed") {
52
+ while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
44
53
  await new Promise((resolve) => setTimeout(resolve, 1e3));
45
54
  runs = await this.getRuns(eventId);
46
- if (runs?.[0]?.status === "Failed" || runs?.[0]?.status === "Cancelled") {
55
+ if (runs?.[0]?.status === "Failed") {
56
+ console.log("run", runs?.[0]);
47
57
  throw new Error(`Function run ${runs?.[0]?.status}`);
58
+ } else if (runs?.[0]?.status === "Cancelled") {
59
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
60
+ workflowName: this.workflowId,
61
+ runId: this.runId
62
+ });
63
+ return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
48
64
  }
49
65
  }
50
66
  return runs?.[0];
51
67
  }
68
+ async sendEvent(event, data) {
69
+ await this.inngest.send({
70
+ name: `user-event-${event}`,
71
+ data
72
+ });
73
+ }
74
+ async cancel() {
75
+ await this.inngest.send({
76
+ name: `cancel.workflow.${this.workflowId}`,
77
+ data: {
78
+ runId: this.runId
79
+ }
80
+ });
81
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
82
+ workflowName: this.workflowId,
83
+ runId: this.runId
84
+ });
85
+ if (snapshot) {
86
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
87
+ workflowName: this.workflowId,
88
+ runId: this.runId,
89
+ snapshot: {
90
+ ...snapshot,
91
+ status: "canceled"
92
+ }
93
+ });
94
+ }
95
+ }
52
96
  async start({
53
97
  inputData
54
98
  }) {
@@ -57,11 +101,13 @@ var InngestRun = class extends vNext.Run {
57
101
  runId: this.runId,
58
102
  snapshot: {
59
103
  runId: this.runId,
104
+ serializedStepGraph: this.serializedStepGraph,
60
105
  value: {},
61
106
  context: {},
62
107
  activePaths: [],
63
108
  suspendedPaths: {},
64
- timestamp: Date.now()
109
+ timestamp: Date.now(),
110
+ status: "running"
65
111
  }
66
112
  });
67
113
  const eventOutput = await this.inngest.send({
@@ -80,10 +126,23 @@ var InngestRun = class extends vNext.Run {
80
126
  if (result.status === "failed") {
81
127
  result.error = new Error(result.error);
82
128
  }
83
- this.cleanup?.();
129
+ if (result.status !== "suspended") {
130
+ this.cleanup?.();
131
+ }
84
132
  return result;
85
133
  }
86
134
  async resume(params) {
135
+ const p = this._resume(params).then((result) => {
136
+ if (result.status !== "suspended") {
137
+ this.closeStreamAction?.().catch(() => {
138
+ });
139
+ }
140
+ return result;
141
+ });
142
+ this.executionResults = p;
143
+ return p;
144
+ }
145
+ async _resume(params) {
87
146
  const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
88
147
  (step) => typeof step === "string" ? step : step?.id
89
148
  );
@@ -117,27 +176,62 @@ var InngestRun = class extends vNext.Run {
117
176
  }
118
177
  return result;
119
178
  }
120
- watch(cb) {
179
+ watch(cb, type = "watch") {
180
+ let active = true;
121
181
  const streamPromise = realtime.subscribe(
122
182
  {
123
183
  channel: `workflow:${this.workflowId}:${this.runId}`,
124
- topics: ["watch"],
184
+ topics: [type],
125
185
  app: this.inngest
126
186
  },
127
187
  (message) => {
128
- cb(message.data);
188
+ if (active) {
189
+ cb(message.data);
190
+ }
129
191
  }
130
192
  );
131
193
  return () => {
132
- streamPromise.then((stream) => {
133
- stream.cancel();
194
+ active = false;
195
+ streamPromise.then(async (stream) => {
196
+ return stream.cancel();
134
197
  }).catch((err) => {
135
198
  console.error(err);
136
199
  });
137
200
  };
138
201
  }
202
+ stream({ inputData, runtimeContext } = {}) {
203
+ const { readable, writable } = new TransformStream();
204
+ const writer = writable.getWriter();
205
+ const unwatch = this.watch(async (event) => {
206
+ try {
207
+ await writer.write(event);
208
+ } catch {
209
+ }
210
+ }, "watch-v2");
211
+ this.closeStreamAction = async () => {
212
+ unwatch();
213
+ try {
214
+ await writer.close();
215
+ } catch (err) {
216
+ console.error("Error closing stream:", err);
217
+ } finally {
218
+ writer.releaseLock();
219
+ }
220
+ };
221
+ this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
222
+ if (result.status !== "suspended") {
223
+ this.closeStreamAction?.().catch(() => {
224
+ });
225
+ }
226
+ return result;
227
+ });
228
+ return {
229
+ stream: readable,
230
+ getWorkflowState: () => this.executionResults
231
+ };
232
+ }
139
233
  };
140
- var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
234
+ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
141
235
  #mastra;
142
236
  inngest;
143
237
  function;
@@ -158,11 +252,32 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
158
252
  const storage = this.#mastra?.getStorage();
159
253
  if (!storage) {
160
254
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
161
- return null;
255
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
162
256
  }
163
257
  const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
164
258
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
165
259
  }
260
+ async getWorkflowRunExecutionResult(runId) {
261
+ const storage = this.#mastra?.getStorage();
262
+ if (!storage) {
263
+ this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
264
+ return null;
265
+ }
266
+ const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
267
+ if (!run?.snapshot) {
268
+ return null;
269
+ }
270
+ if (typeof run.snapshot === "string") {
271
+ return null;
272
+ }
273
+ return {
274
+ status: run.snapshot.status,
275
+ result: run.snapshot.result,
276
+ error: run.snapshot.error,
277
+ payload: run.snapshot.context?.input,
278
+ steps: run.snapshot.context
279
+ };
280
+ }
166
281
  __registerMastra(mastra) {
167
282
  this.#mastra = mastra;
168
283
  this.executionEngine.__registerMastra(mastra);
@@ -189,6 +304,7 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
189
304
  runId: runIdToUse,
190
305
  executionEngine: this.executionEngine,
191
306
  executionGraph: this.executionGraph,
307
+ serializedStepGraph: this.serializedStepGraph,
192
308
  mastra: this.#mastra,
193
309
  retryConfig: this.retryConfig,
194
310
  cleanup: () => this.runs.delete(runIdToUse)
@@ -198,13 +314,55 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
198
314
  this.runs.set(runIdToUse, run);
199
315
  return run;
200
316
  }
317
+ async createRunAsync(options) {
318
+ const runIdToUse = options?.runId || crypto.randomUUID();
319
+ const run = this.runs.get(runIdToUse) ?? new InngestRun(
320
+ {
321
+ workflowId: this.id,
322
+ runId: runIdToUse,
323
+ executionEngine: this.executionEngine,
324
+ executionGraph: this.executionGraph,
325
+ serializedStepGraph: this.serializedStepGraph,
326
+ mastra: this.#mastra,
327
+ retryConfig: this.retryConfig,
328
+ cleanup: () => this.runs.delete(runIdToUse)
329
+ },
330
+ this.inngest
331
+ );
332
+ this.runs.set(runIdToUse, run);
333
+ const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
334
+ if (!workflowSnapshotInStorage) {
335
+ await this.mastra?.getStorage()?.persistWorkflowSnapshot({
336
+ workflowName: this.id,
337
+ runId: runIdToUse,
338
+ snapshot: {
339
+ runId: runIdToUse,
340
+ status: "pending",
341
+ value: {},
342
+ context: {},
343
+ activePaths: [],
344
+ serializedStepGraph: this.serializedStepGraph,
345
+ suspendedPaths: {},
346
+ result: void 0,
347
+ error: void 0,
348
+ // @ts-ignore
349
+ timestamp: Date.now()
350
+ }
351
+ });
352
+ }
353
+ return run;
354
+ }
201
355
  getFunction() {
202
356
  if (this.function) {
203
357
  return this.function;
204
358
  }
205
359
  this.function = this.inngest.createFunction(
206
- // @ts-ignore
207
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
360
+ {
361
+ id: `workflow.${this.id}`,
362
+ // @ts-ignore
363
+ retries: this.retryConfig?.attempts ?? 0,
364
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }]
365
+ },
208
366
  { event: `workflow.${this.id}` },
209
367
  async ({ event, step, attempt, publish }) => {
210
368
  let { inputData, runId, resume } = event.data;
@@ -221,12 +379,18 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
221
379
  try {
222
380
  await publish({
223
381
  channel: `workflow:${this.id}:${runId}`,
224
- topic: "watch",
382
+ topic: event2,
225
383
  data
226
384
  });
227
385
  } catch (err) {
228
386
  this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
229
387
  }
388
+ },
389
+ on: (_event, _callback) => {
390
+ },
391
+ off: (_event, _callback) => {
392
+ },
393
+ once: (_event, _callback) => {
230
394
  }
231
395
  };
232
396
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
@@ -234,12 +398,14 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
234
398
  workflowId: this.id,
235
399
  runId,
236
400
  graph: this.executionGraph,
401
+ serializedStepGraph: this.serializedStepGraph,
237
402
  input: inputData,
238
403
  emitter,
239
404
  retryConfig: this.retryConfig,
240
405
  runtimeContext: new di.RuntimeContext(),
241
406
  // TODO
242
- resume
407
+ resume,
408
+ abortController: new AbortController()
243
409
  });
244
410
  return { result, runId };
245
411
  }
@@ -263,32 +429,141 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
263
429
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
264
430
  }
265
431
  };
266
- function cloneWorkflow(workflow, opts) {
267
- const wf = new InngestWorkflow(
268
- {
269
- id: opts.id,
270
- inputSchema: workflow.inputSchema,
271
- outputSchema: workflow.outputSchema,
272
- steps: workflow.stepDefs,
273
- mastra: workflow.mastra
274
- },
275
- workflow.inngest
276
- );
277
- wf.setStepFlow(workflow.stepGraph);
278
- wf.commit();
279
- return wf;
432
+ function isAgent(params) {
433
+ return params?.component === "AGENT";
434
+ }
435
+ function isTool(params) {
436
+ return params instanceof tools.Tool;
437
+ }
438
+ function createStep(params) {
439
+ if (isAgent(params)) {
440
+ return {
441
+ id: params.name,
442
+ // @ts-ignore
443
+ inputSchema: zod.z.object({
444
+ prompt: zod.z.string()
445
+ // resourceId: z.string().optional(),
446
+ // threadId: z.string().optional(),
447
+ }),
448
+ // @ts-ignore
449
+ outputSchema: zod.z.object({
450
+ text: zod.z.string()
451
+ }),
452
+ execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
453
+ let streamPromise = {};
454
+ streamPromise.promise = new Promise((resolve, reject) => {
455
+ streamPromise.resolve = resolve;
456
+ streamPromise.reject = reject;
457
+ });
458
+ const toolData = {
459
+ name: params.name,
460
+ args: inputData
461
+ };
462
+ await emitter.emit("watch-v2", {
463
+ type: "tool-call-streaming-start",
464
+ ...toolData
465
+ });
466
+ const { fullStream } = await params.stream(inputData.prompt, {
467
+ // resourceId: inputData.resourceId,
468
+ // threadId: inputData.threadId,
469
+ runtimeContext,
470
+ onFinish: (result) => {
471
+ streamPromise.resolve(result.text);
472
+ },
473
+ abortSignal
474
+ });
475
+ if (abortSignal.aborted) {
476
+ return abort();
477
+ }
478
+ for await (const chunk of fullStream) {
479
+ switch (chunk.type) {
480
+ case "text-delta":
481
+ await emitter.emit("watch-v2", {
482
+ type: "tool-call-delta",
483
+ ...toolData,
484
+ argsTextDelta: chunk.textDelta
485
+ });
486
+ break;
487
+ case "step-start":
488
+ case "step-finish":
489
+ case "finish":
490
+ break;
491
+ case "tool-call":
492
+ case "tool-result":
493
+ case "tool-call-streaming-start":
494
+ case "tool-call-delta":
495
+ case "source":
496
+ case "file":
497
+ default:
498
+ await emitter.emit("watch-v2", chunk);
499
+ break;
500
+ }
501
+ }
502
+ return {
503
+ text: await streamPromise.promise
504
+ };
505
+ }
506
+ };
507
+ }
508
+ if (isTool(params)) {
509
+ if (!params.inputSchema || !params.outputSchema) {
510
+ throw new Error("Tool must have input and output schemas defined");
511
+ }
512
+ return {
513
+ // TODO: tool probably should have strong id type
514
+ // @ts-ignore
515
+ id: params.id,
516
+ inputSchema: params.inputSchema,
517
+ outputSchema: params.outputSchema,
518
+ execute: async ({ inputData, mastra, runtimeContext }) => {
519
+ return params.execute({
520
+ context: inputData,
521
+ mastra,
522
+ runtimeContext
523
+ });
524
+ }
525
+ };
526
+ }
527
+ return {
528
+ id: params.id,
529
+ description: params.description,
530
+ inputSchema: params.inputSchema,
531
+ outputSchema: params.outputSchema,
532
+ resumeSchema: params.resumeSchema,
533
+ suspendSchema: params.suspendSchema,
534
+ execute: params.execute
535
+ };
280
536
  }
281
537
  function init(inngest) {
282
538
  return {
283
539
  createWorkflow(params) {
284
540
  return new InngestWorkflow(params, inngest);
285
541
  },
286
- createStep: vNext.createStep,
287
- cloneStep: vNext.cloneStep,
288
- cloneWorkflow
542
+ createStep,
543
+ cloneStep(step, opts) {
544
+ return {
545
+ id: opts.id,
546
+ description: step.description,
547
+ inputSchema: step.inputSchema,
548
+ outputSchema: step.outputSchema,
549
+ execute: step.execute
550
+ };
551
+ },
552
+ cloneWorkflow(workflow, opts) {
553
+ const wf = new workflows.Workflow({
554
+ id: opts.id,
555
+ inputSchema: workflow.inputSchema,
556
+ outputSchema: workflow.outputSchema,
557
+ steps: workflow.stepDefs,
558
+ mastra: workflow.mastra
559
+ });
560
+ wf.setStepFlow(workflow.stepGraph);
561
+ wf.commit();
562
+ return wf;
563
+ }
289
564
  };
290
565
  }
291
- var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
566
+ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
292
567
  inngestStep;
293
568
  inngestAttempts;
294
569
  constructor(mastra, inngestStep, inngestAttempts = 0) {
@@ -296,6 +571,18 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
296
571
  this.inngestStep = inngestStep;
297
572
  this.inngestAttempts = inngestAttempts;
298
573
  }
574
+ async execute(params) {
575
+ await params.emitter.emit("watch-v2", {
576
+ type: "start",
577
+ payload: { runId: params.runId }
578
+ });
579
+ const result = await super.execute(params);
580
+ await params.emitter.emit("watch-v2", {
581
+ type: "finish",
582
+ payload: { runId: params.runId }
583
+ });
584
+ return result;
585
+ }
299
586
  async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
300
587
  const base = {
301
588
  status: lastOutput.status,
@@ -362,6 +649,7 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
362
649
  resume,
363
650
  prevOutput,
364
651
  emitter,
652
+ abortController,
365
653
  runtimeContext
366
654
  }) {
367
655
  return super.executeStep({
@@ -373,9 +661,118 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
373
661
  resume,
374
662
  prevOutput,
375
663
  emitter,
664
+ abortController,
376
665
  runtimeContext
377
666
  });
378
667
  }
668
+ // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
669
+ // await this.inngestStep.sleep(id, duration);
670
+ // }
671
+ async executeSleep({
672
+ workflowId,
673
+ runId,
674
+ entry,
675
+ prevOutput,
676
+ stepResults,
677
+ emitter,
678
+ abortController,
679
+ runtimeContext
680
+ }) {
681
+ let { duration, fn } = entry;
682
+ if (fn) {
683
+ duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
684
+ return await fn({
685
+ runId,
686
+ mastra: this.mastra,
687
+ runtimeContext,
688
+ inputData: prevOutput,
689
+ runCount: -1,
690
+ getInitData: () => stepResults?.input,
691
+ getStepResult: (step) => {
692
+ if (!step?.id) {
693
+ return null;
694
+ }
695
+ const result = stepResults[step.id];
696
+ if (result?.status === "success") {
697
+ return result.output;
698
+ }
699
+ return null;
700
+ },
701
+ // TODO: this function shouldn't have suspend probably?
702
+ suspend: async (_suspendPayload) => {
703
+ },
704
+ bail: () => {
705
+ },
706
+ abort: () => {
707
+ abortController?.abort();
708
+ },
709
+ [_constants.EMITTER_SYMBOL]: emitter,
710
+ engine: { step: this.inngestStep },
711
+ abortSignal: abortController?.signal
712
+ });
713
+ });
714
+ }
715
+ await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
716
+ }
717
+ async executeSleepUntil({
718
+ workflowId,
719
+ runId,
720
+ entry,
721
+ prevOutput,
722
+ stepResults,
723
+ emitter,
724
+ abortController,
725
+ runtimeContext
726
+ }) {
727
+ let { date, fn } = entry;
728
+ if (fn) {
729
+ date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
730
+ return await fn({
731
+ runId,
732
+ mastra: this.mastra,
733
+ runtimeContext,
734
+ inputData: prevOutput,
735
+ runCount: -1,
736
+ getInitData: () => stepResults?.input,
737
+ getStepResult: (step) => {
738
+ if (!step?.id) {
739
+ return null;
740
+ }
741
+ const result = stepResults[step.id];
742
+ if (result?.status === "success") {
743
+ return result.output;
744
+ }
745
+ return null;
746
+ },
747
+ // TODO: this function shouldn't have suspend probably?
748
+ suspend: async (_suspendPayload) => {
749
+ },
750
+ bail: () => {
751
+ },
752
+ abort: () => {
753
+ abortController?.abort();
754
+ },
755
+ [_constants.EMITTER_SYMBOL]: emitter,
756
+ engine: { step: this.inngestStep },
757
+ abortSignal: abortController?.signal
758
+ });
759
+ });
760
+ }
761
+ if (!(date instanceof Date)) {
762
+ return;
763
+ }
764
+ await this.inngestStep.sleepUntil(entry.id, date);
765
+ }
766
+ async executeWaitForEvent({ event, timeout }) {
767
+ const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
768
+ event: `user-event-${event}`,
769
+ timeout: timeout ?? 5e3
770
+ });
771
+ if (eventData === null) {
772
+ throw "Timeout waiting for event";
773
+ }
774
+ return eventData?.data;
775
+ }
379
776
  async executeStep({
380
777
  step,
381
778
  stepResults,
@@ -383,11 +780,13 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
383
780
  resume,
384
781
  prevOutput,
385
782
  emitter,
783
+ abortController,
386
784
  runtimeContext
387
785
  }) {
388
- await this.inngestStep.run(
786
+ const startedAt = await this.inngestStep.run(
389
787
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
390
788
  async () => {
789
+ const startedAt2 = Date.now();
391
790
  await emitter.emit("watch", {
392
791
  type: "watch",
393
792
  payload: {
@@ -409,6 +808,16 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
409
808
  },
410
809
  eventTimestamp: Date.now()
411
810
  });
811
+ await emitter.emit("watch-v2", {
812
+ type: "step-start",
813
+ payload: {
814
+ id: step.id,
815
+ status: "running",
816
+ payload: prevOutput,
817
+ startedAt: startedAt2
818
+ }
819
+ });
820
+ return startedAt2;
412
821
  }
413
822
  );
414
823
  if (step instanceof InngestWorkflow) {
@@ -469,6 +878,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
469
878
  },
470
879
  eventTimestamp: Date.now()
471
880
  });
881
+ await emitter.emit("watch-v2", {
882
+ type: "step-result",
883
+ payload: {
884
+ id: step.id,
885
+ status: "failed",
886
+ error: result?.error,
887
+ payload: prevOutput
888
+ }
889
+ });
472
890
  return { executionContext, result: { status: "failed", error: result?.error } };
473
891
  } else if (result.status === "suspended") {
474
892
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
@@ -495,6 +913,13 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
495
913
  },
496
914
  eventTimestamp: Date.now()
497
915
  });
916
+ await emitter.emit("watch-v2", {
917
+ type: "step-suspended",
918
+ payload: {
919
+ id: step.id,
920
+ status: "suspended"
921
+ }
922
+ });
498
923
  return {
499
924
  executionContext,
500
925
  result: {
@@ -545,6 +970,21 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
545
970
  },
546
971
  eventTimestamp: Date.now()
547
972
  });
973
+ await emitter.emit("watch-v2", {
974
+ type: "step-result",
975
+ payload: {
976
+ id: step.id,
977
+ status: "success",
978
+ output: result?.result
979
+ }
980
+ });
981
+ await emitter.emit("watch-v2", {
982
+ type: "step-finish",
983
+ payload: {
984
+ id: step.id,
985
+ metadata: {}
986
+ }
987
+ });
548
988
  return { executionContext, result: { status: "success", output: result?.result } };
549
989
  }
550
990
  );
@@ -554,8 +994,10 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
554
994
  const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
555
995
  let execResults;
556
996
  let suspended;
997
+ let bailed;
557
998
  try {
558
999
  const result = await step.execute({
1000
+ runId: executionContext.runId,
559
1001
  mastra: this.mastra,
560
1002
  runtimeContext,
561
1003
  inputData: prevOutput,
@@ -572,20 +1014,54 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
572
1014
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
573
1015
  suspended = { payload: suspendPayload };
574
1016
  },
1017
+ bail: (result2) => {
1018
+ bailed = { payload: result2 };
1019
+ },
575
1020
  resume: {
576
1021
  steps: resume?.steps?.slice(1) || [],
577
1022
  resumePayload: resume?.resumePayload,
578
1023
  // @ts-ignore
579
1024
  runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
580
1025
  },
581
- emitter
1026
+ [_constants.EMITTER_SYMBOL]: emitter,
1027
+ engine: {
1028
+ step: this.inngestStep
1029
+ },
1030
+ abortSignal: abortController.signal
582
1031
  });
583
- execResults = { status: "success", output: result };
1032
+ const endedAt = Date.now();
1033
+ execResults = {
1034
+ status: "success",
1035
+ output: result,
1036
+ startedAt,
1037
+ endedAt,
1038
+ payload: prevOutput,
1039
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1040
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1041
+ };
584
1042
  } catch (e) {
585
- execResults = { status: "failed", error: e instanceof Error ? e.message : String(e) };
1043
+ execResults = {
1044
+ status: "failed",
1045
+ payload: prevOutput,
1046
+ error: e instanceof Error ? e.message : String(e),
1047
+ endedAt: Date.now(),
1048
+ startedAt,
1049
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1050
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1051
+ };
586
1052
  }
587
1053
  if (suspended) {
588
- execResults = { status: "suspended", payload: suspended.payload };
1054
+ execResults = {
1055
+ status: "suspended",
1056
+ suspendedPayload: suspended.payload,
1057
+ payload: prevOutput,
1058
+ suspendedAt: Date.now(),
1059
+ startedAt,
1060
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1061
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1062
+ };
1063
+ } else if (bailed) {
1064
+ execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
589
1065
  }
590
1066
  if (execResults.status === "failed") {
591
1067
  if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
@@ -597,18 +1073,41 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
597
1073
  payload: {
598
1074
  currentStep: {
599
1075
  id: step.id,
600
- status: execResults.status,
601
- output: execResults.output
1076
+ ...execResults
602
1077
  },
603
1078
  workflowState: {
604
1079
  status: "running",
605
- steps: stepResults,
1080
+ steps: { ...stepResults, [step.id]: execResults },
606
1081
  result: null,
607
1082
  error: null
608
1083
  }
609
1084
  },
610
1085
  eventTimestamp: Date.now()
611
1086
  });
1087
+ if (execResults.status === "suspended") {
1088
+ await emitter.emit("watch-v2", {
1089
+ type: "step-suspended",
1090
+ payload: {
1091
+ id: step.id,
1092
+ ...execResults
1093
+ }
1094
+ });
1095
+ } else {
1096
+ await emitter.emit("watch-v2", {
1097
+ type: "step-result",
1098
+ payload: {
1099
+ id: step.id,
1100
+ ...execResults
1101
+ }
1102
+ });
1103
+ await emitter.emit("watch-v2", {
1104
+ type: "step-finish",
1105
+ payload: {
1106
+ id: step.id,
1107
+ metadata: {}
1108
+ }
1109
+ });
1110
+ }
612
1111
  return { result: execResults, executionContext, stepResults };
613
1112
  });
614
1113
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
@@ -619,7 +1118,11 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
619
1118
  workflowId,
620
1119
  runId,
621
1120
  stepResults,
622
- executionContext
1121
+ executionContext,
1122
+ serializedStepGraph,
1123
+ workflowStatus,
1124
+ result,
1125
+ error
623
1126
  }) {
624
1127
  await this.inngestStep.run(
625
1128
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -633,6 +1136,10 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
633
1136
  context: stepResults,
634
1137
  activePaths: [],
635
1138
  suspendedPaths: executionContext.suspendedPaths,
1139
+ serializedStepGraph,
1140
+ status: workflowStatus,
1141
+ result,
1142
+ error,
636
1143
  // @ts-ignore
637
1144
  timestamp: Date.now()
638
1145
  }
@@ -647,9 +1154,11 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
647
1154
  prevOutput,
648
1155
  prevStep,
649
1156
  stepResults,
1157
+ serializedStepGraph,
650
1158
  resume,
651
1159
  executionContext,
652
1160
  emitter,
1161
+ abortController,
653
1162
  runtimeContext
654
1163
  }) {
655
1164
  let execResults;
@@ -658,8 +1167,10 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
658
1167
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
659
1168
  try {
660
1169
  const result = await cond({
1170
+ runId,
661
1171
  mastra: this.mastra,
662
1172
  runtimeContext,
1173
+ runCount: -1,
663
1174
  inputData: prevOutput,
664
1175
  getInitData: () => stepResults?.input,
665
1176
  getStepResult: (step) => {
@@ -675,7 +1186,16 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
675
1186
  // TODO: this function shouldn't have suspend probably?
676
1187
  suspend: async (_suspendPayload) => {
677
1188
  },
678
- emitter
1189
+ bail: () => {
1190
+ },
1191
+ abort: () => {
1192
+ abortController.abort();
1193
+ },
1194
+ [_constants.EMITTER_SYMBOL]: emitter,
1195
+ engine: {
1196
+ step: this.inngestStep
1197
+ },
1198
+ abortSignal: abortController.signal
679
1199
  });
680
1200
  return result ? index : null;
681
1201
  } catch (e) {
@@ -694,6 +1214,7 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
694
1214
  prevStep,
695
1215
  stepResults,
696
1216
  resume,
1217
+ serializedStepGraph,
697
1218
  executionContext: {
698
1219
  workflowId,
699
1220
  runId,
@@ -703,21 +1224,22 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
703
1224
  executionSpan: executionContext.executionSpan
704
1225
  },
705
1226
  emitter,
1227
+ abortController,
706
1228
  runtimeContext
707
1229
  })
708
1230
  )
709
1231
  );
710
- const hasFailed = results.find((result) => result.status === "failed");
711
- const hasSuspended = results.find((result) => result.status === "suspended");
1232
+ const hasFailed = results.find((result) => result.result.status === "failed");
1233
+ const hasSuspended = results.find((result) => result.result.status === "suspended");
712
1234
  if (hasFailed) {
713
- execResults = { status: "failed", error: hasFailed.error };
1235
+ execResults = { status: "failed", error: hasFailed.result.error };
714
1236
  } else if (hasSuspended) {
715
- execResults = { status: "suspended", payload: hasSuspended.payload };
1237
+ execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
716
1238
  } else {
717
1239
  execResults = {
718
1240
  status: "success",
719
1241
  output: results.reduce((acc, result, index) => {
720
- if (result.status === "success") {
1242
+ if (result.result.status === "success") {
721
1243
  acc[stepsToRun[index].step.id] = result.output;
722
1244
  }
723
1245
  return acc;
@@ -731,5 +1253,6 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
731
1253
  exports.InngestExecutionEngine = InngestExecutionEngine;
732
1254
  exports.InngestRun = InngestRun;
733
1255
  exports.InngestWorkflow = InngestWorkflow;
1256
+ exports.createStep = createStep;
734
1257
  exports.init = init;
735
1258
  exports.serve = serve;