@mastra/inngest 0.0.0-scorers-ui-refactored-20250916094952 → 0.0.0-scorers-logs-20251208093427

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,34 +1,302 @@
1
1
  'use strict';
2
2
 
3
- var crypto = require('crypto');
4
- var realtime = require('@inngest/realtime');
5
- var aiTracing = require('@mastra/core/ai-tracing');
6
- var di = require('@mastra/core/di');
7
3
  var tools = require('@mastra/core/tools');
8
4
  var workflows = require('@mastra/core/workflows');
9
5
  var _constants = require('@mastra/core/workflows/_constants');
10
- var hono = require('inngest/hono');
11
6
  var zod = require('zod');
7
+ var crypto = require('crypto');
8
+ var web = require('stream/web');
9
+ var di = require('@mastra/core/di');
10
+ var inngest = require('inngest');
11
+ var realtime = require('@inngest/realtime');
12
+ var stream = require('@mastra/core/stream');
13
+ var hono = require('inngest/hono');
12
14
 
13
15
  // src/index.ts
14
- function serve({ mastra, inngest }) {
15
- const wfs = mastra.getWorkflows();
16
- const functions = Array.from(
17
- new Set(
18
- Object.values(wfs).flatMap((wf) => {
19
- if (wf instanceof InngestWorkflow) {
20
- wf.__registerMastra(mastra);
21
- 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()
22
83
  }
23
- return [];
24
- })
25
- )
26
- );
27
- return hono.serve({
28
- client: inngest,
29
- functions
30
- });
31
- }
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
+ };
32
300
  var InngestRun = class extends workflows.Run {
33
301
  inngest;
34
302
  serializedStepGraph;
@@ -50,14 +318,21 @@ var InngestRun = class extends workflows.Run {
50
318
  }
51
319
  async getRunOutput(eventId) {
52
320
  let runs = await this.getRuns(eventId);
321
+ const storage = this.#mastra?.getStorage();
53
322
  while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
54
323
  await new Promise((resolve) => setTimeout(resolve, 1e3));
55
324
  runs = await this.getRuns(eventId);
56
325
  if (runs?.[0]?.status === "Failed") {
57
- console.log("run", runs?.[0]);
58
- throw new Error(`Function run ${runs?.[0]?.status}`);
59
- } else if (runs?.[0]?.status === "Cancelled") {
60
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
326
+ const snapshot = await storage?.loadWorkflowSnapshot({
327
+ workflowName: this.workflowId,
328
+ runId: this.runId
329
+ });
330
+ return {
331
+ output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
332
+ };
333
+ }
334
+ if (runs?.[0]?.status === "Cancelled") {
335
+ const snapshot = await storage?.loadWorkflowSnapshot({
61
336
  workflowName: this.workflowId,
62
337
  runId: this.runId
63
338
  });
@@ -66,57 +341,73 @@ var InngestRun = class extends workflows.Run {
66
341
  }
67
342
  return runs?.[0];
68
343
  }
69
- async sendEvent(event, data) {
70
- await this.inngest.send({
71
- name: `user-event-${event}`,
72
- data
73
- });
74
- }
75
344
  async cancel() {
345
+ const storage = this.#mastra?.getStorage();
76
346
  await this.inngest.send({
77
347
  name: `cancel.workflow.${this.workflowId}`,
78
348
  data: {
79
349
  runId: this.runId
80
350
  }
81
351
  });
82
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
352
+ const snapshot = await storage?.loadWorkflowSnapshot({
83
353
  workflowName: this.workflowId,
84
354
  runId: this.runId
85
355
  });
86
356
  if (snapshot) {
87
- await this.#mastra?.storage?.persistWorkflowSnapshot({
357
+ await storage?.persistWorkflowSnapshot({
88
358
  workflowName: this.workflowId,
89
359
  runId: this.runId,
360
+ resourceId: this.resourceId,
90
361
  snapshot: {
91
362
  ...snapshot,
92
- status: "canceled"
363
+ status: "canceled",
364
+ value: snapshot.value
93
365
  }
94
366
  });
95
367
  }
96
368
  }
97
- async start({
98
- inputData
369
+ async start(params) {
370
+ return this._start(params);
371
+ }
372
+ async _start({
373
+ inputData,
374
+ initialState,
375
+ outputOptions,
376
+ tracingOptions,
377
+ format,
378
+ requestContext
99
379
  }) {
100
380
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
101
381
  workflowName: this.workflowId,
102
382
  runId: this.runId,
383
+ resourceId: this.resourceId,
103
384
  snapshot: {
104
385
  runId: this.runId,
105
386
  serializedStepGraph: this.serializedStepGraph,
387
+ status: "running",
106
388
  value: {},
107
389
  context: {},
108
390
  activePaths: [],
109
391
  suspendedPaths: {},
392
+ activeStepsPath: {},
393
+ resumeLabels: {},
110
394
  waitingPaths: {},
111
- timestamp: Date.now(),
112
- status: "running"
395
+ timestamp: Date.now()
113
396
  }
114
397
  });
398
+ const inputDataToUse = await this._validateInput(inputData);
399
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
115
400
  const eventOutput = await this.inngest.send({
116
401
  name: `workflow.${this.workflowId}`,
117
402
  data: {
118
- inputData,
119
- runId: this.runId
403
+ inputData: inputDataToUse,
404
+ initialState: initialStateToUse,
405
+ runId: this.runId,
406
+ resourceId: this.resourceId,
407
+ outputOptions,
408
+ tracingOptions,
409
+ format,
410
+ requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
120
411
  }
121
412
  });
122
413
  const eventId = eventOutput.ids[0];
@@ -145,27 +436,131 @@ var InngestRun = class extends workflows.Run {
145
436
  return p;
146
437
  }
147
438
  async _resume(params) {
148
- const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
149
- (step) => typeof step === "string" ? step : step?.id
150
- );
151
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
439
+ const storage = this.#mastra?.getStorage();
440
+ let steps = [];
441
+ if (typeof params.step === "string") {
442
+ steps = params.step.split(".");
443
+ } else {
444
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
445
+ (step) => typeof step === "string" ? step : step?.id
446
+ );
447
+ }
448
+ const snapshot = await storage?.loadWorkflowSnapshot({
152
449
  workflowName: this.workflowId,
153
450
  runId: this.runId
154
451
  });
452
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
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 };
155
457
  const eventOutput = await this.inngest.send({
156
458
  name: `workflow.${this.workflowId}`,
157
459
  data: {
158
- inputData: params.resumeData,
460
+ inputData: resumeDataToUse,
461
+ initialState: snapshot?.value ?? {},
159
462
  runId: this.runId,
160
463
  workflowId: this.workflowId,
161
464
  stepResults: snapshot?.context,
162
465
  resume: {
163
466
  steps,
164
467
  stepResults: snapshot?.context,
165
- resumePayload: params.resumeData,
166
- // @ts-ignore
167
- resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
468
+ resumePayload: resumeDataToUse,
469
+ resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
470
+ },
471
+ requestContext: mergedRequestContext
472
+ }
473
+ });
474
+ const eventId = eventOutput.ids[0];
475
+ if (!eventId) {
476
+ throw new Error("Event ID is not set");
477
+ }
478
+ const runOutput = await this.getRunOutput(eventId);
479
+ const result = runOutput?.output?.result;
480
+ if (result.status === "failed") {
481
+ result.error = new Error(result.error);
482
+ }
483
+ return result;
484
+ }
485
+ async timeTravel(params) {
486
+ const p = this._timeTravel(params).then((result) => {
487
+ if (result.status !== "suspended") {
488
+ this.closeStreamAction?.().catch(() => {
489
+ });
490
+ }
491
+ return result;
492
+ });
493
+ this.executionResults = p;
494
+ return p;
495
+ }
496
+ async _timeTravel(params) {
497
+ if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
498
+ throw new Error("Step is required and must be a valid step or array of steps");
499
+ }
500
+ let steps = [];
501
+ if (typeof params.step === "string") {
502
+ steps = params.step.split(".");
503
+ } else {
504
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
505
+ (step) => typeof step === "string" ? step : step?.id
506
+ );
507
+ }
508
+ if (steps.length === 0) {
509
+ throw new Error("No steps provided to timeTravel");
510
+ }
511
+ const storage = this.#mastra?.getStorage();
512
+ const snapshot = await storage?.loadWorkflowSnapshot({
513
+ workflowName: this.workflowId,
514
+ runId: this.runId
515
+ });
516
+ if (!snapshot) {
517
+ await storage?.persistWorkflowSnapshot({
518
+ workflowName: this.workflowId,
519
+ runId: this.runId,
520
+ resourceId: this.resourceId,
521
+ snapshot: {
522
+ runId: this.runId,
523
+ serializedStepGraph: this.serializedStepGraph,
524
+ status: "pending",
525
+ value: {},
526
+ context: {},
527
+ activePaths: [],
528
+ suspendedPaths: {},
529
+ activeStepsPath: {},
530
+ resumeLabels: {},
531
+ waitingPaths: {},
532
+ timestamp: Date.now()
168
533
  }
534
+ });
535
+ }
536
+ if (snapshot?.status === "running") {
537
+ throw new Error("This workflow run is still running, cannot time travel");
538
+ }
539
+ let inputDataToUse = params.inputData;
540
+ if (inputDataToUse && steps.length === 1) {
541
+ inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
542
+ }
543
+ const timeTravelData = workflows.createTimeTravelExecutionParams({
544
+ steps,
545
+ inputData: inputDataToUse,
546
+ resumeData: params.resumeData,
547
+ context: params.context,
548
+ nestedStepsContext: params.nestedStepsContext,
549
+ snapshot: snapshot ?? { context: {} },
550
+ graph: this.executionGraph,
551
+ initialState: params.initialState
552
+ });
553
+ const eventOutput = await this.inngest.send({
554
+ name: `workflow.${this.workflowId}`,
555
+ data: {
556
+ initialState: timeTravelData.state,
557
+ runId: this.runId,
558
+ workflowId: this.workflowId,
559
+ stepResults: timeTravelData.stepResults,
560
+ timeTravel: timeTravelData,
561
+ tracingOptions: params.tracingOptions,
562
+ outputOptions: params.outputOptions,
563
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
169
564
  }
170
565
  });
