@mastra/inngest 0.0.0-toolOptionTypes-20250917085558 → 0.0.0-trace-timeline-update-20251121092347

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,13 @@
1
1
  import { randomUUID } from 'crypto';
2
+ import { ReadableStream, WritableStream } from 'stream/web';
2
3
  import { subscribe } from '@inngest/realtime';
3
- import { wrapMastra, AISpanType } from '@mastra/core/ai-tracing';
4
- import { RuntimeContext } from '@mastra/core/di';
4
+ import { RequestContext } from '@mastra/core/di';
5
+ import { SpanType } from '@mastra/core/observability';
6
+ import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
5
7
  import { ToolStream, Tool } from '@mastra/core/tools';
6
- import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
8
+ import { Run, createTimeTravelExecutionParams, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput, validateStepResumeData } from '@mastra/core/workflows';
7
9
  import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
10
+ import { NonRetriableError, RetryAfterError } from 'inngest';
8
11
  import { serve as serve$1 } from 'inngest/hono';
9
12
  import { z } from 'zod';
10
13
 
@@ -12,9 +15,10 @@ import { z } from 'zod';
12
15
  function serve({
13
16
  mastra,
14
17
  inngest,
15
- functions: userFunctions = []
18
+ functions: userFunctions = [],
19
+ registerOptions
16
20
  }) {
17
- const wfs = mastra.getWorkflows();
21
+ const wfs = mastra.listWorkflows();
18
22
  const workflowFunctions = Array.from(
19
23
  new Set(
20
24
  Object.values(wfs).flatMap((wf) => {
@@ -27,6 +31,7 @@ function serve({
27
31
  )
28
32
  );
29
33
  return serve$1({
34
+ ...registerOptions,
30
35
  client: inngest,
31
36
  functions: [...workflowFunctions, ...userFunctions]
32
37
  });
@@ -52,13 +57,21 @@ var InngestRun = class extends Run {
52
57
  }
53
58
  async getRunOutput(eventId) {
54
59
  let runs = await this.getRuns(eventId);
60
+ const storage = this.#mastra?.getStorage();
55
61
  while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
56
62
  await new Promise((resolve) => setTimeout(resolve, 1e3));
57
63
  runs = await this.getRuns(eventId);
58
64
  if (runs?.[0]?.status === "Failed") {
59
- throw new Error(`Function run ${runs?.[0]?.status}`);
60
- } else if (runs?.[0]?.status === "Cancelled") {
61
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
65
+ const snapshot = await storage?.loadWorkflowSnapshot({
66
+ workflowName: this.workflowId,
67
+ runId: this.runId
68
+ });
69
+ return {
70
+ output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
71
+ };
72
+ }
73
+ if (runs?.[0]?.status === "Cancelled") {
74
+ const snapshot = await storage?.loadWorkflowSnapshot({
62
75
  workflowName: this.workflowId,
63
76
  runId: this.runId
64
77
  });
@@ -67,37 +80,40 @@ var InngestRun = class extends Run {
67
80
  }
68
81
  return runs?.[0];
69
82
  }
70
- async sendEvent(event, data) {
71
- await this.inngest.send({
72
- name: `user-event-${event}`,
73
- data
74
- });
75
- }
76
83
  async cancel() {
84
+ const storage = this.#mastra?.getStorage();
77
85
  await this.inngest.send({
78
86
  name: `cancel.workflow.${this.workflowId}`,
79
87
  data: {
80
88
  runId: this.runId
81
89
  }
82
90
  });
83
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
91
+ const snapshot = await storage?.loadWorkflowSnapshot({
84
92
  workflowName: this.workflowId,
85
93
  runId: this.runId
86
94
  });
87
95
  if (snapshot) {
88
- await this.#mastra?.storage?.persistWorkflowSnapshot({
96
+ await storage?.persistWorkflowSnapshot({
89
97
  workflowName: this.workflowId,
90
98
  runId: this.runId,
91
99
  resourceId: this.resourceId,
92
100
  snapshot: {
93
101
  ...snapshot,
94
- status: "canceled"
102
+ status: "canceled",
103
+ value: snapshot.value
95
104
  }
96
105
  });
97
106
  }
98
107
  }
99
- async start({
100
- inputData
108
+ async start(params) {
109
+ return this._start(params);
110
+ }
111
+ async _start({
112
+ inputData,
113
+ initialState,
114
+ outputOptions,
115
+ tracingOptions,
116
+ format
101
117
  }) {
102
118
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
103
119
  workflowName: this.workflowId,
@@ -106,21 +122,29 @@ var InngestRun = class extends Run {
106
122
  snapshot: {
107
123
  runId: this.runId,
108
124
  serializedStepGraph: this.serializedStepGraph,
125
+ status: "running",
109
126
  value: {},
110
127
  context: {},
111
128
  activePaths: [],
112
129
  suspendedPaths: {},
130
+ activeStepsPath: {},
131
+ resumeLabels: {},
113
132
  waitingPaths: {},
114
- timestamp: Date.now(),
115
- status: "running"
133
+ timestamp: Date.now()
116
134
  }
117
135
  });
136
+ const inputDataToUse = await this._validateInput(inputData);
137
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
118
138
  const eventOutput = await this.inngest.send({
119
139
  name: `workflow.${this.workflowId}`,
120
140
  data: {
121
- inputData,
141
+ inputData: inputDataToUse,
142
+ initialState: initialStateToUse,
122
143
  runId: this.runId,
123
- resourceId: this.resourceId
144
+ resourceId: this.resourceId,
145
+ outputOptions,
146
+ tracingOptions,
147
+ format
124
148
  }
125
149
  });
126
150
  const eventId = eventOutput.ids[0];
@@ -149,27 +173,126 @@ var InngestRun = class extends Run {
149
173
  return p;
150
174
  }
151
175
  async _resume(params) {
152
- const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
153
- (step) => typeof step === "string" ? step : step?.id
154
- );
155
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
176
+ const storage = this.#mastra?.getStorage();
177
+ let steps = [];
178
+ if (typeof params.step === "string") {
179
+ steps = params.step.split(".");
180
+ } else {
181
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
182
+ (step) => typeof step === "string" ? step : step?.id
183
+ );
184
+ }
185
+ const snapshot = await storage?.loadWorkflowSnapshot({
156
186
  workflowName: this.workflowId,
157
187
  runId: this.runId
158
188
  });
189
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
190
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
159
191
  const eventOutput = await this.inngest.send({
160
192
  name: `workflow.${this.workflowId}`,
161
193
  data: {
162
- inputData: params.resumeData,
194
+ inputData: resumeDataToUse,
195
+ initialState: snapshot?.value ?? {},
163
196
  runId: this.runId,
164
197
  workflowId: this.workflowId,
165
198
  stepResults: snapshot?.context,
166
199
  resume: {
167
200
  steps,
168
201
  stepResults: snapshot?.context,
169
- resumePayload: params.resumeData,
170
- // @ts-ignore
171
- resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
202
+ resumePayload: resumeDataToUse,
203
+ resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
204
+ }
205
+ }
206
+ });
207
+ const eventId = eventOutput.ids[0];
208
+ if (!eventId) {
209
+ throw new Error("Event ID is not set");
210
+ }
211
+ const runOutput = await this.getRunOutput(eventId);
212
+ const result = runOutput?.output?.result;
213
+ if (result.status === "failed") {
214
+ result.error = new Error(result.error);
215
+ }
216
+ return result;
217
+ }
218
+ async timeTravel(params) {
219
+ const p = this._timeTravel(params).then((result) => {
220
+ if (result.status !== "suspended") {
221
+ this.closeStreamAction?.().catch(() => {
222
+ });
223
+ }
224
+ return result;
225
+ });
226
+ this.executionResults = p;
227
+ return p;
228
+ }
229
+ async _timeTravel(params) {
230
+ if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
231
+ throw new Error("Step is required and must be a valid step or array of steps");
232
+ }
233
+ let steps = [];
234
+ if (typeof params.step === "string") {
235
+ steps = params.step.split(".");
236
+ } else {
237
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
238
+ (step) => typeof step === "string" ? step : step?.id
239
+ );
240
+ }
241
+ if (steps.length === 0) {
242
+ throw new Error("No steps provided to timeTravel");
243
+ }
244
+ const storage = this.#mastra?.getStorage();
245
+ const snapshot = await storage?.loadWorkflowSnapshot({
246
+ workflowName: this.workflowId,
247
+ runId: this.runId
248
+ });
249
+ if (!snapshot) {
250
+ await storage?.persistWorkflowSnapshot({
251
+ workflowName: this.workflowId,
252
+ runId: this.runId,
253
+ resourceId: this.resourceId,
254
+ snapshot: {
255
+ runId: this.runId,
256
+ serializedStepGraph: this.serializedStepGraph,
257
+ status: "pending",
258
+ value: {},
259
+ context: {},
260
+ activePaths: [],
261
+ suspendedPaths: {},
262
+ activeStepsPath: {},
263
+ resumeLabels: {},
264
+ waitingPaths: {},
265
+ timestamp: Date.now()
172
266
  }
267
+ });
268
+ }
269
+ if (snapshot?.status === "running") {
270
+ throw new Error("This workflow run is still running, cannot time travel");
271
+ }
272
+ let inputDataToUse = params.inputData;
273
+ if (inputDataToUse && steps.length === 1) {
274
+ inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
275
+ }
276
+ const timeTravelData = createTimeTravelExecutionParams({
277
+ steps,
278
+ inputData: inputDataToUse,
279
+ resumeData: params.resumeData,
280
+ context: params.context,
281
+ nestedStepsContext: params.nestedStepsContext,
282
+ snapshot: snapshot ?? { context: {} },
283
+ graph: this.executionGraph,
284
+ initialState: params.initialState
285
+ });
286
+ const eventOutput = await this.inngest.send({
287
+ name: `workflow.${this.workflowId}`,
288
+ data: {
289
+ initialState: timeTravelData.state,
290
+ runId: this.runId,
291
+ workflowId: this.workflowId,
292
+ stepResults: timeTravelData.stepResults,
293
+ timeTravel: timeTravelData,
294
+ tracingOptions: params.tracingOptions,
295
+ outputOptions: params.outputOptions
173
296
  }
174
297
  });
175
298
  const eventId = eventOutput.ids[0];
@@ -183,12 +306,12 @@ var InngestRun = class extends Run {
183
306
  }
184
307
  return result;
185
308
  }
186
- watch(cb, type = "watch") {
309
+ watch(cb) {
187
310
  let active = true;
188
311
  const streamPromise = subscribe(
189
312
  {
190
313
  channel: `workflow:${this.workflowId}:${this.runId}`,
191
- topics: [type],
314
+ topics: ["watch"],
192
315
  app: this.inngest
193
316
  },
194
317
  (message) => {
@@ -206,20 +329,35 @@ var InngestRun = class extends Run {
206
329
  });
207
330
  };
208
331
  }
209
- stream({ inputData, runtimeContext } = {}) {
332
+ streamLegacy({ inputData, requestContext } = {}) {
210
333
  const { readable, writable } = new TransformStream();
211
334
  const writer = writable.getWriter();
212
335
  const unwatch = this.watch(async (event) => {
213
336
  try {
337
+ await writer.write({
338
+ // @ts-ignore
339
+ type: "start",
340
+ // @ts-ignore
341
+ payload: { runId: this.runId }
342
+ });
214
343
  const e = {
215
344
  ...event,
216
345
  type: event.type.replace("workflow-", "")
217
346
  };
347
+ if (e.type === "step-output") {
348
+ e.type = e.payload.output.type;
349
+ e.payload = e.payload.output.payload;
350
+ }
218
351
  await writer.write(e);
219
352
  } catch {
220
353
  }
221
- }, "watch-v2");
354
+ });
222
355
  this.closeStreamAction = async () => {
356
+ await writer.write({
357
+ type: "finish",
358
+ // @ts-ignore
359
+ payload: { runId: this.runId }
360
+ });
223
361
  unwatch();
224
362
  try {
225
363
  await writer.close();
@@ -229,7 +367,7 @@ var InngestRun = class extends Run {
229
367
  writer.releaseLock();
230
368
  }
231
369
  };
232
- this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
370
+ this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
233
371
  if (result.status !== "suspended") {
234
372
  this.closeStreamAction?.().catch(() => {
235
373
  });
@@ -241,6 +379,151 @@ var InngestRun = class extends Run {
241
379
  getWorkflowState: () => this.executionResults
242
380
  };
243
381
  }
382
+ stream({
383
+ inputData,
384
+ requestContext,
385
+ tracingOptions,
386
+ closeOnSuspend = true,
387
+ initialState,
388
+ outputOptions
389
+ } = {}) {
390
+ if (this.closeStreamAction && this.streamOutput) {
391
+ return this.streamOutput;
392
+ }
393
+ this.closeStreamAction = async () => {
394
+ };
395
+ const self = this;
396
+ const stream = new ReadableStream({
397
+ async start(controller) {
398
+ const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
399
+ controller.enqueue({
400
+ type,
401
+ runId: self.runId,
402
+ from,
403
+ payload: {
404
+ stepName: payload?.id,
405
+ ...payload
406
+ }
407
+ });
408
+ });
409
+ self.closeStreamAction = async () => {
410
+ unwatch();
411
+ try {
412
+ await controller.close();
413
+ } catch (err) {
414
+ console.error("Error closing stream:", err);
415
+ }
416
+ };
417
+ const executionResultsPromise = self._start({
418
+ inputData,
419
+ requestContext,
420
+ // tracingContext, // We are not able to pass a reference to a span here, what to do?
421
+ initialState,
422
+ tracingOptions,
423
+ outputOptions,
424
+ format: "vnext"
425
+ });
426
+ let executionResults;
427
+ try {
428
+ executionResults = await executionResultsPromise;
429
+ if (closeOnSuspend) {
430
+ self.closeStreamAction?.().catch(() => {
431
+ });
432
+ } else if (executionResults.status !== "suspended") {
433
+ self.closeStreamAction?.().catch(() => {
434
+ });
435
+ }
436
+ if (self.streamOutput) {
437
+ self.streamOutput.updateResults(
438
+ executionResults
439
+ );
440
+ }
441
+ } catch (err) {
442
+ self.streamOutput?.rejectResults(err);
443
+ self.closeStreamAction?.().catch(() => {
444
+ });
445
+ }
446
+ }
447
+ });
448
+ this.streamOutput = new WorkflowRunOutput({
449
+ runId: this.runId,
450
+ workflowId: this.workflowId,
451
+ stream
452
+ });
453
+ return this.streamOutput;
454
+ }
455
+ streamVNext(args = {}) {
456
+ return this.stream(args);
457
+ }
458
+ timeTravelStream({
459
+ inputData,
460
+ resumeData,
461
+ initialState,
462
+ step,
463
+ context,
464
+ nestedStepsContext,
465
+ requestContext,
466
+ tracingOptions,
467
+ outputOptions
468
+ }) {
469
+ this.closeStreamAction = async () => {
470
+ };
471
+ const self = this;
472
+ const stream = new ReadableStream({
473
+ async start(controller) {
474
+ const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
475
+ controller.enqueue({
476
+ type,
477
+ runId: self.runId,
478
+ from,
479
+ payload: {
480
+ stepName: payload?.id,
481
+ ...payload
482
+ }
483
+ });
484
+ });
485
+ self.closeStreamAction = async () => {
486
+ unwatch();
487
+ try {
488
+ await controller.close();
489
+ } catch (err) {
490
+ console.error("Error closing stream:", err);
491
+ }
492
+ };
493
+ const executionResultsPromise = self._timeTravel({
494
+ inputData,
495
+ step,
496
+ context,
497
+ nestedStepsContext,
498
+ resumeData,
499
+ initialState,
500
+ requestContext,
501
+ tracingOptions,
502
+ outputOptions
503
+ });
504
+ self.executionResults = executionResultsPromise;
505
+ let executionResults;
506
+ try {
507
+ executionResults = await executionResultsPromise;
508
+ self.closeStreamAction?.().catch(() => {
509
+ });
510
+ if (self.streamOutput) {
511
+ self.streamOutput.updateResults(executionResults);
512
+ }
513
+ } catch (err) {
514
+ self.streamOutput?.rejectResults(err);
515
+ self.closeStreamAction?.().catch(() => {
516
+ });
517
+ }
518
+ }
519
+ });
520
+ this.streamOutput = new WorkflowRunOutput({
521
+ runId: this.runId,
522
+ workflowId: this.workflowId,
523
+ stream
524
+ });
525
+ return this.streamOutput;
526
+ }
244
527
  };
245
528
  var InngestWorkflow = class _InngestWorkflow extends Workflow {
246
529
  #mastra;
@@ -250,6 +533,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
250
533
  constructor(params, inngest) {
251
534
  const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
252
535
  super(workflowParams);
536
+ this.engineType = "inngest";
253
537
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
254
538
  ([_, value]) => value !== void 0
255
539
  );
@@ -257,13 +541,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
257
541
  this.#mastra = params.mastra;
258
542
  this.inngest = inngest;
259
543
  }
260
- async getWorkflowRuns(args) {
544
+ async listWorkflowRuns(args) {
261
545
  const storage = this.#mastra?.getStorage();
262
546
  if (!storage) {
263
547
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
264
548
  return { runs: [], total: 0 };
265
549
  }
266
- return storage.getWorkflowRuns({ workflowName: this.id, ...args ?? {} });
550
+ return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
267
551
  }
268
552
  async getWorkflowRunById(runId) {
269
553
  const storage = this.#mastra?.getStorage();
@@ -292,16 +576,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
292
576
  }
293
577
  }
294
578
  }
295
- /**
296
- * @deprecated Use createRunAsync() instead.
297
- * @throws {Error} Always throws an error directing users to use createRunAsync()
298
- */
299
- createRun(_options) {
300
- throw new Error(
301
- "createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async."
302
- );
303
- }
304
- async createRunAsync(options) {
579
+ async createRun(options) {
305
580
  const runIdToUse = options?.runId || randomUUID();
306
581
  const run = this.runs.get(runIdToUse) ?? new InngestRun(
307
582
  {
@@ -313,13 +588,20 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
313
588
  serializedStepGraph: this.serializedStepGraph,
314
589
  mastra: this.#mastra,
315
590
  retryConfig: this.retryConfig,
316
- cleanup: () => this.runs.delete(runIdToUse)
591
+ cleanup: () => this.runs.delete(runIdToUse),
592
+ workflowSteps: this.steps,
593
+ workflowEngineType: this.engineType,
594
+ validateInputs: this.options.validateInputs
317
595
  },
318
596
  this.inngest
319
597
  );
320
598
  this.runs.set(runIdToUse, run);
599
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
600
+ workflowStatus: run.workflowRunStatus,
601
+ stepResults: {}
602
+ });
321
603
  const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
322
- if (!workflowSnapshotInStorage) {
604
+ if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
323
605
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
324
606
  workflowName: this.id,
325
607
  runId: runIdToUse,
@@ -330,12 +612,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
330
612
  value: {},
331
613
  context: {},
332
614
  activePaths: [],
615
+ activeStepsPath: {},
333
616
  waitingPaths: {},
334
617
  serializedStepGraph: this.serializedStepGraph,
335
618
  suspendedPaths: {},
619
+ resumeLabels: {},
336
620
  result: void 0,
337
621
  error: void 0,
338
- // @ts-ignore
339
622
  timestamp: Date.now()
340
623
  }
