@mastra/inngest 0.0.0-share-agent-metadata-with-cloud-20250718110128 → 0.0.0-sidebar-window-undefined-fix-20251029233656

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,16 +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,
186
+ workflowId: this.workflowId,
158
187
  stepResults: snapshot?.context,
159
188
  resume: {
160
189
  steps,
161
190
  stepResults: snapshot?.context,
162
- resumePayload: params.resumeData,
191
+ resumePayload: resumeDataToUse,
163
192
  // @ts-ignore
164
193
  resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
165
194
  }
@@ -199,12 +228,16 @@ var InngestRun = class extends workflows.Run {
199
228
  });
200
229
  };
201
230
  }
202
- stream({ inputData, runtimeContext } = {}) {
231
+ streamLegacy({ inputData, runtimeContext } = {}) {
203
232
  const { readable, writable } = new TransformStream();
204
233
  const writer = writable.getWriter();
205
234
  const unwatch = this.watch(async (event) => {
206
235
  try {
207
- await writer.write(event);
236
+ const e = {
237
+ ...event,
238
+ type: event.type.replace("workflow-", "")
239
+ };
240
+ await writer.write(e);
208
241
  } catch {
209
242
  }
210
243
  }, "watch-v2");
@@ -230,13 +263,71 @@ var InngestRun = class extends workflows.Run {
230
263
  getWorkflowState: () => this.executionResults
231
264
  };
232
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
+ }
233
318
  };
234
319
  var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
235
320
  #mastra;
236
321
  inngest;
237
322
  function;
323
+ flowControlConfig;
238
324
  constructor(params, inngest) {
239
- 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;
240
331
  this.#mastra = params.mastra;
241
332
  this.inngest = inngest;
242
333
  }
@@ -257,27 +348,6 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
257
348
  const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
258
349
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
259
350
  }
260
- async getWorkflowRunExecutionResult(runId) {
261
- const storage = this.#mastra?.getStorage();
262
- if (!storage) {
263
- this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
264
- return null;
265
- }
266
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
267
- if (!run?.snapshot) {
268
- return null;
269
- }
270
- if (typeof run.snapshot === "string") {
271
- return null;
272
- }
273
- return {
274
- status: run.snapshot.status,
275
- result: run.snapshot.result,
276
- error: run.snapshot.error,
277
- payload: run.snapshot.context?.input,
278
- steps: run.snapshot.context
279
- };
280
- }
281
351
  __registerMastra(mastra) {
282
352
  this.#mastra = mastra;
283
353
  this.executionEngine.__registerMastra(mastra);
@@ -296,23 +366,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
296
366
  }
297
367
  }
298
368
  }
299
- createRun(options) {
300
- const runIdToUse = options?.runId || crypto.randomUUID();
301
- const run = this.runs.get(runIdToUse) ?? new InngestRun(
302
- {
303
- workflowId: this.id,
304
- runId: runIdToUse,
305
- executionEngine: this.executionEngine,
306
- executionGraph: this.executionGraph,
307
- serializedStepGraph: this.serializedStepGraph,
308
- mastra: this.#mastra,
309
- retryConfig: this.retryConfig,
310
- cleanup: () => this.runs.delete(runIdToUse)
311
- },
312
- 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."
313
376
  );
314
- this.runs.set(runIdToUse, run);
315
- return run;
316
377
  }
317
378
  async createRunAsync(options) {
318
379
  const runIdToUse = options?.runId || crypto.randomUUID();
@@ -320,29 +381,38 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
320
381
  {
321
382
  workflowId: this.id,
322
383
  runId: runIdToUse,
384
+ resourceId: options?.resourceId,
323
385
  executionEngine: this.executionEngine,
324
386
  executionGraph: this.executionGraph,
325
387
  serializedStepGraph: this.serializedStepGraph,
326
388
  mastra: this.#mastra,
327
389
  retryConfig: this.retryConfig,
328
- cleanup: () => this.runs.delete(runIdToUse)
390
+ cleanup: () => this.runs.delete(runIdToUse),
391
+ workflowSteps: this.steps
329
392
  },
330
393
  this.inngest
331
394
  );
332
395
  this.runs.set(runIdToUse, run);
