@mastra/inngest 0.0.0-course-20250527170450 → 0.0.0-custom-instrumentation-20250708222033

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,20 +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, Workflow, cloneStep, createStep, DefaultExecutionEngine } from '@mastra/core/workflows';
4
+ import { Tool } from '@mastra/core/tools';
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 }) {
10
12
  const wfs = mastra.getWorkflows();
11
- const functions = Object.values(wfs).flatMap((wf) => {
12
- if (wf instanceof InngestWorkflow) {
13
- wf.__registerMastra(mastra);
14
- return wf.getFunctions();
15
- }
16
- return [];
17
- });
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
+ );
18
24
  return serve$1({
19
25
  client: inngest,
20
26
  functions
@@ -22,14 +28,16 @@ function serve({ mastra, inngest }) {
22
28
  }
23
29
  var InngestRun = class extends Run {
24
30
  inngest;
31
+ serializedStepGraph;
25
32
  #mastra;
26
33
  constructor(params, inngest) {
27
34
  super(params);
28
35
  this.inngest = inngest;
36
+ this.serializedStepGraph = params.serializedStepGraph;
29
37
  this.#mastra = params.mastra;
30
38
  }
31
39
  async getRuns(eventId) {
32
- 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`, {
33
41
  headers: {
34
42
  Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
35
43
  }
@@ -39,15 +47,50 @@ var InngestRun = class extends Run {
39
47
  }
40
48
  async getRunOutput(eventId) {
41
49
  let runs = await this.getRuns(eventId);
42
- while (runs?.[0]?.status !== "Completed") {
50
+ while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
43
51
  await new Promise((resolve) => setTimeout(resolve, 1e3));
44
52
  runs = await this.getRuns(eventId);
45
- if (runs?.[0]?.status === "Failed" || runs?.[0]?.status === "Cancelled") {
53
+ if (runs?.[0]?.status === "Failed") {
54
+ console.log("run", runs?.[0]);
46
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" } } };
47
62
  }
48
63
  }
49
64
  return runs?.[0];
50
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
+ }
51
94
  async start({
52
95
  inputData
53
96
  }) {
@@ -56,11 +99,13 @@ var InngestRun = class extends Run {
56
99
  runId: this.runId,
57
100
  snapshot: {
58
101
  runId: this.runId,
102
+ serializedStepGraph: this.serializedStepGraph,
59
103
  value: {},
60
104
  context: {},
61
105
  activePaths: [],
62
106
  suspendedPaths: {},
63
- timestamp: Date.now()
107
+ timestamp: Date.now(),
108
+ status: "running"
64
109
  }
65
110
  });
66
111
  const eventOutput = await this.inngest.send({
@@ -79,10 +124,23 @@ var InngestRun = class extends Run {
79
124
  if (result.status === "failed") {
80
125
  result.error = new Error(result.error);
81
126
  }
82
- this.cleanup?.();
127
+ if (result.status !== "suspended") {
128
+ this.cleanup?.();
129
+ }
83
130
  return result;
84
131
  }
85
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) {
86
144
  const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
87
145
  (step) => typeof step === "string" ? step : step?.id
88
146
  );
@@ -116,25 +174,60 @@ var InngestRun = class extends Run {
116
174
  }
117
175
  return result;
118
176
  }
119
- watch(cb) {
177
+ watch(cb, type = "watch") {
178
+ let active = true;
120
179
  const streamPromise = subscribe(
121
180
  {
122
181
  channel: `workflow:${this.workflowId}:${this.runId}`,
123
- topics: ["watch"],
182
+ topics: [type],
124
183
  app: this.inngest
125
184
  },
126
185
  (message) => {
127
- cb(message.data);
186
+ if (active) {
187
+ cb(message.data);
188
+ }
128
189
  }
129
190
  );
130
191
  return () => {
131
- streamPromise.then((stream) => {
132
- stream.cancel();
192
+ active = false;
193
+ streamPromise.then(async (stream) => {
194
+ return stream.cancel();
133
195
  }).catch((err) => {
134
196
  console.error(err);
135
197
  });
136
198
  };
137
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
+ }
138
231
  };
139
232
  var InngestWorkflow = class _InngestWorkflow extends Workflow {
140
233
  #mastra;
@@ -157,11 +250,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
157
250
  const storage = this.#mastra?.getStorage();
158
251
  if (!storage) {
159
252
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
160
- return null;
253
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
161
254
  }
162
255
  const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
163
256
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
164
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
+ }
165
279
  __registerMastra(mastra) {
166
280
  this.#mastra = mastra;
167
281
  this.executionEngine.__registerMastra(mastra);
@@ -188,6 +302,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
188
302
  runId: runIdToUse,
189
303
  executionEngine: this.executionEngine,
190
304
  executionGraph: this.executionGraph,
305
+ serializedStepGraph: this.serializedStepGraph,
191
306
  mastra: this.#mastra,
192
307
  retryConfig: this.retryConfig,
193
308
  cleanup: () => this.runs.delete(runIdToUse)
@@ -197,13 +312,55 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
197
312
  this.runs.set(runIdToUse, run);
198
313
  return run;
199
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
+ }
200
353
  getFunction() {
201
354
  if (this.function) {
202
355
  return this.function;
203
356
  }
204
357
  this.function = this.inngest.createFunction(
205
- // @ts-ignore
206
- { 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
+ },
207
364
  { event: `workflow.${this.id}` },
208
365
  async ({ event, step, attempt, publish }) => {
209
366
  let { inputData, runId, resume } = event.data;
@@ -220,12 +377,18 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
220
377
  try {
221
378
  await publish({
222
379
  channel: `workflow:${this.id}:${runId}`,
223
- topic: "watch",
380
+ topic: event2,
224
381
  data
225
382
  });
226
383
  } catch (err) {
227
384
  this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
228
385
  }
386
+ },
387
+ on: (_event, _callback) => {
388
+ },
389
+ off: (_event, _callback) => {
390
+ },
391
+ once: (_event, _callback) => {
229
392
  }
230
393
  };
231
394
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
@@ -233,12 +396,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
233
396
  workflowId: this.id,
234
397
  runId,
235
398
  graph: this.executionGraph,
399
+ serializedStepGraph: this.serializedStepGraph,
236
400
  input: inputData,
237
401
  emitter,
238
402
  retryConfig: this.retryConfig,
239
403
  runtimeContext: new RuntimeContext(),
240
404
  // TODO
241
- resume
405
+ resume,
406
+ abortController: new AbortController()
242
407
  });
243
408
  return { result, runId };
244
409
  }
@@ -262,20 +427,110 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
262
427
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
263
428
  }
264
429
  };
265
- function cloneWorkflow(workflow, opts) {
266
- const wf = new InngestWorkflow(
267
- {
268
- id: opts.id,
269
- inputSchema: workflow.inputSchema,
270
- outputSchema: workflow.outputSchema,
271
- steps: workflow.stepDefs,
272
- mastra: workflow.mastra
273
- },
274
- workflow.inngest
275
- );
276
- wf.setStepFlow(workflow.stepGraph);
277
- wf.commit();
278
- 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
+ };
279
534
  }
280
535
  function init(inngest) {
281
536
  return {
@@ -283,8 +538,27 @@ function init(inngest) {
283
538
  return new InngestWorkflow(params, inngest);
284
539
  },
285
540
  createStep,
286
- cloneStep,
287
- 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
+ }
288
562
  };
289
563
  }
290
564
  var InngestExecutionEngine = class extends DefaultExecutionEngine {
@@ -295,6 +569,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
295
569
  this.inngestStep = inngestStep;
296
570
  this.inngestAttempts = inngestAttempts;
297
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
+ }
298
584
  async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
299
585
  const base = {
300
586
  status: lastOutput.status,
@@ -361,6 +647,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
361
647
  resume,
362
648
  prevOutput,
363
649
  emitter,
650
+ abortController,
364
651
  runtimeContext
365
652
  }) {
366
653
  return super.executeStep({
@@ -372,9 +659,118 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
372
659
  resume,
373
660
  prevOutput,
374
661
  emitter,
662
+ abortController,
375
663
  runtimeContext
376
664
  });
377
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
+ }
378
774
  async executeStep({
379
775
  step,
380
776
  stepResults,
@@ -382,11 +778,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
382
778
  resume,
383
779
  prevOutput,
384
780
  emitter,
781
+ abortController,
385
782
  runtimeContext
386
783
  }) {
387
- await this.inngestStep.run(
784
+ const startedAt = await this.inngestStep.run(
388
785
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
389
786
  async () => {
787
+ const startedAt2 = Date.now();
390
788
  await emitter.emit("watch", {
391
789
  type: "watch",
392
790
  payload: {
@@ -408,6 +806,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
408
806
  },
409
807
  eventTimestamp: Date.now()
410
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;
411
819
  }
412
820
  );
413
821
  if (step instanceof InngestWorkflow) {
@@ -468,6 +876,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
468
876
  },
469
877
  eventTimestamp: Date.now()
470
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
+ });
471
888
  return { executionContext, result: { status: "failed", error: result?.error } };
472
889
  } else if (result.status === "suspended") {
473
890
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
@@ -494,6 +911,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
494
911
  },
495
912
  eventTimestamp: Date.now()
496
913
  });
914
+ await emitter.emit("watch-v2", {
915
+ type: "step-suspended",
916
+ payload: {
917
+ id: step.id,
918
+ status: "suspended"
919
+ }
920
+ });
497
921
  return {
498
922
  executionContext,
499
923
  result: {
@@ -544,6 +968,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
544
968
  },
545
969
  eventTimestamp: Date.now()
546
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
+ });
547
986
  return { executionContext, result: { status: "success", output: result?.result } };
548
987
  }
549
988
  );
@@ -553,8 +992,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
553
992
  const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
554
993
  let execResults;
555
994
  let suspended;
995
+ let bailed;
556
996
  try {
557
997
  const result = await step.execute({
998
+ runId: executionContext.runId,
558
999
  mastra: this.mastra,
559
1000
  runtimeContext,
560
1001
  inputData: prevOutput,
@@ -571,20 +1012,54 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
571
1012
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
572
1013
  suspended = { payload: suspendPayload };
573
1014
  },
1015
+ bail: (result2) => {
1016
+ bailed = { payload: result2 };
1017
+ },
574
1018
  resume: {
575
1019
  steps: resume?.steps?.slice(1) || [],
576
1020
  resumePayload: resume?.resumePayload,
577
1021
  // @ts-ignore
578
1022
  runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
579
1023
  },
580
- emitter
1024
+ [EMITTER_SYMBOL]: emitter,
1025
+ engine: {
1026
+ step: this.inngestStep
1027
+ },
1028
+ abortSignal: abortController.signal
581
1029
  });
582
- 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
+ };
583
1040
  } catch (e) {
584
- 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
+ };
585
1050
  }
586
1051
  if (suspended) {
587
- 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 };
588
1063
  }
589
1064
  if (execResults.status === "failed") {
590
1065
  if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
@@ -596,18 +1071,41 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
596
1071
  payload: {
597
1072
  currentStep: {
598
1073
  id: step.id,
599
- status: execResults.status,
600
- output: execResults.output
1074
+ ...execResults
601
1075
  },
602
1076
  workflowState: {
603
1077
  status: "running",
604
- steps: stepResults,
1078
+ steps: { ...stepResults, [step.id]: execResults },
605
1079
  result: null,
606
1080
  error: null
607
1081
  }
608
1082
  },
609
1083
  eventTimestamp: Date.now()
610
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
+ }
611
1109
  return { result: execResults, executionContext, stepResults };
612
1110
  });
613
1111
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
@@ -618,7 +1116,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
618
1116
  workflowId,
619
1117
  runId,
620
1118
  stepResults,
621
- executionContext
1119
+ executionContext,
1120
+ serializedStepGraph,
1121
+ workflowStatus,
1122
+ result,
1123
+ error
622
1124
  }) {
623
1125
  await this.inngestStep.run(
624
1126
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -632,6 +1134,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
632
1134
  context: stepResults,
633
1135
  activePaths: [],
634
1136
  suspendedPaths: executionContext.suspendedPaths,
1137
+ serializedStepGraph,
1138
+ status: workflowStatus,
1139
+ result,
1140
+ error,
635
1141
  // @ts-ignore
636
1142
  timestamp: Date.now()
637
1143
  }
@@ -646,9 +1152,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
646
1152
  prevOutput,
647
1153
  prevStep,
648
1154
  stepResults,
1155
+ serializedStepGraph,
649
1156
  resume,
650
1157
  executionContext,
651
1158
  emitter,
1159
+ abortController,
652
1160
  runtimeContext
653
1161
  }) {
654
1162
  let execResults;
@@ -657,8 +1165,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
657
1165
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
658
1166
  try {
659
1167
  const result = await cond({
1168
+ runId,
660
1169
  mastra: this.mastra,
661
1170
  runtimeContext,
1171
+ runCount: -1,
662
1172
  inputData: prevOutput,
663
1173
  getInitData: () => stepResults?.input,
664
1174
  getStepResult: (step) => {
@@ -674,7 +1184,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
674
1184
  // TODO: this function shouldn't have suspend probably?
675
1185
  suspend: async (_suspendPayload) => {
676
1186
  },
677
- [EMITTER_SYMBOL]: 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
678
1197
  });
679
1198
  return result ? index : null;
680
1199
  } catch (e) {
@@ -693,6 +1212,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
693
1212
  prevStep,
694
1213
  stepResults,
695
1214
  resume,
1215
+ serializedStepGraph,
696
1216
  executionContext: {
697
1217
  workflowId,
698
1218
  runId,
@@ -702,21 +1222,22 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
702
1222
  executionSpan: executionContext.executionSpan
703
1223
  },
704
1224
  emitter,
1225
+ abortController,
705
1226
  runtimeContext
706
1227
  })
707
1228
  )
708
1229
  );
709
- const hasFailed = results.find((result) => result.status === "failed");
710
- 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");
711
1232
  if (hasFailed) {
712
- execResults = { status: "failed", error: hasFailed.error };
1233
+ execResults = { status: "failed", error: hasFailed.result.error };
713
1234
  } else if (hasSuspended) {
714
- execResults = { status: "suspended", payload: hasSuspended.payload };
1235
+ execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
715
1236
  } else {
716
1237
  execResults = {
717
1238
  status: "success",
718
1239
  output: results.reduce((acc, result, index) => {
719
- if (result.status === "success") {
1240
+ if (result.result.status === "success") {
720
1241
  acc[stepsToRun[index].step.id] = result.output;
721
1242
  }
722
1243
  return acc;
@@ -727,4 +1248,4 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
727
1248
  }
728
1249
  };
729
1250
 
730
- export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
1251
+ export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };