@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.js CHANGED
@@ -3,8 +3,9 @@ import { subscribe } from '@inngest/realtime';
3
3
  import { wrapMastra, AISpanType } from '@mastra/core/ai-tracing';
4
4
  import { RuntimeContext } from '@mastra/core/di';
5
5
  import { ToolStream, Tool } from '@mastra/core/tools';
6
- import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
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
 
@@ -12,7 +13,8 @@ import { z } from 'zod';
12
13
  function serve({
13
14
  mastra,
14
15
  inngest,
15
- functions: userFunctions = []
16
+ functions: userFunctions = [],
17
+ registerOptions
16
18
  }) {
17
19
  const wfs = mastra.getWorkflows();
18
20
  const workflowFunctions = Array.from(
@@ -27,6 +29,7 @@ function serve({
27
29
  )
28
30
  );
29
31
  return serve$1({
32
+ ...registerOptions,
30
33
  client: inngest,
31
34
  functions: [...workflowFunctions, ...userFunctions]
32
35
  });
@@ -56,8 +59,15 @@ var InngestRun = class extends Run {
56
59
  await new Promise((resolve) => setTimeout(resolve, 1e3));
57
60
  runs = await this.getRuns(eventId);
58
61
  if (runs?.[0]?.status === "Failed") {
59
- throw new Error(`Function run ${runs?.[0]?.status}`);
60
- } 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") {
61
71
  const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
62
72
  workflowName: this.workflowId,
63
73
  runId: this.runId
@@ -97,7 +107,8 @@ var InngestRun = class extends Run {
97
107
  }
98
108
  }
99
109
  async start({
100
- inputData
110
+ inputData,
111
+ initialState
101
112
  }) {
102
113
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
103
114
  workflowName: this.workflowId,
@@ -115,10 +126,13 @@ var InngestRun = class extends Run {
115
126
  status: "running"
116
127
  }
117
128
  });
129
+ const inputDataToUse = await this._validateInput(inputData);
130
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
118
131
  const eventOutput = await this.inngest.send({
119
132
  name: `workflow.${this.workflowId}`,
120
133
  data: {
121
- inputData,
134
+ inputData: inputDataToUse,
135
+ initialState: initialStateToUse,
122
136
  runId: this.runId,
123
137
  resourceId: this.resourceId
124
138
  }
@@ -156,17 +170,20 @@ var InngestRun = class extends Run {
156
170
  workflowName: this.workflowId,
157
171
  runId: this.runId
158
172
  });
173
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
174
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
159
175
  const eventOutput = await this.inngest.send({
160
176
  name: `workflow.${this.workflowId}`,
161
177
  data: {
162
- inputData: params.resumeData,
178
+ inputData: resumeDataToUse,
179
+ initialState: snapshot?.value ?? {},
163
180
  runId: this.runId,
164
181
  workflowId: this.workflowId,
165
182
  stepResults: snapshot?.context,
166
183
  resume: {
167
184
  steps,
168
185
  stepResults: snapshot?.context,
169
- resumePayload: params.resumeData,
186
+ resumePayload: resumeDataToUse,
170
187
  // @ts-ignore
171
188
  resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
172
189
  }
@@ -313,13 +330,18 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
313
330
  serializedStepGraph: this.serializedStepGraph,
314
331
  mastra: this.#mastra,
315
332
  retryConfig: this.retryConfig,
316
- cleanup: () => this.runs.delete(runIdToUse)
333
+ cleanup: () => this.runs.delete(runIdToUse),
334
+ workflowSteps: this.steps
317
335
  },
318
336
  this.inngest
319
337
  );
320
338
  this.runs.set(runIdToUse, run);
339
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
340
+ workflowStatus: run.workflowRunStatus,
341
+ stepResults: {}
342
+ });
321
343
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
322
- if (!workflowSnapshotInStorage) {
344
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
323
345
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
324
346
  workflowName: this.id,
325
347
  runId: runIdToUse,
@@ -357,7 +379,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
357
379
  },
358
380
  { event: `workflow.${this.id}` },
359
381
  async ({ event, step, attempt, publish }) => {
360
- let { inputData, runId, resourceId, resume } = event.data;
382
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
361
383
  if (!runId) {
362
384
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
363
385
  return randomUUID();
@@ -385,7 +407,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
385
407
  once: (_event, _callback) => {
386
408
  }
387
409
  };
388
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
410
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
389
411
  const result = await engine.execute({
390
412
  workflowId: this.id,
391
413
  runId,
@@ -393,14 +415,24 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
393
415
  graph: this.executionGraph,
394
416
  serializedStepGraph: this.serializedStepGraph,
395
417
  input: inputData,
418
+ initialState,
396
419
  emitter,
397
420
  retryConfig: this.retryConfig,
398
421
  runtimeContext: new RuntimeContext(),
399
422
  // TODO
400
423
  resume,
401
424
  abortController: new AbortController(),
402
- currentSpan: void 0
425
+ currentSpan: void 0,
403
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;
404
436
  });
405
437
  return { result, runId };
406
438
  }
@@ -434,6 +466,7 @@ function createStep(params) {
434
466
  if (isAgent(params)) {
435
467
  return {
436
468
  id: params.name,
469
+ description: params.getDescription(),
437
470
  // @ts-ignore
438
471
  inputSchema: z.object({
439
472
  prompt: z.string()
@@ -452,28 +485,55 @@ function createStep(params) {
452
485
  name: params.name,
453
486
  args: inputData
454
487
  };
455
- const { fullStream } = await params.stream(inputData.prompt, {
456
- runtimeContext,
457
- tracingContext,
458
- onFinish: (result) => {
459
- streamPromise.resolve(result.text);
460
- },
461
- abortSignal
462
- });
463
- if (abortSignal.aborted) {
464
- return abort();
465
- }
466
- await emitter.emit("watch-v2", {
467
- type: "tool-call-streaming-start",
468
- ...toolData ?? {}
469
- });
470
- for await (const chunk of fullStream) {
471
- if (chunk.type === "text-delta") {
472
- await emitter.emit("watch-v2", {
473
- type: "tool-call-delta",
474
- ...toolData ?? {},
475
- argsTextDelta: chunk.textDelta
476
- });
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
+ }
477
537
  }
478
538
  }
479
539
  await emitter.emit("watch-v2", {
@@ -483,7 +543,8 @@ function createStep(params) {
483
543
  return {
484
544
  text: await streamPromise.promise
485
545
  };
486
- }
546
+ },
547
+ component: params.component
487
548
  };
488
549
  }
489
550
  if (isTool(params)) {
@@ -494,16 +555,20 @@ function createStep(params) {
494
555
  // TODO: tool probably should have strong id type
495
556
  // @ts-ignore
496
557
  id: params.id,
558
+ description: params.description,
497
559
  inputSchema: params.inputSchema,
498
560
  outputSchema: params.outputSchema,
499
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
561
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
500
562
  return params.execute({
501
563
  context: inputData,
502
564
  mastra: wrapMastra(mastra, tracingContext),
503
565
  runtimeContext,
504
- tracingContext
566
+ tracingContext,
567
+ suspend,
568
+ resumeData
505
569
  });
506
- }
570
+ },
571
+ component: "TOOL"
507
572
  };
508
573
  }
509
574
  return {
@@ -519,7 +584,10 @@ function createStep(params) {
519
584
  function init(inngest) {
520
585
  return {
521
586
  createWorkflow(params) {
522
- return new InngestWorkflow(params, inngest);
587
+ return new InngestWorkflow(
588
+ params,
589
+ inngest
590
+ );
523
591
  },
524
592
  createStep,
525
593
  cloneStep(step, opts) {
@@ -528,7 +596,11 @@ function init(inngest) {
528
596
  description: step.description,
529
597
  inputSchema: step.inputSchema,
530
598
  outputSchema: step.outputSchema,
531
- execute: step.execute
599
+ resumeSchema: step.resumeSchema,
600
+ suspendSchema: step.suspendSchema,
601
+ stateSchema: step.stateSchema,
602
+ execute: step.execute,
603
+ component: step.component
532
604
  };
533
605
  },
534
606
  cloneWorkflow(workflow, opts) {
@@ -612,7 +684,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
612
684
  });
613
685
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
614
686
  if (stepResult?.status === "suspended") {
615
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
687
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
616
688
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
617
689
  }
618
690
  return [];
@@ -657,21 +729,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
657
729
  mastra: this.mastra,
658
730
  runtimeContext,
659
731
  inputData: prevOutput,
732
+ state: executionContext.state,
733
+ setState: (state) => {
734
+ executionContext.state = state;
735
+ },
660
736
  runCount: -1,
661
737
  tracingContext: {
662
738
  currentSpan: sleepSpan
663
739
  },
664
740
  getInitData: () => stepResults?.input,
665
- getStepResult: (step) => {
666
- if (!step?.id) {
667
- return null;
668
- }
669
- const result = stepResults[step.id];
670
- if (result?.status === "success") {
671
- return result.output;
672
- }
673
- return null;
674
- },
741
+ getStepResult: getStepResult.bind(this, stepResults),
675
742
  // TODO: this function shouldn't have suspend probably?
676
743
  suspend: async (_suspendPayload) => {
677
744
  },
@@ -743,21 +810,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
743
810
  mastra: this.mastra,
744
811
  runtimeContext,
745
812
  inputData: prevOutput,
813
+ state: executionContext.state,
814
+ setState: (state) => {
815
+ executionContext.state = state;
816
+ },
746
817
  runCount: -1,
747
818
  tracingContext: {
748
819
  currentSpan: sleepUntilSpan
749
820
  },
750
821
  getInitData: () => stepResults?.input,
751
- getStepResult: (step) => {
752
- if (!step?.id) {
753
- return null;
754
- }
755
- const result = stepResults[step.id];
756
- if (result?.status === "success") {
757
- return result.output;
758
- }
759
- return null;
760
- },
822
+ getStepResult: getStepResult.bind(this, stepResults),
761
823
  // TODO: this function shouldn't have suspend probably?
762
824
  suspend: async (_suspendPayload) => {
763
825
  },
@@ -836,6 +898,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
836
898
  },
837
899
  tracingPolicy: this.options?.tracingPolicy
838
900
  });
901
+ const { inputData, validationError } = await validateStepInput({
902
+ prevOutput,
903
+ step,
904
+ validateInputs: this.options?.validateInputs ?? false
905
+ });
839
906
  const startedAt = await this.inngestStep.run(
840
907
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
841
908
  async () => {
@@ -866,7 +933,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
866
933
  payload: {
867
934
  id: step.id,
868
935
  status: "running",
869
- payload: prevOutput,
936
+ payload: inputData,
870
937
  startedAt: startedAt2
871
938
  }
872
939
  });
@@ -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: prevOutput,
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: prevOutput
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,141 +1139,173 @@ 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
- const result = await step.execute({
1053
- runId: executionContext.runId,
1054
- mastra: this.mastra,
1055
- runtimeContext,
1056
- writableStream,
1057
- inputData: prevOutput,
1058
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1059
- tracingContext: {
1060
- currentSpan: stepAISpan
1061
- },
1062
- getInitData: () => stepResults?.input,
1063
- getStepResult: (step2) => {
1064
- const result2 = stepResults[step2.id];
1065
- if (result2?.status === "success") {
1066
- return result2.output;
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
+ });
1222
+ }
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
1067
1254
  }
1068
- return null;
1069
1255
  },
1070
- suspend: async (suspendPayload) => {
1071
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1072
- suspended = { payload: suspendPayload };
1073
- },
1074
- bail: (result2) => {
1075
- bailed = { payload: result2 };
1076
- },
1077
- resume: {
1078
- steps: resume?.steps?.slice(1) || [],
1079
- resumePayload: resume?.resumePayload,
1080
- // @ts-ignore
1081
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1082
- },
1083
- [EMITTER_SYMBOL]: emitter,
1084
- engine: {
1085
- step: this.inngestStep
1086
- },
1087
- abortSignal: abortController.signal
1256
+ eventTimestamp: Date.now()
1088
1257
  });