333
- const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
334
- 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) {
335
402
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
336
403
  workflowName: this.id,
337
404
  runId: runIdToUse,
405
+ resourceId: options?.resourceId,
338
406
  snapshot: {
339
407
  runId: runIdToUse,
340
408
  status: "pending",
341
409
  value: {},
342
410
  context: {},
343
411
  activePaths: [],
412
+ waitingPaths: {},
344
413
  serializedStepGraph: this.serializedStepGraph,
345
414
  suspendedPaths: {},
415
+ resumeLabels: {},
346
416
  result: void 0,
347
417
  error: void 0,
348
418
  // @ts-ignore
@@ -361,11 +431,13 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
361
431
  id: `workflow.${this.id}`,
362
432
  // @ts-ignore
363
433
  retries: this.retryConfig?.attempts ?? 0,
364
- cancelOn: [{ event: `cancel.workflow.${this.id}` }]
434
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
435
+ // Spread flow control configuration
436
+ ...this.flowControlConfig
365
437
  },
366
438
  { event: `workflow.${this.id}` },
367
439
  async ({ event, step, attempt, publish }) => {
368
- let { inputData, runId, resume } = event.data;
440
+ let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
369
441
  if (!runId) {
370
442
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
371
443
  return crypto.randomUUID();
@@ -393,19 +465,32 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
393
465
  once: (_event, _callback) => {
394
466
  }
395
467
  };
396
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
468
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
397
469
  const result = await engine.execute({
398
470
  workflowId: this.id,
399
471
  runId,
472
+ resourceId,
400
473
  graph: this.executionGraph,
401
474
  serializedStepGraph: this.serializedStepGraph,
402
475
  input: inputData,
476
+ initialState,
403
477
  emitter,
404
478
  retryConfig: this.retryConfig,
405
479
  runtimeContext: new di.RuntimeContext(),
406
480
  // TODO
407
481
  resume,
408
- 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;
409
494
  });
410
495
  return { result, runId };
411
496
  }
@@ -439,17 +524,16 @@ function createStep(params) {
439
524
  if (isAgent(params)) {
440
525
  return {
441
526
  id: params.name,
527
+ description: params.getDescription(),
442
528
  // @ts-ignore
443
529
  inputSchema: zod.z.object({
444
530
  prompt: zod.z.string()
445
- // resourceId: z.string().optional(),
446
- // threadId: z.string().optional(),
447
531
  }),
448
532
  // @ts-ignore
449
533
  outputSchema: zod.z.object({
450
534
  text: zod.z.string()
451
535
  }),
452
- execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
536
+ execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
453
537
  let streamPromise = {};
454
538
  streamPromise.promise = new Promise((resolve, reject) => {
455
539
  streamPromise.resolve = resolve;
@@ -459,50 +543,66 @@ function createStep(params) {
459
543
  name: params.name,
460
544
  args: inputData
461
545
  };
462
- await emitter.emit("watch-v2", {
463
- type: "tool-call-streaming-start",
464
- ...toolData
465
- });
466
- const { fullStream } = await params.stream(inputData.prompt, {
467
- // resourceId: inputData.resourceId,
468
- // threadId: inputData.threadId,
469
- runtimeContext,
470
- onFinish: (result) => {
471
- streamPromise.resolve(result.text);
472
- },
473
- abortSignal
474
- });
475
- if (abortSignal.aborted) {
476
- return abort();
477
- }
478
- for await (const chunk of fullStream) {
479
- switch (chunk.type) {
480
- 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") {
481
564
  await emitter.emit("watch-v2", {
482
565
  type: "tool-call-delta",
483
- ...toolData,
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") {
589
+ await emitter.emit("watch-v2", {
590
+ type: "tool-call-delta",
591
+ ...toolData ?? {},
484
592
  argsTextDelta: chunk.textDelta
485
593
  });
486
- break;
487
- case "step-start":
488
- case "step-finish":
489
- case "finish":
490
- break;
491
- case "tool-call":
492
- case "tool-result":
493
- case "tool-call-streaming-start":
494
- case "tool-call-delta":
495
- case "source":
496
- case "file":
497
- default:
498
- await emitter.emit("watch-v2", chunk);
499
- break;
594
+ }
500
595
  }
501
596
  }
597
+ await emitter.emit("watch-v2", {
598
+ type: "tool-call-streaming-finish",
599
+ ...toolData ?? {}
600
+ });
502
601
  return {
503
602
  text: await streamPromise.promise
504
603
  };
505
- }
604
+ },
605
+ component: params.component
506
606
  };
507
607
  }
508
608
  if (isTool(params)) {
@@ -513,15 +613,20 @@ function createStep(params) {
513
613
  // TODO: tool probably should have strong id type
514
614
  // @ts-ignore
515
615
  id: params.id,
616
+ description: params.description,
516
617
  inputSchema: params.inputSchema,
517
618
  outputSchema: params.outputSchema,
518
- execute: async ({ inputData, mastra, runtimeContext }) => {
619
+ execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
519
620
  return params.execute({
520
621
  context: inputData,
521
- mastra,
522
- runtimeContext
622
+ mastra: aiTracing.wrapMastra(mastra, tracingContext),
623
+ runtimeContext,
624
+ tracingContext,
625
+ suspend,
626
+ resumeData
523
627
  });
524
- }
628
+ },
629
+ component: "TOOL"
525
630
  };
526
631
  }
527
632
  return {
@@ -537,7 +642,10 @@ function createStep(params) {
537
642
  function init(inngest) {
538
643
  return {
539
644
  createWorkflow(params) {
540
- return new InngestWorkflow(params, inngest);
645
+ return new InngestWorkflow(
646
+ params,
647
+ inngest
648
+ );
541
649
  },
542
650
  createStep,
543
651
  cloneStep(step, opts) {
@@ -546,7 +654,11 @@ function init(inngest) {
546
654
  description: step.description,
547
655
  inputSchema: step.inputSchema,
548
656
  outputSchema: step.outputSchema,
549
- execute: step.execute
657
+ resumeSchema: step.resumeSchema,
658
+ suspendSchema: step.suspendSchema,
659
+ stateSchema: step.stateSchema,
660
+ execute: step.execute,
661
+ component: step.component
550
662
  };
551
663
  },
552
664
  cloneWorkflow(workflow, opts) {
@@ -566,24 +678,24 @@ function init(inngest) {
566
678
  var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
567
679
  inngestStep;
568
680
  inngestAttempts;
569
- constructor(mastra, inngestStep, inngestAttempts = 0) {
570
- super({ mastra });
681
+ constructor(mastra, inngestStep, inngestAttempts = 0, options) {
682
+ super({ mastra, options });
571
683
  this.inngestStep = inngestStep;
572
684
  this.inngestAttempts = inngestAttempts;
573
685
  }
574
686
  async execute(params) {
575
687
  await params.emitter.emit("watch-v2", {
576
- type: "start",
688
+ type: "workflow-start",
577
689
  payload: { runId: params.runId }
578
690
  });
579
691
  const result = await super.execute(params);
580
692
  await params.emitter.emit("watch-v2", {
581
- type: "finish",
693
+ type: "workflow-finish",
582
694
  payload: { runId: params.runId }
583
695
  });
584
696
  return result;
585
697
  }
586
- async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
698
+ async fmtReturnValue(emitter, stepResults, lastOutput, error) {
587
699
  const base = {
588
700
  status: lastOutput.status,
589
701
  steps: stepResults
@@ -630,41 +742,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
630
742
  });
631
743
  const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
632
744
  if (stepResult?.status === "suspended") {
633
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
745
+ const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
634
746
  return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
635
747
  }
636
748
  return [];
637
749
  });
638
750
  base.suspended = suspendedStepIds;
639
751
  }
640
- executionSpan?.end();
641
752
  return base;
642
753
  }
643
- async superExecuteStep({
644
- workflowId,
645
- runId,
646
- step,
647
- stepResults,
648
- executionContext,
649
- resume,
650
- prevOutput,
651
- emitter,
652
- abortController,
653
- runtimeContext
654
- }) {
655
- return super.executeStep({
656
- workflowId,
657
- runId,
658
- step,
659
- stepResults,
660
- executionContext,
661
- resume,
662
- prevOutput,
663
- emitter,
664
- abortController,
665
- runtimeContext
666
- });
667
- }
668
754
  // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
669
755
  // await this.inngestStep.sleep(id, duration);
670
756
  // }
@@ -676,43 +762,87 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
676
762
  stepResults,
677
763
  emitter,
678
764
  abortController,
679
- runtimeContext
765
+ runtimeContext,
766
+ executionContext,
767
+ writableStream,
768
+ tracingContext
680
769
  }) {
681
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
+ });
682
780
  if (fn) {
781
+ const stepCallId = crypto.randomUUID();
683
782
  duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
684
- return await fn({
685
- runId,
686
- mastra: this.mastra,
687
- runtimeContext,
688
- inputData: prevOutput,
689
- runCount: -1,
690
- getInitData: () => stepResults?.input,
691
- getStepResult: (step) => {
692
- if (!step?.id) {
693
- return null;
694
- }
695
- const result = stepResults[step.id];
696
- if (result?.status === "success") {
697
- return result.output;
783
+ return await fn(
784
+ workflows.createDeprecationProxy(
785
+ {
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
+ )
824
+ },
825
+ {
826
+ paramName: "runCount",
827
+ deprecationMessage: workflows.runCountDeprecationMessage,
828
+ logger: this.logger
698
829
  }
699
- return null;
700
- },
701
- // TODO: this function shouldn't have suspend probably?
702
- suspend: async (_suspendPayload) => {
703
- },
704
- bail: () => {
705
- },
706
- abort: () => {
707
- abortController?.abort();
708
- },
709
- [_constants.EMITTER_SYMBOL]: emitter,
710
- engine: { step: this.inngestStep },
711
- abortSignal: abortController?.signal
712
- });
830
+ )
831
+ );
713
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;
714
845
  }
715
- await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
716
846
  }
717
847
  async executeSleepUntil({
718
848
  workflowId,
@@ -722,46 +852,96 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
722
852
  stepResults,
723
853
  emitter,
724
854
  abortController,
725
- runtimeContext
855
+ runtimeContext,
856
+ executionContext,
857
+ writableStream,
858
+ tracingContext
726
859
  }) {
727
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
+ });
728
871
  if (fn) {
729
872
  date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
730
- return await fn({
731
- runId,
732
- mastra: this.mastra,
733
- runtimeContext,
734
- inputData: prevOutput,
735
- runCount: -1,
736
- getInitData: () => stepResults?.input,
737
- getStepResult: (step) => {
738
- if (!step?.id) {
739
- return null;
740
- }
741
- const result = stepResults[step.id];
742
- if (result?.status === "success") {
743
- return result.output;
873
+ const stepCallId = crypto.randomUUID();
874
+ return await fn(
875
+ workflows.createDeprecationProxy(
876
+ {
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
+ )
915
+ },
916
+ {
917
+ paramName: "runCount",
918
+ deprecationMessage: workflows.runCountDeprecationMessage,
919
+ logger: this.logger
744
920
  }
745
- return null;
746
- },
747
- // TODO: this function shouldn't have suspend probably?
748
- suspend: async (_suspendPayload) => {
749
- },
750
- bail: () => {
751
- },
752
- abort: () => {
753
- abortController?.abort();
754
- },
755
- [_constants.EMITTER_SYMBOL]: emitter,
756
- engine: { step: this.inngestStep },
757
- abortSignal: abortController?.signal
758
- });
921
+ )
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
+ }
759
932
  });
