@mastra/inngest 0.0.0-chore-core-swap-aiv5-ai-package-naming-20251009203931 → 0.0.0-client-js-listmessages-agentid-fix-20251119175531

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,9 +1,11 @@
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, getStepResult, validateStepInput } 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';
8
10
  import { NonRetriableError, RetryAfterError } from 'inngest';
9
11
  import { serve as serve$1 } from 'inngest/hono';
@@ -16,7 +18,7 @@ function serve({
16
18
  functions: userFunctions = [],
17
19
  registerOptions
18
20
  }) {
19
- const wfs = mastra.getWorkflows();
21
+ const wfs = mastra.listWorkflows();
20
22
  const workflowFunctions = Array.from(
21
23
  new Set(
22
24
  Object.values(wfs).flatMap((wf) => {
@@ -55,11 +57,12 @@ var InngestRun = class extends Run {
55
57
  }
56
58
  async getRunOutput(eventId) {
57
59
  let runs = await this.getRuns(eventId);
60
+ const storage = this.#mastra?.getStorage();
58
61
  while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
59
62
  await new Promise((resolve) => setTimeout(resolve, 1e3));
60
63
  runs = await this.getRuns(eventId);
61
64
  if (runs?.[0]?.status === "Failed") {
62
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
65
+ const snapshot = await storage?.loadWorkflowSnapshot({
63
66
  workflowName: this.workflowId,
64
67
  runId: this.runId
65
68
  });
@@ -68,7 +71,7 @@ var InngestRun = class extends Run {
68
71
  };
69
72
  }
70
73
  if (runs?.[0]?.status === "Cancelled") {
71
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
74
+ const snapshot = await storage?.loadWorkflowSnapshot({
72
75
  workflowName: this.workflowId,
73
76
  runId: this.runId
74
77
  });
@@ -77,38 +80,40 @@ var InngestRun = class extends Run {
77
80
  }
78
81
  return runs?.[0];
79
82
  }
80
- async sendEvent(event, data) {
81
- await this.inngest.send({
82
- name: `user-event-${event}`,
83
- data
84
- });
85
- }
86
83
  async cancel() {
84
+ const storage = this.#mastra?.getStorage();
87
85
  await this.inngest.send({
88
86
  name: `cancel.workflow.${this.workflowId}`,
89
87
  data: {
90
88
  runId: this.runId
91
89
  }
92
90
  });
93
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
91
+ const snapshot = await storage?.loadWorkflowSnapshot({
94
92
  workflowName: this.workflowId,
95
93
  runId: this.runId
96
94
  });
97
95
  if (snapshot) {
98
- await this.#mastra?.storage?.persistWorkflowSnapshot({
96
+ await storage?.persistWorkflowSnapshot({
99
97
  workflowName: this.workflowId,
100
98
  runId: this.runId,
101
99
  resourceId: this.resourceId,
102
100
  snapshot: {
103
101
  ...snapshot,
104
- status: "canceled"
102
+ status: "canceled",
103
+ value: snapshot.value
105
104
  }
106
105
  });
107
106
  }
108
107
  }
109
- async start({
108
+ async start(params) {
109
+ return this._start(params);
110
+ }
111
+ async _start({
110
112
  inputData,
111
- initialState
113
+ initialState,
114
+ outputOptions,
115
+ tracingOptions,
116
+ format
112
117
  }) {
113
118
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
114
119
  workflowName: this.workflowId,
@@ -117,13 +122,15 @@ var InngestRun = class extends Run {
117
122
  snapshot: {
118
123
  runId: this.runId,
119
124
  serializedStepGraph: this.serializedStepGraph,
125
+ status: "running",
120
126
  value: {},
121
127
  context: {},
122
128
  activePaths: [],
123
129
  suspendedPaths: {},
130
+ activeStepsPath: {},
131
+ resumeLabels: {},
124
132
  waitingPaths: {},
125
- timestamp: Date.now(),
126
- status: "running"
133
+ timestamp: Date.now()
127
134
  }
128
135
  });
129
136
  const inputDataToUse = await this._validateInput(inputData);
@@ -134,7 +141,10 @@ var InngestRun = class extends Run {
134
141
  inputData: inputDataToUse,
135
142
  initialState: initialStateToUse,
136
143
  runId: this.runId,
137
- resourceId: this.resourceId
144
+ resourceId: this.resourceId,
145
+ outputOptions,
146
+ tracingOptions,
147
+ format
138
148
  }
139
149
  });
140
150
  const eventId = eventOutput.ids[0];
@@ -163,10 +173,16 @@ var InngestRun = class extends Run {
163
173
  return p;
164
174
  }
165
175
  async _resume(params) {
166
- const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
167
- (step) => typeof step === "string" ? step : step?.id
168
- );
169
- 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({
170
186
  workflowName: this.workflowId,
171
187
  runId: this.runId
172
188
  });
@@ -184,8 +200,7 @@ var InngestRun = class extends Run {
184
200
  steps,
185
201
  stepResults: snapshot?.context,
186
202
  resumePayload: resumeDataToUse,
187
- // @ts-ignore
188
- resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
203
+ resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
189
204
  }
190
205
  }
191
206
  });
@@ -200,12 +215,103 @@ var InngestRun = class extends Run {
200
215
  }
201
216
  return result;
202
217
  }
203
- watch(cb, type = "watch") {
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()
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
296
+ }
297
+ });
298
+ const eventId = eventOutput.ids[0];
299
+ if (!eventId) {
300
+ throw new Error("Event ID is not set");
301
+ }
302
+ const runOutput = await this.getRunOutput(eventId);
303
+ const result = runOutput?.output?.result;
304
+ if (result.status === "failed") {
305
+ result.error = new Error(result.error);
306
+ }
307
+ return result;
308
+ }
309
+ watch(cb) {
204
310
  let active = true;
205
311
  const streamPromise = subscribe(
206
312
  {
207
313
  channel: `workflow:${this.workflowId}:${this.runId}`,
208
- topics: [type],
314
+ topics: ["watch"],
209
315
  app: this.inngest
210
316
  },
211
317
  (message) => {
@@ -223,20 +329,35 @@ var InngestRun = class extends Run {
223
329
  });
224
330
  };
225
331
  }