1089
- const endedAt = Date.now();
1090
- execResults = {
1091
- status: "success",
1092
- output: result,
1093
- startedAt,
1094
- endedAt,
1095
- payload: prevOutput,
1096
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1097
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1098
- };
1099
- } catch (e) {
1100
- execResults = {
1101
- status: "failed",
1102
- payload: prevOutput,
1103
- error: e instanceof Error ? e.message : String(e),
1104
- endedAt: Date.now(),
1105
- startedAt,
1106
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1107
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1108
- };
1109
- }
1110
- if (suspended) {
1111
- execResults = {
1112
- status: "suspended",
1113
- suspendedPayload: suspended.payload,
1114
- payload: prevOutput,
1115
- suspendedAt: Date.now(),
1116
- startedAt,
1117
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1118
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1119
- };
1120
- } else if (bailed) {
1121
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1122
- }
1123
- if (execResults.status === "failed") {
1124
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1125
- const error = new Error(execResults.error);
1126
- stepAISpan?.error({ error });
1127
- 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
+ });
1128
1281
  }
1129
- }
1130
- await emitter.emit("watch", {
1131
- type: "watch",
1132
- payload: {
1133
- currentStep: {
1134
- id: step.id,
1135
- ...execResults
1136
- },
1137
- workflowState: {
1138
- status: "running",
1139
- steps: { ...stepResults, [step.id]: execResults },
1140
- result: null,
1141
- error: null
1142
- }
1143
- },
1144
- eventTimestamp: Date.now()
1282
+ stepAISpan?.end({ output: execResults });
1283
+ return { result: execResults, executionContext, stepResults };
1145
1284
  });