171
566
  const eventId = eventOutput.ids[0];
@@ -179,12 +574,12 @@ var InngestRun = class extends workflows.Run {
179
574
  }
180
575
  return result;
181
576
  }
182
- watch(cb, type = "watch") {
577
+ watch(cb) {
183
578
  let active = true;
184
579
  const streamPromise = realtime.subscribe(
185
580
  {
186
581
  channel: `workflow:${this.workflowId}:${this.runId}`,
187
- topics: [type],
582
+ topics: ["watch"],
188
583
  app: this.inngest
189
584
  },
190
585
  (message) => {
@@ -202,20 +597,35 @@ var InngestRun = class extends workflows.Run {
202
597
  });
203
598
  };
204
599
  }
205
- stream({ inputData, runtimeContext } = {}) {
600
+ streamLegacy({ inputData, requestContext } = {}) {
206
601
  const { readable, writable } = new TransformStream();
207
602
  const writer = writable.getWriter();
603
+ void writer.write({
604
+ // @ts-ignore
605
+ type: "start",
606
+ // @ts-ignore
607
+ payload: { runId: this.runId }
608
+ });
208
609
  const unwatch = this.watch(async (event) => {
209
610
  try {
210
611
  const e = {
211
612
  ...event,
212
613
  type: event.type.replace("workflow-", "")
213
614
  };
615
+ if (e.type === "step-output") {
616
+ e.type = e.payload.output.type;
617
+ e.payload = e.payload.output.payload;
618
+ }
214
619
  await writer.write(e);
215
620
  } catch {
216
621
  }
217
- }, "watch-v2");
622
+ });
218
623
  this.closeStreamAction = async () => {
624
+ await writer.write({
625
+ type: "finish",
626
+ // @ts-ignore
627
+ payload: { runId: this.runId }
628
+ });
219
629
  unwatch();
220
630
  try {
221
631
  await writer.close();
@@ -225,7 +635,7 @@ var InngestRun = class extends workflows.Run {
225
635
  writer.releaseLock();
226
636
  }
227
637
  };
228
- this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
638
+ this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
229
639
  if (result.status !== "suspended") {
230
640
  this.closeStreamAction?.().catch(() => {
231
641
  });
@@ -237,42 +647,190 @@ var InngestRun = class extends workflows.Run {
237
647
  getWorkflowState: () => this.executionResults
238
648
  };
239
649
  }
240
- };
241
- var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
242
- #mastra;
243
- inngest;
244
- function;
245
- flowControlConfig;
246
- constructor(params, inngest) {
247
- const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
248
- super(workflowParams);
249
- const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
250
- ([_, value]) => value !== void 0
251
- );
252
- this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
253
- this.#mastra = params.mastra;
254
- this.inngest = inngest;
255
- }
256
- async getWorkflowRuns(args) {
257
- const storage = this.#mastra?.getStorage();
258
- if (!storage) {
259
- this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
260
- return { runs: [], total: 0 };
261
- }
262
- return storage.getWorkflowRuns({ workflowName: this.id, ...args ?? {} });
263
- }
264
- async getWorkflowRunById(runId) {
265
- const storage = this.#mastra?.getStorage();
266
- if (!storage) {
267
- this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
268
- return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
650
+ stream({
651
+ inputData,
652
+ requestContext,
653
+ tracingOptions,
654
+ closeOnSuspend = true,
655
+ initialState,
656
+ outputOptions
657
+ } = {}) {
658
+ if (this.closeStreamAction && this.streamOutput) {
659
+ return this.streamOutput;
269
660
  }
270
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
271
- return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
272
- }
273
- __registerMastra(mastra) {
274
- this.#mastra = mastra;
275
- this.executionEngine.__registerMastra(mastra);
661
+ this.closeStreamAction = async () => {
662
+ };
663
+ const self = this;
664
+ const stream$1 = new web.ReadableStream({
665
+ async start(controller) {
666
+ const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
667
+ controller.enqueue({
668
+ type,
669
+ runId: self.runId,
670
+ from,
671
+ payload: {
672
+ stepName: payload?.id,
673
+ ...payload
674
+ }
675
+ });
676
+ });
677
+ self.closeStreamAction = async () => {
678
+ unwatch();
679
+ try {
680
+ await controller.close();
681
+ } catch (err) {
682
+ console.error("Error closing stream:", err);
683
+ }
684
+ };
685
+ const executionResultsPromise = self._start({
686
+ inputData,
687
+ requestContext,
688
+ // tracingContext, // We are not able to pass a reference to a span here, what to do?
689
+ initialState,
690
+ tracingOptions,
691
+ outputOptions,
692
+ format: "vnext"
693
+ });
694
+ let executionResults;
695
+ try {
696
+ executionResults = await executionResultsPromise;
697
+ if (closeOnSuspend) {
698
+ self.closeStreamAction?.().catch(() => {
699
+ });
700
+ } else if (executionResults.status !== "suspended") {
701
+ self.closeStreamAction?.().catch(() => {
702
+ });
703
+ }
704
+ if (self.streamOutput) {
705
+ self.streamOutput.updateResults(
706
+ executionResults
707
+ );
708
+ }
709
+ } catch (err) {
710
+ self.streamOutput?.rejectResults(err);
711
+ self.closeStreamAction?.().catch(() => {
712
+ });
713
+ }
714
+ }
715
+ });
716
+ this.streamOutput = new stream.WorkflowRunOutput({
717
+ runId: this.runId,
718
+ workflowId: this.workflowId,
719
+ stream: stream$1
720
+ });
721
+ return this.streamOutput;
722
+ }
723
+ streamVNext(args = {}) {
724
+ return this.stream(args);
725
+ }
726
+ timeTravelStream({
727
+ inputData,
728
+ resumeData,
729
+ initialState,
730
+ step,
731
+ context,
732
+ nestedStepsContext,
733
+ requestContext,
734
+ tracingOptions,
735
+ outputOptions
736
+ }) {
737
+ this.closeStreamAction = async () => {
738
+ };
739
+ const self = this;
740
+ const stream$1 = new web.ReadableStream({
741
+ async start(controller) {
742
+ const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
743
+ controller.enqueue({
744
+ type,
745
+ runId: self.runId,
746
+ from,
747
+ payload: {
748
+ stepName: payload?.id,
749
+ ...payload
750
+ }
751
+ });
752
+ });
753
+ self.closeStreamAction = async () => {
754
+ unwatch();
755
+ try {
756
+ controller.close();
757
+ } catch (err) {
758
+ console.error("Error closing stream:", err);
759
+ }
760
+ };
761
+ const executionResultsPromise = self._timeTravel({
762
+ inputData,
763
+ step,
764
+ context,
765
+ nestedStepsContext,
766
+ resumeData,
767
+ initialState,
768
+ requestContext,
769
+ tracingOptions,
770
+ outputOptions
771
+ });
772
+ self.executionResults = executionResultsPromise;
773
+ let executionResults;
774
+ try {
775
+ executionResults = await executionResultsPromise;
776
+ self.closeStreamAction?.().catch(() => {
777
+ });
778
+ if (self.streamOutput) {
779
+ self.streamOutput.updateResults(executionResults);
780
+ }
781
+ } catch (err) {
782
+ self.streamOutput?.rejectResults(err);
783
+ self.closeStreamAction?.().catch(() => {
784
+ });
785
+ }
786
+ }
787
+ });
788
+ this.streamOutput = new stream.WorkflowRunOutput({
789
+ runId: this.runId,
790
+ workflowId: this.workflowId,
791
+ stream: stream$1
792
+ });
793
+ return this.streamOutput;
794
+ }
795
+ };
796
+
797
+ // src/workflow.ts
798
+ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
799
+ #mastra;
800
+ inngest;
801
+ function;
802
+ flowControlConfig;
803
+ constructor(params, inngest) {
804
+ const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
805
+ super(workflowParams);
806
+ this.engineType = "inngest";
807
+ const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
808
+ ([_, value]) => value !== void 0
809
+ );
810
+ this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
811
+ this.#mastra = params.mastra;
812
+ this.inngest = inngest;
813
+ }
814
+ async listWorkflowRuns(args) {
815
+ const storage = this.#mastra?.getStorage();
816
+ if (!storage) {
817
+ this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
818
+ return { runs: [], total: 0 };
819
+ }
820
+ return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
821
+ }
822
+ async getWorkflowRunById(runId) {
823
+ const storage = this.#mastra?.getStorage();
824
+ if (!storage) {
825
+ this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
826
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
827
+ }
828
+ const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
829
+ return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
830
+ }
831
+ __registerMastra(mastra) {
832
+ this.#mastra = mastra;
833
+ this.executionEngine.__registerMastra(mastra);
276
834
  const updateNested = (step) => {
277
835
  if ((step.type === "step" || step.type === "loop" || step.type === "foreach") && step.step instanceof _InngestWorkflow) {
278
836
  step.step.__registerMastra(mastra);
@@ -288,57 +846,49 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
288
846
  }
289
847
  }
290
848
  }
