@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.js CHANGED
@@ -5,6 +5,7 @@ import { RuntimeContext } from '@mastra/core/di';
5
5
  import { ToolStream, Tool } from '@mastra/core/tools';
6
6
  import { Run, Workflow, DefaultExecutionEngine, getStepResult, validateStepInput } from '@mastra/core/workflows';
7
7
  import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
8
+ import { NonRetriableError, RetryAfterError } from 'inngest';
8
9
  import { serve as serve$1 } from 'inngest/hono';
9
10
  import { z } from 'zod';
10
11
 
@@ -58,8 +59,15 @@ var InngestRun = class extends Run {
58
59
  await new Promise((resolve) => setTimeout(resolve, 1e3));
59
60
  runs = await this.getRuns(eventId);
60
61
  if (runs?.[0]?.status === "Failed") {
61
- throw new Error(`Function run ${runs?.[0]?.status}`);
62
- } else if (runs?.[0]?.status === "Cancelled") {
62
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
63
+ workflowName: this.workflowId,
64
+ runId: this.runId
65
+ });
66
+ return {
67
+ output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
68
+ };
69
+ }
70
+ if (runs?.[0]?.status === "Cancelled") {
63
71
  const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
64
72
  workflowName: this.workflowId,
65
73
  runId: this.runId
@@ -99,7 +107,8 @@ var InngestRun = class extends Run {
99
107
  }
100
108
  }
101
109
  async start({
102
- inputData
110
+ inputData,
111
+ initialState
103
112
  }) {
104
113
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
105
114
  workflowName: this.workflowId,
@@ -118,10 +127,12 @@ var InngestRun = class extends Run {
118
127
  }
119
128
  });
120
129
  const inputDataToUse = await this._validateInput(inputData);