760
933
  }
761
934
  if (!(date instanceof Date)) {
935
+ sleepUntilSpan?.end();
762
936
  return;
763
937
  }
764
- 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
+ }
765
945
  }
766
946
  async executeWaitForEvent({ event, timeout }) {
767
947
  const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
@@ -781,8 +961,25 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
781
961
  prevOutput,
782
962
  emitter,
783
963
  abortController,
784
- runtimeContext
964
+ runtimeContext,
965
+ tracingContext,
966
+ writableStream,
967
+ disableScorers
785
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
+ });
786
983
  const startedAt = await this.inngestStep.run(
787
984
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
788
985
  async () => {
@@ -809,11 +1006,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
809
1006
  eventTimestamp: Date.now()
810
1007
  });
811
1008
  await emitter.emit("watch-v2", {
812
- type: "step-start",
1009
+ type: "workflow-step-start",
813
1010
  payload: {
814
1011
  id: step.id,
815
1012
  status: "running",
816
- payload: prevOutput,
1013
+ payload: inputData,
817
1014
  startedAt: startedAt2
818
1015
  }
819
1016
  });
@@ -824,38 +1021,60 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
824
1021
  const isResume = !!resume?.steps?.length;
825
1022
  let result;
826
1023
  let runId;
827
- if (isResume) {
828
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? crypto.randomUUID();
829
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
830
- workflowName: step.id,
831
- runId
832
- });
833
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
834
- function: step.getFunction(),
835
- data: {
836
- inputData: prevOutput,
837
- runId,
838
- 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 ?? {},
839
1036
  runId,
840
- steps: resume.steps.slice(1),
841
- stepResults: snapshot?.context,
842
- resumePayload: resume.resumePayload,
843
- // @ts-ignore
844
- 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 }
845
1046
  }
