@mastra/inngest 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-tsconfig-compile-20250703214351

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,20 +3,26 @@
3
3
  var crypto = require('crypto');
4
4
  var realtime = require('@inngest/realtime');
5
5
  var di = require('@mastra/core/di');
6
+ var tools = require('@mastra/core/tools');
6
7
  var workflows = require('@mastra/core/workflows');
7
8
  var _constants = require('@mastra/core/workflows/_constants');
8
9
  var hono = require('inngest/hono');
10
+ var zod = require('zod');
9
11
 
10
12
  // src/index.ts
11
13
  function serve({ mastra, inngest }) {
12
14
  const wfs = mastra.getWorkflows();
13
- const functions = Object.values(wfs).flatMap((wf) => {
14
- if (wf instanceof InngestWorkflow) {
15
- wf.__registerMastra(mastra);
16
- return wf.getFunctions();
17
- }
18
- return [];
19
- });
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
+ );
20
26
  return hono.serve({
21
27
  client: inngest,
22
28
  functions
@@ -43,15 +49,50 @@ var InngestRun = class extends workflows.Run {
43
49
  }
44
50
  async getRunOutput(eventId) {
45
51
  let runs = await this.getRuns(eventId);
46
- while (runs?.[0]?.status !== "Completed") {
52
+ while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
47
53
  await new Promise((resolve) => setTimeout(resolve, 1e3));
48
54
  runs = await this.getRuns(eventId);
49
- if (runs?.[0]?.status === "Failed" || runs?.[0]?.status === "Cancelled") {
55
+ if (runs?.[0]?.status === "Failed") {
56
+ console.log("run", runs?.[0]);
50
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" } } };
51
64
  }
52
65
  }
53
66
  return runs?.[0];
54
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
+ }
55
96
  async start({
56
97
  inputData
57
98
  }) {
@@ -65,7 +106,8 @@ var InngestRun = class extends workflows.Run {
65
106
  context: {},
66
107
  activePaths: [],
67
108
  suspendedPaths: {},
68
- timestamp: Date.now()
109
+ timestamp: Date.now(),
110
+ status: "running"
69
111
  }
70
112
  });
71
113
  const eventOutput = await this.inngest.send({
@@ -84,10 +126,23 @@ var InngestRun = class extends workflows.Run {
84
126
  if (result.status === "failed") {
85
127
  result.error = new Error(result.error);
86
128
  }
87
- this.cleanup?.();
129
+ if (result.status !== "suspended") {
130
+ this.cleanup?.();
131
+ }
88
132
  return result;
89
133
  }
90
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) {
91
146
  const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
92
147
  (step) => typeof step === "string" ? step : step?.id
93
148
  );
@@ -121,25 +176,60 @@ var InngestRun = class extends workflows.Run {
121
176
  }
122
177
  return result;
123
178
  }
124
- watch(cb) {
179
+ watch(cb, type = "watch") {
180
+ let active = true;
125
181
  const streamPromise = realtime.subscribe(
126
182
  {
127
183
  channel: `workflow:${this.workflowId}:${this.runId}`,
128
- topics: ["watch"],
184
+ topics: [type],
129
185
  app: this.inngest
130
186
  },
131
187
  (message) => {
132
- cb(message.data);
188
+ if (active) {
189
+ cb(message.data);
190
+ }
133
191
  }
134
192
  );
135
193
  return () => {
136
- streamPromise.then((stream) => {
137
- stream.cancel();
194
+ active = false;
195
+ streamPromise.then(async (stream) => {
196
+ return stream.cancel();
138
197
  }).catch((err) => {
139
198
  console.error(err);
140
199
  });
141
200
  };
142
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
+ }
143
233
  };
144
234
  var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
145
235
  #mastra;
@@ -162,11 +252,32 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
162
252
  const storage = this.#mastra?.getStorage();
163
253
  if (!storage) {
164
254
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
165
- return null;
255
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
166
256
  }
167
257
  const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
168
258
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
169
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
+ }
170
281
  __registerMastra(mastra) {
171
282
  this.#mastra = mastra;
172
283
  this.executionEngine.__registerMastra(mastra);
@@ -203,13 +314,55 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
203
314
  this.runs.set(runIdToUse, run);
204
315
  return run;
205
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
+ }
206
355
  getFunction() {
207
356
  if (this.function) {
208
357
  return this.function;
209
358
  }
210
359
  this.function = this.inngest.createFunction(
211
- // @ts-ignore
212
- { 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
+ },
213
366
  { event: `workflow.${this.id}` },
214
367
  async ({ event, step, attempt, publish }) => {
215
368
  let { inputData, runId, resume } = event.data;
@@ -226,12 +379,18 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
226
379
  try {
227
380
  await publish({
228
381
  channel: `workflow:${this.id}:${runId}`,
229
- topic: "watch",
382
+ topic: event2,
230
383
  data
231
384
  });
232
385
  } catch (err) {
233
386
  this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
234
387
  }
388
+ },
389
+ on: (_event, _callback) => {
390
+ },
391
+ off: (_event, _callback) => {
392
+ },
393
+ once: (_event, _callback) => {
235
394
  }
236
395
  };
237
396
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
@@ -245,7 +404,8 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
245
404
  retryConfig: this.retryConfig,
246
405
  runtimeContext: new di.RuntimeContext(),
247
406
  // TODO
248
- resume
407
+ resume,
408
+ abortController: new AbortController()
249
409
  });
250
410
  return { result, runId };
251
411
  }
@@ -269,29 +429,138 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
269
429
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
270
430
  }
