@mastra/inngest 0.0.0-iterate-traces-ui-again-20250912091900 → 0.0.0-just-snapshot-20251014192224

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,13 +7,19 @@ 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
 
13
14
  // src/index.ts
14
- function serve({ mastra, inngest }) {
15
+ function serve({
16
+ mastra,
17
+ inngest,
18
+ functions: userFunctions = [],
19
+ registerOptions
20
+ }) {
15
21
  const wfs = mastra.getWorkflows();
16
- const functions = Array.from(
22
+ const workflowFunctions = Array.from(
17
23
  new Set(
18
24
  Object.values(wfs).flatMap((wf) => {
19
25
  if (wf instanceof InngestWorkflow) {
@@ -25,8 +31,9 @@ function serve({ mastra, inngest }) {
25
31
  )
26
32
  );
27
33
  return hono.serve({
34
+ ...registerOptions,
28
35
  client: inngest,
29
- functions
36
+ functions: [...workflowFunctions, ...userFunctions]
30
37
  });
31
38
  }
32
39
  var InngestRun = class extends workflows.Run {
@@ -54,9 +61,15 @@ var InngestRun = class extends workflows.Run {
54
61
  await new Promise((resolve) => setTimeout(resolve, 1e3));
55
62
  runs = await this.getRuns(eventId);
56
63
  if (runs?.[0]?.status === "Failed") {
57
- console.log("run", runs?.[0]);
58
- throw new Error(`Function run ${runs?.[0]?.status}`);
59
- } 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") {
60
73
  const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
61
74
  workflowName: this.workflowId,
62
75
  runId: this.runId
@@ -87,6 +100,7 @@ var InngestRun = class extends workflows.Run {
87
100
  await this.#mastra?.storage?.persistWorkflowSnapshot({
88
101
  workflowName: this.workflowId,
89
102
  runId: this.runId,
103
+ resourceId: this.resourceId,
90
104
  snapshot: {
91
105
  ...snapshot,
92
106
  status: "canceled"
@@ -95,11 +109,13 @@ var InngestRun = class extends workflows.Run {
95
109
  }
96
110
  }
97
111
  async start({
98
- inputData
112
+ inputData,
113
+ initialState
99
114
  }) {
100
115
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
101
116
  workflowName: this.workflowId,
102
117
  runId: this.runId,
118
+ resourceId: this.resourceId,
103
119
  snapshot: {
104
120
  runId: this.runId,
105
121
  serializedStepGraph: this.serializedStepGraph,
@@ -112,11 +128,15 @@ var InngestRun = class extends workflows.Run {
112
128
  status: "running"
113
129
  }
114
130
  });
131
+ const inputDataToUse = await this._validateInput(inputData);
132
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
115
133
  const eventOutput = await this.inngest.send({
116
134
  name: `workflow.${this.workflowId}`,
117
135
  data: {
118
- inputData,
119
- runId: this.runId
136
+ inputData: inputDataToUse,
137
+ initialState: initialStateToUse,
138
+ runId: this.runId,
139
+ resourceId: this.resourceId
120
140
  }
121
141
  });
122
142
  const eventId = eventOutput.ids[0];
@@ -152,17 +172,20 @@ var InngestRun = class extends workflows.Run {
152
172
  workflowName: this.workflowId,
153
173
  runId: this.runId
154
174
  });
175
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
176
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
155
177
  const eventOutput = await this.inngest.send({
156
178
  name: `workflow.${this.workflowId}`,
157
179
  data: {
158
- inputData: params.resumeData,
180
+ inputData: resumeDataToUse,
181
+ initialState: snapshot?.value ?? {},
159
182
  runId: this.runId,
160
183
  workflowId: this.workflowId,
161
184
  stepResults: snapshot?.context,
162
185
  resume: {
163
186
  steps,
164
187
  stepResults: snapshot?.context,
165
- resumePayload: params.resumeData,
188
+ resumePayload: resumeDataToUse,
166
189
  // @ts-ignore
167
190
  resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
168
191
  }
@@ -204,33 +227,9 @@ var InngestRun = class extends workflows.Run {
204
227
  }
205
228
  stream({ inputData, runtimeContext } = {}) {
206
229
  const { readable, writable } = new TransformStream();
207
- let currentToolData = void 0;
208
230
  const writer = writable.getWriter();
209
231
  const unwatch = this.watch(async (event) => {
210
- if (event.type === "workflow-agent-call-start") {
211
- currentToolData = {
212
- name: event.payload.name,
213
- args: event.payload.args
214
- };
215
- await writer.write({
216
- ...event.payload,
217
- type: "tool-call-streaming-start"
218
- });
219
- return;
220
- }
221
232
  try {
222
- if (event.type === "workflow-agent-call-finish") {
223
- return;
224
- } else if (!event.type.startsWith("workflow-")) {
225
- if (event.type === "text-delta") {
226
- await writer.write({
227
- type: "tool-call-delta",
228
- ...currentToolData ?? {},
229
- argsTextDelta: event.textDelta
230
- });
231
- }
232
- return;
233
- }
234
233
  const e = {
235
234
  ...event,
236
235
  type: event.type.replace("workflow-", "")
@@ -312,23 +311,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
312
311
  }
313
312
  }
314
313
  }
315
- createRun(options) {
316
- const runIdToUse = options?.runId || crypto.randomUUID();
317
- const run = this.runs.get(runIdToUse) ?? new InngestRun(
318
- {
319
- workflowId: this.id,
320
- runId: runIdToUse,
321
- executionEngine: this.executionEngine,
322
- executionGraph: this.executionGraph,
323
- serializedStepGraph: this.serializedStepGraph,
324
- mastra: this.#mastra,
325
- retryConfig: this.retryConfig,
326
- cleanup: () => this.runs.delete(runIdToUse)
327
- },
328
- this.inngest
314
+ /**
315
+ * @deprecated Use createRunAsync() instead.
316
+ * @throws {Error} Always throws an error directing users to use createRunAsync()
317
+ */
318
+ createRun(_options) {
319
+ throw new Error(
320
+ "createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async."
329
321
  );
330
- this.runs.set(runIdToUse, run);
331
- return run;
332
322
  }
333
323
  async createRunAsync(options) {
334
324
  const runIdToUse = options?.runId || crypto.randomUUID();
@@ -336,21 +326,28 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
336
326
  {
337
327
  workflowId: this.id,
338
328
  runId: runIdToUse,
329
+ resourceId: options?.resourceId,
339
330
  executionEngine: this.executionEngine,
340
331
  executionGraph: this.executionGraph,
341
332
  serializedStepGraph: this.serializedStepGraph,
342
333
  mastra: this.#mastra,
343
334
  retryConfig: this.retryConfig,
344
- cleanup: () => this.runs.delete(runIdToUse)
335
+ cleanup: () => this.runs.delete(runIdToUse),
336
+ workflowSteps: this.steps
345
337
  },
346
338
  this.inngest
347
339
  );
348
340
  this.runs.set(runIdToUse, run);
341
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
342
+ workflowStatus: run.workflowRunStatus,
343
+ stepResults: {}
344
+ });
349
345
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
350
- if (!workflowSnapshotInStorage) {
346
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
351
347
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
352
348
  workflowName: this.id,
353
349
  runId: runIdToUse,
350
+ resourceId: options?.resourceId,
354
351
  snapshot: {
355
352
  runId: runIdToUse,
356
353
  status: "pending",
@@ -384,7 +381,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
384
381
  },
385
382
  { event: `workflow.${this.id}` },
386
383
  async ({ event, step, attempt, publish }) => {
387
- let { inputData, runId, resume } = event.data;
384
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
388
385
  if (!runId) {
389
386
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
390
387
  return crypto.randomUUID();
@@ -412,21 +409,32 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
412
409
  once: (_event, _callback) => {
413
410
  }
414
411
  };
415
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
412
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
416
413
  const result = await engine.execute({
417
414
  workflowId: this.id,
418
415
  runId,
416
+ resourceId,
419
417
  graph: this.executionGraph,
420
418
  serializedStepGraph: this.serializedStepGraph,
421
419
  input: inputData,
420
+ initialState,
422
421
  emitter,
423
422
  retryConfig: this.retryConfig,
424
423
  runtimeContext: new di.RuntimeContext(),
425
424
  // TODO
426
425
  resume,
427
426
  abortController: new AbortController(),
428
- currentSpan: void 0
427
+ currentSpan: void 0,
429
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;
430
438
  });
431
439
  return { result, runId };
432
440
  }
@@ -460,11 +468,10 @@ function createStep(params) {
460
468
  if (isAgent(params)) {
461
469
  return {
462
470
  id: params.name,
471
+ description: params.getDescription(),
463
472
  // @ts-ignore
464
473
  inputSchema: zod.z.object({
465
474
  prompt: zod.z.string()
466
- // resourceId: z.string().optional(),
467
- // threadId: z.string().optional(),
468
475
  }),
469
476
  // @ts-ignore
470
477
  outputSchema: zod.z.object({
@@ -480,34 +487,66 @@ function createStep(params) {
480
487
  name: params.name,
481
488
  args: inputData
482
489
  };
483
- await emitter.emit("watch-v2", {
484
- type: "workflow-agent-call-start",
485
- payload: toolData
486
- });
487
- const { fullStream } = await params.stream(inputData.prompt, {
488
- // resourceId: inputData.resourceId,
489
- // threadId: inputData.threadId,
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
- for await (const chunk of fullStream) {
501
- await emitter.emit("watch-v2", chunk);
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
+ }
539
+ }
502
540
  }
503
541
  await emitter.emit("watch-v2", {
504
- type: "workflow-agent-call-finish",
505
- payload: toolData
542
+ type: "tool-call-streaming-finish",
543
+ ...toolData ?? {}
506
544
  });
507
545
  return {
508
546
  text: await streamPromise.promise
509
547
  };
510
- }
548
+ },
549
+ component: params.component
511
550
  };
512
551
  }
513
552
  if (isTool(params)) {
@@ -518,16 +557,20 @@ function createStep(params) {
518
557
  // TODO: tool probably should have strong id type
519
558
  // @ts-ignore
520
559
  id: params.id,
560
+ description: params.description,
521
561
  inputSchema: params.inputSchema,
522
562
  outputSchema: params.outputSchema,
523
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
563
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
524
564
  return params.execute({
525
565
  context: inputData,
526
566
  mastra: aiTracing.wrapMastra(mastra, tracingContext),
527
567
  runtimeContext,
528
- tracingContext
568
+ tracingContext,
569
+ suspend,
570
+ resumeData
529
571
  });
530
- }
572
+ },
573
+ component: "TOOL"
531
574
  };
532
575
  }
533
576
  return {
@@ -543,7 +586,10 @@ function createStep(params) {
543
586
  function init(inngest) {
544
587
  return {
545
588
  createWorkflow(params) {
546
- return new InngestWorkflow(params, inngest);
589
+ return new InngestWorkflow(
590
+ params,
591
+ inngest
592
+ );
547
593
  },
548
594
  createStep,
549
595
  cloneStep(step, opts) {
@@ -552,7 +598,11 @@ function init(inngest) {
552
598
  description: step.description,
553
599
  inputSchema: step.inputSchema,
554
600
  outputSchema: step.outputSchema,
555
- execute: step.execute
601
+ resumeSchema: step.resumeSchema,
602
+ suspendSchema: step.suspendSchema,
603
+ stateSchema: step.stateSchema,
604
+ execute: step.execute,
605
+ component: step.component
556
606
  };
557
607
  },
558
608
  cloneWorkflow(workflow, opts) {
@@ -572,8 +622,8 @@ function init(inngest) {
572
622
  var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
573
623
  inngestStep;
574
624
  inngestAttempts;
575
- constructor(mastra, inngestStep, inngestAttempts = 0) {
576
- super({ mastra });
625
+ constructor(mastra, inngestStep, inngestAttempts = 0, options) {
626
+ super({ mastra, options });
577
627
  this.inngestStep = inngestStep;
578
628
  this.inngestAttempts = inngestAttempts;
579
629
  }
@@ -636,7 +686,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
636
686
  });
637
687
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
638
688
  if (stepResult?.status === "suspended") {
639
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
689
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
640
690
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
641
691
  }
642
692
  return [];
@@ -669,7 +719,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
669
719
  attributes: {
670
720
  durationMs: duration,
671
721
  sleepType: fn ? "dynamic" : "fixed"
672
- }
722
+ },
723
+ tracingPolicy: this.options?.tracingPolicy
673
724
  });
674
725
  if (fn) {
675
726
  const stepCallId = crypto.randomUUID();
@@ -680,21 +731,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
680
731
  mastra: this.mastra,
681
732
  runtimeContext,
682
733
  inputData: prevOutput,
734
+ state: executionContext.state,
735
+ setState: (state) => {
736
+ executionContext.state = state;
737
+ },
683
738
  runCount: -1,
684
739
  tracingContext: {
685
740
  currentSpan: sleepSpan
686
741
  },
687
742
  getInitData: () => stepResults?.input,
688
- getStepResult: (step) => {
689
- if (!step?.id) {
690
- return null;
691
- }
692
- const result = stepResults[step.id];
693
- if (result?.status === "success") {
694
- return result.output;
695
- }
696
- return null;
697
- },
743
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
698
744
  // TODO: this function shouldn't have suspend probably?
699
745
  suspend: async (_suspendPayload) => {
700
746
  },
@@ -754,7 +800,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
754
800
  untilDate: date,
755
801
  durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
756
802
  sleepType: fn ? "dynamic" : "fixed"
757
- }
803
+ },
804
+ tracingPolicy: this.options?.tracingPolicy
758
805
  });
759
806
  if (fn) {
760
807
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
@@ -765,21 +812,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
765
812
  mastra: this.mastra,
766
813
  runtimeContext,
767
814
  inputData: prevOutput,
815
+ state: executionContext.state,
816
+ setState: (state) => {
817
+ executionContext.state = state;
818
+ },
768
819
  runCount: -1,
769
820
  tracingContext: {
770
821
  currentSpan: sleepUntilSpan
771
822
  },
772
823
  getInitData: () => stepResults?.input,
773
- getStepResult: (step) => {
774
- if (!step?.id) {
775
- return null;
776
- }
777
- const result = stepResults[step.id];
778
- if (result?.status === "success") {
779
- return result.output;
780
- }
781
- return null;
782
- },
824
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
783
825
  // TODO: this function shouldn't have suspend probably?
784
826
  suspend: async (_suspendPayload) => {
785
827
  },
@@ -804,6 +846,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
804
846
  )
805
847
  });
806
848
  });
849
+ if (date && !(date instanceof Date)) {
850
+ date = new Date(date);
851
+ }
807
852
  const time = !date ? 0 : date.getTime() - Date.now();
808
853
  sleepUntilSpan?.update({
809
854
  attributes: {
@@ -852,7 +897,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
852
897
  input: prevOutput,
853
898
  attributes: {
854
899
  stepId: step.id
855
- }
900
+ },
901
+ tracingPolicy: this.options?.tracingPolicy
902
+ });
903
+ const { inputData, validationError } = await workflows.validateStepInput({
904
+ prevOutput,
905
+ step,
906
+ validateInputs: this.options?.validateInputs ?? false
856
907
  });
857
908
  const startedAt = await this.inngestStep.run(
858
909
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
@@ -884,7 +935,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
884
935
  payload: {
885
936
  id: step.id,
886
937
  status: "running",
887
- payload: prevOutput,
938
+ payload: inputData,
888
939
  startedAt: startedAt2
889
940
  }
890
941
  });
@@ -895,38 +946,60 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
895
946
  const isResume = !!resume?.steps?.length;
896
947
  let result;
897
948
  let runId;
898
- if (isResume) {
899
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? crypto.randomUUID();
900
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
901
- workflowName: step.id,
902
- runId
903
- });
904
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
905
- function: step.getFunction(),
906
- data: {
907
- inputData: prevOutput,
908
- runId,
909
- 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 ?? {},
910
961
  runId,
911
- steps: resume.steps.slice(1),
912
- stepResults: snapshot?.context,
913
- resumePayload: resume.resumePayload,
914
- // @ts-ignore
915
- 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 }
916
971
  }
917
- }
918
- });
919
- result = invokeResp.result;
920
- runId = invokeResp.runId;
921
- } else {
922
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
923
- function: step.getFunction(),
924
- data: {
925
- inputData: prevOutput
926
- }
927
- });
928
- result = invokeResp.result;
929
- 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
+ }
930
1003
  }
