@mastra/core 0.9.0 → 0.9.1-alpha.1

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.
Files changed (94) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.d.cts +4 -2
  3. package/dist/agent/index.d.ts +4 -2
  4. package/dist/agent/index.js +1 -1
  5. package/dist/{base-oP3DoUrm.d.cts → base-CZmT-p10.d.cts} +524 -53
  6. package/dist/{base-Bk5V1doj.d.ts → base-DDoWFpFc.d.ts} +524 -53
  7. package/dist/{chunk-NTHHPNOW.js → chunk-34622N67.js} +1 -1
  8. package/dist/{chunk-ATXF6TIO.cjs → chunk-422BXQRT.cjs} +24 -677
  9. package/dist/{chunk-HARYMLZH.js → chunk-4K4DHXRF.js} +6 -658
  10. package/dist/{chunk-N2ONCUUS.js → chunk-6AHC67YY.js} +132 -12
  11. package/dist/chunk-7AGAXO6B.cjs +588 -0
  12. package/dist/{chunk-GEIPVIW4.js → chunk-BFF2O6RO.js} +1 -1
  13. package/dist/{chunk-RASVJ3TR.js → chunk-BU45BMXY.js} +55 -1
  14. package/dist/{chunk-DIZZQ3E5.cjs → chunk-CEXM6WP5.cjs} +2 -2
  15. package/dist/chunk-HNEE7IF4.js +60 -0
  16. package/dist/{chunk-NZDXKMDP.cjs → chunk-LABUWBKX.cjs} +1 -1
  17. package/dist/chunk-MUNFCOMB.cjs +62 -0
  18. package/dist/{chunk-GJWCFDFN.js → chunk-PS2ZF6MA.js} +1 -1
  19. package/dist/{chunk-M472GIT6.js → chunk-SGGPJWRQ.js} +1 -1
  20. package/dist/{chunk-7CSNWYGJ.cjs → chunk-U5DGGGS2.cjs} +2 -2
  21. package/dist/{chunk-W5IA5OGL.cjs → chunk-V7IE36YV.cjs} +58 -4
  22. package/dist/chunk-VMVXIPGW.js +586 -0
  23. package/dist/{chunk-53P5ZBJE.cjs → chunk-YTTBFAQJ.cjs} +2 -2
  24. package/dist/{chunk-KZWBYRXW.cjs → chunk-YZFNMXY4.cjs} +135 -14
  25. package/dist/di/index.cjs +2 -2
  26. package/dist/di/index.d.cts +1 -52
  27. package/dist/di/index.d.ts +1 -52
  28. package/dist/di/index.js +1 -1
  29. package/dist/eval/index.d.cts +4 -2
  30. package/dist/eval/index.d.ts +4 -2
  31. package/dist/index.cjs +60 -55
  32. package/dist/index.d.cts +5 -3
  33. package/dist/index.d.ts +5 -3
  34. package/dist/index.js +10 -9
  35. package/dist/integration/index.cjs +3 -3
  36. package/dist/integration/index.d.cts +4 -2
  37. package/dist/integration/index.d.ts +4 -2
  38. package/dist/integration/index.js +1 -1
  39. package/dist/llm/index.cjs +8 -0
  40. package/dist/llm/index.d.cts +4 -2
  41. package/dist/llm/index.d.ts +4 -2
  42. package/dist/llm/index.js +1 -1
  43. package/dist/mastra/index.cjs +2 -2
  44. package/dist/mastra/index.d.cts +4 -2
  45. package/dist/mastra/index.d.ts +4 -2
  46. package/dist/mastra/index.js +1 -1
  47. package/dist/memory/index.cjs +7 -3
  48. package/dist/memory/index.d.cts +4 -2
  49. package/dist/memory/index.d.ts +4 -2
  50. package/dist/memory/index.js +1 -1
  51. package/dist/network/index.cjs +4 -4
  52. package/dist/network/index.d.cts +4 -2
  53. package/dist/network/index.d.ts +4 -2
  54. package/dist/network/index.js +2 -2
  55. package/dist/relevance/index.cjs +4 -4
  56. package/dist/relevance/index.d.cts +4 -2
  57. package/dist/relevance/index.d.ts +4 -2
  58. package/dist/relevance/index.js +1 -1
  59. package/dist/runtime-context/index.cjs +7 -68
  60. package/dist/runtime-context/index.js +1 -69
  61. package/dist/server/index.d.cts +4 -2
  62. package/dist/server/index.d.ts +4 -2
  63. package/dist/storage/index.d.cts +4 -2
  64. package/dist/storage/index.d.ts +4 -2
  65. package/dist/storage/libsql/index.cjs +19 -0
  66. package/dist/storage/libsql/index.d.cts +7 -8
  67. package/dist/storage/libsql/index.d.ts +7 -8
  68. package/dist/storage/libsql/index.js +19 -0
  69. package/dist/telemetry/index.d.cts +4 -2
  70. package/dist/telemetry/index.d.ts +4 -2
  71. package/dist/tools/index.cjs +4 -4
  72. package/dist/tools/index.d.cts +4 -2
  73. package/dist/tools/index.d.ts +4 -2
  74. package/dist/tools/index.js +1 -1
  75. package/dist/utils.cjs +14 -14
  76. package/dist/utils.d.cts +6 -4
  77. package/dist/utils.d.ts +6 -4
  78. package/dist/utils.js +1 -1
  79. package/dist/voice/index.d.cts +5 -3
  80. package/dist/voice/index.d.ts +5 -3
  81. package/dist/workflows/index.cjs +22 -26
  82. package/dist/workflows/index.d.cts +5 -3
  83. package/dist/workflows/index.d.ts +5 -3
  84. package/dist/workflows/index.js +1 -1
  85. package/dist/workflows/vNext/index.cjs +1058 -0
  86. package/dist/workflows/vNext/index.d.cts +180 -0
  87. package/dist/workflows/vNext/index.d.ts +180 -0
  88. package/dist/workflows/vNext/index.js +1046 -0
  89. package/package.json +11 -1
  90. package/workflows/vNext.d.ts +1 -0
  91. /package/dist/{chunk-WEYWYKLG.cjs → chunk-27PAET7X.cjs} +0 -0
  92. /package/dist/{chunk-FRQFWZDN.cjs → chunk-HSVOEWAM.cjs} +0 -0
  93. /package/dist/{chunk-ZDWFBE5L.js → chunk-NH5WJNNS.js} +0 -0
  94. /package/dist/{chunk-LANFNMEE.js → chunk-SGTFVHOZ.js} +0 -0
