@mastra/inngest 0.0.0-fix-network-silence-20250930164151 → 0.0.0-fix-runtimeContext-passing-chatRoute-20251008220150

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
 
@@ -60,8 +61,15 @@ var InngestRun = class extends workflows.Run {
60
61
  await new Promise((resolve) => setTimeout(resolve, 1e3));
61
62
  runs = await this.getRuns(eventId);
62
63
  if (runs?.[0]?.status === "Failed") {
63
- throw new Error(`Function run ${runs?.[0]?.status}`);
64
- } 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") {
65
73
  const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
66
74
  workflowName: this.workflowId,
67
75
  runId: this.runId
@@ -101,7 +109,8 @@ var InngestRun = class extends workflows.Run {
101
109
  }
102
110
  }
103
111
  async start({
104
- inputData
112
+ inputData,
113
+ initialState
105
114
  }) {
106
115
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
107
116
  workflowName: this.workflowId,
@@ -120,10 +129,12 @@ var InngestRun = class extends workflows.Run {
120
129
  }
121
130
  });
122
131
  const inputDataToUse = await this._validateInput(inputData);
132
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
123
133
  const eventOutput = await this.inngest.send({
124
134
  name: `workflow.${this.workflowId}`,
125
135
  data: {
126
136
  inputData: inputDataToUse,
137
+ initialState: initialStateToUse,
127
138
  runId: this.runId,
128
139
  resourceId: this.resourceId
129
140
  }
@@ -167,6 +178,7 @@ var InngestRun = class extends workflows.Run {
167
178
  name: `workflow.${this.workflowId}`,
168
179
  data: {
169
180
  inputData: resumeDataToUse,
181
+ initialState: snapshot?.value ?? {},
170
182
  runId: this.runId,
171
183
  workflowId: this.workflowId,
172
184
  stepResults: snapshot?.context,
@@ -326,8 +338,12 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
326
338
  this.inngest
327
339
  );
328
340
  this.runs.set(runIdToUse, run);
341
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
342
+ workflowStatus: run.workflowRunStatus,
343
+ stepResults: {}
344
+ });
329
345
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
330
- if (!workflowSnapshotInStorage) {
346
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
331
347
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
332
348
  workflowName: this.id,
333
349
  runId: runIdToUse,
@@ -365,7 +381,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
365
381
  },
366
382
  { event: `workflow.${this.id}` },
367
383
  async ({ event, step, attempt, publish }) => {
368
- let { inputData, runId, resourceId, resume } = event.data;
384
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
369
385
  if (!runId) {
370
386
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
371
387
  return crypto.randomUUID();
@@ -393,7 +409,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
393
409
  once: (_event, _callback) => {
394
410
  }
395
411
  };
396
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
412
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
397
413
  const result = await engine.execute({
398
414
  workflowId: this.id,
399
415
  runId,
@@ -401,14 +417,24 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
401
417
  graph: this.executionGraph,
402
418
  serializedStepGraph: this.serializedStepGraph,
403
419
  input: inputData,
420
+ initialState,
404
421
  emitter,
405
422
  retryConfig: this.retryConfig,
406
423
  runtimeContext: new di.RuntimeContext(),
407
424
  // TODO
408
425
  resume,
409
426
  abortController: new AbortController(),
410
- currentSpan: void 0
427
+ currentSpan: void 0,
411
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;
412
438
  });
413
439
  return { result, runId };
414
440
  }
@@ -461,28 +487,55 @@ function createStep(params) {
461
487
  name: params.name,
462
488
  args: inputData
463
489
  };
464
- const { fullStream } = await params.stream(inputData.prompt, {
465
- runtimeContext,
466
- tracingContext,
467
- onFinish: (result) => {
468
- streamPromise.resolve(result.text);
469
- },
470
- abortSignal
471
- });
472
- if (abortSignal.aborted) {
473
- return abort();
474
- }
475
- await emitter.emit("watch-v2", {
476
- type: "tool-call-streaming-start",
477
- ...toolData ?? {}
478
- });
479
- for await (const chunk of fullStream) {
480
- if (chunk.type === "text-delta") {
481
- await emitter.emit("watch-v2", {
482
- type: "tool-call-delta",
483
- ...toolData ?? {},
484
- argsTextDelta: chunk.textDelta
485
- });
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
+ }
486
539
  }
487
540
  }
