@mastra/inngest 0.0.0-remove-unused-model-providers-api-20251030210744 → 0.0.0-safe-stringify-telemetry-20251205024938

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
@@ -2,10 +2,10 @@ import { randomUUID } from 'crypto';
2
2
  import { ReadableStream } from 'stream/web';
3
3
  import { subscribe } from '@inngest/realtime';
4
4
  import { wrapMastra, AISpanType } from '@mastra/core/ai-tracing';
5
- import { RequestContext } from '@mastra/core/di';
5
+ import { RuntimeContext } from '@mastra/core/di';
6
6
  import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
7
7
  import { ToolStream, Tool } from '@mastra/core/tools';
8
- import { Run, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput } from '@mastra/core/workflows';
8
+ import { Run, createTimeTravelExecutionParams, Workflow, DefaultExecutionEngine, getStepResult, validateStepInput, validateStepResumeData } from '@mastra/core/workflows';
9
9
  import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
10
10
  import { NonRetriableError, RetryAfterError } from 'inngest';
11
11
  import { serve as serve$1 } from 'inngest/hono';
@@ -18,7 +18,7 @@ function serve({
18
18
  functions: userFunctions = [],
19
19
  registerOptions
20
20
  }) {
21
- const wfs = mastra.listWorkflows();
21
+ const wfs = mastra.getWorkflows();
22
22
  const workflowFunctions = Array.from(
23
23
  new Set(
24
24
  Object.values(wfs).flatMap((wf) => {
@@ -103,20 +103,15 @@ var InngestRun = class extends Run {
103
103
  resourceId: this.resourceId,
104
104
  snapshot: {
105
105
  ...snapshot,
106
- status: "canceled"
106
+ status: "canceled",
107
+ value: snapshot.value
107
108
  }
108
109
  });
109
110
  }
110
111
  }
111
- async start(params) {
112
- return this._start(params);
113
- }
114
- async _start({
112
+ async start({
115
113
  inputData,
116
- initialState,
117
- outputOptions,
118
- tracingOptions,
119
- format
114
+ initialState
120
115
  }) {
121
116
  await this.#mastra.getStorage()?.persistWorkflowSnapshot({
122
117
  workflowName: this.workflowId,
@@ -125,14 +120,15 @@ var InngestRun = class extends Run {
125
120
  snapshot: {
126
121
  runId: this.runId,
127
122
  serializedStepGraph: this.serializedStepGraph,
123
+ status: "running",
128
124
  value: {},
129
125
  context: {},
130
126
  activePaths: [],
131
127
  suspendedPaths: {},
128
+ activeStepsPath: {},
132
129
  resumeLabels: {},
133
130
  waitingPaths: {},
134
- timestamp: Date.now(),
135
- status: "running"
131
+ timestamp: Date.now()
136
132
  }
137
133
  });
138
134
  const inputDataToUse = await this._validateInput(inputData);
@@ -143,10 +139,7 @@ var InngestRun = class extends Run {
143
139
  inputData: inputDataToUse,
144
140
  initialState: initialStateToUse,
145
141
  runId: this.runId,
146
- resourceId: this.resourceId,
147
- outputOptions,
148
- tracingOptions,
149
- format
142
+ resourceId: this.resourceId
150
143
  }
151
144
  });
152
145
  const eventId = eventOutput.ids[0];
@@ -175,10 +168,16 @@ var InngestRun = class extends Run {
175
168
  return p;
176
169
  }
177
170
  async _resume(params) {
178
- const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
179
- (step) => typeof step === "string" ? step : step?.id
180
- );
181
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
171
+ const storage = this.#mastra?.getStorage();
172
+ let steps = [];
173
+ if (typeof params.step === "string") {
174
+ steps = params.step.split(".");
175
+ } else {
176
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
177
+ (step) => typeof step === "string" ? step : step?.id
178
+ );
179
+ }
180
+ const snapshot = await storage?.loadWorkflowSnapshot({
182
181
  workflowName: this.workflowId,
183
182
  runId: this.runId
184
183
  });
@@ -235,35 +234,111 @@ var InngestRun = class extends Run {
235
234
  });
236
235
  };
237
236
  }