341
624
  });
@@ -349,15 +632,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
349
632
  this.function = this.inngest.createFunction(
350
633
  {
351
634
  id: `workflow.${this.id}`,
352
- // @ts-ignore
353
- retries: this.retryConfig?.attempts ?? 0,
635
+ retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
354
636
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
355
637
  // Spread flow control configuration
356
638
  ...this.flowControlConfig
357
639
  },
358
640
  { event: `workflow.${this.id}` },
359
641
  async ({ event, step, attempt, publish }) => {
360
- let { inputData, runId, resourceId, resume } = event.data;
642
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
361
643
  if (!runId) {
362
644
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
363
645
  return randomUUID();
@@ -385,7 +667,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
385
667
  once: (_event, _callback) => {
386
668
  }
387
669
  };
388
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
670
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
389
671
  const result = await engine.execute({
390
672
  workflowId: this.id,
391
673
  runId,
@@ -393,14 +675,31 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
393
675
  graph: this.executionGraph,
394
676
  serializedStepGraph: this.serializedStepGraph,
395
677
  input: inputData,
678
+ initialState,
396
679
  emitter,
397
680
  retryConfig: this.retryConfig,
398
- runtimeContext: new RuntimeContext(),
681
+ requestContext: new RequestContext(),
399
682
  // TODO
400
683
  resume,
684
+ timeTravel,
685
+ format,
401
686
  abortController: new AbortController(),
402
- currentSpan: void 0
403
- // TODO: Pass actual parent AI span from workflow execution context
687
+ // currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
688
+ outputOptions,
689
+ writableStream: new WritableStream({
690
+ write(chunk) {
691
+ void emitter.emit("watch", chunk).catch(() => {
692
+ });
693
+ }
694
+ })
695
+ });
696
+ await step.run(`workflow.${this.id}.finalize`, async () => {
697
+ if (result.status === "failed") {
698
+ throw new NonRetriableError(`Workflow failed`, {
699
+ cause: result
700
+ });
701
+ }
702
+ return result;
404
703
  });
405
704
  return { result, runId };
406
705
  }
@@ -430,19 +729,29 @@ function isAgent(params) {
430
729
  function isTool(params) {
431
730
  return params instanceof Tool;
432
731
  }
433
- function createStep(params) {
732
+ function createStep(params, agentOptions) {
434
733
  if (isAgent(params)) {
435
734
  return {
436
735
  id: params.name,
437
- // @ts-ignore
736
+ description: params.getDescription(),
438
737
  inputSchema: z.object({
439
738
  prompt: z.string()
739
+ // resourceId: z.string().optional(),
740
+ // threadId: z.string().optional(),
440
741
  }),
441
- // @ts-ignore
442
742
  outputSchema: z.object({
443
743
  text: z.string()
444
744
  }),
445
- execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
745
+ execute: async ({
746
+ inputData,
747
+ [EMITTER_SYMBOL]: emitter,
748
+ [STREAM_FORMAT_SYMBOL]: streamFormat,
749
+ requestContext,
750
+ tracingContext,
751
+ abortSignal,
752
+ abort,
753
+ writer
754
+ }) => {
446
755
  let streamPromise = {};
447
756
  streamPromise.promise = new Promise((resolve, reject) => {
448
757
  streamPromise.resolve = resolve;
@@ -452,38 +761,65 @@ function createStep(params) {
452
761
  name: params.name,
453
762
  args: inputData
454
763
  };
455
- const { fullStream } = await params.stream(inputData.prompt, {
456
- runtimeContext,
457
- tracingContext,
458
- onFinish: (result) => {
459
- streamPromise.resolve(result.text);
460
- },
461
- abortSignal
462
- });
463
- if (abortSignal.aborted) {
464
- return abort();
764
+ let stream;
765
+ if ((await params.getModel()).specificationVersion === "v1") {
766
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
767
+ ...agentOptions ?? {},
768
+ // resourceId: inputData.resourceId,
769
+ // threadId: inputData.threadId,
770
+ requestContext,
771
+ tracingContext,
772
+ onFinish: (result) => {
773
+ streamPromise.resolve(result.text);
774
+ void agentOptions?.onFinish?.(result);
775
+ },
776
+ abortSignal
777
+ });
778
+ stream = fullStream;
779
+ } else {
780
+ const modelOutput = await params.stream(inputData.prompt, {
781
+ ...agentOptions ?? {},
782
+ requestContext,
783
+ tracingContext,
784
+ onFinish: (result) => {
785
+ streamPromise.resolve(result.text);
786
+ void agentOptions?.onFinish?.(result);
787
+ },
788
+ abortSignal
789
+ });
790
+ stream = modelOutput.fullStream;
465
791
  }
466
- await emitter.emit("watch-v2", {
467
- type: "tool-call-streaming-start",
468
- ...toolData ?? {}
469
- });
470
- for await (const chunk of fullStream) {
471
- if (chunk.type === "text-delta") {
472
- await emitter.emit("watch-v2", {
473
- type: "tool-call-delta",
474
- ...toolData ?? {},
475
- argsTextDelta: chunk.textDelta
476
- });
792
+ if (streamFormat === "legacy") {
793
+ await emitter.emit("watch", {
794
+ type: "tool-call-streaming-start",
795
+ ...toolData ?? {}
796
+ });
797
+ for await (const chunk of stream) {
798
+ if (chunk.type === "text-delta") {
799
+ await emitter.emit("watch", {
800
+ type: "tool-call-delta",
801
+ ...toolData ?? {},
802
+ argsTextDelta: chunk.textDelta
803
+ });
804
+ }
805
+ }
806
+ await emitter.emit("watch", {
807
+ type: "tool-call-streaming-finish",
808
+ ...toolData ?? {}
809
+ });
810
+ } else {
811
+ for await (const chunk of stream) {
812
+ await writer.write(chunk);
477
813
  }
478
814
  }
479
- await emitter.emit("watch-v2", {
480
- type: "tool-call-streaming-finish",
481
- ...toolData ?? {}
482
- });
815
+ if (abortSignal.aborted) {
816
+ return abort();
817
+ }
483
818
  return {
484
819
  text: await streamPromise.promise
485
820
  };
486
- }
821
+ },
822
+ component: params.component
487
823
  };
488
824
  }
489
825
  if (isTool(params)) {
@@ -492,18 +828,38 @@ function createStep(params) {
492
828
  }
493
829
  return {
494
830
  // TODO: tool probably should have strong id type
495
- // @ts-ignore
496
831
  id: params.id,
832
+ description: params.description,
497
833
  inputSchema: params.inputSchema,
498
834
  outputSchema: params.outputSchema,
499
- execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
500
- return params.execute({
501
- context: inputData,
502
- mastra: wrapMastra(mastra, tracingContext),
503
- runtimeContext,
504
- tracingContext
505
- });
506
- }
835
+ execute: async ({
836
+ inputData,
837
+ mastra,
838
+ requestContext,
839
+ tracingContext,
840
+ suspend,
841
+ resumeData,
842
+ runId,
843
+ workflowId,
844
+ state,
845
+ setState
846
+ }) => {
847
+ const toolContext = {
848
+ mastra,
849
+ requestContext,
850
+ tracingContext,
851
+ resumeData,
852
+ workflow: {
853
+ runId,
854
+ suspend,
855
+ workflowId,
856
+ state,
857
+ setState
858
+ }
859
+ };
860
+ return params.execute(inputData, toolContext);
861
+ },
862
+ component: "TOOL"
507
863
  };
508
864
  }
509
865
  return {
@@ -519,7 +875,10 @@ function createStep(params) {
519
875
  function init(inngest) {
520
876
  return {
521
877
  createWorkflow(params) {
522
- return new InngestWorkflow(params, inngest);
878
+ return new InngestWorkflow(
879
+ params,
880
+ inngest
881
+ );
523
882
  },
524
883
  createStep,
525
884
  cloneStep(step, opts) {
@@ -528,7 +887,13 @@ function init(inngest) {
528
887
  description: step.description,
529
888
  inputSchema: step.inputSchema,
530
889
  outputSchema: step.outputSchema,
531
- execute: step.execute
890
+ resumeSchema: step.resumeSchema,
891
+ suspendSchema: step.suspendSchema,
892
+ stateSchema: step.stateSchema,
893
+ execute: step.execute,
894
+ retries: step.retries,
895
+ scorers: step.scorers,
896
+ component: step.component
532
897
  };
533
898
  },
534
899
  cloneWorkflow(workflow, opts) {
@@ -553,73 +918,25 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
553
918
  this.inngestStep = inngestStep;
554
919
  this.inngestAttempts = inngestAttempts;
555
920
  }
556
- async execute(params) {
557
- await params.emitter.emit("watch-v2", {
558
- type: "workflow-start",
559
- payload: { runId: params.runId }
560
- });
561
- const result = await super.execute(params);
562
- await params.emitter.emit("watch-v2", {
563
- type: "workflow-finish",
564
- payload: { runId: params.runId }
565
- });
566
- return result;
567
- }
568
- async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
921
+ async fmtReturnValue(emitter, stepResults, lastOutput, error) {
569
922
  const base = {
570
923
  status: lastOutput.status,
571
924
  steps: stepResults
572
925
  };
573
926
  if (lastOutput.status === "success") {
574
- await emitter.emit("watch", {
575
- type: "watch",
576
- payload: {
577
- workflowState: {
578
- status: lastOutput.status,
579
- steps: stepResults,
580
- result: lastOutput.output
581
- }
582
- },
583
- eventTimestamp: Date.now()
584
- });
585
927
  base.result = lastOutput.output;
586
928
  } else if (lastOutput.status === "failed") {
587
929
  base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
588
- await emitter.emit("watch", {
589
- type: "watch",
590
- payload: {
591
- workflowState: {
592
- status: lastOutput.status,
593
- steps: stepResults,
594
- result: null,
595
- error: base.error
596
- }
597
- },
598
- eventTimestamp: Date.now()
599
- });
600
930
  } else if (lastOutput.status === "suspended") {
601
- await emitter.emit("watch", {
602
- type: "watch",
603
- payload: {
604
- workflowState: {
605
- status: lastOutput.status,
606
- steps: stepResults,
607
- result: null,
608
- error: null
609
- }
610
- },
611
- eventTimestamp: Date.now()
612
- });
613
931
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
614
932
  if (stepResult?.status === "suspended") {
615
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
933
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
616
934
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
617
935
  }
618
936
  return [];
619
937
  });
620
938
  base.suspended = suspendedStepIds;
621
939
  }
622
- executionSpan?.end();
623
940
  return base;
624
941
  }
625
942
  // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
@@ -633,14 +950,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
633
950
  stepResults,
634
951
  emitter,
635
952
  abortController,
636
- runtimeContext,
953
+ requestContext,
637
954
  executionContext,
638
955
  writableStream,
639
956
  tracingContext
640
957
  }) {
641
958
  let { duration, fn } = entry;
642
959
  const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
643
- type: AISpanType.WORKFLOW_SLEEP,
960
+ type: SpanType.WORKFLOW_SLEEP,
644
961
  name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
645
962
  attributes: {
646
963
  durationMs: duration,
@@ -651,50 +968,53 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
651
968
  if (fn) {
652
969
  const stepCallId = randomUUID();
653
970
  duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
654
- return await fn({
655
- runId,
656
- workflowId,
657
- mastra: this.mastra,
658
- runtimeContext,
659
- inputData: prevOutput,
660
- runCount: -1,
661
- tracingContext: {
662
- currentSpan: sleepSpan
663
- },
664
- getInitData: () => stepResults?.input,
665
- getStepResult: (step) => {
666
- if (!step?.id) {
667
- return null;
668
- }
669
- const result = stepResults[step.id];
670
- if (result?.status === "success") {
671
- return result.output;
672
- }
673
- return null;
674
- },
675
- // TODO: this function shouldn't have suspend probably?
676
- suspend: async (_suspendPayload) => {
677
- },
678
- bail: () => {
679
- },
680
- abort: () => {
681
- abortController?.abort();
682
- },
683
- [EMITTER_SYMBOL]: emitter,
684
- // TODO: add streamVNext support
685
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
686
- engine: { step: this.inngestStep },
687
- abortSignal: abortController?.signal,
688
- writer: new ToolStream(
971
+ return await fn(
972
+ createDeprecationProxy(
689
973
  {
690
- prefix: "workflow-step",
691
- callId: stepCallId,
692
- name: "sleep",
693
- runId
974
+ runId,
975
+ workflowId,
976
+ mastra: this.mastra,
977
+ requestContext,
978
+ inputData: prevOutput,
979
+ state: executionContext.state,
980
+ setState: (state) => {
981
+ executionContext.state = state;
982
+ },
983
+ retryCount: -1,
984
+ tracingContext: {
985
+ currentSpan: sleepSpan
986
+ },
987
+ getInitData: () => stepResults?.input,
988
+ getStepResult: getStepResult.bind(this, stepResults),
989
+ // TODO: this function shouldn't have suspend probably?
990
+ suspend: async (_suspendPayload) => {
991
+ },
992
+ bail: () => {
993
+ },
994
+ abort: () => {
995
+ abortController?.abort();
996
+ },
997
+ [EMITTER_SYMBOL]: emitter,
998
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
999
+ engine: { step: this.inngestStep },
1000
+ abortSignal: abortController?.signal,
1001
+ writer: new ToolStream(
1002
+ {
1003
+ prefix: "workflow-step",
1004
+ callId: stepCallId,
1005
+ name: "sleep",
1006
+ runId
1007
+ },
1008
+ writableStream
1009
+ )
694
1010
  },
695
- writableStream
1011
+ {
1012
+ paramName: "runCount",
1013
+ deprecationMessage: runCountDeprecationMessage,
1014
+ logger: this.logger
1015
+ }
696
1016
  )
697
- });
1017
+ );
698
1018
  });
699
1019
  sleepSpan?.update({
700
1020
  attributes: {
@@ -718,14 +1038,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
718
1038
  stepResults,
719
1039
  emitter,
720
1040
  abortController,
721
- runtimeContext,
1041
+ requestContext,
722
1042
  executionContext,
723
1043
  writableStream,
724
1044
  tracingContext
725
1045
  }) {
726
1046
  let { date, fn } = entry;
727
1047
  const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
728
- type: AISpanType.WORKFLOW_SLEEP,
1048
+ type: SpanType.WORKFLOW_SLEEP,
729
1049
  name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
730
1050
  attributes: {
731
1051
  untilDate: date,
@@ -737,50 +1057,53 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
737
1057
  if (fn) {
738
1058
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
739
1059
  const stepCallId = randomUUID();
740
- return await fn({
741
- runId,
742
- workflowId,
743
- mastra: this.mastra,
744
- runtimeContext,
745
- inputData: prevOutput,
746
- runCount: -1,
747
- tracingContext: {
748
- currentSpan: sleepUntilSpan
749
- },
750
- getInitData: () => stepResults?.input,
751
- getStepResult: (step) => {
752
- if (!step?.id) {
753
- return null;
754
- }
755
- const result = stepResults[step.id];
756
- if (result?.status === "success") {
757
- return result.output;
758
- }
759
- return null;
760
- },
761
- // TODO: this function shouldn't have suspend probably?
762
- suspend: async (_suspendPayload) => {
763
- },
764
- bail: () => {
765
- },
766
- abort: () => {
767
- abortController?.abort();
768
- },
769
- [EMITTER_SYMBOL]: emitter,
770
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
771
- // TODO: add streamVNext support
772
- engine: { step: this.inngestStep },
773
- abortSignal: abortController?.signal,
774
- writer: new ToolStream(
1060
+ return await fn(
1061
+ createDeprecationProxy(
775
1062
  {
776
- prefix: "workflow-step",
777
- callId: stepCallId,
778
- name: "sleep",
779
- runId
1063
+ runId,
1064
+ workflowId,
1065
+ mastra: this.mastra,
1066
+ requestContext,
1067
+ inputData: prevOutput,
1068
+ state: executionContext.state,
1069
+ setState: (state) => {
1070
+ executionContext.state = state;
1071
+ },
1072
+ retryCount: -1,
1073
+ tracingContext: {
1074
+ currentSpan: sleepUntilSpan
1075
+ },
1076
+ getInitData: () => stepResults?.input,
1077
+ getStepResult: getStepResult.bind(this, stepResults),
1078
+ // TODO: this function shouldn't have suspend probably?
1079
+ suspend: async (_suspendPayload) => {
1080
+ },
1081
+ bail: () => {
1082
+ },
1083
+ abort: () => {
1084
+ abortController?.abort();
1085
+ },
1086
+ [EMITTER_SYMBOL]: emitter,
1087
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1088
+ engine: { step: this.inngestStep },
1089
+ abortSignal: abortController?.signal,
1090
+ writer: new ToolStream(
1091
+ {
1092
+ prefix: "workflow-step",
1093
+ callId: stepCallId,
1094
+ name: "sleep",
1095
+ runId
1096
+ },
1097
+ writableStream
1098
+ )
780
1099
  },
781
- writableStream
1100
+ {
1101
+ paramName: "runCount",
1102
+ deprecationMessage: runCountDeprecationMessage,
1103
+ logger: this.logger
1104
+ }
782
1105
  )
783
- });
1106
+ );
784
1107
  });
785
1108
  if (date && !(date instanceof Date)) {
786
1109
  date = new Date(date);
@@ -804,69 +1127,44 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
804
1127
  throw e;
805
1128
  }
806
1129
  }
807
- async executeWaitForEvent({ event, timeout }) {
808
- const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
809
- event: `user-event-${event}`,
810
- timeout: timeout ?? 5e3
811
- });
812
- if (eventData === null) {
813
- throw "Timeout waiting for event";
814
- }
815
- return eventData?.data;
816
- }
817
1130
  async executeStep({
818
1131
  step,
819
1132
  stepResults,
820
1133
  executionContext,
821
1134
  resume,
1135
+ timeTravel,
822
1136
  prevOutput,
823
1137
  emitter,
824
1138
  abortController,
825
- runtimeContext,
1139
+ requestContext,
826
1140
  tracingContext,
827
1141
  writableStream,
828
1142
  disableScorers
829
1143
  }) {
830
- const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
1144
+ const stepSpan = tracingContext?.currentSpan?.createChildSpan({
831
1145
  name: `workflow step: '${step.id}'`,
832
- type: AISpanType.WORKFLOW_STEP,
1146
+ type: SpanType.WORKFLOW_STEP,
833
1147
  input: prevOutput,
834
1148
  attributes: {
835
1149
  stepId: step.id
836
1150
  },
837
1151
  tracingPolicy: this.options?.tracingPolicy
838
1152
  });
1153
+ const { inputData, validationError } = await validateStepInput({
1154
+ prevOutput,
1155
+ step,
1156
+ validateInputs: this.options?.validateInputs ?? true
1157
+ });
839
1158
  const startedAt = await this.inngestStep.run(
840
1159
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
841
1160
  async () => {
842
1161
  const startedAt2 = Date.now();
843
1162
  await emitter.emit("watch", {
844
- type: "watch",
845
- payload: {
846
- currentStep: {
847
- id: step.id,
848
- status: "running"
849
- },
850
- workflowState: {
851
- status: "running",
852
- steps: {
853
- ...stepResults,
854
- [step.id]: {
855
- status: "running"
856
- }
857
- },
858
- result: null,
859
- error: null
860
- }
861
- },
862
- eventTimestamp: Date.now()
863
- });
864
- await emitter.emit("watch-v2", {
865
1163
  type: "workflow-step-start",
866
1164
  payload: {
867
1165
  id: step.id,
868
1166
  status: "running",
869
- payload: prevOutput,
1167
+ payload: inputData,
870
1168
  startedAt: startedAt2
871
1169
  }
872
1170
  });
@@ -877,61 +1175,92 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
877
1175
  const isResume = !!resume?.steps?.length;
878
1176
  let result;
879
1177
  let runId;
880
- if (isResume) {
881
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? randomUUID();
882
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
883
- workflowName: step.id,
884
- runId
885
- });
886
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
887
- function: step.getFunction(),
888
- data: {
889
- inputData: prevOutput,
890
- runId,
891
- resume: {
1178
+ const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
1179
+ try {
1180
+ if (isResume) {
1181
+ runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
1182
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
1183
+ workflowName: step.id,
1184
+ runId
1185
+ });
1186
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1187
+ function: step.getFunction(),
1188
+ data: {
1189
+ inputData,
1190
+ initialState: executionContext.state ?? snapshot?.value ?? {},
892
1191
  runId,
893
- steps: resume.steps.slice(1),
894
- stepResults: snapshot?.context,
895
- resumePayload: resume.resumePayload,
896
- // @ts-ignore
897
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
1192
+ resume: {
1193
+ runId,
1194
+ steps: resume.steps.slice(1),
1195
+ stepResults: snapshot?.context,
1196
+ resumePayload: resume.resumePayload,
1197
+ resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
1198
+ },
1199
+ outputOptions: { includeState: true }
898
1200
  }
899
- }
900
- });
901
- result = invokeResp.result;
902
- runId = invokeResp.runId;
903
- } else {
904
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
905
- function: step.getFunction(),
906
- data: {
907
- inputData: prevOutput
908
- }
909
- });
910
- result = invokeResp.result;
911
- runId = invokeResp.runId;
1201
+ });
1202
+ result = invokeResp.result;
1203
+ runId = invokeResp.runId;
1204
+ executionContext.state = invokeResp.result.state;
1205
+ } else if (isTimeTravel) {
1206
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
1207
+ workflowName: step.id,
1208
+ runId: executionContext.runId
1209
+ }) ?? { context: {} };
1210
+ const timeTravelParams = createTimeTravelExecutionParams({
1211
+ steps: timeTravel.steps.slice(1),
1212
+ inputData: timeTravel.inputData,
1213
+ resumeData: timeTravel.resumeData,
1214
+ context: timeTravel.nestedStepResults?.[step.id] ?? {},
1215
+ nestedStepsContext: timeTravel.nestedStepResults ?? {},
1216
+ snapshot,
1217
+ graph: step.buildExecutionGraph()
1218
+ });
1219
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1220
+ function: step.getFunction(),
1221
+ data: {
1222
+ timeTravel: timeTravelParams,
1223
+ initialState: executionContext.state ?? {},
1224
+ runId: executionContext.runId,
1225
+ outputOptions: { includeState: true }
1226
+ }
1227
+ });
1228
+ result = invokeResp.result;
1229
+ runId = invokeResp.runId;
1230
+ executionContext.state = invokeResp.result.state;
1231
+ } else {
1232
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1233
+ function: step.getFunction(),
1234
+ data: {
1235
+ inputData,
1236
+ initialState: executionContext.state ?? {},
1237
+ outputOptions: { includeState: true }
1238
+ }
1239
+ });
1240
+ result = invokeResp.result;
1241
+ runId = invokeResp.runId;
1242
+ executionContext.state = invokeResp.result.state;
1243
+ }
1244
+ } catch (e) {
1245
+ const errorCause = e?.cause;
1246
+ if (errorCause && typeof errorCause === "object") {
1247
+ result = errorCause;
1248
+ runId = errorCause.runId || randomUUID();
1249
+ } else {
1250
+ runId = randomUUID();
1251
+ result = {
1252
+ status: "failed",
1253
+ error: e instanceof Error ? e : new Error(String(e)),
1254
+ steps: {},
1255
+ input: inputData
1256
+ };
1257
+ }
912
1258
  }