488
541
  await emitter.emit("watch-v2", {
@@ -533,7 +586,10 @@ function createStep(params) {
533
586
  function init(inngest) {
534
587
  return {
535
588
  createWorkflow(params) {
536
- return new InngestWorkflow(params, inngest);
589
+ return new InngestWorkflow(
590
+ params,
591
+ inngest
592
+ );
537
593
  },
538
594
  createStep,
539
595
  cloneStep(step, opts) {
@@ -542,6 +598,9 @@ function init(inngest) {
542
598
  description: step.description,
543
599
  inputSchema: step.inputSchema,
544
600
  outputSchema: step.outputSchema,
601
+ resumeSchema: step.resumeSchema,
602
+ suspendSchema: step.suspendSchema,
603
+ stateSchema: step.stateSchema,
545
604
  execute: step.execute,
546
605
  component: step.component
547
606
  };
@@ -627,7 +686,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
627
686
  });
628
687
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
629
688
  if (stepResult?.status === "suspended") {
630
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
689
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
631
690
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
632
691
  }
633
692
  return [];
@@ -672,6 +731,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
672
731
  mastra: this.mastra,
673
732
  runtimeContext,
674
733
  inputData: prevOutput,
734
+ state: executionContext.state,
735
+ setState: (state) => {
736
+ executionContext.state = state;
737
+ },
675
738
  runCount: -1,
676
739
  tracingContext: {
677
740
  currentSpan: sleepSpan
@@ -749,6 +812,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
749
812
  mastra: this.mastra,
750
813
  runtimeContext,
751
814
  inputData: prevOutput,
815
+ state: executionContext.state,
816
+ setState: (state) => {
817
+ executionContext.state = state;
818
+ },
752
819
  runCount: -1,
753
820
  tracingContext: {
754
821
  currentSpan: sleepUntilSpan
@@ -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,
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
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,132 +1141,167 @@ 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
- if (validationError) {
1055
- throw validationError;
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
+ });
1056
1224
  }
1057
- const result = await step.execute({
1058
- runId: executionContext.runId,
1059
- mastra: this.mastra,
1060
- runtimeContext,
1061
- writableStream,
1062
- inputData,
1063
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1064
- tracingContext: {
1065
- currentSpan: stepAISpan
1066
- },
1067
- getInitData: () => stepResults?.input,
1068
- getStepResult: workflows.getStepResult.bind(this, stepResults),
1069
- suspend: async (suspendPayload) => {
1070
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1071
- suspended = { payload: suspendPayload };
1072
- },
1073
- bail: (result2) => {
1074
- bailed = { payload: result2 };
1075
- },
1076
- resume: {
1077
- steps: resume?.steps?.slice(1) || [],
1078
- resumePayload: resume?.resumePayload,
1079
- // @ts-ignore
1080
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1081
- },
1082
- [_constants.EMITTER_SYMBOL]: emitter,
1083
- engine: {
1084
- step: this.inngestStep
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
1256
+ }
1085
1257
  },
1086
- abortSignal: abortController.signal
1258
+ eventTimestamp: Date.now()
1087
1259
  });
1088
- const endedAt = Date.now();
1089
- execResults = {
1090
- status: "success",
1091
- output: result,
1092
- startedAt,
1093
- endedAt,
1094
- payload: inputData,
1095
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1096
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1097
- };
1098
- } catch (e) {
1099
- execResults = {
1100
- status: "failed",
1101
- payload: inputData,
1102
- error: e instanceof Error ? e.message : String(e),
1103
- endedAt: Date.now(),
1104
- startedAt,
1105
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1106
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1107
- };
1108
- }
1109
- if (suspended) {
1110
- execResults = {
1111
- status: "suspended",
1112
- suspendedPayload: suspended.payload,
1113
- payload: inputData,
1114
- suspendedAt: Date.now(),
1115
- startedAt,
1116
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1117
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1118
- };
1119
- } else if (bailed) {
1120
- execResults = { status: "bailed", output: bailed.payload, payload: inputData, endedAt: Date.now(), startedAt };
1121
- }
1122
- if (execResults.status === "failed") {
1123
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1124
- const error = new Error(execResults.error);
1125
- stepAISpan?.error({ error });
1126
- 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
+ });
1127
1283
  }
