@mastra/inngest 0.0.0-configure-project-root-for-private-packages-20250919100548 → 0.0.0-cor235-20251008175106

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
@@ -7,6 +7,7 @@ var di = require('@mastra/core/di');
7
7
  var tools = require('@mastra/core/tools');
8
8
  var workflows = require('@mastra/core/workflows');
9
9
  var _constants = require('@mastra/core/workflows/_constants');
10
+ var inngest = require('inngest');
10
11
  var hono = require('inngest/hono');
11
12
  var zod = require('zod');
12
13
 
@@ -14,7 +15,8 @@ var zod = require('zod');
14
15
  function serve({
15
16
  mastra,
16
17
  inngest,
17
- functions: userFunctions = []
18
+ functions: userFunctions = [],
19
+ registerOptions
18
20
  }) {
19
21
  const wfs = mastra.getWorkflows();
20
22
  const workflowFunctions = Array.from(
@@ -29,6 +31,7 @@ function serve({
29
31
  )
30
32
  );
31
33
  return hono.serve({
34
+ ...registerOptions,
32
35
  client: inngest,
33
36
  functions: [...workflowFunctions, ...userFunctions]
34
37
  });
@@ -58,8 +61,15 @@ var InngestRun = class extends workflows.Run {
58
61
  await new Promise((resolve) => setTimeout(resolve, 1e3));
59
62
  runs = await this.getRuns(eventId);
60
63
  if (runs?.[0]?.status === "Failed") {
61
- throw new Error(`Function run ${runs?.[0]?.status}`);
62
- } else if (runs?.[0]?.status === "Cancelled") {
64
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
65
+ workflowName: this.workflowId,
66
+ runId: this.runId
67
+ });
68
+ return {
69
+ output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
70
+ };
71
+ }
72
+ if (runs?.[0]?.status === "Cancelled") {
63
73
  const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
64
74
  workflowName: this.workflowId,
65
75
  runId: this.runId
@@ -99,7 +109,8 @@ var InngestRun = class extends workflows.Run {
99
109
  }
100
110
  }
101
111
  async start({
102
- inputData
112
+ inputData,
113
+ initialState
103
114
  }) {
104
115
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
105
116
  workflowName: this.workflowId,
@@ -117,10 +128,13 @@ var InngestRun = class extends workflows.Run {
117
128
  status: "running"
118
129
  }
119
130
  });
131
+ const inputDataToUse = await this._validateInput(inputData);
132
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
120
133
  const eventOutput = await this.inngest.send({
121
134
  name: `workflow.${this.workflowId}`,
122
135
  data: {
123
- inputData,
136
+ inputData: inputDataToUse,
137
+ initialState: initialStateToUse,
124
138
  runId: this.runId,
125
139
  resourceId: this.resourceId
126
140
  }
@@ -158,17 +172,20 @@ var InngestRun = class extends workflows.Run {
158
172
  workflowName: this.workflowId,
159
173
  runId: this.runId
160
174
  });
175
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
176
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
161
177
  const eventOutput = await this.inngest.send({
162
178
  name: `workflow.${this.workflowId}`,
163
179
  data: {
164
- inputData: params.resumeData,
180
+ inputData: resumeDataToUse,
181
+ initialState: snapshot?.value ?? {},
165
182
  runId: this.runId,
166
183
  workflowId: this.workflowId,
167
184
  stepResults: snapshot?.context,
168
185
  resume: {
169
186
  steps,
170
187
  stepResults: snapshot?.context,
171
- resumePayload: params.resumeData,
188
+ resumePayload: resumeDataToUse,
172
189
  // @ts-ignore
173
190
  resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
174
191
  }
@@ -315,13 +332,18 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
315
332
  serializedStepGraph: this.serializedStepGraph,
316
333
  mastra: this.#mastra,
317
334
  retryConfig: this.retryConfig,
318
- cleanup: () => this.runs.delete(runIdToUse)
335
+ cleanup: () => this.runs.delete(runIdToUse),
336
+ workflowSteps: this.steps
319
337
  },
320
338
  this.inngest
321
339
  );
322
340
  this.runs.set(runIdToUse, run);
341
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
342
+ workflowStatus: run.workflowRunStatus,
343
+ stepResults: {}
344
+ });
323
345
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
324
- if (!workflowSnapshotInStorage) {
346
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
325
347
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
326
348
  workflowName: this.id,
327
349
  runId: runIdToUse,
@@ -359,7 +381,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
359
381
  },
