@mastra/inngest 0.0.0-pgvector-index-fix-20250905222058 → 0.0.0-playground-studio-again-20251114100107

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