1128
- }
1129
- await emitter.emit("watch", {
1130
- type: "watch",
1131
- payload: {
1132
- currentStep: {
1133
- id: step.id,
1134
- ...execResults
1135
- },
1136
- workflowState: {
1137
- status: "running",
1138
- steps: { ...stepResults, [step.id]: execResults },
1139
- result: null,
1140
- error: null
1141
- }
1142
- },
1143
- eventTimestamp: Date.now()
1284
+ stepAISpan?.end({ output: execResults });
1285
+ return { result: execResults, executionContext, stepResults };
1144
1286
  });
1145
- if (execResults.status === "suspended") {
1146
- await emitter.emit("watch-v2", {
1147
- type: "workflow-step-suspended",
1148
- payload: {
1149
- id: step.id,
1150
- ...execResults
1151
- }
1152
- });
1153
- } else {
1154
- await emitter.emit("watch-v2", {
1155
- type: "workflow-step-result",
1156
- payload: {
1157
- id: step.id,
1158
- ...execResults
1159
- }
1160
- });
1161
- await emitter.emit("watch-v2", {
1162
- type: "workflow-step-finish",
1163
- payload: {
1164
- id: step.id,
1165
- metadata: {}
1166
- }
1167
- });
1168
- }
1169
- stepAISpan?.end({ output: execResults });
1170
- return { result: execResults, executionContext, stepResults };
1171
- });
1172
- 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") {
1173
1305
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1174
1306
  if (step.scorers) {
1175
1307
  await this.runScorers({
@@ -1188,6 +1320,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1188
1320
  }
1189
1321
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1190
1322
  Object.assign(stepResults, stepRes.stepResults);
1323
+ executionContext.state = stepRes.executionContext.state;
1191
1324
  return stepRes.result;
1192
1325
  }
1193
1326
  async persistStepUpdate({
@@ -1204,13 +1337,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1204
1337
  await this.inngestStep.run(
1205
1338
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1206
1339
  async () => {
1340
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1341
+ if (!shouldPersistSnapshot) {
1342
+ return;
1343
+ }
1207
1344
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1208
1345
  workflowName: workflowId,
1209
1346
  runId,
1210
1347
  resourceId,
1211
1348
  snapshot: {
1212
1349
  runId,
1213
- value: {},
1350
+ value: executionContext.state,
1214
1351
  context: stepResults,
1215
1352
  activePaths: [],
1216
1353
  suspendedPaths: executionContext.suspendedPaths,
@@ -1273,6 +1410,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1273
1410
  runtimeContext,
1274
1411
  runCount: -1,
1275
1412
  inputData: prevOutput,
1413
+ state: executionContext.state,
1414
+ setState: (state) => {
1415
+ executionContext.state = state;
1416
+ },
1276
1417
  tracingContext: {
1277
1418
  currentSpan: evalSpan
1278
1419
  },
@@ -1345,7 +1486,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1345
1486
  executionPath: [...executionContext.executionPath, index],
1346
1487
  suspendedPaths: executionContext.suspendedPaths,
1347
1488
  retryConfig: executionContext.retryConfig,
1348
- executionSpan: executionContext.executionSpan
1489
+ executionSpan: executionContext.executionSpan,
1490
+ state: executionContext.state
1349
1491
  },
1350
1492
  emitter,
1351
1493
  abortController,
@@ -1363,7 +1505,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1363
1505
  if (hasFailed) {
1364
1506
  execResults = { status: "failed", error: hasFailed.result.error };
1365
1507
  } else if (hasSuspended) {
1366
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1508
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1367
1509
  } else {
1368
1510
  execResults = {
1369
1511
  status: "success",