360
382
  { event: `workflow.${this.id}` },
361
383
  async ({ event, step, attempt, publish }) => {
362
- let { inputData, runId, resourceId, resume } = event.data;
384
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
363
385
  if (!runId) {
364
386
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
365
387
  return crypto.randomUUID();
@@ -387,7 +409,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
387
409
  once: (_event, _callback) => {
388
410
  }
389
411
  };
390
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
412
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
391
413
  const result = await engine.execute({
392
414
  workflowId: this.id,
393
415
  runId,
@@ -395,14 +417,24 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
395
417
  graph: this.executionGraph,
396
418
  serializedStepGraph: this.serializedStepGraph,
397
419
  input: inputData,
420
+ initialState,
398
421
  emitter,
399
422
  retryConfig: this.retryConfig,
400
423
  runtimeContext: new di.RuntimeContext(),
401
424
  // TODO
402
425
  resume,
403
426
  abortController: new AbortController(),
404
- currentSpan: void 0
427
+ currentSpan: void 0,
405
428
  // TODO: Pass actual parent AI span from workflow execution context
429
+ outputOptions
430
+ });
431
+ await step.run(`workflow.${this.id}.finalize`, async () => {
432
+ if (result.status === "failed") {
433
+ throw new inngest.NonRetriableError(`Workflow failed`, {
434
+ cause: result
435
+ });
436
+ }
437
+ return result;
406
438
  });
407
439
  return { result, runId };
408
440
  }
