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