@mastra/inngest 1.0.0-beta.2 → 1.0.0-beta.4

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
@@ -1,43 +1,302 @@
1
1
  'use strict';
2
2
 
3
- var crypto = require('crypto');
4
- var web = require('stream/web');
5
- var realtime = require('@inngest/realtime');
6
- var di = require('@mastra/core/di');
7
- var observability = require('@mastra/core/observability');
8
- var stream = require('@mastra/core/stream');
9
3
  var tools = require('@mastra/core/tools');
10
4
  var workflows = require('@mastra/core/workflows');
11
5
  var _constants = require('@mastra/core/workflows/_constants');
6
+ var zod = require('zod');
7
+ var crypto = require('crypto');
8
+ var web = require('stream/web');
9
+ var di = require('@mastra/core/di');
12
10
  var inngest = require('inngest');
11
+ var realtime = require('@inngest/realtime');
12
+ var stream = require('@mastra/core/stream');
13
13
  var hono = require('inngest/hono');
14
- var zod = require('zod');
15
14
 
16
15
  // src/index.ts
17
- function serve({
18
- mastra,
19
- inngest,
20
- functions: userFunctions = [],
21
- registerOptions
22
- }) {
23
- const wfs = mastra.listWorkflows();
24
- const workflowFunctions = Array.from(
25
- new Set(
26
- Object.values(wfs).flatMap((wf) => {
27
- if (wf instanceof InngestWorkflow) {
28
- wf.__registerMastra(mastra);
29
- return wf.getFunctions();
16
+ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
17
+ inngestStep;
18
+ inngestAttempts;
19
+ constructor(mastra, inngestStep, inngestAttempts = 0, options) {
20
+ super({ mastra, options });
21
+ this.inngestStep = inngestStep;
22
+ this.inngestAttempts = inngestAttempts;
23
+ }
24
+ // =============================================================================
25
+ // Hook Overrides
26
+ // =============================================================================
27
+ /**
28
+ * Format errors with stack traces for better debugging in Inngest
29
+ */
30
+ formatResultError(error, lastOutput) {
31
+ if (error instanceof Error) {
32
+ return error.stack ?? error.message;
33
+ }
34
+ const outputError = lastOutput?.error;
35
+ if (outputError instanceof Error) {
36
+ return outputError.message;
37
+ }
38
+ return outputError ?? error ?? "Unknown error";
39
+ }
40
+ /**
41
+ * Detect InngestWorkflow instances for special nested workflow handling
42
+ */
43
+ isNestedWorkflowStep(step) {
44
+ return step instanceof InngestWorkflow;
45
+ }
46
+ /**
47
+ * Inngest requires requestContext serialization for memoization.
48
+ * When steps are replayed, the original function doesn't re-execute,
49
+ * so requestContext modifications must be captured and restored.
50
+ */
51
+ requiresDurableContextSerialization() {
52
+ return true;
53
+ }
54
+ /**
55
+ * Execute a step with retry logic for Inngest.
56
+ * Retries are handled via step-level retry (RetryAfterError thrown INSIDE step.run()).
57
+ * After retries exhausted, error propagates here and we return a failed result.
58
+ */
59
+ async executeStepWithRetry(stepId, runStep, params) {
60
+ try {
61
+ const result = await this.wrapDurableOperation(stepId, runStep, { delay: params.delay });
62
+ return { ok: true, result };
63
+ } catch (e) {
64
+ const cause = e?.cause;
65
+ if (cause?.status === "failed") {
66
+ params.stepSpan?.error({
67
+ error: e,
68
+ attributes: { status: "failed" }
69
+ });
70
+ return { ok: false, error: cause };
71
+ }
72
+ const errorMessage = e instanceof Error ? e.message : String(e);
73
+ params.stepSpan?.error({
74
+ error: e,
75
+ attributes: { status: "failed" }
76
+ });
77
+ return {
78
+ ok: false,
79
+ error: {
80
+ status: "failed",
81
+ error: `Error: ${errorMessage}`,
82
+ endedAt: Date.now()
30
83
  }
31
- return [];
32
- })
33
- )
34
- );
35
- return hono.serve({
36
- ...registerOptions,
37
- client: inngest,
38
- functions: [...workflowFunctions, ...userFunctions]
39
- });
40
- }
84
+ };
85
+ }
86
+ }
87
+ /**
88
+ * Use Inngest's sleep primitive for durability
89
+ */
90
+ async executeSleepDuration(duration, sleepId, workflowId) {
91
+ await this.inngestStep.sleep(`workflow.${workflowId}.sleep.${sleepId}`, duration < 0 ? 0 : duration);
92
+ }
93
+ /**
94
+ * Use Inngest's sleepUntil primitive for durability
95
+ */
96
+ async executeSleepUntilDate(date, sleepUntilId, workflowId) {
97
+ await this.inngestStep.sleepUntil(`workflow.${workflowId}.sleepUntil.${sleepUntilId}`, date);
98
+ }
99
+ /**
100
+ * Wrap durable operations in Inngest step.run() for durability.
101
+ * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
102
+ * Inngest's step-level retry mechanism (not function-level retry).
103
+ */
104
+ async wrapDurableOperation(operationId, operationFn, retryConfig) {
105
+ return this.inngestStep.run(operationId, async () => {
106
+ try {
107
+ return await operationFn();
108
+ } catch (e) {
109
+ if (retryConfig) {
110
+ const errorMessage = e instanceof Error ? e.message : String(e);
111
+ throw new inngest.RetryAfterError(errorMessage, retryConfig.delay, {
112
+ cause: {
113
+ status: "failed",
114
+ error: `Error: ${errorMessage}`,
115
+ endedAt: Date.now()
116
+ }
117
+ });
118
+ }
119
+ throw e;
120
+ }
121
+ });
122
+ }
123
+ /**
124
+ * Provide Inngest step primitive in engine context
125
+ */
126
+ getEngineContext() {
127
+ return { step: this.inngestStep };
128
+ }
129
+ /**
130
+ * Execute nested InngestWorkflow using inngestStep.invoke() for durability.
131
+ * This MUST be called directly (not inside step.run()) due to Inngest constraints.
132
+ */
133
+ async executeWorkflowStep(params) {
134
+ if (!(params.step instanceof InngestWorkflow)) {
135
+ return null;
136
+ }
137
+ const { step, stepResults, executionContext, resume, timeTravel, prevOutput, inputData, emitter, startedAt } = params;
138
+ const isResume = !!resume?.steps?.length;
139
+ let result;
140
+ let runId;
141
+ const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
142
+ try {
143
+ if (isResume) {
144
+ runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
145
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
146
+ workflowName: step.id,
147
+ runId
148
+ });
149
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
150
+ function: step.getFunction(),
151
+ data: {
152
+ inputData,
153
+ initialState: executionContext.state ?? snapshot?.value ?? {},
154
+ runId,
155
+ resume: {
156
+ runId,
157
+ steps: resume.steps.slice(1),
158
+ stepResults: snapshot?.context,
159
+ resumePayload: resume.resumePayload,
160
+ resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
161
+ },
162
+ outputOptions: { includeState: true }
163
+ }
164
+ });
165
+ result = invokeResp.result;
166
+ runId = invokeResp.runId;
167
+ executionContext.state = invokeResp.result.state;
168
+ } else if (isTimeTravel) {
169
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
170
+ workflowName: step.id,
171
+ runId: executionContext.runId
172
+ }) ?? { context: {} };
173
+ const timeTravelParams = workflows.createTimeTravelExecutionParams({
174
+ steps: timeTravel.steps.slice(1),
175
+ inputData: timeTravel.inputData,
176
+ resumeData: timeTravel.resumeData,
177
+ context: timeTravel.nestedStepResults?.[step.id] ?? {},
178
+ nestedStepsContext: timeTravel.nestedStepResults ?? {},
179
+ snapshot,
180
+ graph: step.buildExecutionGraph()
181
+ });
182
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
183
+ function: step.getFunction(),
184
+ data: {
185
+ timeTravel: timeTravelParams,
186
+ initialState: executionContext.state ?? {},
187
+ runId: executionContext.runId,
188
+ outputOptions: { includeState: true }
189
+ }
190
+ });
191
+ result = invokeResp.result;
192
+ runId = invokeResp.runId;
193
+ executionContext.state = invokeResp.result.state;
194
+ } else {
195
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
196
+ function: step.getFunction(),
197
+ data: {
198
+ inputData,
199
+ initialState: executionContext.state ?? {},
200
+ outputOptions: { includeState: true }
201
+ }
202
+ });
203
+ result = invokeResp.result;
204
+ runId = invokeResp.runId;
205
+ executionContext.state = invokeResp.result.state;
206
+ }
207
+ } catch (e) {
208
+ const errorCause = e?.cause;
209
+ if (errorCause && typeof errorCause === "object") {
210
+ result = errorCause;
211
+ runId = errorCause.runId || crypto.randomUUID();
212
+ } else {
213
+ runId = crypto.randomUUID();
214
+ result = {
215
+ status: "failed",
216
+ error: e instanceof Error ? e : new Error(String(e)),
217
+ steps: {},
218
+ input: inputData
219
+ };
220
+ }
221
+ }
222
+ const res = await this.inngestStep.run(
223
+ `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
224
+ async () => {
225
+ if (result.status === "failed") {
226
+ await emitter.emit("watch", {
227
+ type: "workflow-step-result",
228
+ payload: {
229
+ id: step.id,
230
+ status: "failed",
231
+ error: result?.error,
232
+ payload: prevOutput
233
+ }
234
+ });
235
+ return { executionContext, result: { status: "failed", error: result?.error } };
236
+ } else if (result.status === "suspended") {
237
+ const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
238
+ const stepRes = stepResult;
239
+ return stepRes?.status === "suspended";
240
+ });
241
+ for (const [stepName, stepResult] of suspendedSteps) {
242
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
243
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
244
+ await emitter.emit("watch", {
245
+ type: "workflow-step-suspended",
246
+ payload: {
247
+ id: step.id,
248
+ status: "suspended"
249
+ }
250
+ });
251
+ return {
252
+ executionContext,
253
+ result: {
254
+ status: "suspended",
255
+ payload: stepResult.payload,
256
+ suspendPayload: {
257
+ ...stepResult?.suspendPayload,
258
+ __workflow_meta: { runId, path: suspendPath }
259
+ }
260
+ }
261
+ };
262
+ }
263
+ return {
264
+ executionContext,
265
+ result: {
266
+ status: "suspended",
267
+ payload: {}
268
+ }
269
+ };
270
+ }
271
+ await emitter.emit("watch", {
272
+ type: "workflow-step-result",
273
+ payload: {
274
+ id: step.id,
275
+ status: "success",
276
+ output: result?.result
277
+ }
278
+ });
279
+ await emitter.emit("watch", {
280
+ type: "workflow-step-finish",
281
+ payload: {
282
+ id: step.id,
283
+ metadata: {}
284
+ }
285
+ });
286
+ return { executionContext, result: { status: "success", output: result?.result } };
287
+ }
288
+ );
289
+ Object.assign(executionContext, res.executionContext);
290
+ return {
291
+ ...res.result,
292
+ startedAt,
293
+ endedAt: Date.now(),
294
+ payload: inputData,
295
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
296
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
297
+ };
298
+ }
299
+ };
41
300
  var InngestRun = class extends workflows.Run {
42
301
  inngest;
43
302
  serializedStepGraph;
@@ -115,7 +374,8 @@ var InngestRun = class extends workflows.Run {
115
374
  initialState,
116
375
  outputOptions,
117
376
  tracingOptions,
118
- format
377
+ format,
378
+ requestContext
119
379
  }) {
120
380
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
121
381
  workflowName: this.workflowId,
@@ -146,7 +406,8 @@ var InngestRun = class extends workflows.Run {
146
406
  resourceId: this.resourceId,
147
407
  outputOptions,
148
408
  tracingOptions,
149
- format
409
+ format,
410
+ requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
150
411
  }
151
412
  });
152
413
  const eventId = eventOutput.ids[0];
@@ -190,6 +451,9 @@ var InngestRun = class extends workflows.Run {
190
451
  });
191
452
  const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
192
453
  const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
454
+ const persistedRequestContext = snapshot?.requestContext ?? {};
455
+ const newRequestContext = params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {};
456
+ const mergedRequestContext = { ...persistedRequestContext, ...newRequestContext };
193
457
  const eventOutput = await this.inngest.send({
194
458
  name: `workflow.${this.workflowId}`,
195
459
  data: {
@@ -203,7 +467,8 @@ var InngestRun = class extends workflows.Run {
203
467
  stepResults: snapshot?.context,
204
468
  resumePayload: resumeDataToUse,
205
469
  resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
206
- }
470
+ },
471
+ requestContext: mergedRequestContext
207
472
  }
208
473
  });
209
474
  const eventId = eventOutput.ids[0];
@@ -294,7 +559,8 @@ var InngestRun = class extends workflows.Run {
294
559
  stepResults: timeTravelData.stepResults,
295
560
  timeTravel: timeTravelData,
296
561
  tracingOptions: params.tracingOptions,
297
- outputOptions: params.outputOptions
562
+ outputOptions: params.outputOptions,
563
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
298
564
  }
299
565
  });
300
566
  const eventId = eventOutput.ids[0];
@@ -334,14 +600,14 @@ var InngestRun = class extends workflows.Run {
334
600
  streamLegacy({ inputData, requestContext } = {}) {
335
601
  const { readable, writable } = new TransformStream();
336
602
  const writer = writable.getWriter();
603
+ void writer.write({
604
+ // @ts-ignore
605
+ type: "start",
606
+ // @ts-ignore
607
+ payload: { runId: this.runId }
608
+ });
337
609
  const unwatch = this.watch(async (event) => {
338
610
  try {
339
- await writer.write({
340
- // @ts-ignore
341
- type: "start",
342
- // @ts-ignore
343
- payload: { runId: this.runId }
344
- });
345
611
  const e = {
346
612
  ...event,
347
613
  type: event.type.replace("workflow-", "")
@@ -487,7 +753,7 @@ var InngestRun = class extends workflows.Run {
487
753
  self.closeStreamAction = async () => {
488
754
  unwatch();
489
755
  try {
490
- await controller.close();
756
+ controller.close();
491
757
  } catch (err) {
492
758
  console.error("Error closing stream:", err);
493
759
  }
@@ -527,6 +793,8 @@ var InngestRun = class extends workflows.Run {
527
793
  return this.streamOutput;
528
794
  }
529
795
  };
796
+
797
+ // src/workflow.ts
530
798
  var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
531
799
  #mastra;
532
800
  inngest;
@@ -680,8 +948,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
680
948
  initialState,
681
949
  emitter,
682
950
  retryConfig: this.retryConfig,
683
- requestContext: new di.RequestContext(),
684
- // TODO
951
+ requestContext: new di.RequestContext(Object.entries(event.data.requestContext ?? {})),
685
952
  resume,
686
953
  timeTravel,
687
954
  format,
@@ -725,13 +992,48 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
725
992
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
726
993
  }
727
994
  };
995
+ function serve({
996
+ mastra,
997
+ inngest,
998
+ functions: userFunctions = [],
999
+ registerOptions
1000
+ }) {
1001
+ const wfs = mastra.listWorkflows();
1002
+ const workflowFunctions = Array.from(
1003
+ new Set(
1004
+ Object.values(wfs).flatMap((wf) => {
1005
+ if (wf instanceof InngestWorkflow) {
1006
+ wf.__registerMastra(mastra);
1007
+ return wf.getFunctions();
1008
+ }
1009
+ return [];
1010
+ })
1011
+ )
1012
+ );
1013
+ return hono.serve({
1014
+ ...registerOptions,
1015
+ client: inngest,
1016
+ functions: [...workflowFunctions, ...userFunctions]
1017
+ });
1018
+ }
1019
+
1020
+ // src/types.ts
1021
+ var _compatibilityCheck = true;
1022
+
1023
+ // src/index.ts
728
1024
  function isAgent(params) {
729
1025
  return params?.component === "AGENT";
730
1026
  }
731
1027
  function isTool(params) {
732
1028
  return params instanceof tools.Tool;
733
1029
  }
1030
+ function isInngestWorkflow(params) {
1031
+ return params instanceof InngestWorkflow;
1032
+ }
734
1033
  function createStep(params, agentOptions) {
1034
+ if (isInngestWorkflow(params)) {
1035
+ return params;
1036
+ }
735
1037
  if (isAgent(params)) {
736
1038
  return {
737
1039
  id: params.name,
@@ -834,6 +1136,8 @@ function createStep(params, agentOptions) {
834
1136
  description: params.description,
835
1137
  inputSchema: params.inputSchema,
836
1138
  outputSchema: params.outputSchema,
1139
+ suspendSchema: params.suspendSchema,
1140
+ resumeSchema: params.resumeSchema,
837
1141
  execute: async ({
838
1142
  inputData,
839
1143
  mastra,
@@ -850,9 +1154,9 @@ function createStep(params, agentOptions) {
850
1154
  mastra,
851
1155
  requestContext,
852
1156
  tracingContext,
853
- resumeData,
854
1157
  workflow: {
855
1158
  runId,
1159
+ resumeData,
856
1160
  suspend,
857
1161
  workflowId,
858
1162
  state,
@@ -904,7 +1208,8 @@ function init(inngest) {
904
1208
  inputSchema: workflow.inputSchema,
905
1209
  outputSchema: workflow.outputSchema,
906
1210
  steps: workflow.stepDefs,
907
- mastra: workflow.mastra
1211
+ mastra: workflow.mastra,
1212
+ options: workflow.options
908
1213
  });
909
1214
  wf.setStepFlow(workflow.stepGraph);
910
1215
  wf.commit();
@@ -912,849 +1217,11 @@ function init(inngest) {
912
1217
  }
913
1218
  };
914
1219
  }
915
- var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
916
- inngestStep;
917
- inngestAttempts;
918
- constructor(mastra, inngestStep, inngestAttempts = 0, options) {
919
- super({ mastra, options });
920
- this.inngestStep = inngestStep;
921
- this.inngestAttempts = inngestAttempts;
922
- }
923
- async fmtReturnValue(emitter, stepResults, lastOutput, error) {
924
- const base = {
925
- status: lastOutput.status,
926
- steps: stepResults
927
- };
928
- if (lastOutput.status === "success") {
929
- base.result = lastOutput.output;
930
- } else if (lastOutput.status === "failed") {
931
- base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
932
- } else if (lastOutput.status === "suspended") {
933
- const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
934
- if (stepResult?.status === "suspended") {
935
- const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
936
- return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
937
- }
938
- return [];
939
- });
940
- base.suspended = suspendedStepIds;
941
- }
942
- return base;
943
- }
944
- // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
945
- // await this.inngestStep.sleep(id, duration);
946
- // }
947
- async executeSleep({
948
- workflowId,
949
- runId,
950
- entry,
951
- prevOutput,
952
- stepResults,
953
- emitter,
954
- abortController,
955
- requestContext,
956
- executionContext,
957
- writableStream,
958
- tracingContext
959
- }) {
960
- let { duration, fn } = entry;
961
- const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
962
- type: observability.SpanType.WORKFLOW_SLEEP,
963
- name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
964
- attributes: {
965
- durationMs: duration,
966
- sleepType: fn ? "dynamic" : "fixed"
967
- },
968
- tracingPolicy: this.options?.tracingPolicy
969
- });
970
- if (fn) {
971
- const stepCallId = crypto.randomUUID();
972
- duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
973
- return await fn(
974
- workflows.createDeprecationProxy(
975
- {
976
- runId,
977
- workflowId,
978
- mastra: this.mastra,
979
- requestContext,
980
- inputData: prevOutput,
981
- state: executionContext.state,
982
- setState: (state) => {
983
- executionContext.state = state;
984
- },
985
- retryCount: -1,
986
- tracingContext: {
987
- currentSpan: sleepSpan
988
- },
989
- getInitData: () => stepResults?.input,
990
- getStepResult: workflows.getStepResult.bind(this, stepResults),
991
- // TODO: this function shouldn't have suspend probably?
992
- suspend: async (_suspendPayload) => {
993
- },
994
- bail: () => {
995
- },
996
- abort: () => {
997
- abortController?.abort();
998
- },
999
- [_constants.EMITTER_SYMBOL]: emitter,
1000
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1001
- engine: { step: this.inngestStep },
1002
- abortSignal: abortController?.signal,
1003
- writer: new tools.ToolStream(
1004
- {
1005
- prefix: "workflow-step",
1006
- callId: stepCallId,
1007
- name: "sleep",
1008
- runId
1009
- },
1010
- writableStream
1011
- )
1012
- },
1013
- {
1014
- paramName: "runCount",
1015
- deprecationMessage: workflows.runCountDeprecationMessage,
1016
- logger: this.logger
1017
- }
1018
- )
1019
- );
1020
- });
1021
- sleepSpan?.update({
1022
- attributes: {
1023
- durationMs: duration
1024
- }
1025
- });
1026
- }
1027
- try {
1028
- await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
1029
- sleepSpan?.end();
1030
- } catch (e) {
1031
- sleepSpan?.error({ error: e });
1032
- throw e;
1033
- }
1034
- }
1035
- async executeSleepUntil({
1036
- workflowId,
1037
- runId,
1038
- entry,
1039
- prevOutput,
1040
- stepResults,
1041
- emitter,
1042
- abortController,
1043
- requestContext,
1044
- executionContext,
1045
- writableStream,
1046
- tracingContext
1047
- }) {
1048
- let { date, fn } = entry;
1049
- const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
1050
- type: observability.SpanType.WORKFLOW_SLEEP,
1051
- name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
1052
- attributes: {
1053
- untilDate: date,
1054
- durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
1055
- sleepType: fn ? "dynamic" : "fixed"
1056
- },
1057
- tracingPolicy: this.options?.tracingPolicy
1058
- });
1059
- if (fn) {
1060
- date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
1061
- const stepCallId = crypto.randomUUID();
1062
- return await fn(
1063
- workflows.createDeprecationProxy(
1064
- {
1065
- runId,
1066
- workflowId,
1067
- mastra: this.mastra,
1068
- requestContext,
1069
- inputData: prevOutput,
1070
- state: executionContext.state,
1071
- setState: (state) => {
1072
- executionContext.state = state;
1073
- },
1074
- retryCount: -1,
1075
- tracingContext: {
1076
- currentSpan: sleepUntilSpan
1077
- },
1078
- getInitData: () => stepResults?.input,
1079
- getStepResult: workflows.getStepResult.bind(this, stepResults),
1080
- // TODO: this function shouldn't have suspend probably?
1081
- suspend: async (_suspendPayload) => {
1082
- },
1083
- bail: () => {
1084
- },
1085
- abort: () => {
1086
- abortController?.abort();
1087
- },
1088
- [_constants.EMITTER_SYMBOL]: emitter,
1089
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1090
- engine: { step: this.inngestStep },
1091
- abortSignal: abortController?.signal,
1092
- writer: new tools.ToolStream(
1093
- {
1094
- prefix: "workflow-step",
1095
- callId: stepCallId,
1096
- name: "sleep",
1097
- runId
1098
- },
1099
- writableStream
1100
- )
1101
- },
1102
- {
1103
- paramName: "runCount",
1104
- deprecationMessage: workflows.runCountDeprecationMessage,
1105
- logger: this.logger
1106
- }
1107
- )
1108
- );
1109
- });
1110
- if (date && !(date instanceof Date)) {
1111
- date = new Date(date);
1112
- }
1113
- const time = !date ? 0 : date.getTime() - Date.now();
1114
- sleepUntilSpan?.update({
1115
- attributes: {
1116
- durationMs: Math.max(0, time)
1117
- }
1118
- });
1119
- }
1120
- if (!(date instanceof Date)) {
1121
- sleepUntilSpan?.end();
1122
- return;
1123
- }
1124
- try {
1125
- await this.inngestStep.sleepUntil(entry.id, date);
1126
- sleepUntilSpan?.end();
1127
- } catch (e) {
1128
- sleepUntilSpan?.error({ error: e });
1129
- throw e;
1130
- }
1131
- }
1132
- async executeStep({
1133
- step,
1134
- stepResults,
1135
- executionContext,
1136
- resume,
1137
- timeTravel,
1138
- prevOutput,
1139
- emitter,
1140
- abortController,
1141
- requestContext,
1142
- tracingContext,
1143
- writableStream,
1144
- disableScorers
1145
- }) {
1146
- const stepSpan = tracingContext?.currentSpan?.createChildSpan({
1147
- name: `workflow step: '${step.id}'`,
1148
- type: observability.SpanType.WORKFLOW_STEP,
1149
- input: prevOutput,
1150
- attributes: {
1151
- stepId: step.id
1152
- },
1153
- tracingPolicy: this.options?.tracingPolicy
1154
- });
1155
- const { inputData, validationError } = await workflows.validateStepInput({
1156
- prevOutput,
1157
- step,
1158
- validateInputs: this.options?.validateInputs ?? true
1159
- });
1160
- const startedAt = await this.inngestStep.run(
1161
- `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
1162
- async () => {
1163
- const startedAt2 = Date.now();
1164
- await emitter.emit("watch", {
1165
- type: "workflow-step-start",
1166
- payload: {
1167
- id: step.id,
1168
- status: "running",
1169
- payload: inputData,
1170
- startedAt: startedAt2
1171
- }
1172
- });
1173
- return startedAt2;
1174
- }
1175
- );
1176
- if (step instanceof InngestWorkflow) {
1177
- const isResume = !!resume?.steps?.length;
1178
- let result;
1179
- let runId;
1180
- const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
1181
- try {
1182
- if (isResume) {
1183
- runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
1184
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
1185
- workflowName: step.id,
1186
- runId
1187
- });
1188
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1189
- function: step.getFunction(),
1190
- data: {
1191
- inputData,
1192
- initialState: executionContext.state ?? snapshot?.value ?? {},
1193
- runId,
1194
- resume: {
1195
- runId,
1196
- steps: resume.steps.slice(1),
1197
- stepResults: snapshot?.context,
1198
- resumePayload: resume.resumePayload,
1199
- resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
1200
- },
1201
- outputOptions: { includeState: true }
1202
- }
1203
- });
1204
- result = invokeResp.result;
1205
- runId = invokeResp.runId;
1206
- executionContext.state = invokeResp.result.state;
1207
- } else if (isTimeTravel) {
1208
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
1209
- workflowName: step.id,
1210
- runId: executionContext.runId
1211
- }) ?? { context: {} };
1212
- const timeTravelParams = workflows.createTimeTravelExecutionParams({
1213
- steps: timeTravel.steps.slice(1),
1214
- inputData: timeTravel.inputData,
1215
- resumeData: timeTravel.resumeData,
1216
- context: timeTravel.nestedStepResults?.[step.id] ?? {},
1217
- nestedStepsContext: timeTravel.nestedStepResults ?? {},
1218
- snapshot,
1219
- graph: step.buildExecutionGraph()
1220
- });
1221
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1222
- function: step.getFunction(),
1223
- data: {
1224
- timeTravel: timeTravelParams,
1225
- initialState: executionContext.state ?? {},
1226
- runId: executionContext.runId,
1227
- outputOptions: { includeState: true }
1228
- }
1229
- });
1230
- result = invokeResp.result;
1231
- runId = invokeResp.runId;
1232
- executionContext.state = invokeResp.result.state;
1233
- } else {
1234
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1235
- function: step.getFunction(),
1236
- data: {
1237
- inputData,
1238
- initialState: executionContext.state ?? {},
1239
- outputOptions: { includeState: true }
1240
- }
1241
- });
1242
- result = invokeResp.result;
1243
- runId = invokeResp.runId;
1244
- executionContext.state = invokeResp.result.state;
1245
- }
1246
- } catch (e) {
1247
- const errorCause = e?.cause;
1248
- if (errorCause && typeof errorCause === "object") {
1249
- result = errorCause;
1250
- runId = errorCause.runId || crypto.randomUUID();
1251
- } else {
1252
- runId = crypto.randomUUID();
1253
- result = {
1254
- status: "failed",
1255
- error: e instanceof Error ? e : new Error(String(e)),
1256
- steps: {},
1257
- input: inputData
1258
- };
1259
- }
1260
- }
1261
- const res = await this.inngestStep.run(
1262
- `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
1263
- async () => {
1264
- if (result.status === "failed") {
1265
- await emitter.emit("watch", {
1266
- type: "workflow-step-result",
1267
- payload: {
1268
- id: step.id,
1269
- status: "failed",
1270
- error: result?.error,
1271
- payload: prevOutput
1272
- }
1273
- });
1274
- return { executionContext, result: { status: "failed", error: result?.error } };
1275
- } else if (result.status === "suspended") {
1276
- const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
1277
- const stepRes2 = stepResult;
1278
- return stepRes2?.status === "suspended";
1279
- });
1280
- for (const [stepName, stepResult] of suspendedSteps) {
1281
- const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
1282
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1283
- await emitter.emit("watch", {
1284
- type: "workflow-step-suspended",
1285
- payload: {
1286
- id: step.id,
1287
- status: "suspended"
1288
- }
1289
- });
1290
- return {
1291
- executionContext,
1292
- result: {
1293
- status: "suspended",
1294
- payload: stepResult.payload,
1295
- suspendPayload: {
1296
- ...stepResult?.suspendPayload,
1297
- __workflow_meta: { runId, path: suspendPath }
1298
- }
1299
- }
1300
- };
1301
- }
1302
- return {
1303
- executionContext,
1304
- result: {
1305
- status: "suspended",
1306
- payload: {}
1307
- }
1308
- };
1309
- }
1310
- await emitter.emit("watch", {
1311
- type: "workflow-step-result",
1312
- payload: {
1313
- id: step.id,
1314
- status: "success",
1315
- output: result?.result
1316
- }
1317
- });
1318
- await emitter.emit("watch", {
1319
- type: "workflow-step-finish",
1320
- payload: {
1321
- id: step.id,
1322
- metadata: {}
1323
- }
1324
- });
1325
- return { executionContext, result: { status: "success", output: result?.result } };
1326
- }
1327
- );
1328
- Object.assign(executionContext, res.executionContext);
1329
- return {
1330
- ...res.result,
1331
- startedAt,
1332
- endedAt: Date.now(),
1333
- payload: inputData,
1334
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1335
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1336
- };
1337
- }
1338
- const stepCallId = crypto.randomUUID();
1339
- let stepRes;
1340
- try {
1341
- stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1342
- let execResults;
1343
- let suspended;
1344
- let bailed;
1345
- const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
1346
- resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
1347
- step
1348
- });
1349
- let resumeDataToUse;
1350
- if (timeTravelResumeData && !timeTravelResumeValidationError) {
1351
- resumeDataToUse = timeTravelResumeData;
1352
- } else if (timeTravelResumeData && timeTravelResumeValidationError) {
1353
- this.logger.warn("Time travel resume data validation failed", {
1354
- stepId: step.id,
1355
- error: timeTravelResumeValidationError.message
1356
- });
1357
- } else if (resume?.steps[0] === step.id) {
1358
- resumeDataToUse = resume?.resumePayload;
1359
- }
1360
- try {
1361
- if (validationError) {
1362
- throw validationError;
1363
- }
1364
- const retryCount = this.getOrGenerateRetryCount(step.id);
1365
- const result = await step.execute({
1366
- runId: executionContext.runId,
1367
- workflowId: executionContext.workflowId,
1368
- mastra: this.mastra,
1369
- requestContext,
1370
- retryCount,
1371
- writer: new tools.ToolStream(
1372
- {
1373
- prefix: "workflow-step",
1374
- callId: stepCallId,
1375
- name: step.id,
1376
- runId: executionContext.runId
1377
- },
1378
- writableStream
1379
- ),
1380
- state: executionContext?.state ?? {},
1381
- setState: (state) => {
1382
- executionContext.state = state;
1383
- },
1384
- inputData,
1385
- resumeData: resumeDataToUse,
1386
- tracingContext: {
1387
- currentSpan: stepSpan
1388
- },
1389
- getInitData: () => stepResults?.input,
1390
- getStepResult: workflows.getStepResult.bind(this, stepResults),
1391
- suspend: async (suspendPayload, suspendOptions) => {
1392
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1393
- if (suspendOptions?.resumeLabel) {
1394
- const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
1395
- for (const label of resumeLabel) {
1396
- executionContext.resumeLabels[label] = {
1397
- stepId: step.id,
1398
- foreachIndex: executionContext.foreachIndex
1399
- };
1400
- }
1401
- }
1402
- suspended = { payload: suspendPayload };
1403
- },
1404
- bail: (result2) => {
1405
- bailed = { payload: result2 };
1406
- },
1407
- abort: () => {
1408
- abortController?.abort();
1409
- },
1410
- [_constants.EMITTER_SYMBOL]: emitter,
1411
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1412
- engine: {
1413
- step: this.inngestStep
1414
- },
1415
- abortSignal: abortController.signal
1416
- });
1417
- const endedAt = Date.now();
1418
- execResults = {
1419
- status: "success",
1420
- output: result,
1421
- startedAt,
1422
- endedAt,
1423
- payload: inputData,
1424
- resumedAt: resumeDataToUse ? startedAt : void 0,
1425
- resumePayload: resumeDataToUse
1426
- };
1427
- } catch (e) {
1428
- const stepFailure = {
1429
- status: "failed",
1430
- payload: inputData,
1431
- error: e instanceof Error ? e.message : String(e),
1432
- endedAt: Date.now(),
1433
- startedAt,
1434
- resumedAt: resumeDataToUse ? startedAt : void 0,
1435
- resumePayload: resumeDataToUse
1436
- };
1437
- execResults = stepFailure;
1438
- const fallbackErrorMessage = `Step ${step.id} failed`;
1439
- stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1440
- throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1441
- cause: execResults
1442
- });
1443
- }
1444
- if (suspended) {
1445
- execResults = {
1446
- status: "suspended",
1447
- suspendPayload: suspended.payload,
1448
- ...execResults.output ? { suspendOutput: execResults.output } : {},
1449
- payload: inputData,
1450
- suspendedAt: Date.now(),
1451
- startedAt,
1452
- resumedAt: resumeDataToUse ? startedAt : void 0,
1453
- resumePayload: resumeDataToUse
1454
- };
1455
- } else if (bailed) {
1456
- execResults = {
1457
- status: "bailed",
1458
- output: bailed.payload,
1459
- payload: inputData,
1460
- endedAt: Date.now(),
1461
- startedAt
1462
- };
1463
- }
1464
- if (execResults.status === "suspended") {
1465
- await emitter.emit("watch", {
1466
- type: "workflow-step-suspended",
1467
- payload: {
1468
- id: step.id,
1469
- ...execResults
1470
- }
1471
- });
1472
- } else {
1473
- await emitter.emit("watch", {
1474
- type: "workflow-step-result",
1475
- payload: {
1476
- id: step.id,
1477
- ...execResults
1478
- }
1479
- });
1480
- await emitter.emit("watch", {
1481
- type: "workflow-step-finish",
1482
- payload: {
1483
- id: step.id,
1484
- metadata: {}
1485
- }
1486
- });
1487
- }
1488
- stepSpan?.end({ output: execResults });
1489
- return { result: execResults, executionContext, stepResults };
1490
- });
1491
- } catch (e) {
1492
- const stepFailure = e instanceof Error ? e?.cause : {
1493
- status: "failed",
1494
- error: e instanceof Error ? e.message : String(e),
1495
- payload: inputData,
1496
- startedAt,
1497
- endedAt: Date.now()
1498
- };
1499
- stepRes = {
1500
- result: stepFailure,
1501
- executionContext,
1502
- stepResults: {
1503
- ...stepResults,
1504
- [step.id]: stepFailure
1505
- }
1506
- };
1507
- }
1508
- if (disableScorers !== false && stepRes.result.status === "success") {
1509
- await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1510
- if (step.scorers) {
1511
- await this.runScorers({
1512
- scorers: step.scorers,
1513
- runId: executionContext.runId,
1514
- input: inputData,
1515
- output: stepRes.result,
1516
- workflowId: executionContext.workflowId,
1517
- stepId: step.id,
1518
- requestContext,
1519
- disableScorers,
1520
- tracingContext: { currentSpan: stepSpan }
1521
- });
1522
- }
1523
- });
1524
- }
1525
- Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1526
- executionContext.state = stepRes.executionContext.state;
1527
- return stepRes.result;
1528
- }
1529
- async persistStepUpdate({
1530
- workflowId,
1531
- runId,
1532
- stepResults,
1533
- resourceId,
1534
- executionContext,
1535
- serializedStepGraph,
1536
- workflowStatus,
1537
- result,
1538
- error
1539
- }) {
1540
- await this.inngestStep.run(
1541
- `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1542
- async () => {
1543
- const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1544
- if (!shouldPersistSnapshot) {
1545
- return;
1546
- }
1547
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1548
- workflowName: workflowId,
1549
- runId,
1550
- resourceId,
1551
- snapshot: {
1552
- runId,
1553
- status: workflowStatus,
1554
- value: executionContext.state,
1555
- context: stepResults,
1556
- activePaths: executionContext.executionPath,
1557
- activeStepsPath: executionContext.activeStepsPath,
1558
- suspendedPaths: executionContext.suspendedPaths,
1559
- resumeLabels: executionContext.resumeLabels,
1560
- waitingPaths: {},
1561
- serializedStepGraph,
1562
- result,
1563
- error,
1564
- timestamp: Date.now()
1565
- }
1566
- });
1567
- }
1568
- );
1569
- }
1570
- async executeConditional({
1571
- workflowId,
1572
- runId,
1573
- entry,
1574
- prevOutput,
1575
- stepResults,
1576
- timeTravel,
1577
- resume,
1578
- executionContext,
1579
- emitter,
1580
- abortController,
1581
- requestContext,
1582
- writableStream,
1583
- disableScorers,
1584
- tracingContext
1585
- }) {
1586
- const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1587
- type: observability.SpanType.WORKFLOW_CONDITIONAL,
1588
- name: `conditional: '${entry.conditions.length} conditions'`,
1589
- input: prevOutput,
1590
- attributes: {
1591
- conditionCount: entry.conditions.length
1592
- },
1593
- tracingPolicy: this.options?.tracingPolicy
1594
- });
1595
- let execResults;
1596
- const truthyIndexes = (await Promise.all(
1597
- entry.conditions.map(
1598
- (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1599
- const evalSpan = conditionalSpan?.createChildSpan({
1600
- type: observability.SpanType.WORKFLOW_CONDITIONAL_EVAL,
1601
- name: `condition: '${index}'`,
1602
- input: prevOutput,
1603
- attributes: {
1604
- conditionIndex: index
1605
- },
1606
- tracingPolicy: this.options?.tracingPolicy
1607
- });
1608
- try {
1609
- const result = await cond(
1610
- workflows.createDeprecationProxy(
1611
- {
1612
- runId,
1613
- workflowId,
1614
- mastra: this.mastra,
1615
- requestContext,
1616
- retryCount: -1,
1617
- inputData: prevOutput,
1618
- state: executionContext.state,
1619
- setState: (state) => {
1620
- executionContext.state = state;
1621
- },
1622
- tracingContext: {
1623
- currentSpan: evalSpan
1624
- },
1625
- getInitData: () => stepResults?.input,
1626
- getStepResult: workflows.getStepResult.bind(this, stepResults),
1627
- // TODO: this function shouldn't have suspend probably?
1628
- suspend: async (_suspendPayload) => {
1629
- },
1630
- bail: () => {
1631
- },
1632
- abort: () => {
1633
- abortController.abort();
1634
- },
1635
- [_constants.EMITTER_SYMBOL]: emitter,
1636
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1637
- engine: {
1638
- step: this.inngestStep
1639
- },
1640
- abortSignal: abortController.signal,
1641
- writer: new tools.ToolStream(
1642
- {
1643
- prefix: "workflow-step",
1644
- callId: crypto.randomUUID(),
1645
- name: "conditional",
1646
- runId
1647
- },
1648
- writableStream
1649
- )
1650
- },
1651
- {
1652
- paramName: "runCount",
1653
- deprecationMessage: workflows.runCountDeprecationMessage,
1654
- logger: this.logger
1655
- }
1656
- )
1657
- );
1658
- evalSpan?.end({
1659
- output: result,
1660
- attributes: {
1661
- result: !!result
1662
- }
1663
- });
1664
- return result ? index : null;
1665
- } catch (e) {
1666
- evalSpan?.error({
1667
- error: e instanceof Error ? e : new Error(String(e)),
1668
- attributes: {
1669
- result: false
1670
- }
1671
- });
1672
- return null;
1673
- }
1674
- })
1675
- )
1676
- )).filter((index) => index !== null);
1677
- const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
1678
- conditionalSpan?.update({
1679
- attributes: {
1680
- truthyIndexes,
1681
- selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
1682
- }
1683
- });
1684
- const results = await Promise.all(
1685
- stepsToRun.map(async (step, index) => {
1686
- const currStepResult = stepResults[step.step.id];
1687
- if (currStepResult && currStepResult.status === "success") {
1688
- return currStepResult;
1689
- }
1690
- const result = await this.executeStep({
1691
- step: step.step,
1692
- prevOutput,
1693
- stepResults,
1694
- resume,
1695
- timeTravel,
1696
- executionContext: {
1697
- workflowId,
1698
- runId,
1699
- executionPath: [...executionContext.executionPath, index],
1700
- activeStepsPath: executionContext.activeStepsPath,
1701
- suspendedPaths: executionContext.suspendedPaths,
1702
- resumeLabels: executionContext.resumeLabels,
1703
- retryConfig: executionContext.retryConfig,
1704
- state: executionContext.state
1705
- },
1706
- emitter,
1707
- abortController,
1708
- requestContext,
1709
- writableStream,
1710
- disableScorers,
1711
- tracingContext: {
1712
- currentSpan: conditionalSpan
1713
- }
1714
- });
1715
- stepResults[step.step.id] = result;
1716
- return result;
1717
- })
1718
- );
1719
- const hasFailed = results.find((result) => result.status === "failed");
1720
- const hasSuspended = results.find((result) => result.status === "suspended");
1721
- if (hasFailed) {
1722
- execResults = { status: "failed", error: hasFailed.error };
1723
- } else if (hasSuspended) {
1724
- execResults = {
1725
- status: "suspended",
1726
- suspendPayload: hasSuspended.suspendPayload,
1727
- ...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
1728
- };
1729
- } else {
1730
- execResults = {
1731
- status: "success",
1732
- output: results.reduce((acc, result, index) => {
1733
- if (result.status === "success") {
1734
- if ("step" in stepsToRun[index]) {
1735
- acc[stepsToRun[index].step.id] = result.output;
1736
- }
1737
- }
1738
- return acc;
1739
- }, {})
1740
- };
1741
- }
1742
- if (execResults.status === "failed") {
1743
- conditionalSpan?.error({
1744
- error: new Error(execResults.error)
1745
- });
1746
- } else {
1747
- conditionalSpan?.end({
1748
- output: execResults.output || execResults
1749
- });
1750
- }
1751
- return execResults;
1752
- }
1753
- };
1754
1220
 
1755
1221
  exports.InngestExecutionEngine = InngestExecutionEngine;
1756
1222
  exports.InngestRun = InngestRun;
1757
1223
  exports.InngestWorkflow = InngestWorkflow;
1224
+ exports._compatibilityCheck = _compatibilityCheck;
1758
1225
  exports.createStep = createStep;
1759
1226
  exports.init = init;
1760
1227
  exports.serve = serve;