@@ -436,6 +468,7 @@ function createStep(params) {
436
468
  if (isAgent(params)) {
437
469
  return {
438
470
  id: params.name,
471
+ description: params.getDescription(),
439
472
  // @ts-ignore
440
473
  inputSchema: zod.z.object({
441
474
  prompt: zod.z.string()
@@ -454,28 +487,55 @@ function createStep(params) {
454
487
  name: params.name,
455
488
  args: inputData
456
489
  };
457
- const { fullStream } = await params.stream(inputData.prompt, {
458
- runtimeContext,
459
- tracingContext,
460
- onFinish: (result) => {
461
- streamPromise.resolve(result.text);
462
- },
463
- abortSignal
464
- });
465
- if (abortSignal.aborted) {
466
- return abort();
467
- }
468
- await emitter.emit("watch-v2", {
469
- type: "tool-call-streaming-start",
470
- ...toolData ?? {}
471
- });
472
- for await (const chunk of fullStream) {
473
- if (chunk.type === "text-delta") {
474
- await emitter.emit("watch-v2", {
475
- type: "tool-call-delta",
476
- ...toolData ?? {},
477
- argsTextDelta: chunk.textDelta
478
- });
490
+ if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
491
+ const { fullStream } = await params.stream(inputData.prompt, {
492
+ runtimeContext,
493
+ tracingContext,
494
+ onFinish: (result) => {
495
+ streamPromise.resolve(result.text);
496
+ },
497
+ abortSignal
498
+ });
499
+ if (abortSignal.aborted) {
500
+ return abort();
501
+ }
502
+ await emitter.emit("watch-v2", {
503
+ type: "tool-call-streaming-start",
504
+ ...toolData ?? {}
505
+ });
506
+ for await (const chunk of fullStream) {
507
+ if (chunk.type === "text-delta") {
508
+ await emitter.emit("watch-v2", {
509
+ type: "tool-call-delta",
510
+ ...toolData ?? {},
511
+ argsTextDelta: chunk.payload.text
512
+ });
513
+ }
514
+ }
515
+ } else {
516
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
517
+ runtimeContext,
518
+ tracingContext,
519
+ onFinish: (result) => {
520
+ streamPromise.resolve(result.text);
521
+ },
522
+ abortSignal
523
+ });
524
+ if (abortSignal.aborted) {
525
+ return abort();
526
+ }
527
+ await emitter.emit("watch-v2", {
528
+ type: "tool-call-streaming-start",
529
+ ...toolData ?? {}
530
+ });
531
+ for await (const chunk of fullStream) {
532
+ if (chunk.type === "text-delta") {
533
+ await emitter.emit("watch-v2", {
534
+ type: "tool-call-delta",
535
+ ...toolData ?? {},
536
+ argsTextDelta: chunk.textDelta
537
+ });
538
+ }
479
539
  }
480
540
  }
481
541
  await emitter.emit("watch-v2", {
@@ -485,7 +545,8 @@ function createStep(params) {
485
545
  return {
486
546
  text: await streamPromise.promise
487
547
  };
488
- }
548
+ },
549
+ component: params.component
489
550
  };
490
551
  }
491
552
  if (isTool(params)) {
@@ -496,16 +557,20 @@ function createStep(params) {
496
557
  // TODO: tool probably should have strong id type
497
558
  // @ts-ignore
498
559
  id: params.id,
560
+ description: params.description,
499
561
  inputSchema: params.inputSchema,
500
562
  outputSchema: params.outputSchema,
501
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
563
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
502
564
  return params.execute({
503
565
  context: inputData,
504
566
  mastra: aiTracing.wrapMastra(mastra, tracingContext),
505
567
  runtimeContext,
506
- tracingContext
568
+ tracingContext,
569
+ suspend,
570
+ resumeData
507
571
  });
508
- }
572
+ },
573
+ component: "TOOL"
509
574
  };
510
575
  }
511
576
  return {
@@ -521,7 +586,10 @@ function createStep(params) {
521
586
  function init(inngest) {
522
587
  return {
523
588
  createWorkflow(params) {
524
- return new InngestWorkflow(params, inngest);
589
+ return new InngestWorkflow(
590
+ params,
591
+ inngest
592
+ );
525
593
  },
526
594
  createStep,
527
595
  cloneStep(step, opts) {
@@ -530,7 +598,11 @@ function init(inngest) {
530
598
  description: step.description,
531
599
  inputSchema: step.inputSchema,
532
600
  outputSchema: step.outputSchema,
533
- execute: step.execute
601
+ resumeSchema: step.resumeSchema,
602
+ suspendSchema: step.suspendSchema,
603
+ stateSchema: step.stateSchema,
604
+ execute: step.execute,
605
+ component: step.component
534
606
  };
535
607
  },
536
608
  cloneWorkflow(workflow, opts) {
@@ -614,7 +686,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
614
686
  });
615
687
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
616
688
  if (stepResult?.status === "suspended") {
617
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
689
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
618
690
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
619
691
  }
620
692
  return [];
@@ -659,21 +731,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
659
731
  mastra: this.mastra,
660
732
  runtimeContext,
661
733
  inputData: prevOutput,
734
+ state: executionContext.state,
735
+ setState: (state) => {
736
+ executionContext.state = state;
737
+ },
662
738
  runCount: -1,
663
739
  tracingContext: {
664
740
  currentSpan: sleepSpan
665
741
  },
666
742
  getInitData: () => stepResults?.input,
667
- getStepResult: (step) => {
668
- if (!step?.id) {
669
- return null;
670
- }
671
- const result = stepResults[step.id];
672
- if (result?.status === "success") {
673
- return result.output;
674
- }
675
- return null;
676
- },
743
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
677
744
  // TODO: this function shouldn't have suspend probably?
678
745
  suspend: async (_suspendPayload) => {
679
746
  },
@@ -745,21 +812,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
745
812
  mastra: this.mastra,
746
813
  runtimeContext,
747
814
  inputData: prevOutput,
815
+ state: executionContext.state,
816
+ setState: (state) => {
817
+ executionContext.state = state;
818
+ },
748
819
  runCount: -1,
749
820
  tracingContext: {
750
821
  currentSpan: sleepUntilSpan
751
822
  },
752
823
  getInitData: () => stepResults?.input,
753
- getStepResult: (step) => {
754
- if (!step?.id) {
755
- return null;
756
- }
757
- const result = stepResults[step.id];
758
- if (result?.status === "success") {
759
- return result.output;
760
- }
761
- return null;
762
- },
824
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
763
825
  // TODO: this function shouldn't have suspend probably?
764
826
  suspend: async (_suspendPayload) => {
765
827
  },
@@ -838,6 +900,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
838
900
  },
839
901
  tracingPolicy: this.options?.tracingPolicy
840
902
  });
903
+ const { inputData, validationError } = await workflows.validateStepInput({
904
+ prevOutput,
905
+ step,
906
+ validateInputs: this.options?.validateInputs ?? false
907
+ });
841
908
  const startedAt = await this.inngestStep.run(
842
909
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
843
910
  async () => {
@@ -868,7 +935,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
868
935
  payload: {
869
936
  id: step.id,
870
937
  status: "running",
871
- payload: prevOutput,
938
+ payload: inputData,
872
939
  startedAt: startedAt2
873
940
  }
874
941
  });
@@ -879,38 +946,60 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
879
946
  const isResume = !!resume?.steps?.length;
880
947
  let result;
881
948
  let runId;
882
- if (isResume) {
883
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? crypto.randomUUID();
884
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
885
- workflowName: step.id,
886
- runId
887
- });
888
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
889
- function: step.getFunction(),
890
- data: {
891
- inputData: prevOutput,
892
- runId,
893
- resume: {
949
+ try {
950
+ if (isResume) {
951
+ runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
952
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
953
+ workflowName: step.id,
954
+ runId
955
+ });
956
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
957
+ function: step.getFunction(),
958
+ data: {
959
+ inputData,
960
+ initialState: executionContext.state ?? snapshot?.value ?? {},
894
961
  runId,
895
- steps: resume.steps.slice(1),
896
- stepResults: snapshot?.context,
897
- resumePayload: resume.resumePayload,
898
- // @ts-ignore
899
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
962
+ resume: {
963
+ runId,
964
+ steps: resume.steps.slice(1),
965
+ stepResults: snapshot?.context,
966
+ resumePayload: resume.resumePayload,
967
+ // @ts-ignore
968
+ resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
969
+ },
970
+ outputOptions: { includeState: true }
900
971
  }
901
- }
902
- });
903
- result = invokeResp.result;
904
- runId = invokeResp.runId;
905
- } else {
906
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
907
- function: step.getFunction(),
908
- data: {
909
- inputData: prevOutput
910
- }
911
- });
912
- result = invokeResp.result;
913
- runId = invokeResp.runId;
972
+ });
973
+ result = invokeResp.result;
974
+ runId = invokeResp.runId;
975
+ executionContext.state = invokeResp.result.state;
976
+ } else {
977
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
978
+ function: step.getFunction(),
979
+ data: {
980
+ inputData,
981
+ initialState: executionContext.state ?? {},
982
+ outputOptions: { includeState: true }
983
+ }
984
+ });
985
+ result = invokeResp.result;
986
+ runId = invokeResp.runId;
987
+ executionContext.state = invokeResp.result.state;
988
+ }
989
+ } catch (e) {
990
+ const errorCause = e?.cause;
991
+ if (errorCause && typeof errorCause === "object") {
992
+ result = errorCause;
993
+ runId = errorCause.runId || crypto.randomUUID();
994
+ } else {
995
+ runId = crypto.randomUUID();
996
+ result = {
997
+ status: "failed",
998
+ error: e instanceof Error ? e : new Error(String(e)),
999
+ steps: {},
1000
+ input: inputData
1001
+ };
1002
+ }
914
1003
  }