@@ -0,0 +1,1046 @@
1
+ import { Agent } from '../../chunk-4K4DHXRF.js';
2
+ import { Tool } from '../../chunk-34622N67.js';
3
+ import { MastraBase } from '../../chunk-CLJQYXNM.js';
4
+ import { RegisteredLogger } from '../../chunk-2BVZNKLX.js';
5
+ import { RuntimeContext } from '../../chunk-SGGPJWRQ.js';
6
+ import { randomUUID } from 'crypto';
7
+ import EventEmitter from 'events';
8
+ import { z } from 'zod';
9
+
10
+ // src/workflows/vNext/execution-engine.ts
11
+ var ExecutionEngine = class extends MastraBase {
12
+ mastra;
13
+ constructor({ mastra }) {
14
+ super({ name: "ExecutionEngine", component: RegisteredLogger.WORKFLOW });
15
+ this.mastra = mastra;
16
+ }
17
+ __registerMastra(mastra) {
18
+ this.mastra = mastra;
19
+ }
20
+ };
21
+
22
+ // src/workflows/vNext/default.ts
23
+ function fmtReturnValue(stepResults, lastOutput, error) {
24
+ const base = {
25
+ status: lastOutput.status,
26
+ steps: stepResults
27
+ };
28
+ if (lastOutput.status === "success") {
29
+ base.result = lastOutput.output;
30
+ } else if (lastOutput.status === "failed") {
31
+ base.error = error instanceof Error ? error : lastOutput.error ?? new Error("Unknown error: " + error);
32
+ } else if (lastOutput.status === "suspended") {
33
+ const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
34
+ if (stepResult?.status === "suspended") {
35
+ const nestedPath = stepResult?.payload?.__workflow_meta?.path;
36
+ return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
37
+ }
38
+ return [];
39
+ });
40
+ base.suspended = suspendedStepIds;
41
+ }
42
+ return base;
43
+ }
44
+ var DefaultExecutionEngine = class extends ExecutionEngine {
45
+ /**
46
+ * Executes a workflow run with the provided execution graph and input
47
+ * @param graph The execution graph to execute
48
+ * @param input The input data for the workflow
49
+ * @returns A promise that resolves to the workflow output
50
+ */
51
+ async execute(params) {
52
+ const { workflowId, runId, graph, input, resume, retryConfig } = params;
53
+ const { attempts = 0, delay = 0 } = retryConfig ?? {};
54
+ const steps = graph.steps;
55
+ if (steps.length === 0) {
56
+ throw new Error("Workflow must have at least one step");
57
+ }
58
+ await this.mastra?.getStorage()?.init();
59
+ let startIdx = 0;
60
+ if (resume?.resumePath) {
61
+ startIdx = resume.resumePath[0];
62
+ resume.resumePath.shift();
63
+ }
64
+ const stepResults = resume?.stepResults || { input };
65
+ let lastOutput;
66
+ for (let i = startIdx; i < steps.length; i++) {
67
+ const entry = steps[i];
68
+ try {
69
+ lastOutput = await this.executeEntry({
70
+ workflowId,
71
+ runId,
72
+ entry,
73
+ prevStep: steps[i - 1],
74
+ stepResults,
75
+ resume,
76
+ executionContext: {
77
+ executionPath: [i],
78
+ suspendedPaths: {},
79
+ retryConfig: { attempts, delay }
80
+ },
81
+ emitter: params.emitter,
82
+ runtimeContext: params.runtimeContext
83
+ });
84
+ if (lastOutput.status !== "success") {
85
+ if (entry.type === "step") {
86
+ params.emitter.emit("watch", {
87
+ type: "watch",
88
+ payload: {
89
+ currentStep: {
90
+ id: entry.step.id,
91
+ ...lastOutput
92
+ },
93
+ workflowState: {
94
+ status: lastOutput.status,
95
+ steps: stepResults,
96
+ result: null,
97
+ error: lastOutput.error
98
+ }
99
+ },
100
+ eventTimestamp: Date.now()
101
+ });
102
+ }
103
+ return fmtReturnValue(stepResults, lastOutput);
104
+ }
105
+ } catch (e) {
106
+ this.logger.error("Error executing step: " + (e?.stack ?? e));
107
+ if (entry.type === "step") {
108
+ params.emitter.emit("watch", {
109
+ type: "watch",
110
+ payload: {
111
+ currentStep: {
112
+ id: entry.step.id,
113
+ ...lastOutput
114
+ },
115
+ workflowState: {
116
+ status: "running",
117
+ steps: stepResults,
118
+ result: null,
119
+ error: null
120
+ }
121
+ },
122
+ eventTimestamp: Date.now()
123
+ });
124
+ }
125
+ return fmtReturnValue(stepResults, lastOutput, e);
126
+ }
127
+ }
128
+ params.emitter.emit("watch", {
129
+ type: "watch",
130
+ payload: {
131
+ currentStep: null,
132
+ workflowState: {
133
+ status: lastOutput.status,
134
+ steps: stepResults,
135
+ result: lastOutput.output,
136
+ error: lastOutput.error
137
+ }
138
+ },
139
+ eventTimestamp: Date.now()
140
+ });
141
+ return fmtReturnValue(stepResults, lastOutput);
142
+ }
143
+ getStepOutput(stepResults, step) {
144
+ if (!step) {
145
+ return stepResults.input;
146
+ } else if (step.type === "step") {
147
+ return stepResults[step.step.id]?.output;
148
+ } else if (step.type === "parallel" || step.type === "conditional") {
149
+ return step.steps.reduce(
150
+ (acc, entry) => {
151
+ if (entry.type === "step") {
152
+ acc[entry.step.id] = stepResults[entry.step.id]?.output;
153
+ } else if (entry.type === "parallel" || entry.type === "conditional") {
154
+ const parallelResult = this.getStepOutput(stepResults, entry)?.output;
155
+ acc = { ...acc, ...parallelResult };
156
+ } else if (entry.type === "loop") {
157
+ acc[entry.step.id] = stepResults[entry.step.id]?.output;
158
+ } else if (entry.type === "foreach") {
159
+ acc[entry.step.id] = stepResults[entry.step.id]?.output;
160
+ }
161
+ return acc;
162
+ },
163
+ {}
164
+ );
165
+ } else if (step.type === "loop") {
166
+ return stepResults[step.step.id]?.output;
167
+ } else if (step.type === "foreach") {
168
+ return stepResults[step.step.id]?.output;
169
+ }
170
+ }
171
+ async executeStep({
172
+ step,
173
+ stepResults,
174
+ executionContext,
175
+ resume,
176
+ prevOutput,
177
+ emitter,
178
+ runtimeContext
179
+ }) {
180
+ let execResults;
181
+ const retries = step.retries ?? executionContext.retryConfig.attempts ?? 0;
182
+ for (let i = 0; i < retries + 1; i++) {
183
+ try {
184
+ let suspended;
185
+ const result = await step.execute({
186
+ mastra: this.mastra,
187
+ runtimeContext,
188
+ inputData: prevOutput,
189
+ resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
190
+ getInitData: () => stepResults?.input,
191
+ getStepResult: (step2) => {
192
+ const result2 = stepResults[step2.id];
193
+ if (result2?.status === "success") {
194
+ return result2.output;
195
+ }
196
+ return null;
197
+ },
198
+ suspend: async (suspendPayload) => {
199
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
200
+ suspended = { payload: suspendPayload };
201
+ },
202
+ resume: {
203
+ steps: resume?.steps?.slice(1) || [],
204
+ resumePayload: resume?.resumePayload,
205
+ // @ts-ignore
206
+ runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
207
+ },
208
+ emitter
209
+ });
210
+ if (suspended) {
211
+ execResults = { status: "suspended", payload: suspended.payload };
212
+ } else {
213
+ execResults = { status: "success", output: result };
214
+ }
215
+ break;
216
+ } catch (e) {
217
+ this.logger.error("Error executing step: " + (e?.stack ?? e));
218
+ execResults = { status: "failed", error: e instanceof Error ? e : new Error("Unknown error: " + e) };
219
+ }
220
+ }
221
+ return execResults;
222
+ }
223
+ async executeParallel({
224
+ workflowId,
225
+ runId,
226
+ entry,
227
+ prevStep,
228
+ stepResults,
229
+ resume,
230
+ executionContext,
231
+ emitter,
232
+ runtimeContext
233
+ }) {
234
+ let execResults;
235
+ const results = await Promise.all(
236
+ entry.steps.map(
237
+ (step, i) => this.executeEntry({
238
+ workflowId,
239
+ runId,
240
+ entry: step,
241
+ prevStep,
242
+ stepResults,
243
+ resume,
244
+ executionContext: {
245
+ executionPath: [...executionContext.executionPath, i],
246
+ suspendedPaths: executionContext.suspendedPaths,
247
+ retryConfig: executionContext.retryConfig
248
+ },
249
+ emitter,
250
+ runtimeContext
251
+ })
252
+ )
253
+ );
254
+ const hasFailed = results.find((result) => result.status === "failed");
255
+ const hasSuspended = results.find((result) => result.status === "suspended");
256
+ if (hasFailed) {
257
+ execResults = { status: "failed", error: hasFailed.error };
258
+ } else if (hasSuspended) {
259
+ execResults = { status: "suspended", payload: hasSuspended.payload };
260
+ } else {
261
+ execResults = {
262
+ status: "success",
263
+ output: results.reduce((acc, result, index) => {
264
+ if (result.status === "success") {
265
+ acc[entry.steps[index].step.id] = result.output;
266
+ }
267
+ return acc;
268
+ }, {})
269
+ };
270
+ }
271
+ return execResults;
272
+ }
273
+ async executeConditional({
274
+ workflowId,
275
+ runId,
276
+ entry,
277
+ prevOutput,
278
+ prevStep,
279
+ stepResults,
280
+ resume,
281
+ executionContext,
282
+ emitter,
283
+ runtimeContext
284
+ }) {
285
+ let execResults;
286
+ const truthyIndexes = (await Promise.all(
287
+ entry.conditions.map(async (cond, index) => {
288
+ try {
289
+ const result = await cond({
290
+ mastra: this.mastra,
291
+ runtimeContext,
292
+ inputData: prevOutput,
293
+ getInitData: () => stepResults?.input,
294
+ getStepResult: (step) => {
295
+ if (!step?.id) {
296
+ return null;
297
+ }
298
+ const result2 = stepResults[step.id];
299
+ if (result2?.status === "success") {
300
+ return result2.output;
301
+ }
302
+ return null;
303
+ },
304
+ // TODO: this function shouldn't have suspend probably?
305
+ suspend: async (_suspendPayload) => {
306
+ },
307
+ emitter
308
+ });
309
+ return result ? index : null;
310
+ } catch (e) {
311
+ this.logger.error("Error evaluating condition: " + (e?.stack ?? e));
312
+ return null;
313
+ }
314
+ })
315
+ )).filter((index) => index !== null);
316
+ const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
317
+ const results = await Promise.all(
318
+ stepsToRun.map(
319
+ (step, index) => this.executeEntry({
320
+ workflowId,
321
+ runId,
322
+ entry: step,
323
+ prevStep,
324
+ stepResults,
325
+ resume,
326
+ executionContext: {
327
+ executionPath: [...executionContext.executionPath, index],
328
+ suspendedPaths: executionContext.suspendedPaths,
329
+ retryConfig: executionContext.retryConfig
330
+ },
331
+ emitter,
332
+ runtimeContext
333
+ })
334
+ )
335
+ );
336
+ const hasFailed = results.find((result) => result.status === "failed");
337
+ const hasSuspended = results.find((result) => result.status === "suspended");
338
+ if (hasFailed) {
339
+ execResults = { status: "failed", error: hasFailed.error };
340
+ } else if (hasSuspended) {
341
+ execResults = { status: "suspended", payload: hasSuspended.payload };
342
+ } else {
343
+ execResults = {
344
+ status: "success",
345
+ output: results.reduce((acc, result, index) => {
346
+ if (result.status === "success") {
347
+ acc[stepsToRun[index].step.id] = result.output;
348
+ }
349
+ return acc;
350
+ }, {})
351
+ };
352
+ }
353
+ return execResults;
354
+ }
355
+ async executeLoop({
356
+ entry,
357
+ prevOutput,
358
+ stepResults,
359
+ resume,
360
+ executionContext,
361
+ emitter,
362
+ runtimeContext
363
+ }) {
364
+ const { step, condition } = entry;
365
+ let isTrue = true;
366
+ let result = { status: "success", output: prevOutput };
367
+ do {
368
+ result = await this.executeStep({
369
+ step,
370
+ stepResults,
371
+ executionContext,
372
+ resume,
373
+ prevOutput: result.output,
374
+ emitter,
375
+ runtimeContext
376
+ });
377
+ if (result.status !== "success") {
378
+ return result;
379
+ }
380
+ isTrue = await condition({
381
+ mastra: this.mastra,
382
+ runtimeContext,
383
+ inputData: result.output,
384
+ getInitData: () => stepResults?.input,
385
+ getStepResult: (step2) => {
386
+ if (!step2?.id) {
387
+ return null;
388
+ }
389
+ const result2 = stepResults[step2.id];
390
+ return result2?.status === "success" ? result2.output : null;
391
+ },
392
+ suspend: async (_suspendPayload) => {
393
+ },
394
+ emitter
395
+ });
396
+ } while (entry.loopType === "dowhile" ? isTrue : !isTrue);
397
+ return result;
398
+ }
399
+ async executeForeach({
400
+ entry,
401
+ prevOutput,
402
+ stepResults,
403
+ resume,
404
+ executionContext,
405
+ emitter,
406
+ runtimeContext
407
+ }) {
408
+ const { step, opts } = entry;
409
+ const results = [];
410
+ const concurrency = opts.concurrency;
411
+ for (let i = 0; i < prevOutput.length; i += concurrency) {
412
+ const items = prevOutput.slice(i, i + concurrency);
413
+ const itemsResults = await Promise.all(
414
+ items.map((item) => {
415
+ return this.executeStep({
416
+ step,
417
+ stepResults,
418
+ executionContext,
419
+ resume,
420
+ prevOutput: item,
421
+ emitter,
422
+ runtimeContext
423
+ });
424
+ })
425
+ );
426
+ for (const result of itemsResults) {
427
+ if (result.status !== "success") {
428
+ return result;
429
+ }
430
+ results.push(result?.output);
431
+ }
432
+ }
433
+ return { status: "success", output: results };
434
+ }
435
+ async executeEntry({
436
+ workflowId,
437
+ runId,
438
+ entry,
439
+ prevStep,
440
+ stepResults,
441
+ resume,
442
+ executionContext,
443
+ emitter,
444
+ runtimeContext
445
+ }) {
446
+ const prevOutput = this.getStepOutput(stepResults, prevStep);
447
+ let execResults;
448
+ if (entry.type === "step" || entry.type === "loop" || entry.type === "foreach") {
449
+ emitter.emit("watch", {
450
+ type: "watch",
451
+ payload: {
452
+ currentStep: {
453
+ id: entry.step.id,
454
+ status: "running"
455
+ },
456
+ workflowState: {
457
+ status: "running",
458
+ steps: {
459
+ ...stepResults,
460
+ [entry.step.id]: {
461
+ status: "running"
462
+ }
463
+ },
464
+ result: null,
465
+ error: null
466
+ }
467
+ },
468
+ eventTimestamp: Date.now()
469
+ });
470
+ }
471
+ if (entry.type === "step") {
472
+ const { step } = entry;
473
+ execResults = await this.executeStep({
474
+ step,
475
+ stepResults,
476
+ executionContext,
477
+ resume,
478
+ prevOutput,
479
+ emitter,
480
+ runtimeContext
481
+ });
482
+ } else if (resume?.resumePath?.length && (entry.type === "parallel" || entry.type === "conditional")) {
483
+ const idx = resume.resumePath.shift();
484
+ return this.executeEntry({
485
+ workflowId,
486
+ runId,
487
+ entry: entry.steps[idx],
488
+ prevStep,
489
+ stepResults,
490
+ resume,
491
+ executionContext: {
492
+ executionPath: [...executionContext.executionPath, idx],
493
+ suspendedPaths: executionContext.suspendedPaths,
494
+ retryConfig: executionContext.retryConfig
495
+ },
496
+ emitter,
497
+ runtimeContext
498
+ });
499
+ } else if (entry.type === "parallel") {
500
+ execResults = await this.executeParallel({
501
+ workflowId,
502
+ runId,
503
+ entry,
504
+ prevStep,
505
+ stepResults,
506
+ resume,
507
+ executionContext,
508
+ emitter,
509
+ runtimeContext
510
+ });
511
+ } else if (entry.type === "conditional") {
512
+ execResults = await this.executeConditional({
513
+ workflowId,
514
+ runId,
515
+ entry,
516
+ prevStep,
517
+ prevOutput,
518
+ stepResults,
519
+ resume,
520
+ executionContext,
521
+ emitter,
522
+ runtimeContext
523
+ });
524
+ } else if (entry.type === "loop") {
525
+ execResults = await this.executeLoop({
526
+ workflowId,
527
+ runId,
528
+ entry,
529
+ prevStep,
530
+ prevOutput,
531
+ stepResults,
532
+ resume,
533
+ executionContext,
534
+ emitter,
535
+ runtimeContext
536
+ });
537
+ } else if (entry.type === "foreach") {
538
+ execResults = await this.executeForeach({
539
+ workflowId,
540
+ runId,
541
+ entry,
542
+ prevStep,
543
+ prevOutput,
544
+ stepResults,
545
+ resume,
546
+ executionContext,
547
+ emitter,
548
+ runtimeContext
549
+ });
550
+ }
551
+ if (entry.type === "step" || entry.type === "loop" || entry.type === "foreach") {
552
+ stepResults[entry.step.id] = execResults;
553
+ }
554
+ await this.mastra?.getStorage()?.persistWorkflowSnapshot({
555
+ workflowName: workflowId,
556
+ runId,
557
+ snapshot: {
558
+ runId,
559
+ value: {},
560
+ context: stepResults,
561
+ activePaths: [],
562
+ suspendedPaths: executionContext.suspendedPaths,
563
+ // @ts-ignore
564
+ timestamp: Date.now()
565
+ }
566
+ });
567
+ if (entry.type === "step" || entry.type === "loop" || entry.type === "foreach") {
568
+ emitter.emit("watch", {
569
+ type: "watch",
570
+ payload: {
571
+ currentStep: {
572
+ id: entry.step.id,
573
+ status: execResults.status,
574
+ output: execResults.output
575
+ },
576
+ workflowState: {
577
+ status: "running",
578
+ steps: stepResults,
579
+ result: null,
580
+ error: null
581
+ }
582
+ },
583
+ eventTimestamp: Date.now()
584
+ });
585
+ }
586
+ return execResults;
587
+ }
588
+ };
589
+
590
+ // src/workflows/vNext/workflow.ts
591
+ function createStep(params) {
592
+ if (params instanceof Agent) {
593
+ return {
594
+ id: params.name,
595
+ // @ts-ignore
596
+ inputSchema: z.object({
597
+ prompt: z.string()
598
+ // resourceId: z.string().optional(),
599
+ // threadId: z.string().optional(),
600
+ }),
601
+ // @ts-ignore
602
+ outputSchema: z.object({
603
+ text: z.string()
604
+ }),
605
+ execute: async ({ inputData }) => {
606
+ const result = await params.generate(inputData.prompt, {
607
+ // resourceId: inputData.resourceId,
608
+ // threadId: inputData.threadId,
609
+ });
610
+ return {
611
+ text: result.text
612
+ };
613
+ }
614
+ };
615
+ }
616
+ if (params instanceof Tool) {
617
+ if (!params.inputSchema || !params.outputSchema) {
618
+ throw new Error("Tool must have input and output schemas defined");
619
+ }
620
+ return {
621
+ // TODO: tool probably should have strong id type
622
+ // @ts-ignore
623
+ id: params.id,
624
+ inputSchema: params.inputSchema,
625
+ outputSchema: params.outputSchema,
626
+ execute: async ({ inputData, mastra }) => {
627
+ return await params.execute({
628
+ context: inputData,
629
+ mastra
630
+ });
631
+ }
632
+ };
633
+ }
634
+ return {
635
+ id: params.id,
636
+ description: params.description,
637
+ inputSchema: params.inputSchema,
638
+ outputSchema: params.outputSchema,
639
+ resumeSchema: params.resumeSchema,
640
+ suspendSchema: params.suspendSchema,
641
+ execute: params.execute
642
+ };
643
+ }
644
+ function cloneStep(step, opts) {
645
+ return {
646
+ id: opts.id,
647
+ description: step.description,
648
+ inputSchema: step.inputSchema,
649
+ outputSchema: step.outputSchema,
650
+ execute: step.execute
651
+ };
652
+ }
653
+ function createWorkflow(params) {
654
+ return new NewWorkflow(params);
655
+ }
656
+ var NewWorkflow = class extends MastraBase {
657
+ id;
658
+ description;
659
+ inputSchema;
660
+ outputSchema;
661
+ steps;
662
+ stepFlow;
663
+ executionEngine;
664
+ executionGraph;
665
+ retryConfig;
666
+ #mastra;
667
+ #runs = /* @__PURE__ */ new Map();
668
+ constructor({
669
+ mastra,
670
+ id,
671
+ inputSchema,
672
+ outputSchema,
673
+ description,
674
+ executionEngine,
675
+ retryConfig
676
+ }) {
677
+ super({ name: id, component: RegisteredLogger.WORKFLOW });
678
+ this.id = id;
679
+ this.description = description;
680
+ this.inputSchema = inputSchema;
681
+ this.outputSchema = outputSchema;
682
+ this.retryConfig = retryConfig ?? { attempts: 0, delay: 0 };
683
+ this.executionGraph = this.buildExecutionGraph();
684
+ this.stepFlow = [];
685
+ this.#mastra = mastra;
686
+ this.steps = {};
687
+ if (!executionEngine) {
688
+ this.executionEngine = new DefaultExecutionEngine({ mastra: this.#mastra });
689
+ } else {
690
+ this.executionEngine = executionEngine;
691
+ }
692
+ this.#runs = /* @__PURE__ */ new Map();
693
+ }
694
+ __registerMastra(mastra) {
695
+ this.#mastra = mastra;
696
+ this.executionEngine.__registerMastra(mastra);
697
+ }
698
+ __registerPrimitives(p) {
699
+ if (p.telemetry) {
700
+ this.__setTelemetry(p.telemetry);
701
+ }
702
+ if (p.logger) {
703
+ this.__setLogger(p.logger);
704
+ }
705
+ }
706
+ /**
707
+ * Adds a step to the workflow
708
+ * @param step The step to add to the workflow
709
+ * @returns The workflow instance for chaining
710
+ */
711
+ then(step) {
712
+ this.stepFlow.push({ type: "step", step });
713
+ this.steps[step.id] = step;
714
+ return this;
715
+ }
716
+ map(mappingConfig) {
717
+ const mappingStep = createStep({
718
+ id: `mapping_${randomUUID()}`,
719
+ inputSchema: z.object({}),
720
+ outputSchema: z.object({}),
721
+ execute: async ({ getStepResult, getInitData, runtimeContext }) => {
722
+ const result = {};
723
+ for (const [key, mapping] of Object.entries(mappingConfig)) {
724
+ const m = mapping;
725
+ if (m.value) {
726
+ result[key] = m.value;
727
+ continue;
728
+ }
729
+ if (m.runtimeContextPath) {
730
+ result[key] = runtimeContext.get(m.runtimeContextPath);
731
+ continue;
732
+ }
733
+ const stepResult = m.initData ? getInitData() : getStepResult(m.step);
734
+ if (m.path === ".") {
735
+ result[key] = stepResult;
736
+ continue;
737
+ }
738
+ const pathParts = m.path.split(".");
739
+ let value = stepResult;
740
+ for (const part of pathParts) {
741
+ if (typeof value === "object" && value !== null) {
742
+ value = value[part];
743
+ } else {
744
+ throw new Error(`Invalid path ${m.path} in step ${m.step.id}`);
745
+ }
746
+ }
747
+ result[key] = value;
748
+ }
749
+ return result;
750
+ }
751
+ });
752
+ this.stepFlow.push({ type: "step", step: mappingStep });
753
+ return this;
754
+ }
755
+ // TODO: make typing better here
756
+ parallel(steps) {
757
+ this.stepFlow.push({ type: "parallel", steps: steps.map((step) => ({ type: "step", step })) });
758
+ steps.forEach((step) => {
759
+ this.steps[step.id] = step;
760
+ });
761
+ return this;
762
+ }
763
+ // TODO: make typing better here
764
+ branch(steps) {
765
+ this.stepFlow.push({
766
+ type: "conditional",
767
+ steps: steps.map(([_cond, step]) => ({ type: "step", step })),
768
+ conditions: steps.map(([cond]) => cond),
769
+ serializedConditions: steps.map(([cond, _step]) => ({ id: `${_step.id}-condition`, fn: cond.toString() }))
770
+ });
771
+ steps.forEach(([_, step]) => {
772
+ this.steps[step.id] = step;
773
+ });
774
+ return this;
775
+ }
776
+ dowhile(step, condition) {
777
+ this.stepFlow.push({
778
+ type: "loop",
779
+ step,
780
+ condition,
781
+ loopType: "dowhile",
782
+ serializedCondition: { id: `${step.id}-condition`, fn: condition.toString() }
783
+ });
784
+ this.steps[step.id] = step;
785
+ return this;
786
+ }
787
+ dountil(step, condition) {
788
+ this.stepFlow.push({
789
+ type: "loop",
790
+ step,
791
+ condition,
792
+ loopType: "dountil",
793
+ serializedCondition: { id: `${step.id}-condition`, fn: condition.toString() }
794
+ });
795
+ this.steps[step.id] = step;
796
+ return this;
797
+ }
798
+ foreach(step, opts) {
799
+ this.stepFlow.push({ type: "foreach", step, opts: opts ?? { concurrency: 1 } });
800
+ this.steps[step.id] = step;
801
+ return this;
802
+ }
803
+ /**
804
+ * Builds the execution graph for this workflow
805
+ * @returns The execution graph that can be used to execute the workflow
806
+ */
807
+ buildExecutionGraph() {
808
+ return {
809
+ id: randomUUID(),
810
+ steps: this.stepFlow
811
+ };
812
+ }
813
+ /**
814
+ * Finalizes the workflow definition and prepares it for execution
815
+ * This method should be called after all steps have been added to the workflow
816
+ * @returns A built workflow instance ready for execution
817
+ */
818
+ commit() {
819
+ this.executionGraph = this.buildExecutionGraph();
820
+ return this;
821
+ }
822
+ get stepGraph() {
823
+ return this.stepFlow;
824
+ }
825
+ /**
826
+ * Creates a new workflow run instance
827
+ * @param options Optional configuration for the run
828
+ * @returns A Run instance that can be used to execute the workflow
829
+ */
830
+ createRun(options) {
831
+ const runIdToUse = options?.runId || randomUUID();
832
+ const run = this.#runs.get(runIdToUse) ?? new Run({
833
+ workflowId: this.id,
834
+ runId: runIdToUse,
835
+ executionEngine: this.executionEngine,
836
+ executionGraph: this.executionGraph,
837
+ mastra: this.#mastra,
838
+ retryConfig: this.retryConfig,
839
+ cleanup: () => this.#runs.delete(runIdToUse)
840
+ });
841
+ this.#runs.set(runIdToUse, run);
842
+ return run;
843
+ }
844
+ async execute({
845
+ inputData,
846
+ resumeData,
847
+ suspend,
848
+ resume,
849
+ emitter,
850
+ mastra
851
+ }) {
852
+ this.__registerMastra(mastra);
853
+ const run = resume?.steps?.length ? this.createRun({ runId: resume.runId }) : this.createRun();
854
+ const unwatch = run.watch((event) => {
855
+ emitter.emit("nested-watch", { event, workflowId: this.id, runId: run.runId, isResume: !!resume?.steps?.length });
856
+ });
857
+ const res = resume?.steps?.length ? await run.resume({ resumeData, step: resume.steps }) : await run.start({ inputData });
858
+ unwatch();
859
+ const suspendedSteps = Object.entries(res.steps).filter(([_stepName, stepResult]) => {
860
+ const stepRes = stepResult;
861
+ return stepRes?.status === "suspended";
862
+ });
863
+ if (suspendedSteps?.length) {
864
+ for (const [stepName, stepResult] of suspendedSteps) {
865
+ const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
866
+ await suspend({
867
+ ...stepResult?.payload,
868
+ __workflow_meta: { runId: run.runId, path: suspendPath }
869
+ });
870
+ }
871
+ }
872
+ if (res.status === "failed") {
873
+ throw res.error;
874
+ }
875
+ return res.status === "success" ? res.result : void 0;
876
+ }
877
+ async getWorkflowRuns() {
878
+ const storage = this.#mastra?.getStorage();
879
+ if (!storage) {
880
+ this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
881
+ return { runs: [], total: 0 };
882
+ }
883
+ return storage.getWorkflowRuns({ workflowName: this.id });
884
+ }
885
+ async getWorkflowRun(runId) {
886
+ const runs = await this.getWorkflowRuns();
887
+ return runs?.runs.find((r) => r.runId === runId) || this.#runs.get(runId);
888
+ }
889
+ };
890
+ var Run = class {
891
+ emitter;
892
+ /**
893
+ * Unique identifier for this workflow
894
+ */
895
+ workflowId;
896
+ /**
897
+ * Unique identifier for this run
898
+ */
899
+ runId;
900
+ /**
901
+ * Internal state of the workflow run
902
+ */
903
+ state = {};
904
+ /**
905
+ * The execution engine for this run
906
+ */
907
+ executionEngine;
908
+ /**
909
+ * The execution graph for this run
910
+ */
911
+ executionGraph;
912
+ /**
913
+ * The storage for this run
914
+ */
915
+ #mastra;
916
+ cleanup;
917
+ retryConfig;
918
+ constructor(params) {
919
+ this.workflowId = params.workflowId;
920
+ this.runId = params.runId;
921
+ this.executionEngine = params.executionEngine;
922
+ this.executionGraph = params.executionGraph;
923
+ this.#mastra = params.mastra;
924
+ this.emitter = new EventEmitter();
925
+ this.retryConfig = params.retryConfig;
926
+ this.cleanup = params.cleanup;
927
+ }
928
+ /**
929
+ * Starts the workflow execution with the provided input
930
+ * @param input The input data for the workflow
931
+ * @returns A promise that resolves to the workflow output
932
+ */
933
+ async start({
934
+ inputData,
935
+ runtimeContext
936
+ }) {
937
+ const result = await this.executionEngine.execute({
938
+ workflowId: this.workflowId,
939
+ runId: this.runId,
940
+ graph: this.executionGraph,
941
+ input: inputData,
942
+ emitter: this.emitter,
943
+ retryConfig: this.retryConfig,
944
+ runtimeContext: runtimeContext ?? new RuntimeContext()
945
+ });
946
+ this.cleanup?.();
947
+ return result;
948
+ }
949
+ watch(cb) {
950
+ this.emitter.on("watch", ({ type, payload, eventTimestamp }) => {
951
+ this.updateState(payload);
952
+ cb({ type, payload: this.getState(), eventTimestamp });
953
+ });
954
+ this.emitter.on("nested-watch", ({ event, workflowId }) => {
955
+ try {
956
+ const { type, payload, eventTimestamp } = event;
957
+ const prefixedSteps = Object.fromEntries(
958
+ Object.entries(payload?.workflowState?.steps ?? {}).map(([stepId, step]) => [
959
+ `${workflowId}.${stepId}`,
960
+ step
961
+ ])
962
+ );
963
+ const newPayload = {
964
+ currentStep: {
965
+ ...payload?.currentStep,
966
+ id: `${workflowId}.${payload?.currentStep?.id}`
967
+ },
968
+ workflowState: {
969
+ ...payload?.workflowState,
970
+ steps: prefixedSteps
971
+ }
972
+ };
973
+ this.updateState(newPayload);
974
+ cb({ type, payload: this.getState(), eventTimestamp });
975
+ } catch (e) {
976
+ console.error(e);
977
+ }
978
+ });
979
+ return () => {
980
+ this.emitter.off("watch", cb);
981
+ };
982
+ }
983
+ async resume(params) {
984
+ const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
985
+ (step) => typeof step === "string" ? step : step?.id
986
+ );
987
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
988
+ workflowName: this.workflowId,
989
+ runId: this.runId
990
+ });
991
+ return this.executionEngine.execute({
992
+ workflowId: this.workflowId,
993
+ runId: this.runId,
994
+ graph: this.executionGraph,
995
+ input: params.resumeData,
996
+ resume: {
997
+ steps,
998
+ stepResults: snapshot?.context,
999
+ resumePayload: params.resumeData,
1000
+ // @ts-ignore
1001
+ resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
1002
+ },
1003
+ emitter: this.emitter,
1004
+ runtimeContext: params.runtimeContext ?? new RuntimeContext()
1005
+ });
1006
+ }
1007
+ /**
1008
+ * Returns the current state of the workflow run
1009
+ * @returns The current state of the workflow run
1010
+ */
1011
+ getState() {
1012
+ return this.state;
1013
+ }
1014
+ updateState(state) {
1015
+ if (state.currentStep) {
1016
+ this.state.currentStep = state.currentStep;
1017
+ }
1018
+ if (state.workflowState) {
1019
+ this.state.workflowState = deepMerge(this.state.workflowState ?? {}, state.workflowState ?? {});
1020
+ }
1021
+ }
1022
+ };
1023
+ function deepMerge(a, b) {
1024
+ if (!a || typeof a !== "object") return b;
1025
+ if (!b || typeof b !== "object") return a;
1026
+ const result = { ...a };
1027
+ for (const key in b) {
1028
+ if (b[key] === void 0) continue;
1029
+ if (b[key] !== null && typeof b[key] === "object") {
1030
+ const aVal = result[key];
1031
+ const bVal = b[key];
1032
+ if (Array.isArray(bVal)) {
1033
+ result[key] = Array.isArray(aVal) ? [...aVal, ...bVal].filter((item) => item !== void 0) : bVal.filter((item) => item !== void 0);
1034
+ } else if (typeof aVal === "object" && aVal !== null) {
1035
+ result[key] = deepMerge(aVal, bVal);
1036
+ } else {
1037
+ result[key] = bVal;
1038
+ }
1039
+ } else {
1040
+ result[key] = b[key];
1041
+ }
1042
+ }
1043
+ return result;
1044
+ }
1045
+
1046
+ export { DefaultExecutionEngine, ExecutionEngine, NewWorkflow, Run, cloneStep, createStep, createWorkflow };