226
- stream({ inputData, runtimeContext } = {}) {
332
+ streamLegacy({ inputData, requestContext } = {}) {
227
333
  const { readable, writable } = new TransformStream();
228
334
  const writer = writable.getWriter();
229
335
  const unwatch = this.watch(async (event) => {
230
336
  try {
337
+ await writer.write({
338
+ // @ts-ignore
339
+ type: "start",
340
+ // @ts-ignore
341
+ payload: { runId: this.runId }
342
+ });
231
343
  const e = {
232
344
  ...event,
233
345
  type: event.type.replace("workflow-", "")
234
346
  };
347
+ if (e.type === "step-output") {
348
+ e.type = e.payload.output.type;
349
+ e.payload = e.payload.output.payload;
350
+ }
235
351
  await writer.write(e);
236
352
  } catch {
237
353
  }
238
- }, "watch-v2");
354
+ });
239
355
  this.closeStreamAction = async () => {
356
+ await writer.write({
357
+ type: "finish",
358
+ // @ts-ignore
359
+ payload: { runId: this.runId }
360
+ });
240
361
  unwatch();
241
362
  try {
242
363
  await writer.close();
@@ -246,7 +367,7 @@ var InngestRun = class extends Run {
246
367
  writer.releaseLock();
247
368
  }
248
369
  };
249
- this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
370
+ this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
250
371
  if (result.status !== "suspended") {
251
372
  this.closeStreamAction?.().catch(() => {
252
373
  });
@@ -258,6 +379,151 @@ var InngestRun = class extends Run {
258
379
  getWorkflowState: () => this.executionResults
259
380
  };
260
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
+ }
261
527
  };
262
528
  var InngestWorkflow = class _InngestWorkflow extends Workflow {
263
529
  #mastra;
@@ -267,6 +533,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
267
533
  constructor(params, inngest) {
268
534
  const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
269
535
  super(workflowParams);
536
+ this.engineType = "inngest";
270
537
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
271
538
  ([_, value]) => value !== void 0
272
539
  );
@@ -274,13 +541,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
274
541
  this.#mastra = params.mastra;
275
542
  this.inngest = inngest;
276
543
  }
277
- async getWorkflowRuns(args) {
544
+ async listWorkflowRuns(args) {
278
545
  const storage = this.#mastra?.getStorage();
279
546
  if (!storage) {
280
547
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
281
548
  return { runs: [], total: 0 };
282
549
  }
283
- return storage.getWorkflowRuns({ workflowName: this.id, ...args ?? {} });
550
+ return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
284
551
  }
285
552
  async getWorkflowRunById(runId) {
286
553
  const storage = this.#mastra?.getStorage();
@@ -309,16 +576,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
309
576
  }
310
577
  }
311
578
  }
312
- /**
313
- * @deprecated Use createRunAsync() instead.
314
- * @throws {Error} Always throws an error directing users to use createRunAsync()
315
- */
316
- createRun(_options) {
317
- throw new Error(
318
- "createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async."
319
- );
320
- }
321
- async createRunAsync(options) {
579
+ async createRun(options) {
322
580
  const runIdToUse = options?.runId || randomUUID();
323
581
  const run = this.runs.get(runIdToUse) ?? new InngestRun(
324
582
  {
@@ -331,7 +589,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
331
589
  mastra: this.#mastra,
332
590
  retryConfig: this.retryConfig,
333
591
  cleanup: () => this.runs.delete(runIdToUse),
334
- workflowSteps: this.steps
592
+ workflowSteps: this.steps,
593
+ workflowEngineType: this.engineType,
594
+ validateInputs: this.options.validateInputs
335
595
  },
336
596
  this.inngest
337
597
  );
@@ -352,12 +612,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
352
612
  value: {},
353
613
  context: {},
354
614
  activePaths: [],
615
+ activeStepsPath: {},
355
616
  waitingPaths: {},
356
617
  serializedStepGraph: this.serializedStepGraph,
357
618
  suspendedPaths: {},
619
+ resumeLabels: {},
358
620
  result: void 0,
359
621
  error: void 0,
360
- // @ts-ignore
361
622
  timestamp: Date.now()
362
623
  }
363
624
  });