915
1004
  const res = await this.inngestStep.run(
916
1005
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
@@ -949,7 +1038,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
949
1038
  return stepRes2?.status === "suspended";
950
1039
  });
951
1040
  for (const [stepName, stepResult] of suspendedSteps) {
952
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1041
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
953
1042
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
954
1043
  await emitter.emit("watch", {
955
1044
  type: "watch",
@@ -957,7 +1046,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
957
1046
  currentStep: {
958
1047
  id: step.id,
959
1048
  status: "suspended",
960
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1049
+ payload: stepResult.payload,
1050
+ suspendPayload: {
1051
+ ...stepResult?.suspendPayload,
1052
+ __workflow_meta: { runId, path: suspendPath }
1053
+ }
961
1054
  },
962
1055
  workflowState: {
963
1056
  status: "running",
@@ -979,7 +1072,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
979
1072
  executionContext,
980
1073
  result: {
981
1074
  status: "suspended",
982
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1075
+ payload: stepResult.payload,
1076
+ suspendPayload: {
1077
+ ...stepResult?.suspendPayload,
1078
+ __workflow_meta: { runId, path: suspendPath }
1079
+ }
983
1080
  }
984
1081
  };
985
1082
  }
@@ -1044,141 +1141,173 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1044
1141
  }
1045
1142
  );