130
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
121
131
  const eventOutput = await this.inngest.send({
122
132
  name: `workflow.${this.workflowId}`,
123
133
  data: {
124
134
  inputData: inputDataToUse,
135
+ initialState: initialStateToUse,
125
136
  runId: this.runId,
126
137
  resourceId: this.resourceId
127
138
  }
@@ -165,6 +176,7 @@ var InngestRun = class extends Run {
165
176
  name: `workflow.${this.workflowId}`,
166
177
  data: {
167
178
  inputData: resumeDataToUse,
179
+ initialState: snapshot?.value ?? {},
168
180
  runId: this.runId,
169
181
  workflowId: this.workflowId,
170
182
  stepResults: snapshot?.context,
@@ -324,8 +336,12 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
324
336
  this.inngest
325
337
  );
326
338
  this.runs.set(runIdToUse, run);
339
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
340
+ workflowStatus: run.workflowRunStatus,
341
+ stepResults: {}
342
+ });
327
343
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
328
- if (!workflowSnapshotInStorage) {
344
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
329
345
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
330
346
  workflowName: this.id,
331
347
  runId: runIdToUse,
@@ -363,7 +379,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
363
379
  },
364
380
  { event: `workflow.${this.id}` },
365
381
  async ({ event, step, attempt, publish }) => {
366
- let { inputData, runId, resourceId, resume } = event.data;
382
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
367
383
  if (!runId) {
368
384
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
369
385
  return randomUUID();
@@ -391,7 +407,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
391
407
  once: (_event, _callback) => {
392
408
  }
393
409
  };
394
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
410
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
395
411
  const result = await engine.execute({
396
412
  workflowId: this.id,
397
413
  runId,
@@ -399,14 +415,24 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
399
415
  graph: this.executionGraph,
400
416
  serializedStepGraph: this.serializedStepGraph,
401
417
  input: inputData,
418
+ initialState,
402
419
  emitter,
403
420
  retryConfig: this.retryConfig,
404
421
  runtimeContext: new RuntimeContext(),
405
422
  // TODO
406
423
  resume,
407
424
  abortController: new AbortController(),
408
- currentSpan: void 0
425
+ currentSpan: void 0,
409
426
  // TODO: Pass actual parent AI span from workflow execution context
427
+ outputOptions
428
+ });
429
+ await step.run(`workflow.${this.id}.finalize`, async () => {
430
+ if (result.status === "failed") {
431
+ throw new NonRetriableError(`Workflow failed`, {
432
+ cause: result
433
+ });
434
+ }
435
+ return result;
410
436
  });
411
437
  return { result, runId };
412
438
  }
@@ -459,28 +485,55 @@ function createStep(params) {
459
485
  name: params.name,
460
486
  args: inputData
461
487
  };
462
- const { fullStream } = await params.stream(inputData.prompt, {
463
- runtimeContext,
464
- tracingContext,
465
- onFinish: (result) => {
466
- streamPromise.resolve(result.text);
467
- },
468
- abortSignal
469
- });
470
- if (abortSignal.aborted) {
471
- return abort();
472
- }
473
- await emitter.emit("watch-v2", {
474
- type: "tool-call-streaming-start",
475
- ...toolData ?? {}
476
- });
477
- for await (const chunk of fullStream) {
478
- if (chunk.type === "text-delta") {
479
- await emitter.emit("watch-v2", {
480
- type: "tool-call-delta",
481
- ...toolData ?? {},
482
- argsTextDelta: chunk.textDelta
483
- });
488
+ if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
489
+ const { fullStream } = await params.stream(inputData.prompt, {
490
+ runtimeContext,
491
+ tracingContext,
492
+ onFinish: (result) => {
493
+ streamPromise.resolve(result.text);
494
+ },
495
+ abortSignal
496
+ });
497
+ if (abortSignal.aborted) {
498
+ return abort();
499
+ }
500
+ await emitter.emit("watch-v2", {
501
+ type: "tool-call-streaming-start",
502
+ ...toolData ?? {}
503
+ });
504
+ for await (const chunk of fullStream) {
505
+ if (chunk.type === "text-delta") {
506
+ await emitter.emit("watch-v2", {
507
+ type: "tool-call-delta",
508
+ ...toolData ?? {},
509
+ argsTextDelta: chunk.payload.text
510
+ });
511
+ }
512
+ }
513
+ } else {
514
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
515
+ runtimeContext,
516
+ tracingContext,
517
+ onFinish: (result) => {
518
+ streamPromise.resolve(result.text);
519
+ },
520
+ abortSignal
521
+ });
522
+ if (abortSignal.aborted) {
523
+ return abort();
524
+ }
525
+ await emitter.emit("watch-v2", {
526
+ type: "tool-call-streaming-start",
527
+ ...toolData ?? {}
528
+ });
529
+ for await (const chunk of fullStream) {
530
+ if (chunk.type === "text-delta") {
531
+ await emitter.emit("watch-v2", {
532
+ type: "tool-call-delta",
533
+ ...toolData ?? {},
534
+ argsTextDelta: chunk.textDelta
535
+ });
536
+ }
484
537
  }
485
538
  }
