@mastra/inngest 0.0.0-message-file-url-handling-fix-20250904234524 → 0.0.0-model-router-unknown-provider-20251017212006

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,
@@ -105,16 +121,21 @@ var InngestRun = class extends Run {
105
121
  context: {},
106
122
  activePaths: [],
107
123
  suspendedPaths: {},
124
+ resumeLabels: {},
108
125
  waitingPaths: {},
109
126
  timestamp: Date.now(),
110
127
  status: "running"
111
128
  }
112
129
  });
130
+ const inputDataToUse = await this._validateInput(inputData);
131
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
113
132
  const eventOutput = await this.inngest.send({
114
133
  name: `workflow.${this.workflowId}`,
115
134
  data: {
116
- inputData,
117
- runId: this.runId
135
+ inputData: inputDataToUse,
136
+ initialState: initialStateToUse,
137
+ runId: this.runId,
138
+ resourceId: this.resourceId
118
139
  }
119
140
  });
120
141
  const eventId = eventOutput.ids[0];
@@ -150,17 +171,20 @@ var InngestRun = class extends Run {
150
171
  workflowName: this.workflowId,
151
172
  runId: this.runId
152
173
  });
174
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
175
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
153
176
  const eventOutput = await this.inngest.send({
154
177
  name: `workflow.${this.workflowId}`,
155
178
  data: {
156
- inputData: params.resumeData,
179
+ inputData: resumeDataToUse,
180
+ initialState: snapshot?.value ?? {},
157
181
  runId: this.runId,
158
182
  workflowId: this.workflowId,
159
183
  stepResults: snapshot?.context,
160
184
  resume: {
161
185
  steps,
162
186
  stepResults: snapshot?.context,
163
- resumePayload: params.resumeData,
187
+ resumePayload: resumeDataToUse,
164
188
  // @ts-ignore
165
189
  resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
166
190
  }
@@ -202,33 +226,9 @@ var InngestRun = class extends Run {
202
226
  }
203
227
  stream({ inputData, runtimeContext } = {}) {
204
228
  const { readable, writable } = new TransformStream();
205
- let currentToolData = void 0;
206
229
  const writer = writable.getWriter();
207
230
  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
231
  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
232
  const e = {
233
233
  ...event,
234
234
  type: event.type.replace("workflow-", "")
@@ -310,23 +310,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
310
310
  }
311
311
  }
312
312
  }
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
313
+ /**
314
+ * @deprecated Use createRunAsync() instead.
315
+ * @throws {Error} Always throws an error directing users to use createRunAsync()
316
+ */
317
+ createRun(_options) {
318
+ throw new Error(
319
+ "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
320
  );
328
- this.runs.set(runIdToUse, run);
329
- return run;
330
321
  }
331
322
  async createRunAsync(options) {
332
323
  const runIdToUse = options?.runId || randomUUID();
@@ -334,21 +325,28 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
334
325
  {
335
326
  workflowId: this.id,
336
327
  runId: runIdToUse,
328
+ resourceId: options?.resourceId,
337
329
  executionEngine: this.executionEngine,
338
330
  executionGraph: this.executionGraph,
339
331
  serializedStepGraph: this.serializedStepGraph,
340
332
  mastra: this.#mastra,
341
333
  retryConfig: this.retryConfig,
342
- cleanup: () => this.runs.delete(runIdToUse)
334
+ cleanup: () => this.runs.delete(runIdToUse),
335
+ workflowSteps: this.steps
343
336
  },
344
337
  this.inngest
345
338
  );
346
339
  this.runs.set(runIdToUse, run);
340
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
341
+ workflowStatus: run.workflowRunStatus,
342
+ stepResults: {}
343
+ });
347
344
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
348
- if (!workflowSnapshotInStorage) {
345
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
349
346
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
350
347
  workflowName: this.id,
351
348
  runId: runIdToUse,
349
+ resourceId: options?.resourceId,
352
350
  snapshot: {
353
351
  runId: runIdToUse,
354
352
  status: "pending",
@@ -358,6 +356,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
358
356
  waitingPaths: {},
359
357
  serializedStepGraph: this.serializedStepGraph,
360
358
  suspendedPaths: {},
359
+ resumeLabels: {},
361
360
  result: void 0,
362
361
  error: void 0,
363
362
  // @ts-ignore
@@ -382,7 +381,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
382
381
  },
383
382
  { event: `workflow.${this.id}` },
384
383
  async ({ event, step, attempt, publish }) => {
385
- let { inputData, runId, resume } = event.data;
384
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
386
385
  if (!runId) {
387
386
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
388
387
  return randomUUID();
@@ -410,21 +409,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
410
409
  once: (_event, _callback) => {
411
410
  }
412
411
  };
413
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
412
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
414
413
  const result = await engine.execute({
415
414
  workflowId: this.id,
416
415
  runId,
416
+ resourceId,
417
417
  graph: this.executionGraph,
418
418
  serializedStepGraph: this.serializedStepGraph,
419
419
  input: inputData,
420
+ initialState,
420
421
  emitter,
421
422
  retryConfig: this.retryConfig,
422
423
  runtimeContext: new RuntimeContext(),
423
424
  // TODO
424
425
  resume,
425
426
  abortController: new AbortController(),
426
- currentSpan: void 0
427
+ currentSpan: void 0,
427
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 NonRetriableError(`Workflow failed`, {
434
+ cause: result
435
+ });
436
+ }
437
+ return result;
428
438
  });
429
439
  return { result, runId };
430
440
  }