238
- streamLegacy({ inputData, requestContext } = {}) {
237
+ async timeTravel(params) {
238
+ const p = this._timeTravel(params).then((result) => {
239
+ if (result.status !== "suspended") {
240
+ this.closeStreamAction?.().catch(() => {
241
+ });
242
+ }
243
+ return result;
244
+ });
245
+ this.executionResults = p;
246
+ return p;
247
+ }
248
+ async _timeTravel(params) {
249
+ if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
250
+ throw new Error("Step is required and must be a valid step or array of steps");
251
+ }
252
+ let steps = [];
253
+ if (typeof params.step === "string") {
254
+ steps = params.step.split(".");
255
+ } else {
256
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
257
+ (step) => typeof step === "string" ? step : step?.id
258
+ );
259
+ }
260
+ if (steps.length === 0) {
261
+ throw new Error("No steps provided to timeTravel");
262
+ }
263
+ const storage = this.#mastra?.getStorage();
264
+ const snapshot = await storage?.loadWorkflowSnapshot({
265
+ workflowName: this.workflowId,
266
+ runId: this.runId
267
+ });
268
+ if (!snapshot) {
269
+ await storage?.persistWorkflowSnapshot({
270
+ workflowName: this.workflowId,
271
+ runId: this.runId,
272
+ resourceId: this.resourceId,
273
+ snapshot: {
274
+ runId: this.runId,
275
+ serializedStepGraph: this.serializedStepGraph,
276
+ status: "pending",
277
+ value: {},
278
+ context: {},
279
+ activePaths: [],
280
+ suspendedPaths: {},
281
+ activeStepsPath: {},
282
+ resumeLabels: {},
283
+ waitingPaths: {},
284
+ timestamp: Date.now()
285
+ }
286
+ });
287
+ }
288
+ if (snapshot?.status === "running") {
289
+ throw new Error("This workflow run is still running, cannot time travel");
290
+ }
291
+ let inputDataToUse = params.inputData;
292
+ if (inputDataToUse && steps.length === 1) {
293
+ inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
294
+ }
295
+ const timeTravelData = createTimeTravelExecutionParams({
296
+ steps,
297
+ inputData: inputDataToUse,
298
+ resumeData: params.resumeData,
299
+ context: params.context,
300
+ nestedStepsContext: params.nestedStepsContext,
301
+ snapshot: snapshot ?? { context: {} },
302
+ graph: this.executionGraph,
303
+ initialState: params.initialState
304
+ });
305
+ const eventOutput = await this.inngest.send({
306
+ name: `workflow.${this.workflowId}`,
307
+ data: {
308
+ initialState: timeTravelData.state,
309
+ runId: this.runId,
310
+ workflowId: this.workflowId,
311
+ stepResults: timeTravelData.stepResults,
312
+ timeTravel: timeTravelData,
313
+ tracingOptions: params.tracingOptions,
314
+ outputOptions: params.outputOptions
315
+ }
316
+ });
317
+ const eventId = eventOutput.ids[0];
318
+ if (!eventId) {
319
+ throw new Error("Event ID is not set");
320
+ }
321
+ const runOutput = await this.getRunOutput(eventId);
322
+ const result = runOutput?.output?.result;
323
+ if (result.status === "failed") {
324
+ result.error = new Error(result.error);
325
+ }
326
+ return result;
327
+ }
328
+ streamLegacy({ inputData, runtimeContext } = {}) {
239
329
  const { readable, writable } = new TransformStream();
240
330
  const writer = writable.getWriter();
241
331
  const unwatch = this.watch(async (event) => {
242
332
  try {
243
- await writer.write({
244
- // @ts-ignore
245
- type: "start",
246
- // @ts-ignore
247
- payload: { runId: this.runId }
248
- });
249
333
  const e = {
250
334
  ...event,
251
335
  type: event.type.replace("workflow-", "")
252
336
  };
253
- if (e.type === "step-output") {
254
- e.type = e.payload.output.type;
255
- e.payload = e.payload.output.payload;
256
- }
257
337
  await writer.write(e);
258
338
  } catch {
259
339
  }
260
340
  }, "watch-v2");
261
341
  this.closeStreamAction = async () => {
262
- await writer.write({
263
- type: "finish",
264
- // @ts-ignore
265
- payload: { runId: this.runId }
266
- });
267
342
  unwatch();
268
343
  try {
269
344
  await writer.close();
@@ -273,7 +348,7 @@ var InngestRun = class extends Run {
273
348
  writer.releaseLock();
274
349
  }
275
350
  };
276
- this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
351
+ this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
277
352
  if (result.status !== "suspended") {
278
353
  this.closeStreamAction?.().catch(() => {
279
354
  });
@@ -287,18 +362,69 @@ var InngestRun = class extends Run {
287
362
  }
288
363
  stream({
289
364
  inputData,
290
- requestContext,
291
- tracingOptions,
292
- closeOnSuspend = true,
365
+ runtimeContext,
366
+ closeOnSuspend = true
367
+ } = {}) {
368
+ const self = this;
369
+ let streamOutput;
370
+ const stream = new ReadableStream({
371
+ async start(controller) {
372
+ const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
373
+ controller.enqueue({
374
+ type,
375
+ runId: self.runId,
376
+ from,
377
+ payload: {
378
+ stepName: payload.id,
379
+ ...payload
380
+ }
381
+ });
382
+ }, "watch-v2");
383
+ self.closeStreamAction = async () => {
384
+ unwatch();
385
+ try {
386
+ await controller.close();
387
+ } catch (err) {
388
+ console.error("Error closing stream:", err);
389
+ }
390
+ };
391
+ const executionResultsPromise = self.start({
392
+ inputData,
393
+ runtimeContext
394
+ });
395
+ const executionResults = await executionResultsPromise;
396
+ if (closeOnSuspend) {
397
+ self.closeStreamAction?.().catch(() => {
398
+ });
399
+ } else if (executionResults.status !== "suspended") {
400
+ self.closeStreamAction?.().catch(() => {
401
+ });
402
+ }
403
+ if (streamOutput) {
404
+ streamOutput.updateResults(executionResults);
405
+ }
406
+ }
407
+ });
408
+ streamOutput = new WorkflowRunOutput({
409
+ runId: this.runId,
410
+ workflowId: this.workflowId,
411
+ stream
412
+ });
413
+ return streamOutput;
414
+ }
415
+ timeTravelStream({
416
+ inputData,
417
+ resumeData,
293
418
  initialState,
419
+ step,
420
+ context,
421
+ nestedStepsContext,
422
+ runtimeContext,
423
+ tracingOptions,
294
424
  outputOptions
295
- } = {}) {
296
- if (this.closeStreamAction && this.streamOutput) {
297
- return this.streamOutput;
298
- }
299
- this.closeStreamAction = async () => {
300
- };
425
+ }) {
301
426
  const self = this;
427
+ let streamOutput;
302
428
  const stream = new ReadableStream({
303
429
  async start(controller) {
304
430
  const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
@@ -320,46 +446,39 @@ var InngestRun = class extends Run {
320
446
  console.error("Error closing stream:", err);
321
447
  }
322
448
  };
323
- const executionResultsPromise = self._start({
449
+ const executionResultsPromise = self._timeTravel({
324
450
  inputData,
325
- requestContext,
326
- // tracingContext, // We are not able to pass a reference to a span here, what to do?
451
+ step,
452
+ context,
453
+ nestedStepsContext,
454
+ resumeData,
327
455
  initialState,
456
+ runtimeContext,
328
457
  tracingOptions,
329
- outputOptions,
330
- format: "vnext"
458
+ outputOptions
331
459
  });
460
+ self.executionResults = executionResultsPromise;
332
461
  let executionResults;
333
462
  try {
334
463
  executionResults = await executionResultsPromise;
335
- if (closeOnSuspend) {
336
- self.closeStreamAction?.().catch(() => {
337
- });
338
- } else if (executionResults.status !== "suspended") {
339
- self.closeStreamAction?.().catch(() => {
340
- });
341
- }
342
- if (self.streamOutput) {
343
- self.streamOutput.updateResults(
344
- executionResults
345
- );
464
+ self.closeStreamAction?.().catch(() => {
465
+ });
466
+ if (streamOutput) {
467
+ streamOutput.updateResults(executionResults);
346
468
  }
347
469
  } catch (err) {
348
- self.streamOutput?.rejectResults(err);
470
+ streamOutput?.rejectResults(err);
349
471
  self.closeStreamAction?.().catch(() => {
350
472
  });
351
473
  }
352
474
  }
353
475
  });
354
- this.streamOutput = new WorkflowRunOutput({
476
+ streamOutput = new WorkflowRunOutput({
355
477
  runId: this.runId,
356
478
  workflowId: this.workflowId,
357
479
  stream
358
480
  });
359
- return this.streamOutput;
360
- }
361
- streamVNext(args = {}) {
362
- return this.stream(args);
481
+ return streamOutput;
363
482
  }
364
483
  };
365
484
  var InngestWorkflow = class _InngestWorkflow extends Workflow {
@@ -370,6 +489,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
370
489
  constructor(params, inngest) {
371
490
  const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
372
491
  super(workflowParams);
492
+ this.engineType = "inngest";
373
493
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
374
494
  ([_, value]) => value !== void 0
375
495
  );
@@ -377,13 +497,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
377
497
  this.#mastra = params.mastra;
378
498
  this.inngest = inngest;
379
499
  }
380
- async listWorkflowRuns(args) {
500
+ async getWorkflowRuns(args) {
381
501
  const storage = this.#mastra?.getStorage();
382
502
  if (!storage) {
383
503
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
384
504
  return { runs: [], total: 0 };
385
505
  }
386
- return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
506
+ return storage.getWorkflowRuns({ workflowName: this.id, ...args ?? {} });
387
507
  }
388
508
  async getWorkflowRunById(runId) {
389
509
  const storage = this.#mastra?.getStorage();
@@ -434,7 +554,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
434
554
  mastra: this.#mastra,
435
555
  retryConfig: this.retryConfig,
436
556
  cleanup: () => this.runs.delete(runIdToUse),
437
- workflowSteps: this.steps
557
+ workflowSteps: this.steps,
558
+ workflowEngineType: this.engineType,
559
+ validateInputs: this.options.validateInputs
438
560
  },
439
561
  this.inngest
440
562
  );
@@ -455,6 +577,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
455
577
  value: {},
456
578
  context: {},
457
579
  activePaths: [],
580
+ activeStepsPath: {},
458
581
  waitingPaths: {},
459
582
  serializedStepGraph: this.serializedStepGraph,
460
583
  suspendedPaths: {},
@@ -483,7 +606,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
483
606
  },
484
607
  { event: `workflow.${this.id}` },
485
608
  async ({ event, step, attempt, publish }) => {
486
- let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
609
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, timeTravel } = event.data;
487
610
  if (!runId) {
488
611
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
489
612
  return randomUUID();
@@ -522,19 +645,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
522
645
  initialState,
523
646
  emitter,
524
647
  retryConfig: this.retryConfig,
525
- requestContext: new RequestContext(),
648
+ runtimeContext: new RuntimeContext(),
526
649
  // TODO
527
650
  resume,
528
- format,
651
+ timeTravel,
529
652
  abortController: new AbortController(),
530
- // currentSpan: undefined, // TODO: Pass actual parent AI span from workflow execution context
531
- outputOptions,
532
- writableStream: new WritableStream({
533
- write(chunk) {
534
- void emitter.emit("watch-v2", chunk).catch(() => {
535
- });
536
- }
537
- })
653
+ currentSpan: void 0,
654
+ // TODO: Pass actual parent AI span from workflow execution context
655
+ outputOptions
538
656
  });
539
657
  await step.run(`workflow.${this.id}.finalize`, async () => {
540
658
  if (result.status === "failed") {
@@ -572,7 +690,7 @@ function isAgent(params) {
572
690
  function isTool(params) {
573
691
  return params instanceof Tool;
574
692
  }
575
- function createStep(params, agentOptions) {
693
+ function createStep(params) {
576
694
  if (isAgent(params)) {
577
695
  return {
578
696
  id: params.name,
@@ -580,23 +698,12 @@ function createStep(params, agentOptions) {
580
698
  // @ts-ignore
581
699
  inputSchema: z.object({
582
700
  prompt: z.string()
583
- // resourceId: z.string().optional(),
584
- // threadId: z.string().optional(),
585
701
  }),
586
702
  // @ts-ignore
587
703
  outputSchema: z.object({
588
704
  text: z.string()
589
705
  }),
590
- execute: async ({
591
- inputData,
592
- [EMITTER_SYMBOL]: emitter,
593
- [STREAM_FORMAT_SYMBOL]: streamFormat,
594
- requestContext,
595
- tracingContext,
596
- abortSignal,
597
- abort,
598
- writer
599
- }) => {
706
+ execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
600
707
  let streamPromise = {};
601
708
  streamPromise.promise = new Promise((resolve, reject) => {
602
709
  streamPromise.resolve = resolve;
@@ -606,40 +713,48 @@ function createStep(params, agentOptions) {
606
713
  name: params.name,
607
714
  args: inputData
608
715
  };
609
- let stream;
610
- if ((await params.getModel()).specificationVersion === "v1") {
611
- const { fullStream } = await params.streamLegacy(inputData.prompt, {
612
- ...agentOptions ?? {},
613
- // resourceId: inputData.resourceId,
614
- // threadId: inputData.threadId,
615
- requestContext,
716
+ if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
717
+ const { fullStream } = await params.stream(inputData.prompt, {
718
+ runtimeContext,
616
719
  tracingContext,
617
720
  onFinish: (result) => {
618
721
  streamPromise.resolve(result.text);
619
- void agentOptions?.onFinish?.(result);
620
722
  },
621
723
  abortSignal
622
724
  });
623
- stream = fullStream;
725
+ if (abortSignal.aborted) {
726
+ return abort();
727
+ }
728
+ await emitter.emit("watch-v2", {
729
+ type: "tool-call-streaming-start",
730
+ ...toolData ?? {}
731
+ });
732
+ for await (const chunk of fullStream) {
733
+ if (chunk.type === "text-delta") {
734
+ await emitter.emit("watch-v2", {
735
+ type: "tool-call-delta",
736
+ ...toolData ?? {},
737
+ argsTextDelta: chunk.payload.text
738
+ });
739
+ }
740
+ }
624
741
  } else {
625
- const modelOutput = await params.stream(inputData.prompt, {
626
- ...agentOptions ?? {},
627
- requestContext,
742
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
743
+ runtimeContext,
628
744
  tracingContext,
629
745
  onFinish: (result) => {
630
746
  streamPromise.resolve(result.text);
631
- void agentOptions?.onFinish?.(result);
632
747
  },
633
748
  abortSignal
634
749
  });
635
- stream = modelOutput.fullStream;
636
- }
637
- if (streamFormat === "legacy") {
750
+ if (abortSignal.aborted) {
751
+ return abort();
752
+ }
638
753
  await emitter.emit("watch-v2", {
639
754
  type: "tool-call-streaming-start",
640
755
  ...toolData ?? {}
641
756
  });
642
- for await (const chunk of stream) {
757
+ for await (const chunk of fullStream) {
643
758
  if (chunk.type === "text-delta") {
644
759
  await emitter.emit("watch-v2", {
645
760
  type: "tool-call-delta",
@@ -648,18 +763,11 @@ function createStep(params, agentOptions) {
648
763
  });
649
764
  }
650
765
  }
651
- await emitter.emit("watch-v2", {
652
- type: "tool-call-streaming-finish",
653
- ...toolData ?? {}
654
- });
655
- } else {
656
- for await (const chunk of stream) {
657
- await writer.write(chunk);
658
- }
659
- }
660
- if (abortSignal.aborted) {
661
- return abort();
662
766
  }
767
+ await emitter.emit("watch-v2", {
768
+ type: "tool-call-streaming-finish",
769
+ ...toolData ?? {}
770
+ });
663
771
  return {
664
772
  text: await streamPromise.promise
665
773
  };
@@ -678,11 +786,11 @@ function createStep(params, agentOptions) {
678
786
  description: params.description,
679
787
  inputSchema: params.inputSchema,
680
788
  outputSchema: params.outputSchema,
681
- execute: async ({ inputData, mastra, requestContext, tracingContext, suspend, resumeData }) => {
789
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
682
790
  return params.execute({
683
791
  context: inputData,
684
792
  mastra: wrapMastra(mastra, tracingContext),
685
- requestContext,
793
+ runtimeContext,
686
794
  tracingContext,
687
795
  suspend,
688
796
  resumeData
@@ -745,7 +853,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
745
853
  this.inngestStep = inngestStep;
746
854
  this.inngestAttempts = inngestAttempts;
747
855
  }
748
- async fmtReturnValue(emitter, stepResults, lastOutput, error) {
856
+ async execute(params) {
857
+ await params.emitter.emit("watch-v2", {
858
+ type: "workflow-start",
859
+ payload: { runId: params.runId }
860
+ });
861
+ const result = await super.execute(params);
862
+ await params.emitter.emit("watch-v2", {
863
+ type: "workflow-finish",
864
+ payload: { runId: params.runId }
865
+ });
866
+ return result;
867
+ }
868
+ async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
749
869
  const base = {
750
870
  status: lastOutput.status,
751
871
  steps: stepResults
@@ -799,6 +919,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
799
919
  });
800
920
  base.suspended = suspendedStepIds;
801
921
  }
922
+ executionSpan?.end();
802
923
  return base;
803
924
  }
804
925
  // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
@@ -812,7 +933,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
812
933
  stepResults,
813
934
  emitter,
814
935
  abortController,
815
- requestContext,
936
+ runtimeContext,
816
937
  executionContext,
817
938
  writableStream,
818
939
  tracingContext
@@ -830,54 +951,45 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
830
951
  if (fn) {
831
952
  const stepCallId = randomUUID();
832
953
  duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
833
- return await fn(
834
- createDeprecationProxy(
954
+ return await fn({
955
+ runId,
956
+ workflowId,
957
+ mastra: this.mastra,
958
+ runtimeContext,
959
+ inputData: prevOutput,
960
+ state: executionContext.state,
961
+ setState: (state) => {
962
+ executionContext.state = state;
963
+ },
964
+ runCount: -1,
965
+ tracingContext: {
966
+ currentSpan: sleepSpan
967
+ },
968
+ getInitData: () => stepResults?.input,
969
+ getStepResult: getStepResult.bind(this, stepResults),
970
+ // TODO: this function shouldn't have suspend probably?
971
+ suspend: async (_suspendPayload) => {
972
+ },
973
+ bail: () => {
974
+ },
975
+ abort: () => {
976
+ abortController?.abort();
977
+ },
978
+ [EMITTER_SYMBOL]: emitter,
979
+ // TODO: add streamVNext support
980
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
981
+ engine: { step: this.inngestStep },
982
+ abortSignal: abortController?.signal,
983
+ writer: new ToolStream(
835
984
  {
836
- runId,
837
- workflowId,
838
- mastra: this.mastra,
839
- requestContext,
840
- inputData: prevOutput,
841
- state: executionContext.state,
842
- setState: (state) => {
843
- executionContext.state = state;
844
- },
845
- runCount: -1,
846
- retryCount: -1,
847
- tracingContext: {
848
- currentSpan: sleepSpan
849
- },
850
- getInitData: () => stepResults?.input,
851
- getStepResult: getStepResult.bind(this, stepResults),
852
- // TODO: this function shouldn't have suspend probably?
853
- suspend: async (_suspendPayload) => {
854
- },
855
- bail: () => {
856
- },
857
- abort: () => {
858
- abortController?.abort();
859
- },
860
- [EMITTER_SYMBOL]: emitter,
861
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
862
- engine: { step: this.inngestStep },
863
- abortSignal: abortController?.signal,
864
- writer: new ToolStream(
865
- {
866
- prefix: "workflow-step",
867
- callId: stepCallId,
868
- name: "sleep",
869
- runId
870
- },
871
- writableStream
872
- )
985
+ prefix: "workflow-step",
986
+ callId: stepCallId,
987
+ name: "sleep",
988
+ runId
873
989
  },
874
- {
875
- paramName: "runCount",
876
- deprecationMessage: runCountDeprecationMessage,
877
- logger: this.logger
878
- }
990
+ writableStream
879
991
  )
880
- );
992
+ });
881
993
  });
882
994
  sleepSpan?.update({
883
995
  attributes: {
@@ -901,7 +1013,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
901
1013
  stepResults,
902
1014
  emitter,
903
1015
  abortController,
904
- requestContext,
1016
+ runtimeContext,
905
1017
  executionContext,
906
1018
  writableStream,
907
1019
  tracingContext
@@ -920,54 +1032,45 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
920
1032
  if (fn) {
921
1033
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
922
1034
  const stepCallId = randomUUID();
923
- return await fn(
924
- createDeprecationProxy(
1035
+ return await fn({
1036
+ runId,
1037
+ workflowId,
1038
+ mastra: this.mastra,
1039
+ runtimeContext,
1040
+ inputData: prevOutput,
1041
+ state: executionContext.state,
1042
+ setState: (state) => {
1043
+ executionContext.state = state;
1044
+ },
1045
+ runCount: -1,
1046
+ tracingContext: {
1047
+ currentSpan: sleepUntilSpan
1048
+ },
1049
+ getInitData: () => stepResults?.input,
1050
+ getStepResult: getStepResult.bind(this, stepResults),
1051
+ // TODO: this function shouldn't have suspend probably?
1052
+ suspend: async (_suspendPayload) => {
1053
+ },
1054
+ bail: () => {
1055
+ },
1056
+ abort: () => {
1057
+ abortController?.abort();
1058
+ },
1059
+ [EMITTER_SYMBOL]: emitter,
1060
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1061
+ // TODO: add streamVNext support
1062
+ engine: { step: this.inngestStep },
1063
+ abortSignal: abortController?.signal,
1064
+ writer: new ToolStream(
925
1065
  {
926
- runId,
927
- workflowId,
928
- mastra: this.mastra,
929
- requestContext,
930
- inputData: prevOutput,
931
- state: executionContext.state,
932
- setState: (state) => {
933
- executionContext.state = state;
934
- },
935
- runCount: -1,
936
- retryCount: -1,
937
- tracingContext: {
938
- currentSpan: sleepUntilSpan
939
- },
940
- getInitData: () => stepResults?.input,
941
- getStepResult: getStepResult.bind(this, stepResults),
942
- // TODO: this function shouldn't have suspend probably?
943
- suspend: async (_suspendPayload) => {
944
- },
945
- bail: () => {
946
- },
947
- abort: () => {
948
- abortController?.abort();
949
- },
950
- [EMITTER_SYMBOL]: emitter,
951
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
952
- engine: { step: this.inngestStep },
953
- abortSignal: abortController?.signal,
954
- writer: new ToolStream(
955
- {
956
- prefix: "workflow-step",
957
- callId: stepCallId,
958
- name: "sleep",
959
- runId
960
- },
961
- writableStream
962
- )
1066
+ prefix: "workflow-step",
1067
+ callId: stepCallId,
1068
+ name: "sleep",
1069
+ runId
963
1070
  },
964
- {
965
- paramName: "runCount",
966
- deprecationMessage: runCountDeprecationMessage,
967
- logger: this.logger
968
- }
1071
+ writableStream
969
1072
  )
970
- );
1073
+ });
971
1074
  });
972
1075
  if (date && !(date instanceof Date)) {
973
1076
  date = new Date(date);
@@ -1006,10 +1109,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1006
1109
  stepResults,
1007
1110
  executionContext,
1008
1111
  resume,
1112
+ timeTravel,
1009
1113
  prevOutput,
1010
1114
  emitter,
1011
1115
  abortController,
1012
- requestContext,
1116
+ runtimeContext,
1013
1117
  tracingContext,
1014
1118
  writableStream,
1015
1119
  disableScorers
@@ -1069,6 +1173,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1069
1173
  const isResume = !!resume?.steps?.length;
1070
1174
  let result;
1071
1175
  let runId;
1176
+ const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
1072
1177
  try {
1073
1178
  if (isResume) {
1074
1179
  runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
@@ -1096,6 +1201,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1096
1201
  result = invokeResp.result;
1097
1202
  runId = invokeResp.runId;
1098
1203
  executionContext.state = invokeResp.result.state;
1204
+ } else if (isTimeTravel) {
1205
+ const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
1206
+ workflowName: step.id,
1207
+ runId: executionContext.runId
1208
+ }) ?? { context: {} };
1209
+ const timeTravelParams = createTimeTravelExecutionParams({
1210
+ steps: timeTravel.steps.slice(1),
1211
+ inputData: timeTravel.inputData,
1212
+ resumeData: timeTravel.resumeData,
1213
+ context: timeTravel.nestedStepResults?.[step.id] ?? {},
1214
+ nestedStepsContext: timeTravel.nestedStepResults ?? {},
1215
+ snapshot,
1216
+ graph: step.buildExecutionGraph()
1217
+ });
1218
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1219
+ function: step.getFunction(),
1220
+ data: {
1221
+ timeTravel: timeTravelParams,
1222
+ initialState: executionContext.state ?? {},
1223
+ runId: executionContext.runId,
1224
+ outputOptions: { includeState: true }
1225
+ }
1226
+ });
1227
+ result = invokeResp.result;
1228
+ runId = invokeResp.runId;
1229
+ executionContext.state = invokeResp.result.state;
1099
1230
  } else {
1100
1231
  const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
1101
1232
  function: step.getFunction(),
@@ -1156,12 +1287,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1156
1287
  });
1157
1288
  return { executionContext, result: { status: "failed", error: result?.error } };
1158
1289
  } else if (result.status === "suspended") {
1159
- const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
1160
- const stepRes2 = stepResult;
1290
+ const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult2]) => {
1291
+ const stepRes2 = stepResult2;
1161
1292
  return stepRes2?.status === "suspended";
1162
1293
  });
1163
- for (const [stepName, stepResult] of suspendedSteps) {
1164
- const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
1294
+ for (const [stepName, stepResult2] of suspendedSteps) {
1295
+ const suspendPath = [stepName, ...stepResult2?.suspendPayload?.__workflow_meta?.path ?? []];
1165
1296
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1166
1297
  await emitter.emit("watch", {
1167
1298
  type: "watch",
@@ -1169,9 +1300,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1169
1300
  currentStep: {
1170
1301
  id: step.id,
1171
1302
  status: "suspended",
1172
- payload: stepResult.payload,
1303
+ payload: stepResult2.payload,
1173
1304
  suspendPayload: {
1174
- ...stepResult?.suspendPayload,
1305
+ ...stepResult2?.suspendPayload,
1175
1306
  __workflow_meta: { runId, path: suspendPath }
1176
1307
  }
1177
1308
  },
@@ -1195,9 +1326,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1195
1326
  executionContext,
1196
1327
  result: {
1197
1328
  status: "suspended",
1198
- payload: stepResult.payload,
1329
+ payload: stepResult2.payload,
1199
1330
  suspendPayload: {
1200
- ...stepResult?.suspendPayload,
1331
+ ...stepResult2?.suspendPayload,
1201
1332
  __workflow_meta: { runId, path: suspendPath }
1202
1333
  }
1203
1334
  }
@@ -1264,7 +1395,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1264
1395
  }
1265
1396
  );
1266
1397
  Object.assign(executionContext, res.executionContext);
1267
- return {
1398
+ const stepResult = {
1268
1399
  ...res.result,
1269
1400
  startedAt,
1270
1401
  endedAt: Date.now(),
@@ -1272,14 +1403,29 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1272
1403
  resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1273
1404
  resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1274
1405
  };
1406
+ return { result: stepResult, executionContextState: executionContext.state };
1275
1407
  }
1276
- const stepCallId = randomUUID();
1277
1408
  let stepRes;
1278
1409
  try {
1279
1410
  stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
1280
1411
  let execResults;
1281
1412
  let suspended;
1282
1413
  let bailed;
1414
+ const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await validateStepResumeData({
1415
+ resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
1416
+ step
1417
+ });
1418
+ let resumeDataToUse;
1419
+ if (timeTravelResumeData && !timeTravelResumeValidationError) {
1420
+ resumeDataToUse = timeTravelResumeData;
1421
+ } else if (timeTravelResumeData && timeTravelResumeValidationError) {
1422
+ this.logger.warn("Time travel resume data validation failed", {
1423
+ stepId: step.id,
1424
+ error: timeTravelResumeValidationError.message
1425
+ });
1426
+ } else if (resume?.steps[0] === step.id) {
1427
+ resumeDataToUse = resume?.resumePayload;
1428
+ }
1283
1429
  try {
1284
1430
  if (validationError) {
1285
1431
  throw validationError;
@@ -1287,22 +1433,14 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1287
1433
  const result = await step.execute({
1288
1434
  runId: executionContext.runId,
1289
1435
  mastra: this.mastra,
1290
- requestContext,
1291
- writer: new ToolStream(
1292
- {
1293
- prefix: "workflow-step",
1294
- callId: stepCallId,
1295
- name: step.id,
1296
- runId: executionContext.runId
1297
- },
1298
- writableStream
1299
- ),
1436
+ runtimeContext,
1437
+ writableStream,
1300
1438
  state: executionContext?.state ?? {},
1301
1439
  setState: (state) => {
1302
1440
  executionContext.state = state;
1303
1441
  },
1304
1442
  inputData,
1305
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1443
+ resumeData: resumeDataToUse,
1306
1444
  tracingContext: {
1307
1445
  currentSpan: stepAISpan
1308
1446
  },
@@ -1331,7 +1469,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1331
1469
  runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
1332
1470
  },
1333
1471
  [EMITTER_SYMBOL]: emitter,
1334
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
1335
1472
  engine: {
1336
1473
  step: this.inngestStep
1337
1474
  },
@@ -1344,18 +1481,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1344
1481
  startedAt,
1345
1482
  endedAt,
1346
1483
  payload: inputData,
1347
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1348
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1484
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1485
+ resumePayload: resumeDataToUse
1349
1486
  };
1350
1487
  } catch (e) {
1351
1488
  const stepFailure = {
1352
1489
  status: "failed",
1353
1490
  payload: inputData,
1354
- error: e instanceof Error ? e.message : String(e),
1491
+ error: e instanceof Error ? e.stack ?? e.message : String(e),
1355
1492
  endedAt: Date.now(),
1356
1493
  startedAt,
1357
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1358
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1494
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1495
+ resumePayload: resumeDataToUse
1359
1496
  };
1360
1497
  execResults = stepFailure;
1361
1498
  const fallbackErrorMessage = `Step ${step.id} failed`;
@@ -1371,8 +1508,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1371
1508
  payload: inputData,
1372
1509
  suspendedAt: Date.now(),
1373
1510
  startedAt,
1374
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1375
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1511
+ resumedAt: resumeDataToUse ? startedAt : void 0,
1512
+ resumePayload: resumeDataToUse
1376
1513
  };
1377
1514
  } else if (bailed) {
1378
1515
  execResults = {
@@ -1429,11 +1566,25 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1429
1566
  } catch (e) {
1430
1567
  const stepFailure = e instanceof Error ? e?.cause : {
1431
1568
  status: "failed",
1432
- error: e instanceof Error ? e.message : String(e),
1569
+ error: e instanceof Error ? e.stack ?? e.message : String(e),
1433
1570
  payload: inputData,
1434
1571
  startedAt,
1435
1572
  endedAt: Date.now()
1436
1573
  };
1574
+ await emitter.emit("watch-v2", {
1575
+ type: "workflow-step-result",
1576
+ payload: {
1577
+ id: step.id,
1578
+ ...stepFailure
1579
+ }
1580
+ });
1581
+ await emitter.emit("watch-v2", {
1582
+ type: "workflow-step-finish",
1583
+ payload: {
1584
+ id: step.id,
1585
+ metadata: {}
1586
+ }
1587
+ });
1437
1588
  stepRes = {
1438
1589
  result: stepFailure,
1439
1590
  executionContext,
@@ -1453,7 +1604,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1453
1604
  output: stepRes.result,
1454
1605
  workflowId: executionContext.workflowId,
1455
1606
  stepId: step.id,
1456
- requestContext,
1607
+ runtimeContext,
1457
1608
  disableScorers,
1458
1609
  tracingContext: { currentSpan: stepAISpan }
1459
1610
  });
@@ -1461,9 +1612,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1461
1612
  });
1462
1613
  }
1463
1614
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1464
- Object.assign(stepResults, stepRes.stepResults);
1465
1615
  executionContext.state = stepRes.executionContext.state;
1466
- return stepRes.result;
1616
+ return {
1617
+ result: stepRes.result,
1618
+ executionContextState: stepRes.executionContext.state
1619
+ };
1467
1620
  }
1468
1621
  async persistStepUpdate({
1469
1622
  workflowId,
@@ -1489,14 +1642,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1489
1642
  resourceId,
1490
1643
  snapshot: {
1491
1644
  runId,
1645
+ status: workflowStatus,
1492
1646
  value: executionContext.state,
1493
1647
  context: stepResults,
1494
- activePaths: [],
1648
+ activePaths: executionContext.executionPath,
1649
+ activeStepsPath: executionContext.activeStepsPath,
1495
1650
  suspendedPaths: executionContext.suspendedPaths,
1496
1651
  resumeLabels: executionContext.resumeLabels,
1497
1652
  waitingPaths: {},
1498
1653
  serializedStepGraph,
1499
- status: workflowStatus,
1500
1654
  result,
1501
1655
  error,
1502
1656
  // @ts-ignore
@@ -1512,11 +1666,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1512
1666
  entry,
1513
1667
  prevOutput,
1514
1668
  stepResults,
1669
+ timeTravel,
1515
1670
  resume,
1516
1671
  executionContext,
1517
1672
  emitter,
1518
1673
  abortController,
1519
- requestContext,
1674
+ runtimeContext,
1520
1675
  writableStream,
1521
1676
  disableScorers,
1522
1677
  tracingContext
@@ -1544,56 +1699,47 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1544
1699
  tracingPolicy: this.options?.tracingPolicy
1545
1700
  });
1546
1701
  try {
1547
- const result = await cond(
1548
- createDeprecationProxy(
1702
+ const result = await cond({
1703
+ runId,
1704
+ workflowId,
1705
+ mastra: this.mastra,
1706
+ runtimeContext,
1707
+ runCount: -1,
1708
+ inputData: prevOutput,
1709
+ state: executionContext.state,
1710
+ setState: (state) => {
1711
+ executionContext.state = state;
1712
+ },
1713
+ tracingContext: {
1714
+ currentSpan: evalSpan
1715
+ },
1716
+ getInitData: () => stepResults?.input,
1717
+ getStepResult: getStepResult.bind(this, stepResults),
1718
+ // TODO: this function shouldn't have suspend probably?
1719
+ suspend: async (_suspendPayload) => {
1720
+ },
1721
+ bail: () => {
1722
+ },
1723
+ abort: () => {
1724
+ abortController.abort();
1725
+ },
1726
+ [EMITTER_SYMBOL]: emitter,
1727
+ [STREAM_FORMAT_SYMBOL]: executionContext.format,
1728
+ // TODO: add streamVNext support
1729
+ engine: {
1730
+ step: this.inngestStep
1731
+ },
1732
+ abortSignal: abortController.signal,
1733
+ writer: new ToolStream(
1549
1734
  {
1550
- runId,
1551
- workflowId,
1552
- mastra: this.mastra,
1553
- requestContext,
1554
- runCount: -1,
1555
- retryCount: -1,
1556
- inputData: prevOutput,
1557
- state: executionContext.state,
1558
- setState: (state) => {
1559
- executionContext.state = state;
1560
- },
1561
- tracingContext: {
1562
- currentSpan: evalSpan
1563
- },
1564
- getInitData: () => stepResults?.input,
1565
- getStepResult: getStepResult.bind(this, stepResults),
1566
- // TODO: this function shouldn't have suspend probably?
1567
- suspend: async (_suspendPayload) => {
1568
- },
1569
- bail: () => {
1570
- },
1571
- abort: () => {
1572
- abortController.abort();
1573
- },
1574
- [EMITTER_SYMBOL]: emitter,
1575
- [STREAM_FORMAT_SYMBOL]: executionContext.format,
1576
- engine: {
1577
- step: this.inngestStep
1578
- },
1579
- abortSignal: abortController.signal,
1580
- writer: new ToolStream(
1581
- {
1582
- prefix: "workflow-step",
1583
- callId: randomUUID(),
1584
- name: "conditional",
1585
- runId
1586
- },
1587
- writableStream
1588
- )
1735
+ prefix: "workflow-step",
1736
+ callId: randomUUID(),
1737
+ name: "conditional",
1738
+ runId
1589
1739
  },
1590
- {
1591
- paramName: "runCount",
1592
- deprecationMessage: runCountDeprecationMessage,
1593
- logger: this.logger
1594
- }
1740
+ writableStream
1595
1741
  )
1596
- );
1742
+ });
1597
1743
  evalSpan?.end({
1598
1744
  output: result,
1599
1745
  attributes: {
@@ -1631,26 +1777,30 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
1631
1777
  prevOutput,
1632
1778
  stepResults,
1633
1779
  resume,
1780
+ timeTravel,
1634
1781
  executionContext: {
1635
1782
  workflowId,
1636
1783
  runId,
1637
1784
  executionPath: [...executionContext.executionPath, index],
1785
+ activeStepsPath: executionContext.activeStepsPath,
1638
1786
  suspendedPaths: executionContext.suspendedPaths,
1639
1787
  resumeLabels: executionContext.resumeLabels,
1640
1788
  retryConfig: executionContext.retryConfig,
1789
+ executionSpan: executionContext.executionSpan,
1641
1790
  state: executionContext.state
1642
1791
  },
1643
1792
  emitter,
1644
1793
  abortController,
1645
- requestContext,
1794
+ runtimeContext,
1646
1795
  writableStream,
1647
1796
  disableScorers,
1648
1797
  tracingContext: {
1649
1798
  currentSpan: conditionalSpan
1650
1799
  }
1651
1800
  });
1652
- stepResults[step.step.id] = result;
1653
- return result;
1801
+ stepResults[step.step.id] = result.result;
1802
+ executionContext.state = result.executionContextState;
1803
+ return result.result;
1654
1804
  })
1655
1805
  );
1656
1806
  const hasFailed = results.find((result) => result.status === "failed");