@@ -371,15 +632,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
371
632
  this.function = this.inngest.createFunction(
372
633
  {
373
634
  id: `workflow.${this.id}`,
374
- // @ts-ignore
375
- retries: this.retryConfig?.attempts ?? 0,
635
+ retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
376
636
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
377
637
  // Spread flow control configuration
378
638
  ...this.flowControlConfig
379
639
  },
380
640
  { event: `workflow.${this.id}` },
381
641
  async ({ event, step, attempt, publish }) => {
382
- let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
642
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
383
643
  if (!runId) {
384
644
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
385
645
  return randomUUID();
@@ -418,13 +678,20 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
418
678
  initialState,
419
679
  emitter,
420
680
  retryConfig: this.retryConfig,
421
- runtimeContext: new RuntimeContext(),
681
+ requestContext: new RequestContext(),
422
682
  // TODO
423
683
  resume,
684
+ timeTravel,
685
+ format,
424
686
  abortController: new AbortController(),
425
- currentSpan: void 0,
426
- // TODO: Pass actual parent AI span from workflow execution context
427
- outputOptions
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
+ })
428
695
  });
429
696
  await step.run(`workflow.${this.id}.finalize`, async () => {
430
697
  if (result.status === "failed") {
@@ -462,20 +729,29 @@ function isAgent(params) {
462
729
  function isTool(params) {
463
730
  return params instanceof Tool;
464
731
  }
465
- function createStep(params) {
732
+ function createStep(params, agentOptions) {
466
733
  if (isAgent(params)) {
467
734
  return {
468
735
  id: params.name,
469
736
  description: params.getDescription(),
470
- // @ts-ignore
471
737
  inputSchema: z.object({
472
738
  prompt: z.string()
739
+ // resourceId: z.string().optional(),
740
+ // threadId: z.string().optional(),
473
741
  }),
474
- // @ts-ignore
475
742
  outputSchema: z.object({
476
743
  text: z.string()
477
744
  }),
478
- 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
+ }) => {
479
755
  let streamPromise = {};
480
756
  streamPromise.promise = new Promise((resolve, reject) => {
481
757
  streamPromise.resolve = resolve;
@@ -485,61 +761,60 @@ function createStep(params) {
485
761
  name: params.name,
486
762
  args: inputData
487
763
  };
488
- if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
489
- const { fullStream } = await params.stream(inputData.prompt, {
490
- runtimeContext,
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,
491
771
  tracingContext,
492
772
  onFinish: (result) => {
493
773
  streamPromise.resolve(result.text);
774
+ void agentOptions?.onFinish?.(result);
494
775
  },
495
776
  abortSignal
496
777
  });
497
- if (abortSignal.aborted) {
498
- return abort();
499
- }
500
- await emitter.emit("watch-v2", {
501
- type: "tool-call-streaming-start",
502
- ...toolData ?? {}
503
- });
504
- for await (const chunk of fullStream) {
505
- if (chunk.type === "text-delta") {
506
- await emitter.emit("watch-v2", {
507
- type: "tool-call-delta",
508
- ...toolData ?? {},
509
- argsTextDelta: chunk.payload.text
510
- });
511
- }
512
- }
778
+ stream = fullStream;
513
779
  } else {
514
- const { fullStream } = await params.streamLegacy(inputData.prompt, {
515
- runtimeContext,
780
+ const modelOutput = await params.stream(inputData.prompt, {
781
+ ...agentOptions ?? {},
782
+ requestContext,
516
783
  tracingContext,
517
784
  onFinish: (result) => {
518
785
  streamPromise.resolve(result.text);
786
+ void agentOptions?.onFinish?.(result);
519
787
  },
520
788
  abortSignal
521
789
  });
522
- if (abortSignal.aborted) {
523
- return abort();
524
- }
525
- await emitter.emit("watch-v2", {
790
+ stream = modelOutput.fullStream;
791
+ }
792
+ if (streamFormat === "legacy") {
793
+ await emitter.emit("watch", {
526
794
  type: "tool-call-streaming-start",
527
795
  ...toolData ?? {}
528
796
  });
529
- for await (const chunk of fullStream) {
797
+ for await (const chunk of stream) {
530
798
  if (chunk.type === "text-delta") {
531
- await emitter.emit("watch-v2", {
799
+ await emitter.emit("watch", {
532
800
  type: "tool-call-delta",
533
801
  ...toolData ?? {},
534
802
  argsTextDelta: chunk.textDelta
535
803
  });
536
804
  }
537
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);
813
+ }
814
+ }
815
+ if (abortSignal.aborted) {
816
+ return abort();
538
817
  }
539
- await emitter.emit("watch-v2", {
540
- type: "tool-call-streaming-finish",
541
- ...toolData ?? {}
542
- });
543
818
  return {
544
819
  text: await streamPromise.promise
545
820
  };
@@ -553,20 +828,36 @@ function createStep(params) {
553
828
  }
554
829
  return {
555
830
  // TODO: tool probably should have strong id type
556
- // @ts-ignore
557
831
  id: params.id,
558
832
  description: params.description,
559
833
  inputSchema: params.inputSchema,
560
834
  outputSchema: params.outputSchema,
561
- execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
562
- return params.execute({
563
- context: inputData,
564
- mastra: wrapMastra(mastra, tracingContext),
565
- runtimeContext,
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,
566
850
  tracingContext,
567
- suspend,
568
- resumeData
569
- });
851
+ resumeData,
852
+ workflow: {
853
+ runId,
854
+ suspend,
855
+ workflowId,
856
+ state,
857
+ setState
858
+ }
859
+ };
860
+ return params.execute(inputData, toolContext);
570
861
  },
571
862
  component: "TOOL"
572
863
  };
@@ -600,6 +891,8 @@ function init(inngest) {
600
891
  suspendSchema: step.suspendSchema,
601
892
  stateSchema: step.stateSchema,
602
893
  execute: step.execute,
894
+ retries: step.retries,
895
+ scorers: step.scorers,
603
896
  component: step.component
604
897
  };
605
898
  },
@@ -625,63 +918,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
625
918
  this.inngestStep = inngestStep;
626
919
  this.inngestAttempts = inngestAttempts;
627
920
  }
628
- async execute(params) {
629
- await params.emitter.emit("watch-v2", {
630
- type: "workflow-start",
631
- payload: { runId: params.runId }
632
- });
633
- const result = await super.execute(params);
634
- await params.emitter.emit("watch-v2", {
635
- type: "workflow-finish",
636
- payload: { runId: params.runId }
637
- });
638
- return result;
639
- }
640
- async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
921
+ async fmtReturnValue(emitter, stepResults, lastOutput, error) {
641
922
  const base = {
642
923
  status: lastOutput.status,
643
924
  steps: stepResults
644
925
  };
645
926
  if (lastOutput.status === "success") {
646
- await emitter.emit("watch", {
647
- type: "watch",
648
- payload: {
649
- workflowState: {
650
- status: lastOutput.status,
651
- steps: stepResults,
652
- result: lastOutput.output
653
- }
654
- },
655
- eventTimestamp: Date.now()
656
- });
657
927
  base.result = lastOutput.output;
658
928
  } else if (lastOutput.status === "failed") {
659
929
  base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
660
- await emitter.emit("watch", {
661
- type: "watch",
662
- payload: {
663
- workflowState: {
664
- status: lastOutput.status,
665
- steps: stepResults,
666
- result: null,
667
- error: base.error
668
- }
669
- },
670
- eventTimestamp: Date.now()
671
- });
672
930
  } else if (lastOutput.status === "suspended") {
673
- await emitter.emit("watch", {
674
- type: "watch",
675
- payload: {
676
- workflowState: {
677
- status: lastOutput.status,
678
- steps: stepResults,
679
- result: null,
680
- error: null
681
- }
682
- },
683
- eventTimestamp: Date.now()
684
- });
685
931
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
686
932
  if (stepResult?.status === "suspended") {
687
933
  const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
@@ -691,7 +937,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
691
937
  });
692
938
  base.suspended = suspendedStepIds;
693
939
  }
694
- executionSpan?.end();
695
940
  return base;
696
941
  }
697
942
  // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
@@ -705,14 +950,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
705
950
  stepResults,
706
951
  emitter,
707
952
  abortController,
708
- runtimeContext,
953
+ requestContext,
709
954
  executionContext,
710
955
  writableStream,
711
956
  tracingContext
712
957
  }) {
713
958
  let { duration, fn } = entry;
714
959
  const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
715
- type: AISpanType.WORKFLOW_SLEEP,
960
+ type: SpanType.WORKFLOW_SLEEP,
716
961
  name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
717
962
  attributes: {
718
963
  durationMs: duration,
@@ -723,45 +968,53 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
723
968
  if (fn) {
724
969
  const stepCallId = randomUUID();
725
970
  duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
726
- return await fn({
727
- runId,
728
- workflowId,
729
- mastra: this.mastra,
730
- runtimeContext,
731
- inputData: prevOutput,
732
- state: executionContext.state,
733
- setState: (state) => {
734
- executionContext.state = state;
735
- },
736
- runCount: -1,
737
- tracingContext: {
738
- currentSpan: sleepSpan
739
- },
740
- getInitData: () => stepResults?.input,
741
- getStepResult: getStepResult.bind(this, stepResults),
742
- // TODO: this function shouldn't have suspend probably?
743
- suspend: async (_suspendPayload) => {
744
- },
745
- bail: () => {
746
- },
747
- abort: () => {
748
- abortController?.abort();
749
- },
750
- [EMITTER_SYMBOL]: emitter,
751
- // TODO: add streamVNext support
752
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
753
- engine: { step: this.inngestStep },
754
- abortSignal: abortController?.signal,
755
- writer: new ToolStream(
971
+ return await fn(
972
+ createDeprecationProxy(
756
973
  {
757
- prefix: "workflow-step",
758
- callId: stepCallId,
759
- name: "sleep",
760
- 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
+ )
761
1010
  },
762
- writableStream
1011
+ {
1012
+ paramName: "runCount",
1013
+ deprecationMessage: runCountDeprecationMessage,
1014
+ logger: this.logger
1015
+ }
763
1016
  )
764
- });
1017
+ );
765
1018
  });
766
1019
  sleepSpan?.update({
767
1020
  attributes: {
@@ -785,14 +1038,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
785
1038
  stepResults,
786
1039
  emitter,
787
1040
  abortController,
788
- runtimeContext,
1041
+ requestContext,
789
1042
  executionContext,
790
1043
  writableStream,
791
1044
  tracingContext
792
1045
  }) {
793
1046
  let { date, fn } = entry;
794
1047
  const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
795
- type: AISpanType.WORKFLOW_SLEEP,
1048
+ type: SpanType.WORKFLOW_SLEEP,
796
1049
  name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
797
1050
  attributes: {
798
1051
  untilDate: date,
@@ -804,45 +1057,53 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
804
1057
  if (fn) {
805
1058
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
806
1059
  const stepCallId = randomUUID();
807
- return await fn({
808
- runId,
809
- workflowId,
810
- mastra: this.mastra,
811
- runtimeContext,
812
- inputData: prevOutput,
813
- state: executionContext.state,
814
- setState: (state) => {
815
- executionContext.state = state;
816
- },
817
- runCount: -1,
818
- tracingContext: {
819
- currentSpan: sleepUntilSpan
820
- },
821
- getInitData: () => stepResults?.input,
822
- getStepResult: getStepResult.bind(this, stepResults),
823
- // TODO: this function shouldn't have suspend probably?
824
- suspend: async (_suspendPayload) => {
825
- },
826
- bail: () => {
827
- },
828
- abort: () => {
829
- abortController?.abort();
830
- },
831
- [EMITTER_SYMBOL]: emitter,
832
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
833
- // TODO: add streamVNext support
834
- engine: { step: this.inngestStep },
835
- abortSignal: abortController?.signal,
836
- writer: new ToolStream(
1060
+ return await fn(
1061
+ createDeprecationProxy(
837
1062
  {
838
- prefix: "workflow-step",
839
- callId: stepCallId,
840
- name: "sleep",
841
- 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
+ )
842
1099
  },
843
- writableStream
1100
+ {
1101
+ paramName: "runCount",
1102
+ deprecationMessage: runCountDeprecationMessage,
1103
+ logger: this.logger
1104
+ }
844
1105
  )
845
- });
1106
+ );
846
1107
  });
847
1108
  if (date && !(date instanceof Date)) {
848
1109
  date = new Date(date);
@@ -866,32 +1127,23 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
866
1127
  throw e;
867
1128
  }
868
1129
  }
869
- async executeWaitForEvent({ event, timeout }) {
870
- const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
871
- event: `user-event-${event}`,
872
- timeout: timeout ?? 5e3
873
- });
874
- if (eventData === null) {
875
- throw "Timeout waiting for event";
876
- }
877
- return eventData?.data;
878
- }
879
1130
  async executeStep({
880
1131
  step,
881
1132
  stepResults,
882
1133
  executionContext,
883
1134
  resume,
1135
+ timeTravel,
884
1136
  prevOutput,
885
1137
  emitter,
886
1138
  abortController,
887
- runtimeContext,
1139
+ requestContext,
888
1140
  tracingContext,
889
1141
  writableStream,
890
1142
  disableScorers
891
1143
  }) {
892
- const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
1144
+ const stepSpan = tracingContext?.currentSpan?.createChildSpan({
893
1145
  name: `workflow step: '${step.id}'`,
894
- type: AISpanType.WORKFLOW_STEP,
1146
+ type: SpanType.WORKFLOW_STEP,
895
1147
  input: prevOutput,
896
1148
  attributes: {
897
1149
  stepId: step.id
@@ -901,34 +1153,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
901
1153
  const { inputData, validationError } = await validateStepInput({
902
1154
  prevOutput,
903
1155
  step,
904
- validateInputs: this.options?.validateInputs ?? false
1156
+ validateInputs: this.options?.validateInputs ?? true
905
1157
  });
906
1158
  const startedAt = await this.inngestStep.run(
907
1159
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
908
1160
  async () => {
909
1161
  const startedAt2 = Date.now();
910
1162
  await emitter.emit("watch", {
911
- type: "watch",
912
- payload: {
913
- currentStep: {
914
- id: step.id,
915
- status: "running"
916
- },
917
- workflowState: {
918
- status: "running",
919
- steps: {
920
- ...stepResults,
921
- [step.id]: {
922
- status: "running"
923
- }
924
- },
925
- result: null,
926
- error: null
927
- }
928
- },
929
- eventTimestamp: Date.now()
930
- });
931
- await emitter.emit("watch-v2", {
932
1163
  type: "workflow-step-start",
933
1164
  payload: {
934
1165
  id: step.id,
@@ -944,9 +1175,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
944
1175
  const isResume = !!resume?.steps?.length;
945
1176
  let result;
946
1177
  let runId;
1178
+ const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
947
1179
  try {
948
1180
  if (isResume) {
949
- runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
1181
+ runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
950
1182
  const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
951
1183
  workflowName: step.id,
952
1184
  runId
@@ -962,8 +1194,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
962
1194
  steps: resume.steps.slice(1),
963
1195
  stepResults: snapshot?.context,
964
1196
  resumePayload: resume.resumePayload,
965
- // @ts-ignore
966
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
1197
+ resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
967
1198
  },
968
1199
  outputOptions: { includeState: true }
969
1200
  }
@@ -971,6 +1202,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
971
1202
  result = invokeResp.result;
972
1203
  runId = invokeResp.runId;
973
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;
974
1231
  } else {
975
1232
  const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
976
1233
  function: step.getFunction(),
@@ -1004,23 +1261,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1004
1261
  async () => {
1005
1262
  if (result.status === "failed") {
1006
1263
  await emitter.emit("watch", {
1007
- type: "watch",
1008
- payload: {
1009
- currentStep: {
1010
- id: step.id,
1011
- status: "failed",
1012
- error: result?.error
1013
- },
1014
- workflowState: {
1015
- status: "running",
1016
- steps: stepResults,
1017
- result: null,
1018
- error: null
1019
- }
1020
- },
1021
- eventTimestamp: Date.now()
1022
- });
1023
- await emitter.emit("watch-v2", {
1024
1264
  type: "workflow-step-result",
1025
1265
  payload: {
1026
1266
  id: step.id,
@@ -1039,27 +1279,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1039
1279
  const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
1040
1280
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1041
1281
  await emitter.emit("watch", {
1042
- type: "watch",
1043
- payload: {
1044
- currentStep: {
1045
- id: step.id,
1046
- status: "suspended",
1047
- payload: stepResult.payload,
1048
- suspendPayload: {
1049
- ...stepResult?.suspendPayload,
1050
- __workflow_meta: { runId, path: suspendPath }
1051
- }
1052
- },
1053
- workflowState: {
1054
- status: "running",
1055
- steps: stepResults,
1056
- result: null,
1057
- error: null
1058
- }
1059
- },
1060
- eventTimestamp: Date.now()
1061
- });
1062
- await emitter.emit("watch-v2", {
1063
1282
  type: "workflow-step-suspended",
1064
1283
  payload: {
1065
1284
  id: step.id,
@@ -1078,23 +1297,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1078
1297
  }
1079
1298
  };
1080
1299
  }
1081
- await emitter.emit("watch", {
1082
- type: "watch",
1083
- payload: {
1084
- currentStep: {
1085
- id: step.id,
1086
- status: "suspended",
1087
- payload: {}
1088
- },
1089
- workflowState: {
1090
- status: "running",
1091
- steps: stepResults,
1092
- result: null,
1093
- error: null
1094
- }
1095
- },
1096
- eventTimestamp: Date.now()
1097
- });
1098
1300
  return {
1099
1301
  executionContext,
1100
1302
  result: {
@@ -1104,23 +1306,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1104
1306
  };
1105
1307
  }
1106
1308
  await emitter.emit("watch", {
1107
- type: "watch",
1108
- payload: {
1109
- currentStep: {
1110
- id: step.id,
1111
- status: "success",
1112
- output: result?.result
1113
- },
1114
- workflowState: {
1115
- status: "running",
1116
- steps: stepResults,
1117
- result: null,
1118
- error: null
1119
- }
1120
- },
1121
- eventTimestamp: Date.now()
1122
- });
1123
- await emitter.emit("watch-v2", {
1124
1309
  type: "workflow-step-result",
1125
1310
  payload: {
1126
1311
  id: step.id,
@@ -1128,7 +1313,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1128
1313
  output: result?.result
1129
1314
  }
1130
1315
  });
1131
- await emitter.emit("watch-v2", {
1316
+ await emitter.emit("watch", {
1132
1317
  type: "workflow-step-finish",
1133
1318
  payload: {
1134
1319
  id: step.id,
@@ -1148,46 +1333,80 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1148
1333
  resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1149
1334
  };
1150
1335
  }
1336
+ const stepCallId = randomUUID();
1151
1337
  let stepRes;
1152
1338
  try {
1153
1339
  stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1154
1340
  let execResults;
1155
1341
  let suspended;
1156
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
1346
+ });
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;
1357
+ }
1157
1358
  try {
1158
1359
  if (validationError) {
1159
1360
  throw validationError;
1160
1361
  }
1362
+ const retryCount = this.getOrGenerateRetryCount(step.id);
1161
1363
  const result = await step.execute({
1162
1364
  runId: executionContext.runId,
1365
+ workflowId: executionContext.workflowId,
1163
1366
  mastra: this.mastra,
1164
- runtimeContext,
1165
- writableStream,
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
+ ),
1166
1378
  state: executionContext?.state ?? {},
1167
1379
  setState: (state) => {
1168
1380
  executionContext.state = state;
1169
1381
  },
1170
1382
  inputData,
1171
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1383
+ resumeData: resumeDataToUse,
1172
1384
  tracingContext: {
1173
- currentSpan: stepAISpan
1385
+ currentSpan: stepSpan
1174
1386
  },
1175
1387
  getInitData: () => stepResults?.input,
1176
1388
  getStepResult: getStepResult.bind(this, stepResults),
1177
- suspend: async (suspendPayload) => {
1389
+ suspend: async (suspendPayload, suspendOptions) => {
1178
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
+ }
1179
1400
  suspended = { payload: suspendPayload };
1180
1401
  },
1181
1402
  bail: (result2) => {
1182
1403
  bailed = { payload: result2 };
1183
1404
  },
1184
- resume: {
1185
- steps: resume?.steps?.slice(1) || [],
1186
- resumePayload: resume?.resumePayload,
1187
- // @ts-ignore
1188
- runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
1405
+ abort: () => {
1406
+ abortController?.abort();
1189
1407
  },
1190
1408
  [EMITTER_SYMBOL]: emitter,
1409
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1191
1410
  engine: {
1192
1411
  step: this.inngestStep
1193
1412
  },
@@ -1200,8 +1419,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1200
1419
  startedAt,
1201
1420
  endedAt,
1202
1421
  payload: inputData,
1203
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1204
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1422
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1423
+ resumePayload: resumeDataToUse
1205
1424
  };
1206
1425
  } catch (e) {
1207
1426
  const stepFailure = {
@@ -1210,12 +1429,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1210
1429
  error: e instanceof Error ? e.message : String(e),
1211
1430
  endedAt: Date.now(),
1212
1431
  startedAt,
1213
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1214
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1432
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1433
+ resumePayload: resumeDataToUse
1215
1434
  };
1216
1435
  execResults = stepFailure;
1217
1436
  const fallbackErrorMessage = `Step ${step.id} failed`;
1218
- stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1437
+ stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
1219
1438
  throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
1220
1439
  cause: execResults
1221
1440
  });
@@ -1224,11 +1443,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1224
1443
  execResults = {
1225
1444
  status: "suspended",
1226
1445
  suspendPayload: suspended.payload,
1446
+ ...execResults.output ? { suspendOutput: execResults.output } : {},
1227
1447
  payload: inputData,
1228
1448
  suspendedAt: Date.now(),
1229
1449
  startedAt,
1230
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1231
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1450
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1451
+ resumePayload: resumeDataToUse
1232
1452
  };
1233
1453
  } else if (bailed) {
1234
1454
  execResults = {
@@ -1239,24 +1459,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1239
1459
  startedAt
1240
1460
  };
1241
1461
  }
1242
- await emitter.emit("watch", {
1243
- type: "watch",
1244
- payload: {
1245
- currentStep: {
1246
- id: step.id,
1247
- ...execResults
1248
- },
1249
- workflowState: {
1250
- status: "running",
1251
- steps: { ...stepResults, [step.id]: execResults },
1252
- result: null,
1253
- error: null
1254
- }
1255
- },
1256
- eventTimestamp: Date.now()
1257
- });
1258
1462
  if (execResults.status === "suspended") {
1259
- await emitter.emit("watch-v2", {
1463
+ await emitter.emit("watch", {
1260
1464
  type: "workflow-step-suspended",
1261
1465
  payload: {
1262
1466
  id: step.id,
@@ -1264,14 +1468,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1264
1468
  }
1265
1469
  });
1266
1470
  } else {
1267
- await emitter.emit("watch-v2", {
1471
+ await emitter.emit("watch", {
1268
1472
  type: "workflow-step-result",
1269
1473
  payload: {
1270
1474
  id: step.id,
1271
1475
  ...execResults
1272
1476
  }
1273
1477
  });
1274
- await emitter.emit("watch-v2", {
1478
+ await emitter.emit("watch", {
1275
1479
  type: "workflow-step-finish",
1276
1480
  payload: {
1277
1481
  id: step.id,
@@ -1279,7 +1483,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1279
1483
  }
1280
1484
  });
1281
1485
  }
1282
- stepAISpan?.end({ output: execResults });
1486
+ stepSpan?.end({ output: execResults });
1283
1487
  return { result: execResults, executionContext, stepResults };
1284
1488
  });
1285
1489
  } catch (e) {
@@ -1309,15 +1513,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1309
1513
  output: stepRes.result,
1310
1514
  workflowId: executionContext.workflowId,
1311
1515
  stepId: step.id,
1312
- runtimeContext,
1516
+ requestContext,
1313
1517
  disableScorers,
1314
- tracingContext: { currentSpan: stepAISpan }
1518
+ tracingContext: { currentSpan: stepSpan }
1315
1519
  });
1316
1520
  }
1317
1521
  });
1318
1522
  }
1319
1523
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1320
- Object.assign(stepResults, stepRes.stepResults);
1321
1524
  executionContext.state = stepRes.executionContext.state;
1322
1525
  return stepRes.result;
1323
1526
  }
@@ -1345,16 +1548,17 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1345
1548
  resourceId,
1346
1549
  snapshot: {
1347
1550
  runId,
1551
+ status: workflowStatus,
1348
1552
  value: executionContext.state,
1349
1553
  context: stepResults,
1350
- activePaths: [],
1554
+ activePaths: executionContext.executionPath,
1555
+ activeStepsPath: executionContext.activeStepsPath,
1351
1556
  suspendedPaths: executionContext.suspendedPaths,
1557
+ resumeLabels: executionContext.resumeLabels,
1352
1558
  waitingPaths: {},
1353
1559
  serializedStepGraph,
1354
- status: workflowStatus,
1355
1560
  result,
1356
1561
  error,
1357
- // @ts-ignore
1358
1562
  timestamp: Date.now()
1359
1563
  }
1360
1564
  });
@@ -1366,20 +1570,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1366
1570
  runId,
1367
1571
  entry,
1368
1572
  prevOutput,
1369
- prevStep,
1370
1573
  stepResults,
1371
- serializedStepGraph,
1574
+ timeTravel,
1372
1575
  resume,
1373
1576
  executionContext,
1374
1577
  emitter,
1375
1578
  abortController,
1376
- runtimeContext,
1579
+ requestContext,
1377
1580
  writableStream,
1378
1581
  disableScorers,
1379
1582
  tracingContext
1380
1583
  }) {
1381
1584
  const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1382
- type: AISpanType.WORKFLOW_CONDITIONAL,
1585
+ type: SpanType.WORKFLOW_CONDITIONAL,
1383
1586
  name: `conditional: '${entry.conditions.length} conditions'`,
1384
1587
  input: prevOutput,
1385
1588
  attributes: {
@@ -1392,7 +1595,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1392
1595
  entry.conditions.map(
1393
1596
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1394
1597
  const evalSpan = conditionalSpan?.createChildSpan({
1395
- type: AISpanType.WORKFLOW_CONDITIONAL_EVAL,
1598
+ type: SpanType.WORKFLOW_CONDITIONAL_EVAL,
1396
1599
  name: `condition: '${index}'`,
1397
1600
  input: prevOutput,
1398
1601
  attributes: {
@@ -1401,47 +1604,55 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1401
1604
  tracingPolicy: this.options?.tracingPolicy
1402
1605
  });
1403
1606
  try {
1404
- const result = await cond({
1405
- runId,
1406
- workflowId,
1407
- mastra: this.mastra,
1408
- runtimeContext,
1409
- runCount: -1,
1410
- inputData: prevOutput,
1411
- state: executionContext.state,
1412
- setState: (state) => {
1413
- executionContext.state = state;
1414
- },
1415
- tracingContext: {
1416
- currentSpan: evalSpan
1417
- },
1418
- getInitData: () => stepResults?.input,
1419
- getStepResult: getStepResult.bind(this, stepResults),
1420
- // TODO: this function shouldn't have suspend probably?
1421
- suspend: async (_suspendPayload) => {
1422
- },
1423
- bail: () => {
1424
- },
1425
- abort: () => {
1426
- abortController.abort();
1427
- },
1428
- [EMITTER_SYMBOL]: emitter,
1429
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
1430
- // TODO: add streamVNext support
1431
- engine: {
1432
- step: this.inngestStep
1433
- },
1434
- abortSignal: abortController.signal,
1435
- writer: new ToolStream(
1607
+ const result = await cond(
1608
+ createDeprecationProxy(
1436
1609
  {
1437
- prefix: "workflow-step",
1438
- callId: randomUUID(),
1439
- name: "conditional",
1440
- 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
+ )
1441
1648
  },
1442
- writableStream
1649
+ {
1650
+ paramName: "runCount",
1651
+ deprecationMessage: runCountDeprecationMessage,
1652
+ logger: this.logger
1653
+ }
1443
1654
  )
1444
- });
1655
+ );
1445
1656
  evalSpan?.end({
1446
1657
  output: result,
1447
1658
  attributes: {
@@ -1469,47 +1680,58 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1469
1680
  }
1470
1681
  });
1471
1682
  const results = await Promise.all(
1472
- stepsToRun.map(
1473
- (step, index) => this.executeEntry({
1474
- workflowId,
1475
- runId,
1476
- entry: step,
1477
- serializedStepGraph,
1478
- 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,
1479
1691
  stepResults,
1480
1692
  resume,
1693
+ timeTravel,
1481
1694
  executionContext: {
1482
1695
  workflowId,
1483
1696
  runId,
1484
1697
  executionPath: [...executionContext.executionPath, index],
1698
+ activeStepsPath: executionContext.activeStepsPath,
1485
1699
  suspendedPaths: executionContext.suspendedPaths,
1700
+ resumeLabels: executionContext.resumeLabels,
1486
1701
  retryConfig: executionContext.retryConfig,
1487
- executionSpan: executionContext.executionSpan,
1488
1702
  state: executionContext.state
1489
1703
  },
1490
1704
  emitter,
1491
1705
  abortController,
1492
- runtimeContext,
1706
+ requestContext,
1493
1707
  writableStream,
1494
1708
  disableScorers,
1495
1709
  tracingContext: {
1496
1710
  currentSpan: conditionalSpan
1497
1711
  }
1498
- })
1499
- )
1712
+ });
1713
+ stepResults[step.step.id] = result;
1714
+ return result;
1715
+ })
1500
1716
  );
1501
- const hasFailed = results.find((result) => result.result.status === "failed");
1502
- 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");
1503
1719
  if (hasFailed) {
1504
- execResults = { status: "failed", error: hasFailed.result.error };
1720
+ execResults = { status: "failed", error: hasFailed.error };
1505
1721
  } else if (hasSuspended) {
1506
- execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
1722
+ execResults = {
1723
+ status: "suspended",
1724
+ suspendPayload: hasSuspended.suspendPayload,
1725
+ ...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
1726
+ };
1507
1727
  } else {
1508
1728
  execResults = {
1509
1729
  status: "success",
1510
1730
  output: results.reduce((acc, result, index) => {
1511
- if (result.result.status === "success") {
1512
- 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
+ }
1513
1735
  }
1514
1736
  return acc;
1515
1737
  }, {})