486
539
  await emitter.emit("watch-v2", {
@@ -531,7 +584,10 @@ function createStep(params) {
531
584
  function init(inngest) {
532
585
  return {
533
586
  createWorkflow(params) {
534
- return new InngestWorkflow(params, inngest);
587
+ return new InngestWorkflow(
588
+ params,
589
+ inngest
590
+ );
535
591
  },
536
592
  createStep,
537
593
  cloneStep(step, opts) {
@@ -540,6 +596,9 @@ function init(inngest) {
540
596
  description: step.description,
541
597
  inputSchema: step.inputSchema,
542
598
  outputSchema: step.outputSchema,
599
+ resumeSchema: step.resumeSchema,
600
+ suspendSchema: step.suspendSchema,
601
+ stateSchema: step.stateSchema,
543
602
  execute: step.execute,
544
603
  component: step.component
545
604
  };
@@ -625,7 +684,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
625
684
  });
626
685
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
627
686
  if (stepResult?.status === "suspended") {
628
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
687
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
629
688
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
630
689
  }
631
690
  return [];
@@ -670,6 +729,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
670
729
  mastra: this.mastra,
671
730
  runtimeContext,
672
731
  inputData: prevOutput,
732
+ state: executionContext.state,
733
+ setState: (state) => {
734
+ executionContext.state = state;
735
+ },
673
736
  runCount: -1,
674
737
  tracingContext: {
675
738
  currentSpan: sleepSpan
@@ -747,6 +810,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
747
810
  mastra: this.mastra,
748
811
  runtimeContext,
749
812
  inputData: prevOutput,
813
+ state: executionContext.state,
814
+ setState: (state) => {
815
+ executionContext.state = state;
816
+ },
750
817
  runCount: -1,
751
818
  tracingContext: {
752
819
  currentSpan: sleepUntilSpan
@@ -877,38 +944,60 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
877
944
  const isResume = !!resume?.steps?.length;
878
945
  let result;
879
946
  let runId;
880
- if (isResume) {
881
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? randomUUID();
882
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
883
- workflowName: step.id,
884
- runId
885
- });
886
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
887
- function: step.getFunction(),
888
- data: {
889
- inputData,
890
- runId,
891
- resume: {
947
+ try {
948
+ if (isResume) {
949
+ runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
950
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
951
+ workflowName: step.id,
952
+ runId
953
+ });
954
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
955
+ function: step.getFunction(),
956
+ data: {
957
+ inputData,
958
+ initialState: executionContext.state ?? snapshot?.value ?? {},
892
959
  runId,
893
- steps: resume.steps.slice(1),
894
- stepResults: snapshot?.context,
895
- resumePayload: resume.resumePayload,
896
- // @ts-ignore
897
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
960
+ resume: {
961
+ runId,
962
+ steps: resume.steps.slice(1),
963
+ stepResults: snapshot?.context,
964
+ resumePayload: resume.resumePayload,
965
+ // @ts-ignore
966
+ resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
967
+ },
968
+ outputOptions: { includeState: true }
898
969
  }
899
- }
900
- });
901
- result = invokeResp.result;
902
- runId = invokeResp.runId;
903
- } else {
904
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
905
- function: step.getFunction(),
906
- data: {
907
- inputData
908
- }
909
- });
910
- result = invokeResp.result;
911
- runId = invokeResp.runId;
970
+ });
971
+ result = invokeResp.result;
972
+ runId = invokeResp.runId;
973
+ executionContext.state = invokeResp.result.state;
974
+ } else {
975
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
976
+ function: step.getFunction(),
977
+ data: {
978
+ inputData,
979
+ initialState: executionContext.state ?? {},
980
+ outputOptions: { includeState: true }
981
+ }
982
+ });
983
+ result = invokeResp.result;
984
+ runId = invokeResp.runId;
985
+ executionContext.state = invokeResp.result.state;
986
+ }
987
+ } catch (e) {
988
+ const errorCause = e?.cause;
989
+ if (errorCause && typeof errorCause === "object") {
990
+ result = errorCause;
991
+ runId = errorCause.runId || randomUUID();
992
+ } else {
993
+ runId = randomUUID();
994
+ result = {
995
+ status: "failed",
996
+ error: e instanceof Error ? e : new Error(String(e)),
997
+ steps: {},
998
+ input: inputData
999
+ };
1000
+ }
912
1001
  }
913
1002
  const res = await this.inngestStep.run(
914
1003
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
@@ -947,7 +1036,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
947
1036
  return stepRes2?.status === "suspended";
948
1037
  });