846
- }
847
- });
848
- result = invokeResp.result;
849
- runId = invokeResp.runId;
850
- } else {
851
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
852
- function: step.getFunction(),
853
- data: {
854
- inputData: prevOutput
855
- }
856
- });
857
- result = invokeResp.result;
858
- 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
+ }
859
1078
  }
860
1079
  const res = await this.inngestStep.run(
861
1080
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
@@ -879,7 +1098,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
879
1098
  eventTimestamp: Date.now()
880
1099
  });
881
1100
  await emitter.emit("watch-v2", {
882
- type: "step-result",
1101
+ type: "workflow-step-result",
883
1102
  payload: {
884
1103
  id: step.id,
885
1104
  status: "failed",
@@ -894,7 +1113,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
894
1113
  return stepRes2?.status === "suspended";
895
1114
  });
896
1115
  for (const [stepName, stepResult] of suspendedSteps) {
897
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
1116
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
898
1117
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
899
1118
  await emitter.emit("watch", {
900
1119
  type: "watch",
@@ -902,7 +1121,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
902
1121
  currentStep: {
903
1122
  id: step.id,
904
1123
  status: "suspended",
905
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1124
+ payload: stepResult.payload,
1125
+ suspendPayload: {
1126
+ ...stepResult?.suspendPayload,
1127
+ __workflow_meta: { runId, path: suspendPath }
1128
+ }
906
1129
  },
907
1130
  workflowState: {
908
1131
  status: "running",
@@ -914,7 +1137,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
914
1137
  eventTimestamp: Date.now()
915
1138
  });
916
1139
  await emitter.emit("watch-v2", {
917
- type: "step-suspended",
1140
+ type: "workflow-step-suspended",
918
1141
  payload: {
919
1142
  id: step.id,
920
1143
  status: "suspended"
@@ -924,7 +1147,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
924
1147
  executionContext,
925
1148
  result: {
926
1149
  status: "suspended",
927
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
1150
+ payload: stepResult.payload,
1151
+ suspendPayload: {
1152
+ ...stepResult?.suspendPayload,
1153
+ __workflow_meta: { runId, path: suspendPath }
1154
+ }
928
1155
  }
929
1156
  };
930
1157
  }
@@ -971,7 +1198,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
971
1198
  eventTimestamp: Date.now()
972
1199
  });
973
1200
  await emitter.emit("watch-v2", {
974
- type: "step-result",
1201
+ type: "workflow-step-result",
975
1202
  payload: {
976
1203
  id: step.id,
977
1204
  status: "success",
@@ -979,7 +1206,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
979
1206
  }
980
1207
  });
981
1208
  await emitter.emit("watch-v2", {
982
- type: "step-finish",
1209
+ type: "workflow-step-finish",
983
1210
  payload: {
984
1211
  id: step.id,
985
1212
  metadata: {}
@@ -989,135 +1216,202 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
989
1216
  }
990
1217
  );
991
1218
  Object.assign(executionContext, res.executionContext);
992
- 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
+ };
993
1227
  }
994
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
995
- let execResults;
996
- let suspended;
997
- let bailed;
998
- try {
999
- const result = await step.execute({
1000
- runId: executionContext.runId,
1001
- mastra: this.mastra,
1002
- runtimeContext,
1003
- inputData: prevOutput,
1004
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
1005
- getInitData: () => stepResults?.input,
1006
- getStepResult: (step2) => {
1007
- const result2 = stepResults[step2.id];
1008
- if (result2?.status === "success") {
1009
- 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
1010
1340
  }
1011
- return null;
1012
- },
1013
- suspend: async (suspendPayload) => {
1014
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
1015
- suspended = { payload: suspendPayload };
1016
- },
1017
- bail: (result2) => {
1018
- bailed = { payload: result2 };
1019
- },
1020
- resume: {
1021
- steps: resume?.steps?.slice(1) || [],
1022
- resumePayload: resume?.resumePayload,
1023
- // @ts-ignore
1024
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
1025
1341
  },
1026
- [_constants.EMITTER_SYMBOL]: emitter,
1027
- engine: {
1028
- step: this.inngestStep
1029
- },
1030
- abortSignal: abortController.signal
1342
+ eventTimestamp: Date.now()
1031
1343
  });
1032
- const endedAt = Date.now();
1033
- execResults = {
1034
- status: "success",
1035
- output: result,
1036
- startedAt,
1037
- endedAt,
1038
- payload: prevOutput,
1039
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1040
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1041
- };
1042
- } catch (e) {
1043
- execResults = {
1044
- status: "failed",
1045
- payload: prevOutput,
1046
- error: e instanceof Error ? e.message : String(e),
1047
- endedAt: Date.now(),
1048
- startedAt,
1049
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1050
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1051
- };
1052
- }
1053
- if (suspended) {
1054
- execResults = {
1055
- status: "suspended",
1056
- suspendedPayload: suspended.payload,
1057
- payload: prevOutput,
1058
- suspendedAt: Date.now(),
1059
- startedAt,
1060
- resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
1061
- resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
1062
- };
1063
- } else if (bailed) {
1064
- execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
1065
- }
1066
- if (execResults.status === "failed") {
1067
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
1068
- 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
+ });
1069
1367
  }
