@mastra/inngest 0.0.0-new-scorer-api-20250801075530 → 0.0.0-playground-studio-cloud-20251031080052

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