949
1038
  for (const [stepName, stepResult] of suspendedSteps) {
950
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1039
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
951
1040
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
952
1041
  await emitter.emit("watch", {
953
1042
  type: "watch",
@@ -955,7 +1044,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
955
1044
  currentStep: {
956
1045
  id: step.id,
957
1046
  status: "suspended",
958
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1047
+ payload: stepResult.payload,
1048
+ suspendPayload: {
1049
+ ...stepResult?.suspendPayload,
1050
+ __workflow_meta: { runId, path: suspendPath }
1051
+ }
959
1052
  },
960
1053
  workflowState: {
961
1054
  status: "running",
@@ -977,7 +1070,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
977
1070
  executionContext,
978
1071
  result: {
979
1072
  status: "suspended",
980
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1073
+ payload: stepResult.payload,
1074
+ suspendPayload: {
1075
+ ...stepResult?.suspendPayload,
1076
+ __workflow_meta: { runId, path: suspendPath }
1077
+ }
981
1078
  }
982
1079
  };
983
1080
  }
@@ -1042,132 +1139,167 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1042
1139
  }
1043
1140
  );
1044
1141
  Object.assign(executionContext, res.executionContext);
1045
- return res.result;
1142
+ return {
1143
+ ...res.result,
1144
+ startedAt,
1145
+ endedAt: Date.now(),
1146
+ payload: inputData,
1147
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1148
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1149
+ };
1046
1150
  }