@@ -458,11 +468,10 @@ function createStep(params) {
458
468
  if (isAgent(params)) {
459
469
  return {
460
470
  id: params.name,
471
+ description: params.getDescription(),
461
472
  // @ts-ignore
462
473
  inputSchema: z.object({
463
474
  prompt: z.string()
464
- // resourceId: z.string().optional(),
465
- // threadId: z.string().optional(),
466
475
  }),
467
476
  // @ts-ignore
468
477
  outputSchema: z.object({
@@ -478,34 +487,66 @@ function createStep(params) {
478
487
  name: params.name,
479
488
  args: inputData
480
489
  };
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);
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
+ }
500
540
  }
501
541
  await emitter.emit("watch-v2", {
502
- type: "workflow-agent-call-finish",
503
- payload: toolData
542
+ type: "tool-call-streaming-finish",
543
+ ...toolData ?? {}
504
544
  });
505
545
  return {
506
546
  text: await streamPromise.promise
507
547
  };
508
- }
548
+ },
549
+ component: params.component
509
550
  };
510
551
  }
511
552
  if (isTool(params)) {
@@ -516,16 +557,20 @@ function createStep(params) {
516
557
  // TODO: tool probably should have strong id type
517
558
  // @ts-ignore
518
559
  id: params.id,
560
+ description: params.description,
519
561
  inputSchema: params.inputSchema,
520
562
  outputSchema: params.outputSchema,
521
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
563
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
522
564
  return params.execute({
523
565
  context: inputData,
524
566
  mastra: wrapMastra(mastra, tracingContext),
525
567
  runtimeContext,
526
- tracingContext
568
+ tracingContext,
569
+ suspend,
570
+ resumeData
527
571
  });
528
- }
572
+ },
573
+ component: "TOOL"
529
574
  };
530
575
  }
531
576
  return {
@@ -541,7 +586,10 @@ function createStep(params) {
541
586
  function init(inngest) {
542
587
  return {
543
588
  createWorkflow(params) {
544
- return new InngestWorkflow(params, inngest);
589
+ return new InngestWorkflow(
590
+ params,
591
+ inngest
592
+ );
545
593
  },
546
594
  createStep,
547
595
  cloneStep(step, opts) {
@@ -550,7 +598,11 @@ function init(inngest) {
550
598
  description: step.description,
551
599
  inputSchema: step.inputSchema,
552
600
  outputSchema: step.outputSchema,
553
- execute: step.execute
601
+ resumeSchema: step.resumeSchema,
602
+ suspendSchema: step.suspendSchema,
603
+ stateSchema: step.stateSchema,
604
+ execute: step.execute,
605
+ component: step.component
554
606
  };
555
607
  },
556
608
  cloneWorkflow(workflow, opts) {
@@ -570,8 +622,8 @@ function init(inngest) {
570
622
  var InngestExecutionEngine = class extends DefaultExecutionEngine {
571
623
  inngestStep;
572
624
  inngestAttempts;
573
- constructor(mastra, inngestStep, inngestAttempts = 0) {
574
- super({ mastra });
625
+ constructor(mastra, inngestStep, inngestAttempts = 0, options) {
626
+ super({ mastra, options });
575
627
  this.inngestStep = inngestStep;
576
628
  this.inngestAttempts = inngestAttempts;
577
629
  }
@@ -634,7 +686,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
634
686
  });
635
687
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
636
688
  if (stepResult?.status === "suspended") {
637
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
689
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
638
690
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
639
691
  }
640
692
  return [];
@@ -667,7 +719,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
667
719
  attributes: {
668
720
  durationMs: duration,
669
721
  sleepType: fn ? "dynamic" : "fixed"
670
- }
722
+ },
723
+ tracingPolicy: this.options?.tracingPolicy
671
724
  });
672
725
  if (fn) {
673
726
  const stepCallId = randomUUID();
@@ -678,21 +731,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
678
731
  mastra: this.mastra,
679
732
  runtimeContext,
680
733
  inputData: prevOutput,
734
+ state: executionContext.state,
735
+ setState: (state) => {
736
+ executionContext.state = state;
737
+ },
681
738
  runCount: -1,
682
739
  tracingContext: {
683
740
  currentSpan: sleepSpan
684
741
  },
685
742
  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
- },
743
+ getStepResult: getStepResult.bind(this, stepResults),
696
744
  // TODO: this function shouldn't have suspend probably?
697
745
  suspend: async (_suspendPayload) => {
698
746
  },
@@ -752,7 +800,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
752
800
  untilDate: date,
753
801
  durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
754
802
  sleepType: fn ? "dynamic" : "fixed"
755
- }
803
+ },
804
+ tracingPolicy: this.options?.tracingPolicy
756
805
  });