931
1004
  const res = await this.inngestStep.run(
932
1005
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
@@ -965,7 +1038,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
965
1038
  return stepRes2?.status === "suspended";
966
1039
  });
967
1040
  for (const [stepName, stepResult] of suspendedSteps) {
968
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1041
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
969
1042
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
970
1043
  await emitter.emit("watch", {
971
1044
  type: "watch",
@@ -973,7 +1046,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
973
1046
  currentStep: {
974
1047
  id: step.id,
975
1048
  status: "suspended",
976
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1049
+ payload: stepResult.payload,
1050
+ suspendPayload: {
1051
+ ...stepResult?.suspendPayload,
1052
+ __workflow_meta: { runId, path: suspendPath }
1053
+ }
977
1054
  },
978
1055
  workflowState: {
979
1056
  status: "running",
@@ -995,7 +1072,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
995
1072
  executionContext,
996
1073
  result: {
997
1074
  status: "suspended",
998
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1075
+ payload: stepResult.payload,
1076
+ suspendPayload: {
1077
+ ...stepResult?.suspendPayload,
1078
+ __workflow_meta: { runId, path: suspendPath }
1079
+ }
999
1080
  }
1000
1081
  };
1001
1082
  }
@@ -1060,141 +1141,173 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1060
1141
  }
1061
1142
  );
