@mastra/inngest 0.0.0-1.x-tester-20251106055847

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