271
431
  };
272
- function cloneWorkflow(workflow, opts) {
273
- const wf = new InngestWorkflow(
274
- {
275
- id: opts.id,
276
- inputSchema: workflow.inputSchema,
277
- outputSchema: workflow.outputSchema,
278
- steps: workflow.stepDefs,
279
- mastra: workflow.mastra
280
- },
281
- workflow.inngest
282
- );
283
- wf.setStepFlow(workflow.stepGraph);
284
- wf.commit();
285
- 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
+ };
286
536
  }
287
537
  function init(inngest) {
288
538
  return {
289
539
  createWorkflow(params) {
290
540
  return new InngestWorkflow(params, inngest);
291
541
  },
292
- createStep: workflows.createStep,
293
- cloneStep: workflows.cloneStep,
294
- 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
+ }
295
564
  };
296
565
  }
297
566
  var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
@@ -302,6 +571,18 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
302
571
  this.inngestStep = inngestStep;
303
572
  this.inngestAttempts = inngestAttempts;
304
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
+ }
305
586
  async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
306
587
  const base = {
307
588
  status: lastOutput.status,
@@ -368,6 +649,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
368
649
  resume,
369
650
  prevOutput,
370
651
  emitter,
652
+ abortController,
371
653
  runtimeContext
372
654
  }) {
373
655
  return super.executeStep({
@@ -379,9 +661,118 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
379
661
  resume,
380
662
  prevOutput,
381
663
  emitter,
664
+ abortController,
382
665
  runtimeContext
383
666
  });
384
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
+ }
385
776
  async executeStep({
386
777
  step,
387
778
  stepResults,
@@ -389,11 +780,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
389
780
  resume,
390
781
  prevOutput,
391
782
  emitter,
783
+ abortController,
392
784
  runtimeContext
393
785
  }) {
394
- await this.inngestStep.run(
786
+ const startedAt = await this.inngestStep.run(
395
787
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
396
788
  async () => {
789
+ const startedAt2 = Date.now();
397
790
  await emitter.emit("watch", {
398
791
  type: "watch",
399
792
  payload: {
@@ -415,6 +808,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
415
808
  },
416
809
  eventTimestamp: Date.now()
417
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;
418
821
  }
419
822
  );
420
823
  if (step instanceof InngestWorkflow) {
@@ -475,6 +878,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
475
878
  },
476
879
  eventTimestamp: Date.now()
477
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
+ });
478
890
  return { executionContext, result: { status: "failed", error: result?.error } };
479
891
  } else if (result.status === "suspended") {
480
892
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
@@ -501,6 +913,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
501
913
  },
502
914
  eventTimestamp: Date.now()
503
915
  });
916
+ await emitter.emit("watch-v2", {
917
+ type: "step-suspended",
918
+ payload: {
919
+ id: step.id,
920
+ status: "suspended"
921
+ }
922
+ });
504
923
  return {
505
924
  executionContext,
506
925
  result: {
@@ -551,6 +970,21 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
551
970
  },
552
971
  eventTimestamp: Date.now()
553
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
+ });
554
988
  return { executionContext, result: { status: "success", output: result?.result } };
555
989
  }
556
990
  );
@@ -560,6 +994,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
560
994
  const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
561
995
  let execResults;
562
996
  let suspended;