1070
- }
1071
- await emitter.emit("watch", {
1072
- type: "watch",
1073
- payload: {
1074
- currentStep: {
1075
- id: step.id,
1076
- ...execResults
1077
- },
1078
- workflowState: {
1079
- status: "running",
1080
- steps: { ...stepResults, [step.id]: execResults },
1081
- result: null,
1082
- error: null
1083
- }
1084
- },
1085
- eventTimestamp: Date.now()
1368
+ stepAISpan?.end({ output: execResults });
1369
+ return { result: execResults, executionContext, stepResults };
1086
1370
  });
1087
- if (execResults.status === "suspended") {
1088
- await emitter.emit("watch-v2", {
1089
- type: "step-suspended",
1090
- payload: {
1091
- id: step.id,
1092
- ...execResults
1093
- }
1094
- });
1095
- } else {
1096
- await emitter.emit("watch-v2", {
1097
- type: "step-result",
1098
- payload: {
1099
- id: step.id,
1100
- ...execResults
1101
- }
1102
- });
1103
- await emitter.emit("watch-v2", {
1104
- type: "step-finish",
1105
- payload: {
1106
- id: step.id,
1107
- metadata: {}
1108
- }
1109
- });
1110
- }
1111
- return { result: execResults, executionContext, stepResults };
1112
- });
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
+ }
1113
1405
  Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