291
- createRun(options) {
849
+ async createRun(options) {
292
850
  const runIdToUse = options?.runId || crypto.randomUUID();
293
851
  const run = this.runs.get(runIdToUse) ?? new InngestRun(
294
852
  {
295
853
  workflowId: this.id,
296
854
  runId: runIdToUse,
855
+ resourceId: options?.resourceId,
297
856
  executionEngine: this.executionEngine,
298
857
  executionGraph: this.executionGraph,
299
858
  serializedStepGraph: this.serializedStepGraph,
300
859
  mastra: this.#mastra,
301
860
  retryConfig: this.retryConfig,
302
- cleanup: () => this.runs.delete(runIdToUse)
303
- },
304
- this.inngest
305
- );
306
- this.runs.set(runIdToUse, run);
307
- return run;
308
- }
309
- async createRunAsync(options) {
310
- const runIdToUse = options?.runId || crypto.randomUUID();
311
- const run = this.runs.get(runIdToUse) ?? new InngestRun(
312
- {
313
- workflowId: this.id,
314
- runId: runIdToUse,
315
- executionEngine: this.executionEngine,
316
- executionGraph: this.executionGraph,
317
- serializedStepGraph: this.serializedStepGraph,
318
- mastra: this.#mastra,
319
- retryConfig: this.retryConfig,
320
- cleanup: () => this.runs.delete(runIdToUse)
861
+ cleanup: () => this.runs.delete(runIdToUse),
862
+ workflowSteps: this.steps,
863
+ workflowEngineType: this.engineType,
864
+ validateInputs: this.options.validateInputs
321
865
  },
322
866
  this.inngest
323
867
  );
324
868
  this.runs.set(runIdToUse, run);
869
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
870
+ workflowStatus: run.workflowRunStatus,
871
+ stepResults: {}
872
+ });
325
873
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
326
- if (!workflowSnapshotInStorage) {
874
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
327
875
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
328
876
  workflowName: this.id,
329
877
  runId: runIdToUse,
878
+ resourceId: options?.resourceId,
330
879
  snapshot: {
331
880
  runId: runIdToUse,
332
881
  status: "pending",
333
882
  value: {},
334
883
  context: {},
335
884
  activePaths: [],
885
+ activeStepsPath: {},
336
886
  waitingPaths: {},
337
887
  serializedStepGraph: this.serializedStepGraph,
338
888
  suspendedPaths: {},
889
+ resumeLabels: {},
339
890
  result: void 0,
340
891
  error: void 0,
341
- // @ts-ignore
342
892
  timestamp: Date.now()
343
893
  }
344
894
  });