1047
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1048
- let execResults;
1049
- let suspended;
1050
- let bailed;
1051
- try {
1052
- if (validationError) {
1053
- throw validationError;
1151
+ let stepRes;
1152
+ try {
1153
+ stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1154
+ let execResults;
1155
+ let suspended;
1156
+ let bailed;
1157
+ try {
1158
+ if (validationError) {
1159
+ throw validationError;
1160
+ }
1161
+ const result = await step.execute({
1162
+ runId: executionContext.runId,
1163
+ mastra: this.mastra,
1164
+ runtimeContext,
1165
+ writableStream,
1166
+ state: executionContext?.state ?? {},
1167
+ setState: (state) => {
1168
+ executionContext.state = state;
1169
+ },
1170
+ inputData,
1171
+ resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1172
+ tracingContext: {
1173
+ currentSpan: stepAISpan
1174
+ },
1175
+ getInitData: () => stepResults?.input,
1176
+ getStepResult: getStepResult.bind(this, stepResults),
1177
+ suspend: async (suspendPayload) => {
1178
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1179
+ suspended = { payload: suspendPayload };
1180
+ },
1181
+ bail: (result2) => {
1182
+ bailed = { payload: result2 };
1183
+ },
1184
+ resume: {
1185
+ steps: resume?.steps?.slice(1) || [],
1186
+ resumePayload: resume?.resumePayload,
1187
+ // @ts-ignore
1188
+ runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
1189
+ },
1190
+ [EMITTER_SYMBOL]: emitter,
1191
+ engine: {
1192
+ step: this.inngestStep
1193
+ },
1194
+ abortSignal: abortController.signal
1195
+ });
1196
+ const endedAt = Date.now();
1197
+ execResults = {
1198
+ status: "success",
1199
+ output: result,
1200
+ startedAt,
1201
+ endedAt,
1202
+ payload: inputData,
1203
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1204
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1205
+ };
1206
+ } catch (e) {
1207
+ const stepFailure = {
1208
+ status: "failed",
1209
+ payload: inputData,
1210
+ error: e instanceof Error ? e.message : String(e),
1211
+ endedAt: Date.now(),
1212
+ startedAt,
1213
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1214
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1215
+ };
1216
+ execResults = stepFailure;
1217
+ const fallbackErrorMessage = `Step ${step.id} failed`;
1218
+ stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1219
+ throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1220
+ cause: execResults
1221
+ });
1054
1222
  }
1055
- const result = await step.execute({
1056
- runId: executionContext.runId,
1057
- mastra: this.mastra,
1058
- runtimeContext,
1059
- writableStream,
1060
- inputData,
1061
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1062
- tracingContext: {
1063
- currentSpan: stepAISpan
1064
- },
1065
- getInitData: () => stepResults?.input,
1066
- getStepResult: getStepResult.bind(this, stepResults),
1067
- suspend: async (suspendPayload) => {
1068
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1069
- suspended = { payload: suspendPayload };
1070
- },
1071
- bail: (result2) => {
1072
- bailed = { payload: result2 };
1073
- },
1074
- resume: {
1075
- steps: resume?.steps?.slice(1) || [],
1076
- resumePayload: resume?.resumePayload,
1077
- // @ts-ignore
1078
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1079
- },
1080
- [EMITTER_SYMBOL]: emitter,
1081
- engine: {
1082
- step: this.inngestStep
1223
+ if (suspended) {
1224
+ execResults = {
1225
+ status: "suspended",
1226
+ suspendPayload: suspended.payload,
1227
+ payload: inputData,
1228
+ suspendedAt: Date.now(),
1229
+ startedAt,
1230
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1231
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1232
+ };
1233
+ } else if (bailed) {
1234
+ execResults = {
1235
+ status: "bailed",
1236
+ output: bailed.payload,
1237
+ payload: inputData,
1238
+ endedAt: Date.now(),
1239
+ startedAt
1240
+ };
1241
+ }
1242
+ await emitter.emit("watch", {
1243
+ type: "watch",
1244
+ payload: {
1245
+ currentStep: {
1246
+ id: step.id,
1247
+ ...execResults
1248
+ },
1249
+ workflowState: {
1250
+ status: "running",
1251
+ steps: { ...stepResults, [step.id]: execResults },
1252
+ result: null,
1253
+ error: null
1254
+ }
1083
1255
  },
1084
- abortSignal: abortController.signal
1256
+ eventTimestamp: Date.now()
1085
1257
  });
1086
- const endedAt = Date.now();
1087
- execResults = {
1088
- status: "success",
1089
- output: result,
1090
- startedAt,
1091
- endedAt,
1092
- payload: inputData,
1093
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1094
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1095
- };
1096
- } catch (e) {
1097
- execResults = {
1098
- status: "failed",
1099
- payload: inputData,
1100
- error: e instanceof Error ? e.message : String(e),
1101
- endedAt: Date.now(),
1102
- startedAt,
1103
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1104
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1105
- };
1106
- }
1107
- if (suspended) {
1108
- execResults = {
1109
- status: "suspended",
1110
- suspendedPayload: suspended.payload,
1111
- payload: inputData,
1112
- suspendedAt: Date.now(),
1113
- startedAt,
1114
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1115
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1116
- };
1117
- } else if (bailed) {
1118
- execResults = { status: "bailed", output: bailed.payload, payload: inputData, endedAt: Date.now(), startedAt };
1119
- }
1120
- if (execResults.status === "failed") {
1121
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1122
- const error = new Error(execResults.error);
1123
- stepAISpan?.error({ error });
1124
- throw error;
1258
+ if (execResults.status === "suspended") {
1259
+ await emitter.emit("watch-v2", {
1260
+ type: "workflow-step-suspended",
1261
+ payload: {
1262
+ id: step.id,
1263
+ ...execResults
1264
+ }
1265
+ });
1266
+ } else {
1267
+ await emitter.emit("watch-v2", {
1268
+ type: "workflow-step-result",
1269
+ payload: {
1270
+ id: step.id,
1271
+ ...execResults
1272
+ }
1273
+ });
1274
+ await emitter.emit("watch-v2", {
1275
+ type: "workflow-step-finish",
1276
+ payload: {
1277
+ id: step.id,
1278
+ metadata: {}
1279
+ }
1280
+ });
1125
1281
  }
1126
- }
1127
- await emitter.emit("watch", {
1128
- type: "watch",
1129
- payload: {
1130
- currentStep: {
1131
- id: step.id,
1132
- ...execResults
1133
- },
1134
- workflowState: {
1135
- status: "running",
1136
- steps: { ...stepResults, [step.id]: execResults },
1137
- result: null,
1138
- error: null
1139
- }
1140
- },
1141
- eventTimestamp: Date.now()
1282
+ stepAISpan?.end({ output: execResults });
1283
+ return { result: execResults, executionContext, stepResults };
1142
1284
  });
1143
- if (execResults.status === "suspended") {
1144
- await emitter.emit("watch-v2", {
1145
- type: "workflow-step-suspended",
1146
- payload: {
1147
- id: step.id,
1148
- ...execResults
1149
- }
1150
- });
1151
- } else {
1152
- await emitter.emit("watch-v2", {
1153
- type: "workflow-step-result",
1154
- payload: {
1155
- id: step.id,
1156
- ...execResults
1157
- }
1158
- });
1159
- await emitter.emit("watch-v2", {
1160
- type: "workflow-step-finish",
1161
- payload: {
1162
- id: step.id,
1163
- metadata: {}
1164
- }
1165
- });
1166
- }
1167
- stepAISpan?.end({ output: execResults });
1168
- return { result: execResults, executionContext, stepResults };
1169
- });
1170
- if (disableScorers !== false) {
1285
+ } catch (e) {
1286
+ const stepFailure = e instanceof Error ? e?.cause : {
1287
+ status: "failed",
1288
+ error: e instanceof Error ? e.message : String(e),
1289
+ payload: inputData,
1290
+ startedAt,
1291
+ endedAt: Date.now()
1292
+ };
1293
+ stepRes = {
1294
+ result: stepFailure,
1295
+ executionContext,
1296
+ stepResults: {
1297
+ ...stepResults,
1298
+ [step.id]: stepFailure
1299
+ }
1300
+ };
1301
+ }
1302
+ if (disableScorers !== false && stepRes.result.status === "success") {
1171
1303
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1172
1304
  if (step.scorers) {
1173
1305
  await this.runScorers({
@@ -1186,6 +1318,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1186
1318
  }
1187
1319
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1188
1320
  Object.assign(stepResults, stepRes.stepResults);
1321
+ executionContext.state = stepRes.executionContext.state;
1189
1322
  return stepRes.result;
1190
1323
  }
1191
1324
  async persistStepUpdate({
@@ -1202,13 +1335,17 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1202
1335
  await this.inngestStep.run(
1203
1336
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1204
1337
  async () => {
1338
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1339
+ if (!shouldPersistSnapshot) {
1340
+ return;
1341
+ }
1205
1342
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1206
1343
  workflowName: workflowId,
1207
1344
  runId,
1208
1345
  resourceId,
1209
1346
  snapshot: {
1210
1347
  runId,
1211
- value: {},
1348
+ value: executionContext.state,
1212
1349
  context: stepResults,
1213
1350
  activePaths: [],
1214
1351
  suspendedPaths: executionContext.suspendedPaths,
@@ -1271,6 +1408,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1271
1408
  runtimeContext,
1272
1409
  runCount: -1,
1273
1410
  inputData: prevOutput,
1411
+ state: executionContext.state,
1412
+ setState: (state) => {
1413
+ executionContext.state = state;
1414
+ },
1274
1415
  tracingContext: {
1275
1416
  currentSpan: evalSpan
1276
1417
  },
@@ -1343,7 +1484,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1343
1484
  executionPath: [...executionContext.executionPath, index],
1344
1485
  suspendedPaths: executionContext.suspendedPaths,
1345
1486
  retryConfig: executionContext.retryConfig,
1346
- executionSpan: executionContext.executionSpan
1487
+ executionSpan: executionContext.executionSpan,
1488
+ state: executionContext.state
1347
1489
  },
1348
1490
  emitter,
1349
1491
  abortController,
@@ -1361,7 +1503,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1361
1503
  if (hasFailed) {
1362
1504
  execResults = { status: "failed", error: hasFailed.result.error };
1363
1505
  } else if (hasSuspended) {
1364
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1506
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1365
1507
  } else {
1366
1508
  execResults = {
1367
1509
  status: "success",