1062
1143
  Object.assign(executionContext, res.executionContext);
1063
- 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
+ };
1064
1152
  }
1065
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1066
- let execResults;
1067
- let suspended;
1068
- let bailed;
1069
- try {
1070
- const result = await step.execute({
1071
- runId: executionContext.runId,
1072
- mastra: this.mastra,
1073
- runtimeContext,
1074
- writableStream,
1075
- inputData: prevOutput,
1076
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1077
- tracingContext: {
1078
- currentSpan: stepAISpan
1079
- },
1080
- getInitData: () => stepResults?.input,
1081
- getStepResult: (step2) => {
1082
- const result2 = stepResults[step2.id];
1083
- if (result2?.status === "success") {
1084
- 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
1085
1256
  }
1086
- return null;
1087
- },
1088
- suspend: async (suspendPayload) => {
1089
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1090
- suspended = { payload: suspendPayload };
1091
- },
1092
- bail: (result2) => {
1093
- bailed = { payload: result2 };
1094
1257
  },
1095
- resume: {
1096
- steps: resume?.steps?.slice(1) || [],
1097
- resumePayload: resume?.resumePayload,
1098
- // @ts-ignore
1099
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1100
- },
1101
- [_constants.EMITTER_SYMBOL]: emitter,
1102
- engine: {
1103
- step: this.inngestStep
1104
- },
1105
- abortSignal: abortController.signal
1258
+ eventTimestamp: Date.now()
1106
1259
  });
1107
- const endedAt = Date.now();
1108
- execResults = {
1109
- status: "success",
1110
- output: result,
1111
- startedAt,
1112
- endedAt,
1113
- payload: prevOutput,
1114
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1115
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1116
- };
1117
- } catch (e) {
1118
- execResults = {
1119
- status: "failed",
1120
- payload: prevOutput,
1121
- error: e instanceof Error ? e.message : String(e),
1122
- endedAt: Date.now(),
1123
- startedAt,
1124
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1125
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1126
- };
1127
- }
1128
- if (suspended) {
1129
- execResults = {
1130
- status: "suspended",
1131
- suspendedPayload: suspended.payload,
1132
- payload: prevOutput,
1133
- suspendedAt: Date.now(),
1134
- startedAt,
1135
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1136
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1137
- };
1138
- } else if (bailed) {
1139
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1140
- }
1141
- if (execResults.status === "failed") {
1142
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1143
- const error = new Error(execResults.error);
1144
- stepAISpan?.error({ error });
1145
- 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
+ });
1146
1283
  }