@@ -352,15 +902,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
352
902
  this.function = this.inngest.createFunction(
353
903
  {
354
904
  id: `workflow.${this.id}`,
355
- // @ts-ignore
356
- retries: this.retryConfig?.attempts ?? 0,
905
+ retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
357
906
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
358
907
  // Spread flow control configuration
359
908
  ...this.flowControlConfig
360
909
  },
361
910
  { event: `workflow.${this.id}` },
362
911
  async ({ event, step, attempt, publish }) => {
363
- let { inputData, runId, resume } = event.data;
912
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
364
913
  if (!runId) {
365
914
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
366
915
  return crypto.randomUUID();
@@ -388,21 +937,38 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
388
937
  once: (_event, _callback) => {
389
938
  }
390
939
  };
391
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
940
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
392
941
  const result = await engine.execute({
393
942
  workflowId: this.id,
394
943
  runId,
944
+ resourceId,
395
945
  graph: this.executionGraph,
396
946
  serializedStepGraph: this.serializedStepGraph,
397
947
  input: inputData,
948
+ initialState,
398
949
  emitter,
399
950
  retryConfig: this.retryConfig,
400
- runtimeContext: new di.RuntimeContext(),
401
- // TODO
951
+ requestContext: new di.RequestContext(Object.entries(event.data.requestContext ?? {})),
402
952
  resume,
953
+ timeTravel,
954
+ format,
403
955
  abortController: new AbortController(),
404
- currentSpan: void 0
405
- // TODO: Pass actual parent AI span from workflow execution context
956
+ // currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
957
+ outputOptions,
958
+ writableStream: new web.WritableStream({
959
+ write(chunk) {
960
+ void emitter.emit("watch", chunk).catch(() => {
961
+ });
962
+ }
963
+ })
964
+ });
965
+ await step.run(`workflow.${this.id}.finalize`, async () => {
966
+ if (result.status === "failed") {
967
+ throw new inngest.NonRetriableError(`Workflow failed`, {
968
+ cause: result
969
+ });
970
+ }
971
+ return result;
406
972
  });
407
973
  return { result, runId };
408
974
  }
@@ -426,27 +992,70 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
426
992
  return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
427
993
  }
428
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
429
1024
  function isAgent(params) {
430
1025
  return params?.component === "AGENT";
431
1026
  }
432
1027
  function isTool(params) {
433
1028
  return params instanceof tools.Tool;
434
1029
  }
