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