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