1147
- }
1148
- await emitter.emit("watch", {
1149
- type: "watch",
1150
- payload: {
1151
- currentStep: {
1152
- id: step.id,
1153
- ...execResults
1154
- },
1155
- workflowState: {
1156
- status: "running",
1157
- steps: { ...stepResults, [step.id]: execResults },
1158
- result: null,
1159
- error: null
1160
- }
1161
- },
1162
- eventTimestamp: Date.now()
1284
+ stepAISpan?.end({ output: execResults });
1285
+ return { result: execResults, executionContext, stepResults };
1163
1286
  });
1164
- if (execResults.status === "suspended") {
1165
- await emitter.emit("watch-v2", {
1166
- type: "workflow-step-suspended",
1167
- payload: {
1168
- id: step.id,
1169
- ...execResults
1170
- }
1171
- });
1172
- } else {
1173
- await emitter.emit("watch-v2", {
1174
- type: "workflow-step-result",
1175
- payload: {
1176
- id: step.id,
1177
- ...execResults
1178
- }
1179
- });
1180
- await emitter.emit("watch-v2", {
1181
- type: "workflow-step-finish",
1182
- payload: {
1183
- id: step.id,
1184
- metadata: {}
1185
- }
1186
- });
1187
- }
1188
- stepAISpan?.end({ output: execResults });
1189
- return { result: execResults, executionContext, stepResults };
1190
- });
1191
- 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") {
1192
1305
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1193
1306
  if (step.scorers) {
1194
1307
  await this.runScorers({
1195
1308
  scorers: step.scorers,
1196
1309
  runId: executionContext.runId,
1197
- input: prevOutput,
1310
+ input: inputData,
1198
1311
  output: stepRes.result,
1199
1312
  workflowId: executionContext.workflowId,
1200
1313
  stepId: step.id,
@@ -1207,12 +1320,14 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1207
1320
  }
1208
1321
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1209
1322
  Object.assign(stepResults, stepRes.stepResults);
1323
+ executionContext.state = stepRes.executionContext.state;
1210
1324
  return stepRes.result;
1211
1325
  }
1212
1326
  async persistStepUpdate({
1213
1327
  workflowId,
1214
1328
  runId,
1215
1329
  stepResults,
1330
+ resourceId,
1216
1331
  executionContext,
1217
1332
  serializedStepGraph,
1218
1333
  workflowStatus,
@@ -1222,12 +1337,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1222
1337
  await this.inngestStep.run(
1223
1338
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1224
1339
  async () => {
1340
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1341
+ if (!shouldPersistSnapshot) {
1342
+ return;
1343
+ }
1225
1344
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1226
1345
  workflowName: workflowId,
1227
1346
  runId,
1347
+ resourceId,
1228
1348
  snapshot: {
1229
1349
  runId,
1230
- value: {},
1350
+ value: executionContext.state,
1231
1351
  context: stepResults,
1232
1352
  activePaths: [],
1233
1353
  suspendedPaths: executionContext.suspendedPaths,
@@ -1266,7 +1386,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1266
1386
  input: prevOutput,
1267
1387
  attributes: {
1268
1388
  conditionCount: entry.conditions.length
1269
- }
1389
+ },
1390
+ tracingPolicy: this.options?.tracingPolicy
1270
1391
  });
1271
1392
  let execResults;
1272
1393
  const truthyIndexes = (await Promise.all(
@@ -1278,7 +1399,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1278
1399
  input: prevOutput,
1279
1400
  attributes: {
1280
1401
  conditionIndex: index
1281
- }
1402
+ },
1403
+ tracingPolicy: this.options?.tracingPolicy
1282
1404
  });
1283
1405
  try {
1284
1406
  const result = await cond({
@@ -1288,20 +1410,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1288
1410
  runtimeContext,
1289
1411
  runCount: -1,
1290
1412
  inputData: prevOutput,
1413
+ state: executionContext.state,
1414
+ setState: (state) => {
1415
+ executionContext.state = state;
1416
+ },
1291
1417
  tracingContext: {
1292
1418
  currentSpan: evalSpan
1293
1419
  },
1294
1420
  getInitData: () => stepResults?.input,
1295
- getStepResult: (step) => {
1296
- if (!step?.id) {
1297
- return null;
1298
- }
1299
- const result2 = stepResults[step.id];
1300
- if (result2?.status === "success") {
1301
- return result2.output;
1302
- }
1303
- return null;
1304
- },
1421
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
1305
1422
  // TODO: this function shouldn't have suspend probably?
1306
1423
  suspend: async (_suspendPayload) => {
1307
1424
  },
@@ -1369,7 +1486,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1369
1486
  executionPath: [...executionContext.executionPath, index],
1370
1487
  suspendedPaths: executionContext.suspendedPaths,
1371
1488
  retryConfig: executionContext.retryConfig,
1372
- executionSpan: executionContext.executionSpan
1489
+ executionSpan: executionContext.executionSpan,
1490
+ state: executionContext.state
1373
1491
  },
1374
1492
  emitter,
1375
1493
  abortController,
@@ -1387,7 +1505,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1387
1505
  if (hasFailed) {
1388
1506
  execResults = { status: "failed", error: hasFailed.result.error };
1389
1507
  } else if (hasSuspended) {
1390
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1508
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1391
1509
  } else {
1392
1510
  execResults = {
1393
1511
  status: "success",