435
- function createStep(params) {
1030
+ function isInngestWorkflow(params) {
1031
+ return params instanceof InngestWorkflow;
1032
+ }
1033
+ function createStep(params, agentOptions) {
1034
+ if (isInngestWorkflow(params)) {
1035
+ return params;
1036
+ }
436
1037
  if (isAgent(params)) {
437
1038
  return {
438
1039
  id: params.name,
439
- // @ts-ignore
1040
+ description: params.getDescription(),
440
1041
  inputSchema: zod.z.object({
441
1042
  prompt: zod.z.string()
442
1043
  // resourceId: z.string().optional(),
443
1044
  // threadId: z.string().optional(),
444
1045
  }),
445
- // @ts-ignore
446
1046
  outputSchema: zod.z.object({
447
1047
  text: zod.z.string()
448
1048
  }),
449
- execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
1049
+ execute: async ({
1050
+ inputData,
1051
+ [_constants.EMITTER_SYMBOL]: emitter,
1052
+ [_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
1053
+ requestContext,
1054
+ tracingContext,
1055
+ abortSignal,
1056
+ abort,
1057
+ writer
1058
+ }) => {
450
1059
  let streamPromise = {};
451
1060
  streamPromise.promise = new Promise((resolve, reject) => {
452
1061
  streamPromise.resolve = resolve;
@@ -456,40 +1065,65 @@ function createStep(params) {
456
1065
  name: params.name,
457
1066
  args: inputData
458
1067
  };
459
- const { fullStream } = await params.stream(inputData.prompt, {
460
- // resourceId: inputData.resourceId,
461
- // threadId: inputData.threadId,
462
- runtimeContext,
463
- tracingContext,
464
- onFinish: (result) => {
465
- streamPromise.resolve(result.text);
466
- },
467
- abortSignal
468
- });
469
- if (abortSignal.aborted) {
470
- return abort();
1068
+ let stream;
1069
+ if ((await params.getModel()).specificationVersion === "v1") {
1070
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
1071
+ ...agentOptions ?? {},
1072
+ // resourceId: inputData.resourceId,
1073
+ // threadId: inputData.threadId,
1074
+ requestContext,
1075
+ tracingContext,
1076
+ onFinish: (result) => {
1077
+ streamPromise.resolve(result.text);
1078
+ void agentOptions?.onFinish?.(result);
1079
+ },
1080
+ abortSignal
1081
+ });
1082
+ stream = fullStream;
1083
+ } else {
1084
+ const modelOutput = await params.stream(inputData.prompt, {
1085
+ ...agentOptions ?? {},
1086
+ requestContext,
1087
+ tracingContext,
1088
+ onFinish: (result) => {
1089
+ streamPromise.resolve(result.text);
1090
+ void agentOptions?.onFinish?.(result);
1091
+ },
1092
+ abortSignal
1093
+ });
1094
+ stream = modelOutput.fullStream;
471
1095
  }
472
- await emitter.emit("watch-v2", {
473
- type: "tool-call-streaming-start",
474
- ...toolData ?? {}
475
- });
476
- for await (const chunk of fullStream) {
477
- if (chunk.type === "text-delta") {
478
- await emitter.emit("watch-v2", {
479
- type: "tool-call-delta",
480
- ...toolData ?? {},
481
- argsTextDelta: chunk.textDelta
482
- });
1096
+ if (streamFormat === "legacy") {
1097
+ await emitter.emit("watch", {
1098
+ type: "tool-call-streaming-start",
1099
+ ...toolData ?? {}
1100
+ });
1101
+ for await (const chunk of stream) {
1102
+ if (chunk.type === "text-delta") {
1103
+ await emitter.emit("watch", {
1104
+ type: "tool-call-delta",
1105
+ ...toolData ?? {},
1106
+ argsTextDelta: chunk.textDelta
1107
+ });
1108
+ }
1109
+ }
1110
+ await emitter.emit("watch", {
1111
+ type: "tool-call-streaming-finish",
1112
+ ...toolData ?? {}
1113
+ });
1114
+ } else {
1115
+ for await (const chunk of stream) {
1116
+ await writer.write(chunk);
483
1117
  }
484
1118
  }
485
- await emitter.emit("watch-v2", {
486
- type: "tool-call-streaming-finish",
487
- ...toolData ?? {}
488
- });
1119
+ if (abortSignal.aborted) {
1120
+ return abort();
1121
+ }
489
1122
  return {
490
1123
  text: await streamPromise.promise
491
1124
  };
492
- }
1125
+ },
1126
+ component: params.component
493
1127
  };
494
1128
  }
495
1129
  if (isTool(params)) {
@@ -498,18 +1132,40 @@ function createStep(params) {
498
1132
  }
499
1133
  return {
500
1134
  // TODO: tool probably should have strong id type
501
- // @ts-ignore
502
1135
  id: params.id,
1136
+ description: params.description,
503
1137
  inputSchema: params.inputSchema,
504
1138
  outputSchema: params.outputSchema,
505
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
506
- return params.execute({
507
- context: inputData,
508
- mastra: aiTracing.wrapMastra(mastra, tracingContext),
509
- runtimeContext,
510
- tracingContext
511
- });
512
- }
1139
+ suspendSchema: params.suspendSchema,
1140
+ resumeSchema: params.resumeSchema,
1141
+ execute: async ({
1142
+ inputData,
1143
+ mastra,
1144
+ requestContext,
1145
+ tracingContext,
1146
+ suspend,
1147
+ resumeData,
1148
+ runId,
1149
+ workflowId,
1150
+ state,
1151
+ setState
1152
+ }) => {
1153
+ const toolContext = {
1154
+ mastra,
1155
+ requestContext,
1156
+ tracingContext,
1157
+ workflow: {
1158
+ runId,
1159
+ resumeData,
1160
+ suspend,
1161
+ workflowId,
1162
+ state,
1163
+ setState
1164
+ }
1165
+ };
1166
+ return params.execute(inputData, toolContext);
1167
+ },
1168
+ component: "TOOL"
513
1169
  };
514
1170
  }
515
1171
  return {
@@ -525,7 +1181,10 @@ function createStep(params) {
525
1181
  function init(inngest) {
526
1182
  return {
527
1183
  createWorkflow(params) {
528
- return new InngestWorkflow(params, inngest);
1184
+ return new InngestWorkflow(
1185
+ params,
1186
+ inngest
1187
+ );
529
1188
  },
530
1189
  createStep,
531
1190
  cloneStep(step, opts) {
@@ -534,7 +1193,13 @@ function init(inngest) {
534
1193
  description: step.description,
535
1194
  inputSchema: step.inputSchema,
536
1195
  outputSchema: step.outputSchema,
537
- execute: step.execute
1196
+ resumeSchema: step.resumeSchema,
1197
+ suspendSchema: step.suspendSchema,
1198
+ stateSchema: step.stateSchema,
1199
+ execute: step.execute,
1200
+ retries: step.retries,
1201
+ scorers: step.scorers,
1202
+ component: step.component
538
1203
  };
539
1204
  },
540
1205
  cloneWorkflow(workflow, opts) {
@@ -543,7 +1208,8 @@ function init(inngest) {
543
1208
  inputSchema: workflow.inputSchema,
544
1209
  outputSchema: workflow.outputSchema,
545
1210
  steps: workflow.stepDefs,
546
- mastra: workflow.mastra
1211
+ mastra: workflow.mastra,
1212
+ options: workflow.options
547
1213
  });
548
1214
  wf.setStepFlow(workflow.stepGraph);
549
1215
  wf.commit();
@@ -551,862 +1217,11 @@ function init(inngest) {
551
1217
  }
552
1218
  };
553
1219
  }
554
- var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
555
- inngestStep;
556
- inngestAttempts;
557
- constructor(mastra, inngestStep, inngestAttempts = 0) {
558
- super({ mastra });
559
- this.inngestStep = inngestStep;
560
- this.inngestAttempts = inngestAttempts;
561
- }
562
- async execute(params) {
563
- await params.emitter.emit("watch-v2", {
564
- type: "workflow-start",
565
- payload: { runId: params.runId }
566
- });
567
- const result = await super.execute(params);
568
- await params.emitter.emit("watch-v2", {
569
- type: "workflow-finish",
570
- payload: { runId: params.runId }
571
- });
572
- return result;
573
- }
574
- async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
575
- const base = {
576
- status: lastOutput.status,
577
- steps: stepResults
578
- };
579
- if (lastOutput.status === "success") {
580
- await emitter.emit("watch", {
581
- type: "watch",
582
- payload: {
583
- workflowState: {
584
- status: lastOutput.status,
585
- steps: stepResults,
586
- result: lastOutput.output
587
- }
588
- },
589
- eventTimestamp: Date.now()
590
- });
591
- base.result = lastOutput.output;
592
- } else if (lastOutput.status === "failed") {
593
- base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
594
- await emitter.emit("watch", {
595
- type: "watch",
596
- payload: {
597
- workflowState: {
598
- status: lastOutput.status,
599
- steps: stepResults,
600
- result: null,
601
- error: base.error
602
- }
603
- },
604
- eventTimestamp: Date.now()
605
- });
606
- } else if (lastOutput.status === "suspended") {
607
- await emitter.emit("watch", {
608
- type: "watch",
609
- payload: {
610
- workflowState: {
611
- status: lastOutput.status,
612
- steps: stepResults,
613
- result: null,
614
- error: null
615
- }
616
- },
617
- eventTimestamp: Date.now()
618
- });
619
- const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
620
- if (stepResult?.status === "suspended") {
621
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
622
- return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
623
- }
624
- return [];
625
- });
626
- base.suspended = suspendedStepIds;
627
- }
628
- executionSpan?.end();
629
- return base;
630
- }
631
- // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
632
- // await this.inngestStep.sleep(id, duration);
633
- // }
634
- async executeSleep({
635
- workflowId,
636
- runId,
637
- entry,
638
- prevOutput,
639
- stepResults,
640
- emitter,
641
- abortController,
642
- runtimeContext,
643
- executionContext,
644
- writableStream,
645
- tracingContext
646
- }) {
647
- let { duration, fn } = entry;
648
- const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
649
- type: aiTracing.AISpanType.WORKFLOW_SLEEP,
650
- name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
651
- attributes: {
652
- durationMs: duration,
653
- sleepType: fn ? "dynamic" : "fixed"
654
- },
655
- isInternal: tracingContext?.isInternal
656
- });
657
- if (fn) {
658
- const stepCallId = crypto.randomUUID();
659
- duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
660
- return await fn({
661
- runId,
662
- workflowId,
663
- mastra: this.mastra,
664
- runtimeContext,
665
- inputData: prevOutput,
666
- runCount: -1,
667
- tracingContext: {
668
- currentSpan: sleepSpan,
669
- isInternal: sleepSpan?.isInternal
670
- },
671
- getInitData: () => stepResults?.input,
672
- getStepResult: (step) => {
673
- if (!step?.id) {
674
- return null;
675
- }
676
- const result = stepResults[step.id];
677
- if (result?.status === "success") {
678
- return result.output;
679
- }
680
- return null;
681
- },
682
- // TODO: this function shouldn't have suspend probably?
683
- suspend: async (_suspendPayload) => {
684
- },
685
- bail: () => {
686
- },
687
- abort: () => {
688
- abortController?.abort();
689
- },
690
- [_constants.EMITTER_SYMBOL]: emitter,
691
- // TODO: add streamVNext support
692
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
693
- engine: { step: this.inngestStep },
694
- abortSignal: abortController?.signal,
695
- writer: new tools.ToolStream(
696
- {
697
- prefix: "workflow-step",
698
- callId: stepCallId,
699
- name: "sleep",
700
- runId
701
- },
702
- writableStream
703
- )
704
- });
705
- });
706
- sleepSpan?.update({
707
- attributes: {
708
- durationMs: duration
709
- }
710
- });
711
- }
712
- try {
713
- await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
714
- sleepSpan?.end();
715
- } catch (e) {
716
- sleepSpan?.error({ error: e });
717
- throw e;
718
- }
719
- }
720
- async executeSleepUntil({
721
- workflowId,
722
- runId,
723
- entry,
724
- prevOutput,
725
- stepResults,
726
- emitter,
727
- abortController,
728
- runtimeContext,
729
- executionContext,
730
- writableStream,
731
- tracingContext
732
- }) {
733
- let { date, fn } = entry;
734
- const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
735
- type: aiTracing.AISpanType.WORKFLOW_SLEEP,
736
- name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
737
- attributes: {
738
- untilDate: date,
739
- durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
740
- sleepType: fn ? "dynamic" : "fixed"
741
- },
742
- isInternal: tracingContext?.isInternal
743
- });
744
- if (fn) {
745
- date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
746
- const stepCallId = crypto.randomUUID();
747
- return await fn({
748
- runId,
749
- workflowId,
750
- mastra: this.mastra,
751
- runtimeContext,
752
- inputData: prevOutput,
753
- runCount: -1,
754
- tracingContext: {
755
- currentSpan: sleepUntilSpan,
756
- isInternal: sleepUntilSpan?.isInternal
757
- },
758
- getInitData: () => stepResults?.input,
759
- getStepResult: (step) => {
760
- if (!step?.id) {
761
- return null;
762
- }
763
- const result = stepResults[step.id];
764
- if (result?.status === "success") {
765
- return result.output;
766
- }
767
- return null;
768
- },
769
- // TODO: this function shouldn't have suspend probably?
770
- suspend: async (_suspendPayload) => {
771
- },
772
- bail: () => {
773
- },
774
- abort: () => {
775
- abortController?.abort();
776
- },
777
- [_constants.EMITTER_SYMBOL]: emitter,
778
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
779
- // TODO: add streamVNext support
780
- engine: { step: this.inngestStep },
781
- abortSignal: abortController?.signal,
782
- writer: new tools.ToolStream(
783
- {
784
- prefix: "workflow-step",
785
- callId: stepCallId,
786
- name: "sleep",
787
- runId
788
- },
789
- writableStream
790
- )
791
- });
792
- });
793
- const time = !date ? 0 : date.getTime() - Date.now();
794
- sleepUntilSpan?.update({
795
- attributes: {
796
- durationMs: Math.max(0, time)
797
- }
798
- });
799
- }
800
- if (!(date instanceof Date)) {
801
- sleepUntilSpan?.end();
802
- return;
803
- }
804
- try {
805
- await this.inngestStep.sleepUntil(entry.id, date);
806
- sleepUntilSpan?.end();
807
- } catch (e) {
808
- sleepUntilSpan?.error({ error: e });
809
- throw e;
810
- }
811
- }
812
- async executeWaitForEvent({ event, timeout }) {
813
- const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
814
- event: `user-event-${event}`,
815
- timeout: timeout ?? 5e3
816
- });
817
- if (eventData === null) {
818
- throw "Timeout waiting for event";
819
- }
820
- return eventData?.data;
821
- }
822
- async executeStep({
823
- step,
824
- stepResults,
825
- executionContext,
826
- resume,
827
- prevOutput,
828
- emitter,
829
- abortController,
830
- runtimeContext,
831
- tracingContext,
832
- writableStream,
833
- disableScorers
834
- }) {
835
- const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
836
- name: `workflow step: '${step.id}'`,
837
- type: aiTracing.AISpanType.WORKFLOW_STEP,
838
- input: prevOutput,
839
- attributes: {
840
- stepId: step.id
841
- },
842
- isInternal: tracingContext?.isInternal
843
- });
844
- const startedAt = await this.inngestStep.run(
845
- `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
846
- async () => {
847
- const startedAt2 = Date.now();
848
- await emitter.emit("watch", {
849
- type: "watch",
850
- payload: {
851
- currentStep: {
852
- id: step.id,
853
- status: "running"
854
- },
855
- workflowState: {
856
- status: "running",
857
- steps: {
858
- ...stepResults,
859
- [step.id]: {
860
- status: "running"
861
- }
862
- },
863
- result: null,
864
- error: null
865
- }
866
- },
867
- eventTimestamp: Date.now()
868
- });
869
- await emitter.emit("watch-v2", {
870
- type: "workflow-step-start",
871
- payload: {
872
- id: step.id,
873
- status: "running",
874
- payload: prevOutput,
875
- startedAt: startedAt2
876
- }
877
- });
878
- return startedAt2;
879
- }
880
- );
881
- if (step instanceof InngestWorkflow) {
882
- const isResume = !!resume?.steps?.length;
883
- let result;
884
- let runId;
885
- if (isResume) {
886
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? crypto.randomUUID();
887
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
888
- workflowName: step.id,
889
- runId
890
- });
891
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
892
- function: step.getFunction(),
893
- data: {
894
- inputData: prevOutput,
895
- runId,
896
- resume: {
897
- runId,
898
- steps: resume.steps.slice(1),
899
- stepResults: snapshot?.context,
900
- resumePayload: resume.resumePayload,
901
- // @ts-ignore
902
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
903
- }
904
- }
905
- });
906
- result = invokeResp.result;
907
- runId = invokeResp.runId;
908
- } else {
909
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
910
- function: step.getFunction(),
911
- data: {
912
- inputData: prevOutput
913
- }
914
- });
915
- result = invokeResp.result;
916
- runId = invokeResp.runId;
917
- }
918
- const res = await this.inngestStep.run(
919
- `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
920
- async () => {
921
- if (result.status === "failed") {
922
- await emitter.emit("watch", {
923
- type: "watch",
924
- payload: {
925
- currentStep: {
926
- id: step.id,
927
- status: "failed",
928
- error: result?.error
929
- },
930
- workflowState: {
931
- status: "running",
932
- steps: stepResults,
933
- result: null,
934
- error: null
935
- }
936
- },
937
- eventTimestamp: Date.now()
938
- });
939
- await emitter.emit("watch-v2", {
940
- type: "workflow-step-result",
941
- payload: {
942
- id: step.id,
943
- status: "failed",
944
- error: result?.error,
945
- payload: prevOutput
946
- }
947
- });
948
- return { executionContext, result: { status: "failed", error: result?.error } };
949
- } else if (result.status === "suspended") {
950
- const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
951
- const stepRes2 = stepResult;
952
- return stepRes2?.status === "suspended";
953
- });
954
- for (const [stepName, stepResult] of suspendedSteps) {
955
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
956
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
957
- await emitter.emit("watch", {
958
- type: "watch",
959
- payload: {
960
- currentStep: {
961
- id: step.id,
962
- status: "suspended",
963
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
964
- },
965
- workflowState: {
966
- status: "running",
967
- steps: stepResults,
968
- result: null,
969
- error: null
970
- }
971
- },
972
- eventTimestamp: Date.now()
973
- });
974
- await emitter.emit("watch-v2", {
975
- type: "workflow-step-suspended",
976
- payload: {
977
- id: step.id,
978
- status: "suspended"
979
- }
980
- });
981
- return {
982
- executionContext,
983
- result: {
984
- status: "suspended",
985
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
986
- }
987
- };
988
- }
989
- await emitter.emit("watch", {
990
- type: "watch",
991
- payload: {
992
- currentStep: {
993
- id: step.id,
994
- status: "suspended",
995
- payload: {}
996
- },
997
- workflowState: {
998
- status: "running",
999
- steps: stepResults,
1000
- result: null,
1001
- error: null
1002
- }
1003
- },
1004
- eventTimestamp: Date.now()
1005
- });
1006
- return {
1007
- executionContext,
1008
- result: {
1009
- status: "suspended",
1010
- payload: {}
1011
- }
1012
- };
1013
- }
1014
- await emitter.emit("watch", {
1015
- type: "watch",
1016
- payload: {
1017
- currentStep: {
1018
- id: step.id,
1019
- status: "success",
1020
- output: result?.result
1021
- },
1022
- workflowState: {
1023
- status: "running",
1024
- steps: stepResults,
1025
- result: null,
1026
- error: null
1027
- }
1028
- },
1029
- eventTimestamp: Date.now()
1030
- });
1031
- await emitter.emit("watch-v2", {
1032
- type: "workflow-step-result",
1033
- payload: {
1034
- id: step.id,
1035
- status: "success",
1036
- output: result?.result
1037
- }
1038
- });
1039
- await emitter.emit("watch-v2", {
1040
- type: "workflow-step-finish",
1041
- payload: {
1042
- id: step.id,
1043
- metadata: {}
1044
- }
1045
- });
1046
- return { executionContext, result: { status: "success", output: result?.result } };
1047
- }
1048
- );
1049
- Object.assign(executionContext, res.executionContext);
1050
- return res.result;
1051
- }
1052
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1053
- let execResults;
1054
- let suspended;
1055
- let bailed;
1056
- try {
1057
- const result = await step.execute({
1058
- runId: executionContext.runId,
1059
- mastra: this.mastra,
1060
- runtimeContext,
1061
- writableStream,
1062
- inputData: prevOutput,
1063
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1064
- tracingContext: {
1065
- currentSpan: stepAISpan,
1066
- isInternal: stepAISpan?.isInternal
1067
- },
1068
- getInitData: () => stepResults?.input,
1069
- getStepResult: (step2) => {
1070
- const result2 = stepResults[step2.id];
1071
- if (result2?.status === "success") {
1072
- return result2.output;
1073
- }
1074
- return null;
1075
- },
1076
- suspend: async (suspendPayload) => {
1077
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1078
- suspended = { payload: suspendPayload };
1079
- },
1080
- bail: (result2) => {
1081
- bailed = { payload: result2 };
1082
- },
1083
- resume: {
1084
- steps: resume?.steps?.slice(1) || [],
1085
- resumePayload: resume?.resumePayload,
1086
- // @ts-ignore
1087
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1088
- },
1089
- [_constants.EMITTER_SYMBOL]: emitter,
1090
- engine: {
1091
- step: this.inngestStep
1092
- },
1093
- abortSignal: abortController.signal
1094
- });
1095
- const endedAt = Date.now();
1096
- execResults = {
1097
- status: "success",
1098
- output: result,
1099
- startedAt,
1100
- endedAt,
1101
- payload: prevOutput,
1102
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1103
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1104
- };
1105
- } catch (e) {
1106
- execResults = {
1107
- status: "failed",
1108
- payload: prevOutput,
1109
- error: e instanceof Error ? e.message : String(e),
1110
- endedAt: Date.now(),
1111
- startedAt,
1112
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1113
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1114
- };
1115
- }
1116
- if (suspended) {
1117
- execResults = {
1118
- status: "suspended",
1119
- suspendedPayload: suspended.payload,
1120
- payload: prevOutput,
1121
- suspendedAt: Date.now(),
1122
- startedAt,
1123
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1124
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1125
- };
1126
- } else if (bailed) {
1127
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1128
- }
1129
- if (execResults.status === "failed") {
1130
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1131
- const error = new Error(execResults.error);
1132
- stepAISpan?.error({ error });
1133
- throw error;
1134
- }
1135
- }
1136
- await emitter.emit("watch", {
1137
- type: "watch",
1138
- payload: {
1139
- currentStep: {
1140
- id: step.id,
1141
- ...execResults
1142
- },
1143
- workflowState: {
1144
- status: "running",
1145
- steps: { ...stepResults, [step.id]: execResults },
1146
- result: null,
1147
- error: null
1148
- }
1149
- },
1150
- eventTimestamp: Date.now()
1151
- });
1152
- if (execResults.status === "suspended") {
1153
- await emitter.emit("watch-v2", {
1154
- type: "workflow-step-suspended",
1155
- payload: {
1156
- id: step.id,
1157
- ...execResults
1158
- }
1159
- });
1160
- } else {
1161
- await emitter.emit("watch-v2", {
1162
- type: "workflow-step-result",
1163
- payload: {
1164
- id: step.id,
1165
- ...execResults
1166
- }
1167
- });
1168
- await emitter.emit("watch-v2", {
1169
- type: "workflow-step-finish",
1170
- payload: {
1171
- id: step.id,
1172
- metadata: {}
1173
- }
1174
- });
1175
- }
1176
- stepAISpan?.end({ output: execResults });
1177
- return { result: execResults, executionContext, stepResults };
1178
- });
1179
- if (disableScorers !== false) {
1180
- await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1181
- if (step.scorers) {
1182
- await this.runScorers({
1183
- scorers: step.scorers,
1184
- runId: executionContext.runId,
1185
- input: prevOutput,
1186
- output: stepRes.result,
1187
- workflowId: executionContext.workflowId,
1188
- stepId: step.id,
1189
- runtimeContext,
1190
- disableScorers,
1191
- tracingContext: { currentSpan: stepAISpan, isInternal: true }
1192
- });
1193
- }
1194
- });
1195
- }
1196
- Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1197
- Object.assign(stepResults, stepRes.stepResults);
1198
- return stepRes.result;
1199
- }
1200
- async persistStepUpdate({
1201
- workflowId,
1202
- runId,
1203
- stepResults,
1204
- executionContext,
1205
- serializedStepGraph,
1206
- workflowStatus,
1207
- result,
1208
- error
1209
- }) {
1210
- await this.inngestStep.run(
1211
- `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1212
- async () => {
1213
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1214
- workflowName: workflowId,
1215
- runId,
1216
- snapshot: {
1217
- runId,
1218
- value: {},
1219
- context: stepResults,
1220
- activePaths: [],
1221
- suspendedPaths: executionContext.suspendedPaths,
1222
- waitingPaths: {},
1223
- serializedStepGraph,
1224
- status: workflowStatus,
1225
- result,
1226
- error,
1227
- // @ts-ignore
1228
- timestamp: Date.now()
1229
- }
1230
- });
1231
- }
1232
- );
1233
- }
1234
- async executeConditional({
1235
- workflowId,
1236
- runId,
1237
- entry,
1238
- prevOutput,
1239
- prevStep,
1240
- stepResults,
1241
- serializedStepGraph,
1242
- resume,
1243
- executionContext,
1244
- emitter,
1245
- abortController,
1246
- runtimeContext,
1247
- writableStream,
1248
- disableScorers,
1249
- tracingContext
1250
- }) {
1251
- const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1252
- type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
1253
- name: `conditional: '${entry.conditions.length} conditions'`,
1254
- input: prevOutput,
1255
- attributes: {
1256
- conditionCount: entry.conditions.length
1257
- },
1258
- isInternal: tracingContext?.isInternal
1259
- });
1260
- let execResults;
1261
- const truthyIndexes = (await Promise.all(
1262
- entry.conditions.map(
1263
- (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1264
- const evalSpan = conditionalSpan?.createChildSpan({
1265
- type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
1266
- name: `condition: '${index}'`,
1267
- input: prevOutput,
1268
- attributes: {
1269
- conditionIndex: index
1270
- },
1271
- isInternal: tracingContext?.isInternal
1272
- });
1273
- try {
1274
- const result = await cond({
1275
- runId,
1276
- workflowId,
1277
- mastra: this.mastra,
1278
- runtimeContext,
1279
- runCount: -1,
1280
- inputData: prevOutput,
1281
- tracingContext: {
1282
- currentSpan: evalSpan,
1283
- isInternal: evalSpan?.isInternal
1284
- },
1285
- getInitData: () => stepResults?.input,
1286
- getStepResult: (step) => {
1287
- if (!step?.id) {
1288
- return null;
1289
- }
1290
- const result2 = stepResults[step.id];
1291
- if (result2?.status === "success") {
1292
- return result2.output;
1293
- }
1294
- return null;
1295
- },
1296
- // TODO: this function shouldn't have suspend probably?
1297
- suspend: async (_suspendPayload) => {
1298
- },
1299
- bail: () => {
1300
- },
1301
- abort: () => {
1302
- abortController.abort();
1303
- },
1304
- [_constants.EMITTER_SYMBOL]: emitter,
1305
- [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1306
- // TODO: add streamVNext support
1307
- engine: {
1308
- step: this.inngestStep
1309
- },
1310
- abortSignal: abortController.signal,
1311
- writer: new tools.ToolStream(
1312
- {
1313
- prefix: "workflow-step",
1314
- callId: crypto.randomUUID(),
1315
- name: "conditional",
1316
- runId
1317
- },
1318
- writableStream
1319
- )
1320
- });
1321
- evalSpan?.end({
1322
- output: result,
1323
- attributes: {
1324
- result: !!result
1325
- }
1326
- });
1327
- return result ? index : null;
1328
- } catch (e) {
1329
- evalSpan?.error({
1330
- error: e instanceof Error ? e : new Error(String(e)),
1331
- attributes: {
1332
- result: false
1333
- }
1334
- });
1335
- return null;
1336
- }
1337
- })
1338
- )
1339
- )).filter((index) => index !== null);
1340
- const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
1341
- conditionalSpan?.update({
1342
- attributes: {
1343
- truthyIndexes,
1344
- selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
1345
- }
1346
- });
1347
- const results = await Promise.all(
1348
- stepsToRun.map(
1349
- (step, index) => this.executeEntry({
1350
- workflowId,
1351
- runId,
1352
- entry: step,
1353
- serializedStepGraph,
1354
- prevStep,
1355
- stepResults,
1356
- resume,
1357
- executionContext: {
1358
- workflowId,
1359
- runId,
1360
- executionPath: [...executionContext.executionPath, index],
1361
- suspendedPaths: executionContext.suspendedPaths,
1362
- retryConfig: executionContext.retryConfig,
1363
- executionSpan: executionContext.executionSpan
1364
- },
1365
- emitter,
1366
- abortController,
1367
- runtimeContext,
1368
- writableStream,
1369
- disableScorers,
1370
- tracingContext: {
1371
- currentSpan: conditionalSpan,
1372
- isInternal: conditionalSpan?.isInternal
1373
- }
1374
- })
1375
- )
1376
- );
1377
- const hasFailed = results.find((result) => result.result.status === "failed");
1378
- const hasSuspended = results.find((result) => result.result.status === "suspended");
1379
- if (hasFailed) {
1380
- execResults = { status: "failed", error: hasFailed.result.error };
1381
- } else if (hasSuspended) {
1382
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1383
- } else {
1384
- execResults = {
1385
- status: "success",
1386
- output: results.reduce((acc, result, index) => {
1387
- if (result.result.status === "success") {
1388
- acc[stepsToRun[index].step.id] = result.output;
1389
- }
1390
- return acc;
1391
- }, {})
1392
- };
1393
- }
1394
- if (execResults.status === "failed") {
1395
- conditionalSpan?.error({
1396
- error: new Error(execResults.error)
1397
- });
1398
- } else {
1399
- conditionalSpan?.end({
1400
- output: execResults.output || execResults
1401
- });
1402
- }
1403
- return execResults;
1404
- }
1405
- };
1406
1220
 
1407
1221
  exports.InngestExecutionEngine = InngestExecutionEngine;
1408
1222
  exports.InngestRun = InngestRun;
1409
1223
  exports.InngestWorkflow = InngestWorkflow;
1224
+ exports._compatibilityCheck = _compatibilityCheck;
1410
1225
  exports.createStep = createStep;
1411
1226
  exports.init = init;
1412
1227
  exports.serve = serve;