757
806
  if (fn) {
758
807
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
@@ -763,21 +812,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
763
812
  mastra: this.mastra,
764
813
  runtimeContext,
765
814
  inputData: prevOutput,
815
+ state: executionContext.state,
816
+ setState: (state) => {
817
+ executionContext.state = state;
818
+ },
766
819
  runCount: -1,
767
820
  tracingContext: {
768
821
  currentSpan: sleepUntilSpan
769
822
  },
770
823
  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
- },
824
+ getStepResult: getStepResult.bind(this, stepResults),
781
825
  // TODO: this function shouldn't have suspend probably?
782
826
  suspend: async (_suspendPayload) => {
783
827
  },
@@ -802,6 +846,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
802
846
  )
803
847
  });
804
848
  });
849
+ if (date && !(date instanceof Date)) {
850
+ date = new Date(date);
851
+ }
805
852
  const time = !date ? 0 : date.getTime() - Date.now();
806
853
  sleepUntilSpan?.update({
807
854
  attributes: {
@@ -850,7 +897,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
850
897
  input: prevOutput,
851
898
  attributes: {
852
899
  stepId: step.id
853
- }
900
+ },
901
+ tracingPolicy: this.options?.tracingPolicy
902
+ });
903
+ const { inputData, validationError } = await validateStepInput({
904
+ prevOutput,
905
+ step,
906
+ validateInputs: this.options?.validateInputs ?? false
854
907
  });
855
908
  const startedAt = await this.inngestStep.run(
856
909
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
@@ -882,7 +935,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
882
935
  payload: {
883
936
  id: step.id,
884
937
  status: "running",
885
- payload: prevOutput,
938
+ payload: inputData,
886
939
  startedAt: startedAt2
887
940
  }
888
941
  });
@@ -893,38 +946,60 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
893
946
  const isResume = !!resume?.steps?.length;
894
947
  let result;
895
948
  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: {
949
+ try {
950
+ if (isResume) {
951
+ runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? 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 ?? {},
908
961
  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]]
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 }
914
971
  }
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;
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 || randomUUID();
994
+ } else {
995
+ runId = randomUUID();
996
+ result = {
997
+ status: "failed",
998
+ error: e instanceof Error ? e : new Error(String(e)),
999
+ steps: {},
1000
+ input: inputData
1001
+ };
1002
+ }
928
1003
  }
929
1004
  const res = await this.inngestStep.run(
930
1005
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
@@ -963,7 +1038,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
963
1038
  return stepRes2?.status === "suspended";
964
1039
  });
965
1040
  for (const [stepName, stepResult] of suspendedSteps) {
966
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1041
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
967
1042
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
968
1043
  await emitter.emit("watch", {
969
1044
  type: "watch",
@@ -971,7 +1046,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
971
1046
  currentStep: {
972
1047
  id: step.id,
973
1048
  status: "suspended",
974
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1049
+ payload: stepResult.payload,
1050
+ suspendPayload: {
1051
+ ...stepResult?.suspendPayload,
1052
+ __workflow_meta: { runId, path: suspendPath }
1053
+ }
975
1054
  },
976
1055
  workflowState: {
977
1056
  status: "running",
@@ -993,7 +1072,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
993
1072
  executionContext,
994
1073
  result: {
995
1074
  status: "suspended",
996
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1075
+ payload: stepResult.payload,
1076
+ suspendPayload: {
1077
+ ...stepResult?.suspendPayload,
1078
+ __workflow_meta: { runId, path: suspendPath }
1079
+ }
997
1080
  }
998
1081
  };
999
1082
  }
@@ -1058,141 +1141,176 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1058
1141
  }
1059
1142
  );