1146
- if (execResults.status === "suspended") {
1147
- await emitter.emit("watch-v2", {
1148
- type: "workflow-step-suspended",
1149
- payload: {
1150
- id: step.id,
1151
- ...execResults
1152
- }
1153
- });
1154
- } else {
1155
- await emitter.emit("watch-v2", {
1156
- type: "workflow-step-result",
1157
- payload: {
1158
- id: step.id,
1159
- ...execResults
1160
- }
1161
- });
1162
- await emitter.emit("watch-v2", {
1163
- type: "workflow-step-finish",
1164
- payload: {
1165
- id: step.id,
1166
- metadata: {}
1167
- }
1168
- });
1169
- }
1170
- stepAISpan?.end({ output: execResults });
1171
- return { result: execResults, executionContext, stepResults };
1172
- });
1173
- 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") {
1174
1303
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1175
1304
  if (step.scorers) {
1176
1305
  await this.runScorers({
1177
1306
  scorers: step.scorers,
1178
1307
  runId: executionContext.runId,
1179
- input: prevOutput,
1308
+ input: inputData,
1180
1309
  output: stepRes.result,
1181
1310
  workflowId: executionContext.workflowId,
1182
1311
  stepId: step.id,
@@ -1189,6 +1318,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1189
1318
  }
1190
1319
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1191
1320
  Object.assign(stepResults, stepRes.stepResults);
1321
+ executionContext.state = stepRes.executionContext.state;
1192
1322
  return stepRes.result;
1193
1323
  }
1194
1324
  async persistStepUpdate({
@@ -1205,13 +1335,17 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1205
1335
  await this.inngestStep.run(
1206
1336
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1207
1337
  async () => {
1338
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1339
+ if (!shouldPersistSnapshot) {
1340
+ return;
1341
+ }
1208
1342
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1209
1343
  workflowName: workflowId,
1210
1344
  runId,
1211
1345
  resourceId,
1212
1346
  snapshot: {
1213
1347
  runId,
1214
- value: {},
1348
+ value: executionContext.state,
1215
1349
  context: stepResults,
1216
1350
  activePaths: [],
1217
1351
  suspendedPaths: executionContext.suspendedPaths,
@@ -1274,20 +1408,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1274
1408
  runtimeContext,
1275
1409
  runCount: -1,
1276
1410
  inputData: prevOutput,
1411
+ state: executionContext.state,
1412
+ setState: (state) => {
1413
+ executionContext.state = state;
1414
+ },
1277
1415
  tracingContext: {
1278
1416
  currentSpan: evalSpan
1279
1417
  },
1280
1418
  getInitData: () => stepResults?.input,
1281
- getStepResult: (step) => {
1282
- if (!step?.id) {
1283
- return null;
1284
- }
1285
- const result2 = stepResults[step.id];
1286
- if (result2?.status === "success") {
1287
- return result2.output;
1288
- }
1289
- return null;
1290
- },
1419
+ getStepResult: getStepResult.bind(this, stepResults),
1291
1420
  // TODO: this function shouldn't have suspend probably?
1292
1421
  suspend: async (_suspendPayload) => {
1293
1422
  },
@@ -1355,7 +1484,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1355
1484
  executionPath: [...executionContext.executionPath, index],
1356
1485
  suspendedPaths: executionContext.suspendedPaths,
1357
1486
  retryConfig: executionContext.retryConfig,
1358
- executionSpan: executionContext.executionSpan
1487
+ executionSpan: executionContext.executionSpan,
1488
+ state: executionContext.state
1359
1489
  },
1360
1490
  emitter,
1361
1491
  abortController,
@@ -1373,7 +1503,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1373
1503
  if (hasFailed) {
1374
1504
  execResults = { status: "failed", error: hasFailed.result.error };
1375
1505
  } else if (hasSuspended) {
1376
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1506
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1377
1507
  } else {
1378
1508
  execResults = {
1379
1509
  status: "success",