913
1259
  const res = await this.inngestStep.run(
914
1260
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
915
1261
  async () => {
916
1262
  if (result.status === "failed") {
917
1263
  await emitter.emit("watch", {
918
- type: "watch",
919
- payload: {
920
- currentStep: {
921
- id: step.id,
922
- status: "failed",
923
- error: result?.error
924
- },
925
- workflowState: {
926
- status: "running",
927
- steps: stepResults,
928
- result: null,
929
- error: null
930
- }
931
- },
932
- eventTimestamp: Date.now()
933
- });
934
- await emitter.emit("watch-v2", {
935
1264
  type: "workflow-step-result",
936
1265
  payload: {
937
1266
  id: step.id,
@@ -947,26 +1276,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
947
1276
  return stepRes2?.status === "suspended";
948
1277
  });
949
1278
  for (const [stepName, stepResult] of suspendedSteps) {
950
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1279
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
951
1280
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
952
1281
  await emitter.emit("watch", {
953
- type: "watch",
954
- payload: {
955
- currentStep: {
956
- id: step.id,
957
- status: "suspended",
958
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
959
- },
960
- workflowState: {
961
- status: "running",
962
- steps: stepResults,
963
- result: null,
964
- error: null
965
- }
966
- },
967
- eventTimestamp: Date.now()
968
- });
969
- await emitter.emit("watch-v2", {
970
1282
  type: "workflow-step-suspended",
971
1283
  payload: {
972
1284
  id: step.id,
@@ -977,27 +1289,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
977
1289
  executionContext,
978
1290
  result: {
979
1291
  status: "suspended",
980
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1292
+ payload: stepResult.payload,
1293
+ suspendPayload: {
1294
+ ...stepResult?.suspendPayload,
1295
+ __workflow_meta: { runId, path: suspendPath }
1296
+ }
981
1297
  }
982
1298
  };
983
1299
  }
984
- await emitter.emit("watch", {
985
- type: "watch",
986
- payload: {
987
- currentStep: {
988
- id: step.id,
989
- status: "suspended",
990
- payload: {}
991
- },
992
- workflowState: {
993
- status: "running",
994
- steps: stepResults,
995
- result: null,
996
- error: null
997
- }
998
- },
999
- eventTimestamp: Date.now()
1000
- });
1001
1300
  return {
1002
1301
  executionContext,
1003
1302
  result: {
@@ -1007,23 +1306,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1007
1306
  };
1008
1307
  }
1009
1308
  await emitter.emit("watch", {
1010
- type: "watch",
1011
- payload: {
1012
- currentStep: {
1013
- id: step.id,
1014
- status: "success",
1015
- output: result?.result
1016
- },
1017
- workflowState: {
1018
- status: "running",
1019
- steps: stepResults,
1020
- result: null,
1021
- error: null
1022
- }
1023
- },
1024
- eventTimestamp: Date.now()
1025
- });
1026
- await emitter.emit("watch-v2", {
1027
1309
  type: "workflow-step-result",
1028
1310
  payload: {
1029
1311
  id: step.id,
@@ -1031,7 +1313,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1031
1313
  output: result?.result
1032
1314
  }
1033
1315
  });
1034
- await emitter.emit("watch-v2", {
1316
+ await emitter.emit("watch", {
1035
1317
  type: "workflow-step-finish",
1036
1318
  payload: {
1037
1319
  id: step.id,
@@ -1042,153 +1324,204 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1042
1324
  }
1043
1325
  );
1044
1326
  Object.assign(executionContext, res.executionContext);
1045
- return res.result;
1327
+ return {
1328
+ ...res.result,
1329
+ startedAt,
1330
+ endedAt: Date.now(),
1331
+ payload: inputData,
1332
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1333
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1334
+ };
1046
1335
  }
1047
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1048
- let execResults;
1049
- let suspended;
1050
- let bailed;
1051
- try {
1052
- const result = await step.execute({
1053
- runId: executionContext.runId,
1054
- mastra: this.mastra,
1055
- runtimeContext,
1056
- writableStream,
1057
- inputData: prevOutput,
1058
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1059
- tracingContext: {
1060
- currentSpan: stepAISpan
1061
- },
1062
- getInitData: () => stepResults?.input,
1063
- getStepResult: (step2) => {
1064
- const result2 = stepResults[step2.id];
1065
- if (result2?.status === "success") {
1066
- return result2.output;
1067
- }
1068
- return null;
1069
- },
1070
- suspend: async (suspendPayload) => {
1071
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1072
- suspended = { payload: suspendPayload };
1073
- },
1074
- bail: (result2) => {
1075
- bailed = { payload: result2 };
1076
- },
1077
- resume: {
1078
- steps: resume?.steps?.slice(1) || [],
1079
- resumePayload: resume?.resumePayload,
1080
- // @ts-ignore
1081
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1082
- },
1083
- [EMITTER_SYMBOL]: emitter,
1084
- engine: {
1085
- step: this.inngestStep
1086
- },
1087
- abortSignal: abortController.signal
1336
+ const stepCallId = randomUUID();
1337
+ let stepRes;
1338
+ try {
1339
+ stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1340
+ let execResults;
1341
+ let suspended;
1342
+ let bailed;
1343
+ const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await validateStepResumeData({
1344
+ resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
1345
+ step
1088
1346
  });
1089
- const endedAt = Date.now();
1090
- execResults = {
1091
- status: "success",
1092
- output: result,
1093
- startedAt,
1094
- endedAt,
1095
- payload: prevOutput,
1096
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1097
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1098
- };
1099
- } catch (e) {
1100
- execResults = {
1101
- status: "failed",
1102
- payload: prevOutput,
1103
- error: e instanceof Error ? e.message : String(e),
1104
- endedAt: Date.now(),
1105
- startedAt,
1106
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1107
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1108
- };
1109
- }
1110
- if (suspended) {
1111
- execResults = {
1112
- status: "suspended",
1113
- suspendedPayload: suspended.payload,
1114
- payload: prevOutput,
1115
- suspendedAt: Date.now(),
1116
- startedAt,
1117
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1118
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1119
- };
1120
- } else if (bailed) {
1121
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1122
- }
1123
- if (execResults.status === "failed") {
1124
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1125
- const error = new Error(execResults.error);
1126
- stepAISpan?.error({ error });
1127
- throw error;
1347
+ let resumeDataToUse;
1348
+ if (timeTravelResumeData && !timeTravelResumeValidationError) {
1349
+ resumeDataToUse = timeTravelResumeData;
1350
+ } else if (timeTravelResumeData && timeTravelResumeValidationError) {
1351
+ this.logger.warn("Time travel resume data validation failed", {
1352
+ stepId: step.id,
1353
+ error: timeTravelResumeValidationError.message
1354
+ });
1355
+ } else if (resume?.steps[0] === step.id) {
1356
+ resumeDataToUse = resume?.resumePayload;
1128
1357
  }
1129
- }
1130
- await emitter.emit("watch", {
1131
- type: "watch",
1132
- payload: {
1133
- currentStep: {
1134
- id: step.id,
1135
- ...execResults
1136
- },
1137
- workflowState: {
1138
- status: "running",
1139
- steps: { ...stepResults, [step.id]: execResults },
1140
- result: null,
1141
- error: null
1358
+ try {
1359
+ if (validationError) {
1360
+ throw validationError;
1142
1361
  }
1143
- },
1144
- eventTimestamp: Date.now()
1362
+ const retryCount = this.getOrGenerateRetryCount(step.id);
1363
+ const result = await step.execute({
1364
+ runId: executionContext.runId,
1365
+ workflowId: executionContext.workflowId,
1366
+ mastra: this.mastra,
1367
+ requestContext,
1368
+ retryCount,
1369
+ writer: new ToolStream(
1370
+ {
1371
+ prefix: "workflow-step",
1372
+ callId: stepCallId,
1373
+ name: step.id,
1374
+ runId: executionContext.runId
1375
+ },
1376
+ writableStream
1377
+ ),
1378
+ state: executionContext?.state ?? {},
1379
+ setState: (state) => {
1380
+ executionContext.state = state;
1381
+ },
1382
+ inputData,
1383
+ resumeData: resumeDataToUse,
1384
+ tracingContext: {
1385
+ currentSpan: stepSpan
1386
+ },
1387
+ getInitData: () => stepResults?.input,
1388
+ getStepResult: getStepResult.bind(this, stepResults),
1389
+ suspend: async (suspendPayload, suspendOptions) => {
1390
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1391
+ if (suspendOptions?.resumeLabel) {
1392
+ const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
1393
+ for (const label of resumeLabel) {
1394
+ executionContext.resumeLabels[label] = {
1395
+ stepId: step.id,
1396
+ foreachIndex: executionContext.foreachIndex
1397
+ };
1398
+ }
1399
+ }
1400
+ suspended = { payload: suspendPayload };
1401
+ },
1402
+ bail: (result2) => {
1403
+ bailed = { payload: result2 };
1404
+ },
1405
+ abort: () => {
1406
+ abortController?.abort();
1407
+ },
1408
+ [EMITTER_SYMBOL]: emitter,
1409
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1410
+ engine: {
1411
+ step: this.inngestStep
1412
+ },
1413
+ abortSignal: abortController.signal
1414
+ });
1415
+ const endedAt = Date.now();
1416
+ execResults = {
1417
+ status: "success",
1418
+ output: result,
1419
+ startedAt,
1420
+ endedAt,
1421
+ payload: inputData,
1422
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1423
+ resumePayload: resumeDataToUse
1424
+ };
1425
+ } catch (e) {
1426
+ const stepFailure = {
1427
+ status: "failed",
1428
+ payload: inputData,
1429
+ error: e instanceof Error ? e.message : String(e),
1430
+ endedAt: Date.now(),
1431
+ startedAt,
1432
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1433
+ resumePayload: resumeDataToUse
1434
+ };
1435
+ execResults = stepFailure;
1436
+ const fallbackErrorMessage = `Step ${step.id} failed`;
1437
+ stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1438
+ throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1439
+ cause: execResults
1440
+ });
1441
+ }
1442
+ if (suspended) {
1443
+ execResults = {
1444
+ status: "suspended",
1445
+ suspendPayload: suspended.payload,
1446
+ ...execResults.output ? { suspendOutput: execResults.output } : {},
1447
+ payload: inputData,
1448
+ suspendedAt: Date.now(),
1449
+ startedAt,
1450
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1451
+ resumePayload: resumeDataToUse
1452
+ };
1453
+ } else if (bailed) {
1454
+ execResults = {
1455
+ status: "bailed",
1456
+ output: bailed.payload,
1457
+ payload: inputData,
1458
+ endedAt: Date.now(),
1459
+ startedAt
1460
+ };
1461
+ }
1462
+ if (execResults.status === "suspended") {
1463
+ await emitter.emit("watch", {
1464
+ type: "workflow-step-suspended",
1465
+ payload: {
1466
+ id: step.id,
1467
+ ...execResults
1468
+ }
1469
+ });
1470
+ } else {
1471
+ await emitter.emit("watch", {
1472
+ type: "workflow-step-result",
1473
+ payload: {
1474
+ id: step.id,
1475
+ ...execResults
1476
+ }
1477
+ });
1478
+ await emitter.emit("watch", {
1479
+ type: "workflow-step-finish",
1480
+ payload: {
1481
+ id: step.id,
1482
+ metadata: {}
1483
+ }
1484
+ });
1485
+ }
1486
+ stepSpan?.end({ output: execResults });
1487
+ return { result: execResults, executionContext, stepResults };
1145
1488
  });
1146
- if (execResults.status === "suspended") {
1147
- await emitter.emit("watch-v2", {
1148
- type: "workflow-step-suspended",
1149
- payload: {
1150
- id: step.id,
1151
- ...execResults
1152
- }
1153
- });
1154
- } else {
1155
- await emitter.emit("watch-v2", {
1156
- type: "workflow-step-result",
1157
- payload: {
1158
- id: step.id,
1159
- ...execResults
1160
- }
1161
- });
1162
- await emitter.emit("watch-v2", {
1163
- type: "workflow-step-finish",
1164
- payload: {
1165
- id: step.id,
1166
- metadata: {}
1167
- }
1168
- });
1169
- }
1170
- stepAISpan?.end({ output: execResults });
1171
- return { result: execResults, executionContext, stepResults };
1172
- });
1173
- if (disableScorers !== false) {
1489
+ } catch (e) {
1490
+ const stepFailure = e instanceof Error ? e?.cause : {
1491
+ status: "failed",
1492
+ error: e instanceof Error ? e.message : String(e),
1493
+ payload: inputData,
1494
+ startedAt,
1495
+ endedAt: Date.now()
1496
+ };
1497
+ stepRes = {
1498
+ result: stepFailure,
1499
+ executionContext,
1500
+ stepResults: {
1501
+ ...stepResults,
1502
+ [step.id]: stepFailure
1503
+ }
1504
+ };
1505
+ }
1506
+ if (disableScorers !== false && stepRes.result.status === "success") {
1174
1507
  await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
1175
1508
  if (step.scorers) {
1176
1509
  await this.runScorers({
1177
1510
  scorers: step.scorers,
1178
1511
  runId: executionContext.runId,
1179
- input: prevOutput,
1512
+ input: inputData,
1180
1513
  output: stepRes.result,
1181
1514
  workflowId: executionContext.workflowId,
1182
1515
  stepId: step.id,
1183
- runtimeContext,
1516
+ requestContext,
1184
1517
  disableScorers,
1185
- tracingContext: { currentSpan: stepAISpan }
1518
+ tracingContext: { currentSpan: stepSpan }
1186
1519
  });
1187
1520
  }
1188
1521
  });
1189
1522
  }
1190
1523
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1191
- Object.assign(stepResults, stepRes.stepResults);
1524
+ executionContext.state = stepRes.executionContext.state;
1192
1525
  return stepRes.result;
1193
1526
  }
1194
1527
  async persistStepUpdate({
@@ -1205,22 +1538,27 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1205
1538
  await this.inngestStep.run(
1206
1539
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1207
1540
  async () => {
1541
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1542
+ if (!shouldPersistSnapshot) {
1543
+ return;
1544
+ }
1208
1545
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1209
1546
  workflowName: workflowId,
1210
1547
  runId,
1211
1548
  resourceId,
1212
1549
  snapshot: {
1213
1550
  runId,
1214
- value: {},
1551
+ status: workflowStatus,
1552
+ value: executionContext.state,
1215
1553
  context: stepResults,
1216
- activePaths: [],
1554
+ activePaths: executionContext.executionPath,
1555
+ activeStepsPath: executionContext.activeStepsPath,
1217
1556
  suspendedPaths: executionContext.suspendedPaths,
1557
+ resumeLabels: executionContext.resumeLabels,
1218
1558
  waitingPaths: {},
1219
1559
  serializedStepGraph,
1220
- status: workflowStatus,
1221
1560
  result,
1222
1561
  error,
1223
- // @ts-ignore
1224
1562
  timestamp: Date.now()
1225
1563
  }
1226
1564
  });
@@ -1232,20 +1570,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1232
1570
  runId,
1233
1571
  entry,
1234
1572
  prevOutput,
1235
- prevStep,
1236
1573
  stepResults,
1237
- serializedStepGraph,
1574
+ timeTravel,
1238
1575
  resume,
1239
1576
  executionContext,
1240
1577
  emitter,
1241
1578
  abortController,
1242
- runtimeContext,
1579
+ requestContext,
1243
1580
  writableStream,
1244
1581
  disableScorers,
1245
1582
  tracingContext
1246
1583
  }) {
1247
1584
  const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1248
- type: AISpanType.WORKFLOW_CONDITIONAL,
1585
+ type: SpanType.WORKFLOW_CONDITIONAL,
1249
1586
  name: `conditional: '${entry.conditions.length} conditions'`,
1250
1587
  input: prevOutput,
1251
1588
  attributes: {
@@ -1258,7 +1595,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1258
1595
  entry.conditions.map(
1259
1596
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1260
1597
  const evalSpan = conditionalSpan?.createChildSpan({
1261
- type: AISpanType.WORKFLOW_CONDITIONAL_EVAL,
1598
+ type: SpanType.WORKFLOW_CONDITIONAL_EVAL,
1262
1599
  name: `condition: '${index}'`,
1263
1600
  input: prevOutput,
1264
1601
  attributes: {
@@ -1267,52 +1604,55 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1267
1604
  tracingPolicy: this.options?.tracingPolicy
1268
1605
  });
1269
1606
  try {
1270
- const result = await cond({
1271
- runId,
1272
- workflowId,
1273
- mastra: this.mastra,
1274
- runtimeContext,
1275
- runCount: -1,
1276
- inputData: prevOutput,
1277
- tracingContext: {
1278
- currentSpan: evalSpan
1279
- },
1280
- getInitData: () => stepResults?.input,
1281
- getStepResult: (step) => {
1282
- if (!step?.id) {
1283
- return null;
1284
- }
1285
- const result2 = stepResults[step.id];
1286
- if (result2?.status === "success") {
1287
- return result2.output;
1288
- }
1289
- return null;
1290
- },
1291
- // TODO: this function shouldn't have suspend probably?
1292
- suspend: async (_suspendPayload) => {
1293
- },
1294
- bail: () => {
1295
- },
1296
- abort: () => {
1297
- abortController.abort();
1298
- },
1299
- [EMITTER_SYMBOL]: emitter,
1300
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
1301
- // TODO: add streamVNext support
1302
- engine: {
1303
- step: this.inngestStep
1304
- },
1305
- abortSignal: abortController.signal,
1306
- writer: new ToolStream(
1607
+ const result = await cond(
1608
+ createDeprecationProxy(
1307
1609
  {
1308
- prefix: "workflow-step",
1309
- callId: randomUUID(),
1310
- name: "conditional",
1311
- runId
1610
+ runId,
1611
+ workflowId,
1612
+ mastra: this.mastra,
1613
+ requestContext,
1614
+ retryCount: -1,
1615
+ inputData: prevOutput,
1616
+ state: executionContext.state,
1617
+ setState: (state) => {
1618
+ executionContext.state = state;
1619
+ },
1620
+ tracingContext: {
1621
+ currentSpan: evalSpan
1622
+ },
1623
+ getInitData: () => stepResults?.input,
1624
+ getStepResult: getStepResult.bind(this, stepResults),
1625
+ // TODO: this function shouldn't have suspend probably?
1626
+ suspend: async (_suspendPayload) => {
1627
+ },
1628
+ bail: () => {
1629
+ },
1630
+ abort: () => {
1631
+ abortController.abort();
1632
+ },
1633
+ [EMITTER_SYMBOL]: emitter,
1634
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1635
+ engine: {
1636
+ step: this.inngestStep
1637
+ },
1638
+ abortSignal: abortController.signal,
1639
+ writer: new ToolStream(
1640
+ {
1641
+ prefix: "workflow-step",
1642
+ callId: randomUUID(),
1643
+ name: "conditional",
1644
+ runId
1645
+ },
1646
+ writableStream
1647
+ )
1312
1648
  },
1313
- writableStream
1649
+ {
1650
+ paramName: "runCount",
1651
+ deprecationMessage: runCountDeprecationMessage,
1652
+ logger: this.logger
1653
+ }
1314
1654
  )
1315
- });
1655
+ );
1316
1656
  evalSpan?.end({
1317
1657
  output: result,
1318
1658
  attributes: {
@@ -1340,46 +1680,58 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1340
1680
  }
1341
1681
  });
1342
1682
  const results = await Promise.all(
1343
- stepsToRun.map(
1344
- (step, index) => this.executeEntry({
1345
- workflowId,
1346
- runId,
1347
- entry: step,
1348
- serializedStepGraph,
1349
- prevStep,
1683
+ stepsToRun.map(async (step, index) => {
1684
+ const currStepResult = stepResults[step.step.id];
1685
+ if (currStepResult && currStepResult.status === "success") {
1686
+ return currStepResult;
1687
+ }
1688
+ const result = await this.executeStep({
1689
+ step: step.step,
1690
+ prevOutput,
1350
1691
  stepResults,
1351
1692
  resume,
1693
+ timeTravel,
1352
1694
  executionContext: {
1353
1695
  workflowId,
1354
1696
  runId,
1355
1697
  executionPath: [...executionContext.executionPath, index],
1698
+ activeStepsPath: executionContext.activeStepsPath,
1356
1699
  suspendedPaths: executionContext.suspendedPaths,
1700
+ resumeLabels: executionContext.resumeLabels,
1357
1701
  retryConfig: executionContext.retryConfig,
1358
- executionSpan: executionContext.executionSpan
1702
+ state: executionContext.state
1359
1703
  },
1360
1704
  emitter,
1361
1705
  abortController,
1362
- runtimeContext,
1706
+ requestContext,
1363
1707
  writableStream,
1364
1708
  disableScorers,
1365
1709
  tracingContext: {
1366
1710
  currentSpan: conditionalSpan
1367
1711
  }
1368
- })
1369
- )
1712
+ });
1713
+ stepResults[step.step.id] = result;
1714
+ return result;
1715
+ })
1370
1716
  );
1371
- const hasFailed = results.find((result) => result.result.status === "failed");
1372
- const hasSuspended = results.find((result) => result.result.status === "suspended");
1717
+ const hasFailed = results.find((result) => result.status === "failed");
1718
+ const hasSuspended = results.find((result) => result.status === "suspended");
1373
1719
  if (hasFailed) {
1374
- execResults = { status: "failed", error: hasFailed.result.error };
1720
+ execResults = { status: "failed", error: hasFailed.error };
1375
1721
  } else if (hasSuspended) {
1376
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1722
+ execResults = {
1723
+ status: "suspended",
1724
+ suspendPayload: hasSuspended.suspendPayload,
1725
+ ...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
1726
+ };
1377
1727
  } else {
1378
1728
  execResults = {
1379
1729
  status: "success",
1380
1730
  output: results.reduce((acc, result, index) => {
1381
- if (result.result.status === "success") {
1382
- acc[stepsToRun[index].step.id] = result.output;
1731
+ if (result.status === "success") {
1732
+ if ("step" in stepsToRun[index]) {
1733
+ acc[stepsToRun[index].step.id] = result.output;
1734
+ }
1383
1735
  }
1384
1736
  return acc;
1385
1737
  }, {})