1046
1143
  Object.assign(executionContext, res.executionContext);
1047
- return res.result;
1144
+ return {
1145
+ ...res.result,
1146
+ startedAt,
1147
+ endedAt: Date.now(),
1148
+ payload: inputData,
1149
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1150
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1151
+ };
1048
1152
  }
1049
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1050
- let execResults;
1051
- let suspended;
1052
- let bailed;
1053
- try {
1054
- const result = await step.execute({
1055
- runId: executionContext.runId,
1056
- mastra: this.mastra,
1057
- runtimeContext,
1058
- writableStream,
1059
- inputData: prevOutput,
1060
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1061
- tracingContext: {
1062
- currentSpan: stepAISpan
1063
- },
1064
- getInitData: () => stepResults?.input,
1065
- getStepResult: (step2) => {
1066
- const result2 = stepResults[step2.id];
1067
- if (result2?.status === "success") {
1068
- return result2.output;
1153
+ let stepRes;
1154
+ try {
1155
+ stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1156
+ let execResults;
1157
+ let suspended;
1158
+ let bailed;
1159
+ try {
1160
+ if (validationError) {
1161
+ throw validationError;
1162
+ }
1163
+ const result = await step.execute({
1164
+ runId: executionContext.runId,
1165
+ mastra: this.mastra,
1166
+ runtimeContext,
1167
+ writableStream,
1168
+ state: executionContext?.state ?? {},
1169
+ setState: (state) => {
1170
+ executionContext.state = state;
1171
+ },
1172
+ inputData,
1173
+ resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1174
+ tracingContext: {
1175
+ currentSpan: stepAISpan
1176
+ },
1177
+ getInitData: () => stepResults?.input,
1178
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
1179
+ suspend: async (suspendPayload) => {
1180
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1181
+ suspended = { payload: suspendPayload };
1182
+ },
1183
+ bail: (result2) => {
1184
+ bailed = { payload: result2 };
1185
+ },
1186
+ resume: {
1187
+ steps: resume?.steps?.slice(1) || [],
1188
+ resumePayload: resume?.resumePayload,
1189
+ // @ts-ignore
1190
+ runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
1191
+ },
1192
+ [_constants.EMITTER_SYMBOL]: emitter,
1193
+ engine: {
1194
+ step: this.inngestStep
1195
+ },
1196
+ abortSignal: abortController.signal
1197
+ });
1198
+ const endedAt = Date.now();
1199
+ execResults = {
1200
+ status: "success",
1201
+ output: result,
1202
+ startedAt,
1203
+ endedAt,
1204
+ payload: inputData,
1205
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1206
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1207
+ };
1208
+ } catch (e) {
1209
+ const stepFailure = {
1210
+ status: "failed",
1211
+ payload: inputData,
1212
+ error: e instanceof Error ? e.message : String(e),
1213
+ endedAt: Date.now(),
1214
+ startedAt,
1215
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1216
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1217
+ };
1218
+ execResults = stepFailure;
1219
+ const fallbackErrorMessage = `Step ${step.id} failed`;
1220
+ stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1221
+ throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1222
+ cause: execResults
1223
+ });
1224
+ }
1225
+ if (suspended) {
1226
+ execResults = {
1227
+ status: "suspended",
1228
+ suspendPayload: suspended.payload,
1229
+ payload: inputData,
1230
+ suspendedAt: Date.now(),
1231
+ startedAt,
1232
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1233
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1234
+ };
1235
+ } else if (bailed) {
1236
+ execResults = {
1237
+ status: "bailed",
1238
+ output: bailed.payload,
1239
+ payload: inputData,
1240
+ endedAt: Date.now(),
1241
+ startedAt
1242
+ };
1243
+ }
1244
+ await emitter.emit("watch", {
1245
+ type: "watch",
1246
+ payload: {
1247
+ currentStep: {
1248
+ id: step.id,
1249
+ ...execResults
1250
+ },
1251
+ workflowState: {
1252
+ status: "running",
1253
+ steps: { ...stepResults, [step.id]: execResults },
1254
+ result: null,
1255
+ error: null
1069
1256
  }
1070
- return null;
1071
1257
  },
1072
- suspend: async (suspendPayload) => {
1073
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1074
- suspended = { payload: suspendPayload };
1075
- },
1076
- bail: (result2) => {
1077
- bailed = { payload: result2 };
1078
- },
1079
- resume: {
1080
- steps: resume?.steps?.slice(1) || [],
1081
- resumePayload: resume?.resumePayload,
1082
- // @ts-ignore
1083
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1084
- },
1085
- [_constants.EMITTER_SYMBOL]: emitter,
1086
- engine: {
1087
- step: this.inngestStep
1088
- },
1089
- abortSignal: abortController.signal
1258
+ eventTimestamp: Date.now()
1090
1259
  });
1091
- const endedAt = Date.now();
1092
- execResults = {
1093
- status: "success",
1094
- output: result,
1095
- startedAt,
1096
- endedAt,
1097
- payload: prevOutput,
1098
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1099
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1100
- };
1101
- } catch (e) {
1102
- execResults = {
1103
- status: "failed",
1104
- payload: prevOutput,
1105
- error: e instanceof Error ? e.message : String(e),
1106
- endedAt: Date.now(),
1107
- startedAt,
1108
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1109
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1110
- };
1111
- }
1112
- if (suspended) {
1113
- execResults = {
1114
- status: "suspended",
1115
- suspendedPayload: suspended.payload,
1116
- payload: prevOutput,
1117
- suspendedAt: Date.now(),
1118
- startedAt,
1119
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1120
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1121
- };
1122
- } else if (bailed) {
1123
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1124
- }
1125
- if (execResults.status === "failed") {
1126
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1127
- const error = new Error(execResults.error);
1128
- stepAISpan?.error({ error });
1129
- throw error;
1260
+ if (execResults.status === "suspended") {
1261
+ await emitter.emit("watch-v2", {
1262
+ type: "workflow-step-suspended",
1263
+ payload: {
1264
+ id: step.id,
1265
+ ...execResults
1266
+ }
1267
+ });
1268
+ } else {
1269
+ await emitter.emit("watch-v2", {
1270
+ type: "workflow-step-result",
1271
+ payload: {
1272
+ id: step.id,
1273
+ ...execResults
1274
+ }
1275
+ });
1276
+ await emitter.emit("watch-v2", {
1277
+ type: "workflow-step-finish",
1278
+ payload: {
1279
+ id: step.id,
1280
+ metadata: {}
1281
+ }
1282
+ });
1130
1283
  }
1131
- }
1132
- await emitter.emit("watch", {
1133
- type: "watch",
1134
- payload: {
1135
- currentStep: {
1136
- id: step.id,
1137
- ...execResults
1138
- },
1139
- workflowState: {
1140
- status: "running",
1141
- steps: { ...stepResults, [step.id]: execResults },
1142
- result: null,
1143
- error: null
1144
- }
1145
- },
1146
- eventTimestamp: Date.now()
1284
+ stepAISpan?.end({ output: execResults });
1285
+ return { result: execResults, executionContext, stepResults };
1147
1286
  });
1148
- if (execResults.status === "suspended") {
1149
- await emitter.emit("watch-v2", {
1150
- type: "workflow-step-suspended",
1151
- payload: {
1152
- id: step.id,
1153
- ...execResults
1154
- }
1155
- });
1156
- } else {
1157
- await emitter.emit("watch-v2", {
1158
- type: "workflow-step-result",
1159
- payload: {
1160
- id: step.id,
1161
- ...execResults
1162
- }
1163
- });
1164
- await emitter.emit("watch-v2", {
1165
- type: "workflow-step-finish",
1166
- payload: {
1167
- id: step.id,
1168
- metadata: {}
1169
- }
1170
- });
1171
- }
1172
- stepAISpan?.end({ output: execResults });
1173
- return { result: execResults, executionContext, stepResults };
1174
- });
1175
- if (disableScorers !== false) {
1287
+ } catch (e) {
1288
+ const stepFailure = e instanceof Error ? e?.cause : {
1289
+ status: "failed",
1290
+ error: e instanceof Error ? e.message : String(e),
1291
+ payload: inputData,
1292
+ startedAt,
1293
+ endedAt: Date.now()
1294
+ };
1295
+ stepRes = {
1296
+ result: stepFailure,
1297
+ executionContext,
1298
+ stepResults: {
1299
+ ...stepResults,
1300
+ [step.id]: stepFailure
1301
+ }
1302
+ };
1303
+ }
1304
+ if (disableScorers !== false && stepRes.result.status === "success") {
1176
1305
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1177
1306
  if (step.scorers) {
1178
1307
  await this.runScorers({
1179
1308
  scorers: step.scorers,
1180
1309
  runId: executionContext.runId,
1181
- input: prevOutput,
1310
+ input: inputData,
1182
1311
  output: stepRes.result,
1183
1312
  workflowId: executionContext.workflowId,
1184
1313
  stepId: step.id,
@@ -1191,6 +1320,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1191
1320
  }
1192
1321
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1193
1322
  Object.assign(stepResults, stepRes.stepResults);
1323
+ executionContext.state = stepRes.executionContext.state;
1194
1324
  return stepRes.result;
1195
1325
  }
1196
1326
  async persistStepUpdate({
@@ -1207,13 +1337,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1207
1337
  await this.inngestStep.run(
1208
1338
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1209
1339
  async () => {
1340
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1341
+ if (!shouldPersistSnapshot) {
1342
+ return;
1343
+ }
1210
1344
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1211
1345
  workflowName: workflowId,
1212
1346
  runId,
1213
1347
  resourceId,
1214
1348
  snapshot: {
1215
1349
  runId,
1216
- value: {},
1350
+ value: executionContext.state,
1217
1351
  context: stepResults,
1218
1352
  activePaths: [],
1219
1353
  suspendedPaths: executionContext.suspendedPaths,
@@ -1276,20 +1410,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1276
1410
  runtimeContext,
1277
1411
  runCount: -1,
1278
1412
  inputData: prevOutput,
1413
+ state: executionContext.state,
1414
+ setState: (state) => {
1415
+ executionContext.state = state;
1416
+ },
1279
1417
  tracingContext: {
1280
1418
  currentSpan: evalSpan
1281
1419
  },
1282
1420
  getInitData: () => stepResults?.input,
1283
- getStepResult: (step) => {
1284
- if (!step?.id) {
1285
- return null;
1286
- }
1287
- const result2 = stepResults[step.id];
1288
- if (result2?.status === "success") {
1289
- return result2.output;
1290
- }
1291
- return null;
1292
- },
1421
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
1293
1422
  // TODO: this function shouldn't have suspend probably?
1294
1423
  suspend: async (_suspendPayload) => {
1295
1424
  },
@@ -1357,7 +1486,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1357
1486
  executionPath: [...executionContext.executionPath, index],
1358
1487
  suspendedPaths: executionContext.suspendedPaths,
1359
1488
  retryConfig: executionContext.retryConfig,
1360
- executionSpan: executionContext.executionSpan
1489
+ executionSpan: executionContext.executionSpan,
1490
+ state: executionContext.state
1361
1491
  },
1362
1492
  emitter,
1363
1493
  abortController,
@@ -1375,7 +1505,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1375
1505
  if (hasFailed) {
1376
1506
  execResults = { status: "failed", error: hasFailed.result.error };
1377
1507
  } else if (hasSuspended) {
1378
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1508
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1379
1509
  } else {
1380
1510
  execResults = {
1381
1511
  status: "success",