997
+ let bailed;
563
998
  try {
564
999
  const result = await step.execute({
565
1000
  runId: executionContext.runId,
@@ -579,20 +1014,54 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
579
1014
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
580
1015
  suspended = { payload: suspendPayload };
581
1016
  },
1017
+ bail: (result2) => {
1018
+ bailed = { payload: result2 };
1019
+ },
582
1020
  resume: {
583
1021
  steps: resume?.steps?.slice(1) || [],
584
1022
  resumePayload: resume?.resumePayload,
585
1023
  // @ts-ignore
586
1024
  runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
587
1025
  },
588
- emitter
1026
+ [_constants.EMITTER_SYMBOL]: emitter,
1027
+ engine: {
1028
+ step: this.inngestStep
1029
+ },
1030
+ abortSignal: abortController.signal
589
1031
  });
590
- 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
+ };
591
1042
  } catch (e) {
592
- 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
+ };
593
1052
  }
594
1053
  if (suspended) {
595
- 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 };
596
1065
  }
597
1066
  if (execResults.status === "failed") {
598
1067
  if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
@@ -604,18 +1073,41 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
604
1073
  payload: {
605
1074
  currentStep: {
606
1075
  id: step.id,
607
- status: execResults.status,
608
- output: execResults.output
1076
+ ...execResults
609
1077
  },
610
1078
  workflowState: {
611
1079
  status: "running",
612
- steps: stepResults,
1080
+ steps: { ...stepResults, [step.id]: execResults },
613
1081
  result: null,
614
1082
  error: null
615
1083
  }
616
1084
  },
617
1085
  eventTimestamp: Date.now()
618
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
+ }
619
1111
  return { result: execResults, executionContext, stepResults };
620
1112
  });
621
1113
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
@@ -627,7 +1119,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
627
1119
  runId,
628
1120
  stepResults,
629
1121
  executionContext,
630
- serializedStepGraph
1122
+ serializedStepGraph,
1123
+ workflowStatus,
1124
+ result,
1125
+ error
631
1126
  }) {
632
1127
  await this.inngestStep.run(
633
1128
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -642,6 +1137,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
642
1137
  activePaths: [],
643
1138
  suspendedPaths: executionContext.suspendedPaths,
644
1139
  serializedStepGraph,
1140
+ status: workflowStatus,
1141
+ result,
1142
+ error,
645
1143
  // @ts-ignore
646
1144
  timestamp: Date.now()
647
1145
  }
@@ -660,6 +1158,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
660
1158
  resume,
661
1159
  executionContext,
662
1160
  emitter,
1161
+ abortController,
663
1162
  runtimeContext
664
1163
  }) {
665
1164
  let execResults;
@@ -671,6 +1170,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
671
1170
  runId,
672
1171
  mastra: this.mastra,
673
1172
  runtimeContext,
1173
+ runCount: -1,
674
1174
  inputData: prevOutput,
675
1175
  getInitData: () => stepResults?.input,
676
1176
  getStepResult: (step) => {
@@ -686,7 +1186,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
686
1186
  // TODO: this function shouldn't have suspend probably?
687
1187
  suspend: async (_suspendPayload) => {
688
1188
  },
689
- [_constants.EMITTER_SYMBOL]: 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
690
1199
  });
691
1200
  return result ? index : null;
692
1201
  } catch (e) {
@@ -715,21 +1224,22 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
715
1224
  executionSpan: executionContext.executionSpan
716
1225
  },
717
1226
  emitter,
1227
+ abortController,
718
1228
  runtimeContext
719
1229
  })
720
1230
  )
721
1231
  );
722
- const hasFailed = results.find((result) => result.status === "failed");
723
- 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");
724
1234
  if (hasFailed) {
725
- execResults = { status: "failed", error: hasFailed.error };
1235
+ execResults = { status: "failed", error: hasFailed.result.error };
726
1236
  } else if (hasSuspended) {
727
- execResults = { status: "suspended", payload: hasSuspended.payload };
1237
+ execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
728
1238
  } else {
729
1239
  execResults = {
730
1240
  status: "success",
731
1241
  output: results.reduce((acc, result, index) => {
732
- if (result.status === "success") {
1242
+ if (result.result.status === "success") {
733
1243
  acc[stepsToRun[index].step.id] = result.output;
734
1244
  }
735
1245
  return acc;
@@ -743,5 +1253,6 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
743
1253
  exports.InngestExecutionEngine = InngestExecutionEngine;
744
1254
  exports.InngestRun = InngestRun;
745
1255
  exports.InngestWorkflow = InngestWorkflow;
1256
+ exports.createStep = createStep;
746
1257
  exports.init = init;
747
1258
  exports.serve = serve;