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