1114
1406
  Object.assign(stepResults, stepRes.stepResults);
1407
+ executionContext.state = stepRes.executionContext.state;
1115
1408
  return stepRes.result;
1116
1409
  }
1117
1410
  async persistStepUpdate({
1118
1411
  workflowId,
1119
1412
  runId,
1120
1413
  stepResults,
1414
+ resourceId,
1121
1415
  executionContext,
1122
1416
  serializedStepGraph,
1123
1417
  workflowStatus,
@@ -1127,15 +1421,22 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1127
1421
  await this.inngestStep.run(
1128
1422
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
1129
1423
  async () => {
1424
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
1425
+ if (!shouldPersistSnapshot) {
1426
+ return;
1427
+ }
1130
1428
  await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1131
1429
  workflowName: workflowId,
1132
1430
  runId,
1431
+ resourceId,
1133
1432
  snapshot: {
1134
1433
  runId,
1135
- value: {},
1434
+ value: executionContext.state,
1136
1435
  context: stepResults,
1137
1436
  activePaths: [],
1138
1437
  suspendedPaths: executionContext.suspendedPaths,
1438
+ resumeLabels: executionContext.resumeLabels,
1439
+ waitingPaths: {},
1139
1440
  serializedStepGraph,
1140
1441
  status: workflowStatus,
1141
1442
  result,
@@ -1152,100 +1453,175 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
1152
1453
  runId,
1153
1454
  entry,
1154
1455
  prevOutput,
1155
- prevStep,
1156
1456
  stepResults,
1157
- serializedStepGraph,
1158
1457
  resume,
1159
1458
  executionContext,
1160
1459
  emitter,
1161
1460
  abortController,
1162
- runtimeContext
1461
+ runtimeContext,
1462
+ writableStream,
1463
+ disableScorers,
1464
+ tracingContext
1163
1465
  }) {
1466
+ const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
1467
+ type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
1468
+ name: `conditional: '${entry.conditions.length} conditions'`,
1469
+ input: prevOutput,
1470
+ attributes: {
1471
+ conditionCount: entry.conditions.length
1472
+ },
1473
+ tracingPolicy: this.options?.tracingPolicy
1474
+ });
1164
1475
  let execResults;
1165
1476
  const truthyIndexes = (await Promise.all(
1166
1477
  entry.conditions.map(
1167
1478
  (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
1479
+ const evalSpan = conditionalSpan?.createChildSpan({
1480
+ type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
1481
+ name: `condition: '${index}'`,
1482
+ input: prevOutput,
1483
+ attributes: {
1484
+ conditionIndex: index
1485
+ },
1486
+ tracingPolicy: this.options?.tracingPolicy
1487
+ });
1168
1488
  try {
1169
- const result = await cond({
1170
- runId,
1171
- mastra: this.mastra,
1172
- runtimeContext,
1173
- runCount: -1,
1174
- inputData: prevOutput,
1175
- getInitData: () => stepResults?.input,
1176
- getStepResult: (step) => {
1177
- if (!step?.id) {
1178
- return null;
1179
- }
1180
- const result2 = stepResults[step.id];
1181
- if (result2?.status === "success") {
1182
- return result2.output;
1489
+ const result = await cond(
1490
+ workflows.createDeprecationProxy(
1491
+ {
1492
+ runId,
1493
+ workflowId,
1494
+ mastra: this.mastra,
1495
+ runtimeContext,
1496
+ runCount: -1,
1497
+ retryCount: -1,
1498
+ inputData: prevOutput,
1499
+ state: executionContext.state,
1500
+ setState: (state) => {
1501
+ executionContext.state = state;
1502
+ },
1503
+ tracingContext: {
1504
+ currentSpan: evalSpan
1505
+ },
1506
+ getInitData: () => stepResults?.input,
1507
+ getStepResult: workflows.getStepResult.bind(this, stepResults),
1508
+ // TODO: this function shouldn't have suspend probably?
1509
+ suspend: async (_suspendPayload) => {
1510
+ },
1511
+ bail: () => {
1512
+ },
1513
+ abort: () => {
1514
+ abortController.abort();
1515
+ },
1516
+ [_constants.EMITTER_SYMBOL]: emitter,
1517
+ [_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
1518
+ // TODO: add streamVNext support
1519
+ engine: {
1520
+ step: this.inngestStep
1521
+ },
1522
+ abortSignal: abortController.signal,
1523
+ writer: new tools.ToolStream(
1524
+ {
1525
+ prefix: "workflow-step",
1526
+ callId: crypto.randomUUID(),
1527
+ name: "conditional",
1528
+ runId
1529
+ },
1530
+ writableStream
1531
+ )
1532
+ },
1533
+ {
1534
+ paramName: "runCount",
1535
+ deprecationMessage: workflows.runCountDeprecationMessage,
1536
+ logger: this.logger
1183
1537
  }
1184
- return null;
1185
- },
1186
- // TODO: this function shouldn't have suspend probably?
1187
- suspend: async (_suspendPayload) => {
1188
- },
1189
- bail: () => {
1190
- },
1191
- abort: () => {
1192
- abortController.abort();
1193
- },
1194
- [_constants.EMITTER_SYMBOL]: emitter,
1195
- engine: {
1196
- step: this.inngestStep
1197
- },
1198
- abortSignal: abortController.signal
1538
+ )
1539
+ );
1540
+ evalSpan?.end({
1541
+ output: result,
1542
+ attributes: {
1543
+ result: !!result
1544
+ }
1199
1545
  });
1200
1546
  return result ? index : null;
1201
1547
  } catch (e) {
1548
+ evalSpan?.error({
1549
+ error: e instanceof Error ? e : new Error(String(e)),
1550
+ attributes: {
1551
+ result: false
1552
+ }
1553
+ });
1202
1554
  return null;
1203
1555
  }
1204
1556
  })
1205
1557
  )
1206
1558
  )).filter((index) => index !== null);
1207
1559
  const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
1560
+ conditionalSpan?.update({
1561
+ attributes: {
1562
+ truthyIndexes,
1563
+ selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
1564
+ }
1565
+ });
1208
1566
  const results = await Promise.all(
1209
- stepsToRun.map(
1210
- (step, index) => this.executeEntry({
1211
- workflowId,
1212
- runId,
1213
- entry: step,
1214
- prevStep,
1567
+ stepsToRun.map(async (step, index) => {
1568
+ const currStepResult = stepResults[step.step.id];
1569
+ if (currStepResult && currStepResult.status === "success") {
1570
+ return currStepResult;
1571
+ }
1572
+ const result = await this.executeStep({
1573
+ step: step.step,
1574
+ prevOutput,
1215
1575
  stepResults,
1216
1576
  resume,
1217
- serializedStepGraph,
1218
1577
  executionContext: {
1219
1578
  workflowId,
1220
1579
  runId,
1221
1580
  executionPath: [...executionContext.executionPath, index],
1222
1581
  suspendedPaths: executionContext.suspendedPaths,
1582
+ resumeLabels: executionContext.resumeLabels,
1223
1583
  retryConfig: executionContext.retryConfig,
1224
- executionSpan: executionContext.executionSpan
1584
+ state: executionContext.state
1225
1585
  },
1226
1586
  emitter,
1227
1587
  abortController,
1228
- runtimeContext
1229
- })
1230
- )
1588
+ runtimeContext,
1589
+ writableStream,
1590
+ disableScorers,
1591
+ tracingContext: {
1592
+ currentSpan: conditionalSpan
1593
+ }
1594
+ });
1595
+ stepResults[step.step.id] = result;
1596
+ return result;
1597
+ })
1231
1598
  );
1232
- const hasFailed = results.find((result) => result.result.status === "failed");
1233
- const hasSuspended = results.find((result) => result.result.status === "suspended");
1599
+ const hasFailed = results.find((result) => result.status === "failed");
1600
+ const hasSuspended = results.find((result) => result.status === "suspended");
1234
1601
  if (hasFailed) {
1235
- execResults = { status: "failed", error: hasFailed.result.error };
1602
+ execResults = { status: "failed", error: hasFailed.error };
1236
1603
  } else if (hasSuspended) {
1237
- execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
1604
+ execResults = { status: "suspended", suspendPayload: hasSuspended.suspendPayload };
1238
1605
  } else {
1239
1606
  execResults = {
1240
1607
  status: "success",
1241
1608
  output: results.reduce((acc, result, index) => {
1242
- if (result.result.status === "success") {
1609
+ if (result.status === "success") {
1243
1610
  acc[stepsToRun[index].step.id] = result.output;
1244
1611
  }
1245
1612
  return acc;
1246
1613
  }, {})
1247
1614
  };
1248
1615
  }
1616
+ if (execResults.status === "failed") {
1617
+ conditionalSpan?.error({
1618
+ error: new Error(execResults.error)
1619
+ });
1620
+ } else {
1621
+ conditionalSpan?.end({
1622
+ output: execResults.output || execResults
1623
+ });
1624
+ }
1249
1625
  return execResults;
1250
1626
  }
1251
1627
  };
@@ -1256,3 +1632,5 @@ exports.InngestWorkflow = InngestWorkflow;
1256
1632
  exports.createStep = createStep;
1257
1633
  exports.init = init;
1258
1634
  exports.serve = serve;
1635
+ //# sourceMappingURL=index.cjs.map
1636
+ //# sourceMappingURL=index.cjs.map