1060
1143
  Object.assign(executionContext, res.executionContext);
1061
- 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
+ };
1062
1152
  }
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;
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: getStepResult.bind(this, stepResults),
1179
+ suspend: async (suspendPayload, suspendOptions) => {
1180
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1181
+ if (suspendOptions?.resumeLabel) {
1182
+ executionContext.resumeLabels[suspendOptions.resumeLabel] = step.id;
1183
+ }
1184
+ suspended = { payload: suspendPayload };
1185
+ },
1186
+ bail: (result2) => {
1187
+ bailed = { payload: result2 };
1188
+ },
1189
+ resume: {
1190
+ steps: resume?.steps?.slice(1) || [],
1191
+ resumePayload: resume?.resumePayload,
1192
+ // @ts-ignore
1193
+ runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
1194
+ },
1195
+ [EMITTER_SYMBOL]: emitter,
1196
+ engine: {
1197
+ step: this.inngestStep
1198
+ },
1199
+ abortSignal: abortController.signal
1200
+ });
1201
+ const endedAt = Date.now();
1202
+ execResults = {
1203
+ status: "success",
1204
+ output: result,
1205
+ startedAt,
1206
+ endedAt,
1207
+ payload: inputData,
1208
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1209
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1210
+ };
1211
+ } catch (e) {
1212
+ const stepFailure = {
1213
+ status: "failed",
1214
+ payload: inputData,
1215
+ error: e instanceof Error ? e.message : String(e),
1216
+ endedAt: Date.now(),
1217
+ startedAt,
1218
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1219
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1220
+ };
1221
+ execResults = stepFailure;
1222
+ const fallbackErrorMessage = `Step ${step.id} failed`;
1223
+ stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1224
+ throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1225
+ cause: execResults
1226
+ });
1227
+ }
1228
+ if (suspended) {
1229
+ execResults = {
1230
+ status: "suspended",
1231
+ suspendPayload: suspended.payload,
1232
+ payload: inputData,
1233
+ suspendedAt: Date.now(),
1234
+ startedAt,
1235
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1236
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1237
+ };
1238
+ } else if (bailed) {
1239
+ execResults = {
1240
+ status: "bailed",
1241
+ output: bailed.payload,
1242
+ payload: inputData,
1243
+ endedAt: Date.now(),
1244
+ startedAt
1245
+ };
1246
+ }
1247
+ await emitter.emit("watch", {
1248
+ type: "watch",
1249
+ payload: {
1250
+ currentStep: {
1251
+ id: step.id,
1252
+ ...execResults
1253
+ },
1254
+ workflowState: {
1255
+ status: "running",
1256
+ steps: { ...stepResults, [step.id]: execResults },
1257
+ result: null,
1258
+ error: null
1083
1259
  }
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
1260
  },
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
1261
+ eventTimestamp: Date.now()
1104
1262
  });
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;
1263
+ if (execResults.status === "suspended") {
1264
+ await emitter.emit("watch-v2", {
1265
+ type: "workflow-step-suspended",
1266
+ payload: {
1267
+ id: step.id,
1268
+ ...execResults
1269
+ }
1270
+ });
1271
+ } else {
1272
+ await emitter.emit("watch-v2", {
1273
+ type: "workflow-step-result",
1274
+ payload: {
1275
+ id: step.id,
1276
+ ...execResults
1277
+ }
1278
+ });
1279
+ await emitter.emit("watch-v2", {
1280
+ type: "workflow-step-finish",
1281
+ payload: {
1282
+ id: step.id,
1283
+ metadata: {}
1284
+ }
1285
+ });
1144
1286
  }
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()
1287
+ stepAISpan?.end({ output: execResults });
1288
+ return { result: execResults, executionContext, stepResults };
1161
1289
  });
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) {
1290
+ } catch (e) {
1291
+ const stepFailure = e instanceof Error ? e?.cause : {
1292
+ status: "failed",
1293
+ error: e instanceof Error ? e.message : String(e),
1294
+ payload: inputData,
1295
+ startedAt,
1296
+ endedAt: Date.now()
1297
+ };
1298
+ stepRes = {
1299
+ result: stepFailure,
1300
+ executionContext,
1301
+ stepResults: {
1302
+ ...stepResults,
1303
+ [step.id]: stepFailure
1304
+ }
1305
+ };
1306
+ }
1307
+ if (disableScorers !== false && stepRes.result.status === "success") {
1190
1308
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1191
1309
  if (step.scorers) {
1192
1310
  await this.runScorers({
1193
1311
  scorers: step.scorers,
1194
1312
  runId: executionContext.runId,
1195
- input: prevOutput,
1313
+ input: inputData,
1196
1314
  output: stepRes.result,
1197
1315
  workflowId: executionContext.workflowId,
1198
1316
  stepId: step.id,
@@ -1205,12 +1323,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1205
1323
  }
1206
1324
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1207
1325
  Object.assign(stepResults, stepRes.stepResults);
1326
+ executionContext.state = stepRes.executionContext.state;
1208
1327
  return stepRes.result;
1209
1328
  }
1210
1329
  async persistStepUpdate({
1211
1330
  workflowId,
1212
1331
  runId,
1213
1332
  stepResults,
1333
+ resourceId,
1214
1334
  executionContext,
1215
1335
  serializedStepGraph,
1216
1336
  workflowStatus,
@@ -1220,15 +1340,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1220
1340
  await this.inngestStep.run(
1221
1341
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1222
1342
  async () => {
1343
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1344
+ if (!shouldPersistSnapshot) {
1345
+ return;
1346
+ }
1223
1347
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1224
1348
  workflowName: workflowId,
1225
1349
  runId,
1350
+ resourceId,
1226
1351
  snapshot: {
1227
1352
  runId,
1228
- value: {},
1353
+ value: executionContext.state,
1229
1354
  context: stepResults,
1230
1355
  activePaths: [],
1231
1356
  suspendedPaths: executionContext.suspendedPaths,
1357
+ resumeLabels: executionContext.resumeLabels,
1232
1358
  waitingPaths: {},
1233
1359
  serializedStepGraph,
1234
1360
  status: workflowStatus,
@@ -1260,11 +1386,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1260
1386
  }) {
1261
1387
  const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1262
1388
  type: AISpanType.WORKFLOW_CONDITIONAL,
1263
- name: `conditional: ${entry.conditions.length} conditions`,
1389
+ name: `conditional: '${entry.conditions.length} conditions'`,
1264
1390
  input: prevOutput,
1265
1391
  attributes: {
1266
1392
  conditionCount: entry.conditions.length
1267
- }
1393
+ },
1394
+ tracingPolicy: this.options?.tracingPolicy
1268
1395
  });
1269
1396
  let execResults;
1270
1397
  const truthyIndexes = (await Promise.all(
@@ -1272,11 +1399,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1272
1399
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1273
1400
  const evalSpan = conditionalSpan?.createChildSpan({
1274
1401
  type: AISpanType.WORKFLOW_CONDITIONAL_EVAL,
1275
- name: `condition ${index}`,
1402
+ name: `condition: '${index}'`,
1276
1403
  input: prevOutput,
1277
1404
  attributes: {
1278
1405
  conditionIndex: index
1279
- }
1406
+ },
1407
+ tracingPolicy: this.options?.tracingPolicy
1280
1408
  });
1281
1409
  try {
1282
1410
  const result = await cond({
@@ -1286,20 +1414,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1286
1414
  runtimeContext,
1287
1415
  runCount: -1,
1288
1416
  inputData: prevOutput,
1417
+ state: executionContext.state,
1418
+ setState: (state) => {
1419
+ executionContext.state = state;
1420
+ },
1289
1421
  tracingContext: {
1290
1422
  currentSpan: evalSpan
1291
1423
  },
1292
1424
  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
- },
1425
+ getStepResult: getStepResult.bind(this, stepResults),
1303
1426
  // TODO: this function shouldn't have suspend probably?
1304
1427
  suspend: async (_suspendPayload) => {
1305
1428
  },
@@ -1366,8 +1489,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1366
1489
  runId,
1367
1490
  executionPath: [...executionContext.executionPath, index],
1368
1491
  suspendedPaths: executionContext.suspendedPaths,
1492
+ resumeLabels: executionContext.resumeLabels,
1369
1493
  retryConfig: executionContext.retryConfig,
1370
- executionSpan: executionContext.executionSpan
1494
+ executionSpan: executionContext.executionSpan,
1495
+ state: executionContext.state
1371
1496
  },
1372
1497
  emitter,
1373
1498
  abortController,
@@ -1385,7 +1510,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1385
1510
  if (hasFailed) {
1386
1511
  execResults = { status: "failed", error: hasFailed.result.error };
1387
1512
  } else if (hasSuspended) {
1388
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1513
+ execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1389
1514
  } else {
1390
1515
  execResults = {
1391
1516
  status: "success",