@mastra/core 0.0.0-commonjs-20250227130920

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 (137) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +180 -0
  3. package/dist/agent/index.cjs +1865 -0
  4. package/dist/agent/index.d.cts +15 -0
  5. package/dist/agent/index.d.ts +15 -0
  6. package/dist/agent/index.js +1 -0
  7. package/dist/base-D90KQ4XI.d.ts +139 -0
  8. package/dist/base-hs9NDAZ2.d.cts +139 -0
  9. package/dist/base-nKCMCNrM.d.ts +920 -0
  10. package/dist/base-nhesrHv3.d.cts +920 -0
  11. package/dist/base.cjs +138 -0
  12. package/dist/base.d.cts +6 -0
  13. package/dist/base.d.ts +6 -0
  14. package/dist/base.js +1 -0
  15. package/dist/bundler/index.cjs +158 -0
  16. package/dist/bundler/index.d.cts +28 -0
  17. package/dist/bundler/index.d.ts +28 -0
  18. package/dist/bundler/index.js +1 -0
  19. package/dist/chunk-33GSTUNK.js +620 -0
  20. package/dist/chunk-4YRYBCOZ.js +10 -0
  21. package/dist/chunk-55NFNRKO.js +10 -0
  22. package/dist/chunk-5XPCMNGW.js +215 -0
  23. package/dist/chunk-B3M27AMP.js +1479 -0
  24. package/dist/chunk-BB4KXGBU.js +83 -0
  25. package/dist/chunk-C6A6W6XS.js +77 -0
  26. package/dist/chunk-HQ55LN2U.js +318 -0
  27. package/dist/chunk-KNVTCZW7.js +416 -0
  28. package/dist/chunk-LH47WVJL.js +61 -0
  29. package/dist/chunk-NGD2HQYW.js +346 -0
  30. package/dist/chunk-NUDAZEOG.js +35 -0
  31. package/dist/chunk-OZ4XVJ6F.js +49 -0
  32. package/dist/chunk-PHMSPCTC.js +145 -0
  33. package/dist/chunk-PNZK456O.js +88 -0
  34. package/dist/chunk-QAAJAHDB.js +37 -0
  35. package/dist/chunk-RG66XEJT.js +8 -0
  36. package/dist/chunk-SIFBBGY6.js +190 -0
  37. package/dist/chunk-SVEAENO7.js +22 -0
  38. package/dist/chunk-SY5244IR.js +1499 -0
  39. package/dist/chunk-W5HVJX45.js +402 -0
  40. package/dist/chunk-WIBGG4X6.js +173 -0
  41. package/dist/chunk-ZDWFBE5L.js +1 -0
  42. package/dist/chunk-ZINPRHAN.js +22 -0
  43. package/dist/deployer/index.cjs +165 -0
  44. package/dist/deployer/index.d.cts +19 -0
  45. package/dist/deployer/index.d.ts +19 -0
  46. package/dist/deployer/index.js +1 -0
  47. package/dist/eval/index.cjs +110 -0
  48. package/dist/eval/index.d.cts +28 -0
  49. package/dist/eval/index.d.ts +28 -0
  50. package/dist/eval/index.js +1 -0
  51. package/dist/filter/index.cjs +192 -0
  52. package/dist/filter/index.d.cts +90 -0
  53. package/dist/filter/index.d.ts +90 -0
  54. package/dist/filter/index.js +1 -0
  55. package/dist/hooks/index.cjs +87 -0
  56. package/dist/hooks/index.d.cts +33 -0
  57. package/dist/hooks/index.d.ts +33 -0
  58. package/dist/hooks/index.js +1 -0
  59. package/dist/index-mKY1XrpK.d.cts +90 -0
  60. package/dist/index-mKY1XrpK.d.ts +90 -0
  61. package/dist/index.cjs +6844 -0
  62. package/dist/index.d.cts +97 -0
  63. package/dist/index.d.ts +97 -0
  64. package/dist/index.js +119 -0
  65. package/dist/integration/index.cjs +113 -0
  66. package/dist/integration/index.d.cts +52 -0
  67. package/dist/integration/index.d.ts +52 -0
  68. package/dist/integration/index.js +1 -0
  69. package/dist/llm/index.cjs +2 -0
  70. package/dist/llm/index.d.cts +15 -0
  71. package/dist/llm/index.d.ts +15 -0
  72. package/dist/llm/index.js +1 -0
  73. package/dist/logger/index.cjs +159 -0
  74. package/dist/logger/index.d.cts +3 -0
  75. package/dist/logger/index.d.ts +3 -0
  76. package/dist/logger/index.js +1 -0
  77. package/dist/mastra/index.cjs +1741 -0
  78. package/dist/mastra/index.d.cts +67 -0
  79. package/dist/mastra/index.d.ts +67 -0
  80. package/dist/mastra/index.js +1 -0
  81. package/dist/memory/index.cjs +1907 -0
  82. package/dist/memory/index.d.cts +15 -0
  83. package/dist/memory/index.d.ts +15 -0
  84. package/dist/memory/index.js +1 -0
  85. package/dist/relevance/index.cjs +1927 -0
  86. package/dist/relevance/index.d.cts +21 -0
  87. package/dist/relevance/index.d.ts +21 -0
  88. package/dist/relevance/index.js +1 -0
  89. package/dist/storage/index.cjs +361 -0
  90. package/dist/storage/index.d.cts +15 -0
  91. package/dist/storage/index.d.ts +15 -0
  92. package/dist/storage/index.js +2 -0
  93. package/dist/storage/libsql/index.cjs +770 -0
  94. package/dist/storage/libsql/index.d.cts +81 -0
  95. package/dist/storage/libsql/index.d.ts +81 -0
  96. package/dist/storage/libsql/index.js +1 -0
  97. package/dist/telemetry/index.cjs +413 -0
  98. package/dist/telemetry/index.d.cts +51 -0
  99. package/dist/telemetry/index.d.ts +51 -0
  100. package/dist/telemetry/index.js +1 -0
  101. package/dist/telemetry/otel-vendor.cjs +52 -0
  102. package/dist/telemetry/otel-vendor.d.cts +7 -0
  103. package/dist/telemetry/otel-vendor.d.ts +7 -0
  104. package/dist/telemetry/otel-vendor.js +7 -0
  105. package/dist/tools/index.cjs +25 -0
  106. package/dist/tools/index.d.cts +29 -0
  107. package/dist/tools/index.d.ts +29 -0
  108. package/dist/tools/index.js +1 -0
  109. package/dist/tts/index.cjs +328 -0
  110. package/dist/tts/index.d.cts +28 -0
  111. package/dist/tts/index.d.ts +28 -0
  112. package/dist/tts/index.js +1 -0
  113. package/dist/types-m9RryK9a.d.cts +14 -0
  114. package/dist/types-m9RryK9a.d.ts +14 -0
  115. package/dist/utils.cjs +179 -0
  116. package/dist/utils.d.cts +26 -0
  117. package/dist/utils.d.ts +26 -0
  118. package/dist/utils.js +1 -0
  119. package/dist/vector/index.cjs +145 -0
  120. package/dist/vector/index.d.cts +30 -0
  121. package/dist/vector/index.d.ts +30 -0
  122. package/dist/vector/index.js +1 -0
  123. package/dist/vector/libsql/index.cjs +951 -0
  124. package/dist/vector/libsql/index.d.cts +29 -0
  125. package/dist/vector/libsql/index.d.ts +29 -0
  126. package/dist/vector/libsql/index.js +1 -0
  127. package/dist/voice/index.cjs +369 -0
  128. package/dist/voice/index.d.cts +67 -0
  129. package/dist/voice/index.d.ts +67 -0
  130. package/dist/voice/index.js +76 -0
  131. package/dist/workflow-DqQ4pON_.d.cts +84 -0
  132. package/dist/workflow-Ng_F_Zaf.d.ts +84 -0
  133. package/dist/workflows/index.cjs +1628 -0
  134. package/dist/workflows/index.d.cts +48 -0
  135. package/dist/workflows/index.d.ts +48 -0
  136. package/dist/workflows/index.js +1 -0
  137. package/package.json +162 -0
@@ -0,0 +1,1479 @@
1
+ import { MastraBase } from './chunk-OZ4XVJ6F.js';
2
+ import { setTimeout } from 'node:timers/promises';
3
+ import { context, trace } from '@opentelemetry/api';
4
+ import EventEmitter from 'node:events';
5
+ import { get } from 'radash';
6
+ import sift from 'sift';
7
+ import { createActor, assign, fromPromise, setup } from 'xstate';
8
+
9
+ // src/workflows/utils.ts
10
+ function isErrorEvent(stateEvent) {
11
+ return stateEvent.type.startsWith("xstate.error.actor.");
12
+ }
13
+ function isTransitionEvent(stateEvent) {
14
+ return stateEvent.type.startsWith("xstate.done.actor.");
15
+ }
16
+ function isVariableReference(value) {
17
+ return typeof value === "object" && "step" in value && "path" in value;
18
+ }
19
+ function getStepResult(result) {
20
+ if (result?.status === "success") return result.output;
21
+ return void 0;
22
+ }
23
+ function getSuspendedPaths({
24
+ value,
25
+ path,
26
+ suspendedPaths
27
+ }) {
28
+ if (typeof value === "string") {
29
+ if (value === "suspended") {
30
+ suspendedPaths.add(path);
31
+ }
32
+ } else {
33
+ Object.keys(value).forEach(
34
+ (key) => getSuspendedPaths({ value: value[key], path: path ? `${path}.${key}` : key, suspendedPaths })
35
+ );
36
+ }
37
+ }
38
+ function isFinalState(status) {
39
+ return ["completed", "failed"].includes(status);
40
+ }
41
+ function recursivelyCheckForFinalState({
42
+ value,
43
+ suspendedPaths,
44
+ path
45
+ }) {
46
+ if (typeof value === "string") {
47
+ return isFinalState(value) || suspendedPaths.has(path);
48
+ }
49
+ return Object.keys(value).every(
50
+ (key) => recursivelyCheckForFinalState({ value: value[key], suspendedPaths, path: path ? `${path}.${key}` : key })
51
+ );
52
+ }
53
+ function getActivePathsAndStatus(value) {
54
+ const paths = [];
55
+ const traverse = (current, path = []) => {
56
+ for (const [key, value2] of Object.entries(current)) {
57
+ const currentPath = [...path, key];
58
+ if (typeof value2 === "string") {
59
+ paths.push({
60
+ stepPath: currentPath,
61
+ stepId: key,
62
+ status: value2
63
+ });
64
+ } else if (typeof value2 === "object" && value2 !== null) {
65
+ traverse(value2, currentPath);
66
+ }
67
+ }
68
+ };
69
+ traverse(value);
70
+ return paths;
71
+ }
72
+ function mergeChildValue(startStepId, parent, child) {
73
+ const traverse = (current) => {
74
+ const obj = {};
75
+ for (const [key, value] of Object.entries(current)) {
76
+ if (key === startStepId) {
77
+ obj[key] = { ...child };
78
+ } else if (typeof value === "string") {
79
+ obj[key] = value;
80
+ } else if (typeof value === "object" && value !== null) {
81
+ obj[key] = traverse(value);
82
+ }
83
+ }
84
+ return obj;
85
+ };
86
+ return traverse(parent);
87
+ }
88
+ var updateStepInHierarchy = (value, targetStepId) => {
89
+ const result = {};
90
+ for (const key of Object.keys(value)) {
91
+ const currentValue = value[key];
92
+ if (key === targetStepId) {
93
+ result[key] = "pending";
94
+ } else if (typeof currentValue === "object" && currentValue !== null) {
95
+ result[key] = updateStepInHierarchy(currentValue, targetStepId);
96
+ } else {
97
+ result[key] = currentValue;
98
+ }
99
+ }
100
+ return result;
101
+ };
102
+ var Machine = class extends EventEmitter {
103
+ logger;
104
+ #mastra;
105
+ #workflowInstance;
106
+ #executionSpan;
107
+ #stepGraph;
108
+ #machine;
109
+ #runId;
110
+ #startStepId;
111
+ name;
112
+ #actor = null;
113
+ #steps = {};
114
+ #retryConfig;
115
+ constructor({
116
+ logger,
117
+ mastra,
118
+ workflowInstance,
119
+ executionSpan,
120
+ name,
121
+ runId,
122
+ steps,
123
+ stepGraph,
124
+ retryConfig,
125
+ startStepId
126
+ }) {
127
+ super();
128
+ this.#mastra = mastra;
129
+ this.#workflowInstance = workflowInstance;
130
+ this.#executionSpan = executionSpan;
131
+ this.logger = logger;
132
+ this.#runId = runId;
133
+ this.#startStepId = startStepId;
134
+ this.name = name;
135
+ this.#stepGraph = stepGraph;
136
+ this.#steps = steps;
137
+ this.#retryConfig = retryConfig;
138
+ this.initializeMachine();
139
+ }
140
+ get startStepId() {
141
+ return this.#startStepId;
142
+ }
143
+ async execute({
144
+ stepId,
145
+ input,
146
+ snapshot
147
+ } = {}) {
148
+ if (snapshot) {
149
+ this.logger.debug(`Workflow snapshot received`, { runId: this.#runId, snapshot });
150
+ }
151
+ this.logger.debug(`Machine input prepared`, { runId: this.#runId, input });
152
+ const actorSnapshot = snapshot ? {
153
+ ...snapshot,
154
+ context: input
155
+ } : void 0;
156
+ this.logger.debug(`Creating actor with configuration`, {
157
+ input,
158
+ actorSnapshot,
159
+ runId: this.#runId,
160
+ machineStates: this.#machine.config.states
161
+ });
162
+ this.#actor = createActor(this.#machine, {
163
+ inspect: (inspectionEvent) => {
164
+ this.logger.debug("XState inspection event", {
165
+ type: inspectionEvent.type,
166
+ event: inspectionEvent.event,
167
+ runId: this.#runId
168
+ });
169
+ },
170
+ input,
171
+ snapshot: actorSnapshot
172
+ });
173
+ this.#actor.start();
174
+ if (stepId) {
175
+ this.#actor.send({ type: "RESET_TO_PENDING", stepId });
176
+ }
177
+ this.logger.debug("Actor started", { runId: this.#runId });
178
+ return new Promise((resolve, reject) => {
179
+ if (!this.#actor) {
180
+ const e = new Error("Actor not initialized");
181
+ this.#executionSpan?.recordException(e);
182
+ this.#executionSpan?.end();
183
+ reject(e);
184
+ return;
185
+ }
186
+ const suspendedPaths = /* @__PURE__ */ new Set();
187
+ this.#actor.subscribe(async (state) => {
188
+ this.emit("state-update", this.#startStepId, state.value, state.context);
189
+ getSuspendedPaths({
190
+ value: state.value,
191
+ path: "",
192
+ suspendedPaths
193
+ });
194
+ const allStatesValue = state.value;
195
+ const allStatesComplete = recursivelyCheckForFinalState({
196
+ value: allStatesValue,
197
+ suspendedPaths,
198
+ path: ""
199
+ });
200
+ this.logger.debug("State completion check", {
201
+ allStatesComplete,
202
+ suspendedPaths: Array.from(suspendedPaths),
203
+ runId: this.#runId
204
+ });
205
+ if (!allStatesComplete) return;
206
+ try {
207
+ await this.#workflowInstance.persistWorkflowSnapshot();
208
+ this.#cleanup();
209
+ this.#executionSpan?.end();
210
+ resolve({
211
+ results: state.context.steps
212
+ });
213
+ } catch (error) {
214
+ this.logger.debug("Failed to persist final snapshot", { error });
215
+ this.#cleanup();
216
+ this.#executionSpan?.end();
217
+ resolve({
218
+ results: state.context.steps
219
+ });
220
+ }
221
+ });
222
+ });
223
+ }
224
+ #cleanup() {
225
+ if (this.#actor) {
226
+ this.#actor.stop();
227
+ this.#actor = null;
228
+ }
229
+ this.removeAllListeners();
230
+ }
231
+ #makeDelayMap() {
232
+ const delayMap = {};
233
+ Object.keys(this.#steps).forEach((stepId) => {
234
+ delayMap[stepId] = this.#steps[stepId]?.retryConfig?.delay || this.#retryConfig?.delay || 1e3;
235
+ });
236
+ return delayMap;
237
+ }
238
+ #getDefaultActions() {
239
+ return {
240
+ updateStepResult: assign({
241
+ steps: ({ context, event }) => {
242
+ if (!isTransitionEvent(event)) return context.steps;
243
+ const { stepId, result } = event.output;
244
+ return {
245
+ ...context.steps,
246
+ [stepId]: {
247
+ status: "success",
248
+ output: result
249
+ }
250
+ };
251
+ }
252
+ }),
253
+ setStepError: assign({
254
+ steps: ({ context, event }, params) => {
255
+ if (!isErrorEvent(event)) return context.steps;
256
+ const { stepId } = params;
257
+ if (!stepId) return context.steps;
258
+ return {
259
+ ...context.steps,
260
+ [stepId]: {
261
+ status: "failed",
262
+ error: event.error.message
263
+ }
264
+ };
265
+ }
266
+ }),
267
+ notifyStepCompletion: async (_, params) => {
268
+ const { stepId } = params;
269
+ this.logger.debug(`Step ${stepId} completed`);
270
+ },
271
+ snapshotStep: assign({
272
+ _snapshot: ({}, params) => {
273
+ const { stepId } = params;
274
+ return { stepId };
275
+ }
276
+ }),
277
+ persistSnapshot: async ({ context }) => {
278
+ if (context._snapshot) {
279
+ await this.#workflowInstance.persistWorkflowSnapshot();
280
+ }
281
+ return;
282
+ },
283
+ decrementAttemptCount: assign({
284
+ attempts: ({ context, event }, params) => {
285
+ if (!isTransitionEvent(event)) return context.attempts;
286
+ const { stepId } = params;
287
+ const attemptCount = context.attempts[stepId];
288
+ if (attemptCount === void 0) return context.attempts;
289
+ return { ...context.attempts, [stepId]: attemptCount - 1 };
290
+ }
291
+ })
292
+ };
293
+ }
294
+ #getDefaultActors() {
295
+ return {
296
+ resolverFunction: fromPromise(async ({ input }) => {
297
+ const { stepNode, context } = input;
298
+ const resolvedData = this.#resolveVariables({
299
+ stepConfig: stepNode.config,
300
+ context,
301
+ stepId: stepNode.step.id
302
+ });
303
+ this.logger.debug(`Resolved variables for ${stepNode.step.id}`, {
304
+ resolvedData,
305
+ runId: this.#runId
306
+ });
307
+ const result = await stepNode.config.handler({
308
+ context: resolvedData,
309
+ suspend: async () => {
310
+ await this.#workflowInstance.suspend(stepNode.step.id, this);
311
+ if (this.#actor) {
312
+ context.steps[stepNode.step.id] = {
313
+ status: "suspended"
314
+ };
315
+ this.logger.debug(`Sending SUSPENDED event for step ${stepNode.step.id}`);
316
+ this.#actor?.send({ type: "SUSPENDED", stepId: stepNode.step.id });
317
+ } else {
318
+ this.logger.debug(`Actor not available for step ${stepNode.step.id}`);
319
+ }
320
+ },
321
+ runId: this.#runId,
322
+ mastra: this.#mastra
323
+ });
324
+ this.logger.debug(`Step ${stepNode.step.id} result`, {
325
+ stepId: stepNode.step.id,
326
+ result,
327
+ runId: this.#runId
328
+ });
329
+ return {
330
+ stepId: stepNode.step.id,
331
+ result
332
+ };
333
+ }),
334
+ conditionCheck: fromPromise(async ({ input }) => {
335
+ const { context, stepNode } = input;
336
+ const stepConfig = stepNode.config;
337
+ const attemptCount = context.attempts[stepNode.step.id];
338
+ this.logger.debug(`Checking conditions for step ${stepNode.step.id}`, {
339
+ stepId: stepNode.step.id,
340
+ runId: this.#runId
341
+ });
342
+ this.logger.debug(`Attempt count for step ${stepNode.step.id}`, {
343
+ attemptCount,
344
+ attempts: context.attempts,
345
+ runId: this.#runId,
346
+ stepId: stepNode.step.id
347
+ });
348
+ if (!attemptCount || attemptCount < 0) {
349
+ if (stepConfig?.snapshotOnTimeout) {
350
+ return { type: "SUSPENDED", stepId: stepNode.step.id };
351
+ }
352
+ return { type: "CONDITION_FAILED", error: `Step:${stepNode.step.id} condition check failed` };
353
+ }
354
+ if (!stepConfig?.when) {
355
+ return { type: "CONDITIONS_MET" };
356
+ }
357
+ this.logger.debug(`Checking conditions for step ${stepNode.step.id}`, {
358
+ stepId: stepNode.step.id,
359
+ runId: this.#runId
360
+ });
361
+ if (typeof stepConfig?.when === "function") {
362
+ const conditionMet = await stepConfig.when({
363
+ context: {
364
+ ...context,
365
+ getStepResult: (stepId) => {
366
+ if (stepId === "trigger") {
367
+ return context.triggerData;
368
+ }
369
+ const result = context.steps[stepId];
370
+ if (result && result.status === "success") {
371
+ return result.output;
372
+ }
373
+ return void 0;
374
+ }
375
+ },
376
+ mastra: this.#mastra
377
+ });
378
+ if (conditionMet) {
379
+ this.logger.debug(`Condition met for step ${stepNode.step.id}`, {
380
+ stepId: stepNode.step.id,
381
+ runId: this.#runId
382
+ });
383
+ return { type: "CONDITIONS_MET" };
384
+ }
385
+ if (!attemptCount || attemptCount < 0) {
386
+ return { type: "CONDITION_FAILED", error: `Step:${stepNode.step.id} condition check failed` };
387
+ }
388
+ return { type: "WAITING", stepId: stepNode.step.id };
389
+ } else {
390
+ const conditionMet = this.#evaluateCondition(stepConfig.when, context);
391
+ if (!conditionMet) {
392
+ return {
393
+ type: "CONDITION_FAILED",
394
+ error: `Step:${stepNode.step.id} condition check failed`
395
+ };
396
+ }
397
+ }
398
+ return { type: "CONDITIONS_MET" };
399
+ }),
400
+ spawnSubscriberFunction: fromPromise(
401
+ async ({
402
+ input
403
+ }) => {
404
+ const { parentStepId, context } = input;
405
+ const result = await this.#workflowInstance.runMachine(parentStepId, context);
406
+ return Promise.resolve({ steps: result?.results });
407
+ }
408
+ )
409
+ };
410
+ }
411
+ #resolveVariables({
412
+ stepConfig,
413
+ context,
414
+ stepId
415
+ }) {
416
+ this.logger.debug(`Resolving variables for step ${stepId}`, {
417
+ stepId,
418
+ runId: this.#runId
419
+ });
420
+ const resolvedData = {
421
+ ...context,
422
+ getStepResult: (stepId2) => {
423
+ if (stepId2 === "trigger") {
424
+ return context.triggerData;
425
+ }
426
+ const result = context.steps[stepId2];
427
+ if (result && result.status === "success") {
428
+ return result.output;
429
+ }
430
+ return void 0;
431
+ }
432
+ };
433
+ for (const [key, variable] of Object.entries(stepConfig.data)) {
434
+ const sourceData = variable.step === "trigger" ? context.triggerData : getStepResult(context.steps[variable.step.id]);
435
+ this.logger.debug(
436
+ `Got source data for ${key} variable from ${variable.step === "trigger" ? "trigger" : variable.step.id}`,
437
+ {
438
+ sourceData,
439
+ path: variable.path,
440
+ runId: this.#runId
441
+ }
442
+ );
443
+ if (!sourceData && variable.step !== "trigger") {
444
+ resolvedData[key] = void 0;
445
+ continue;
446
+ }
447
+ const value = variable.path === "" || variable.path === "." ? sourceData : get(sourceData, variable.path);
448
+ this.logger.debug(`Resolved variable ${key}`, {
449
+ value,
450
+ runId: this.#runId
451
+ });
452
+ resolvedData[key] = value;
453
+ }
454
+ return resolvedData;
455
+ }
456
+ initializeMachine() {
457
+ const machine = setup({
458
+ types: {},
459
+ delays: this.#makeDelayMap(),
460
+ actions: this.#getDefaultActions(),
461
+ actors: this.#getDefaultActors()
462
+ }).createMachine({
463
+ id: this.name,
464
+ type: "parallel",
465
+ context: ({ input }) => ({
466
+ ...input
467
+ }),
468
+ states: this.#buildStateHierarchy(this.#stepGraph)
469
+ });
470
+ this.#machine = machine;
471
+ return machine;
472
+ }
473
+ #buildStateHierarchy(stepGraph) {
474
+ const states = {};
475
+ stepGraph.initial.forEach((stepNode) => {
476
+ const nextSteps = [...stepGraph[stepNode.step.id] || []];
477
+ states[stepNode.step.id] = {
478
+ ...this.#buildBaseState(stepNode, nextSteps)
479
+ };
480
+ });
481
+ return states;
482
+ }
483
+ #buildBaseState(stepNode, nextSteps = []) {
484
+ const nextStep = nextSteps.shift();
485
+ return {
486
+ initial: "pending",
487
+ on: {
488
+ RESET_TO_PENDING: {
489
+ target: ".pending"
490
+ // Note the dot to target child state
491
+ }
492
+ },
493
+ states: {
494
+ pending: {
495
+ entry: () => {
496
+ this.logger.debug(`Step ${stepNode.step.id} pending`, {
497
+ stepId: stepNode.step.id,
498
+ runId: this.#runId
499
+ });
500
+ },
501
+ exit: () => {
502
+ this.logger.debug(`Step ${stepNode.step.id} finished pending`, {
503
+ stepId: stepNode.step.id,
504
+ runId: this.#runId
505
+ });
506
+ },
507
+ invoke: {
508
+ src: "conditionCheck",
509
+ input: ({ context }) => {
510
+ return {
511
+ context,
512
+ stepNode
513
+ };
514
+ },
515
+ onDone: [
516
+ {
517
+ guard: ({ event }) => {
518
+ return event.output.type === "SUSPENDED";
519
+ },
520
+ target: "suspended",
521
+ actions: [
522
+ assign({
523
+ steps: ({ context, event }) => {
524
+ if (event.output.type !== "SUSPENDED") return context.steps;
525
+ return {
526
+ ...context.steps,
527
+ [stepNode.step.id]: {
528
+ status: "suspended",
529
+ ...context.steps?.[stepNode.step.id] || {}
530
+ }
531
+ };
532
+ },
533
+ attempts: ({ context, event }) => {
534
+ if (event.output.type !== "SUSPENDED") return context.attempts;
535
+ return { ...context.attempts, [stepNode.step.id]: stepNode.step.retryConfig?.attempts || 3 };
536
+ }
537
+ })
538
+ ]
539
+ },
540
+ {
541
+ guard: ({ event }) => {
542
+ return event.output.type === "WAITING";
543
+ },
544
+ target: "waiting",
545
+ actions: [
546
+ { type: "decrementAttemptCount", params: { stepId: stepNode.step.id } },
547
+ assign({
548
+ steps: ({ context, event }) => {
549
+ if (event.output.type !== "WAITING") return context.steps;
550
+ return {
551
+ ...context.steps,
552
+ [stepNode.step.id]: {
553
+ status: "waiting"
554
+ }
555
+ };
556
+ }
557
+ })
558
+ ]
559
+ },
560
+ {
561
+ guard: ({ event }) => {
562
+ return event.output.type === "CONDITIONS_MET";
563
+ },
564
+ target: "executing"
565
+ },
566
+ {
567
+ guard: ({ event }) => {
568
+ return event.output.type === "CONDITION_FAILED";
569
+ },
570
+ target: "failed",
571
+ actions: assign({
572
+ steps: ({ context, event }) => {
573
+ if (event.output.type !== "CONDITION_FAILED") return context.steps;
574
+ this.logger.debug(`Workflow condition check failed`, {
575
+ error: event.output.error,
576
+ stepId: stepNode.step.id
577
+ });
578
+ return {
579
+ ...context.steps,
580
+ [stepNode.step.id]: {
581
+ status: "failed",
582
+ error: event.output.error
583
+ }
584
+ };
585
+ }
586
+ })
587
+ }
588
+ ]
589
+ }
590
+ },
591
+ waiting: {
592
+ entry: () => {
593
+ this.logger.debug(`Step ${stepNode.step.id} waiting`, {
594
+ stepId: stepNode.step.id,
595
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
596
+ runId: this.#runId
597
+ });
598
+ },
599
+ exit: () => {
600
+ this.logger.debug(`Step ${stepNode.step.id} finished waiting`, {
601
+ stepId: stepNode.step.id,
602
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
603
+ runId: this.#runId
604
+ });
605
+ },
606
+ after: {
607
+ [stepNode.step.id]: {
608
+ target: "pending"
609
+ }
610
+ }
611
+ },
612
+ suspended: {
613
+ type: "final",
614
+ entry: [
615
+ () => {
616
+ this.logger.debug(`Step ${stepNode.step.id} suspended`, {
617
+ stepId: stepNode.step.id,
618
+ runId: this.#runId
619
+ });
620
+ },
621
+ assign({
622
+ steps: ({ context }) => ({
623
+ ...context.steps,
624
+ [stepNode.step.id]: {
625
+ ...context?.steps?.[stepNode.step.id] || {},
626
+ status: "suspended"
627
+ }
628
+ })
629
+ })
630
+ ]
631
+ },
632
+ executing: {
633
+ entry: () => {
634
+ this.logger.debug(`Step ${stepNode.step.id} executing`, {
635
+ stepId: stepNode.step.id,
636
+ runId: this.#runId
637
+ });
638
+ },
639
+ on: {
640
+ SUSPENDED: {
641
+ target: "suspended",
642
+ actions: [
643
+ assign({
644
+ steps: ({ context }) => ({
645
+ ...context.steps,
646
+ [stepNode.step.id]: {
647
+ status: "suspended"
648
+ }
649
+ })
650
+ })
651
+ ]
652
+ }
653
+ },
654
+ invoke: {
655
+ src: "resolverFunction",
656
+ input: ({ context }) => ({
657
+ context,
658
+ stepNode
659
+ }),
660
+ onDone: {
661
+ target: "runningSubscribers",
662
+ actions: [
663
+ ({ event }) => this.logger.debug(`Step ${stepNode.step.id} finished executing`, {
664
+ stepId: stepNode.step.id,
665
+ output: event.output,
666
+ runId: this.#runId
667
+ }),
668
+ { type: "updateStepResult", params: { stepId: stepNode.step.id } },
669
+ { type: "spawnSubscribers", params: { stepId: stepNode.step.id } }
670
+ ]
671
+ },
672
+ onError: {
673
+ target: "failed",
674
+ actions: [{ type: "setStepError", params: { stepId: stepNode.step.id } }]
675
+ }
676
+ }
677
+ },
678
+ runningSubscribers: {
679
+ entry: () => {
680
+ this.logger.debug(`Step ${stepNode.step.id} running subscribers`, {
681
+ stepId: stepNode.step.id,
682
+ runId: this.#runId
683
+ });
684
+ },
685
+ exit: () => {
686
+ this.logger.debug(`Step ${stepNode.step.id} finished running subscribers`, {
687
+ stepId: stepNode.step.id,
688
+ runId: this.#runId
689
+ });
690
+ },
691
+ invoke: {
692
+ src: "spawnSubscriberFunction",
693
+ input: ({ context }) => ({
694
+ parentStepId: stepNode.step.id,
695
+ context
696
+ }),
697
+ onDone: {
698
+ target: nextStep ? nextStep.step.id : "completed",
699
+ actions: [
700
+ assign({
701
+ steps: ({ context, event }) => ({
702
+ ...context.steps,
703
+ ...event.output.steps
704
+ })
705
+ }),
706
+ () => this.logger.debug(`Subscriber execution completed`, { stepId: stepNode.step.id })
707
+ ]
708
+ },
709
+ onError: {
710
+ target: nextStep ? nextStep.step.id : "completed",
711
+ actions: ({ event }) => {
712
+ this.logger.debug(`Subscriber execution failed`, {
713
+ error: event.error,
714
+ stepId: stepNode.step.id
715
+ });
716
+ }
717
+ }
718
+ }
719
+ },
720
+ completed: {
721
+ type: "final",
722
+ entry: [
723
+ { type: "notifyStepCompletion", params: { stepId: stepNode.step.id } },
724
+ { type: "snapshotStep", params: { stepId: stepNode.step.id } },
725
+ { type: "persistSnapshot" }
726
+ ]
727
+ },
728
+ failed: {
729
+ type: "final",
730
+ entry: [
731
+ { type: "notifyStepCompletion", params: { stepId: stepNode.step.id } },
732
+ { type: "snapshotStep", params: { stepId: stepNode.step.id } },
733
+ { type: "persistSnapshot" }
734
+ ]
735
+ },
736
+ // build chain of next steps recursively
737
+ ...nextStep ? { [nextStep.step.id]: { ...this.#buildBaseState(nextStep, nextSteps) } } : {}
738
+ }
739
+ };
740
+ }
741
+ #evaluateCondition(condition, context) {
742
+ let andBranchResult = true;
743
+ let baseResult = true;
744
+ let orBranchResult = true;
745
+ const simpleCondition = Object.entries(condition).find(([key]) => key.includes("."));
746
+ if (simpleCondition) {
747
+ const [key, queryValue] = simpleCondition;
748
+ const [stepId, ...pathParts] = key.split(".");
749
+ const path = pathParts.join(".");
750
+ const sourceData = stepId === "trigger" ? context.triggerData : getStepResult(context.steps[stepId]);
751
+ this.logger.debug(`Got condition data from step ${stepId}`, {
752
+ stepId,
753
+ sourceData,
754
+ runId: this.#runId
755
+ });
756
+ if (!sourceData) {
757
+ return false;
758
+ }
759
+ let value = get(sourceData, path);
760
+ if (stepId !== "trigger" && path === "status" && !value) {
761
+ value = "success";
762
+ }
763
+ if (typeof queryValue === "object" && queryValue !== null) {
764
+ baseResult = sift(queryValue)(value);
765
+ } else {
766
+ baseResult = value === queryValue;
767
+ }
768
+ }
769
+ if ("ref" in condition) {
770
+ const { ref, query } = condition;
771
+ const sourceData = ref.step === "trigger" ? context.triggerData : getStepResult(context.steps[ref.step.id]);
772
+ this.logger.debug(`Got condition data from ${ref.step === "trigger" ? "trigger" : ref.step.id}`, {
773
+ sourceData,
774
+ runId: this.#runId
775
+ });
776
+ if (!sourceData) {
777
+ return false;
778
+ }
779
+ let value = get(sourceData, ref.path);
780
+ if (ref.step !== "trigger" && ref.path === "status" && !value) {
781
+ value = "success";
782
+ }
783
+ baseResult = sift(query)(value);
784
+ }
785
+ if ("and" in condition) {
786
+ andBranchResult = condition.and.every((cond) => this.#evaluateCondition(cond, context));
787
+ this.logger.debug(`Evaluated AND condition`, {
788
+ andBranchResult,
789
+ runId: this.#runId
790
+ });
791
+ }
792
+ if ("or" in condition) {
793
+ orBranchResult = condition.or.some((cond) => this.#evaluateCondition(cond, context));
794
+ this.logger.debug(`Evaluated OR condition`, {
795
+ orBranchResult,
796
+ runId: this.#runId
797
+ });
798
+ }
799
+ const finalResult = baseResult && andBranchResult && orBranchResult;
800
+ this.logger.debug(`Evaluated condition`, {
801
+ finalResult,
802
+ runId: this.#runId
803
+ });
804
+ return finalResult;
805
+ }
806
+ getSnapshot() {
807
+ const snapshot = this.#actor?.getSnapshot();
808
+ return snapshot;
809
+ }
810
+ };
811
+
812
+ // src/workflows/workflow-instance.ts
813
+ var WorkflowInstance = class {
814
+ name;
815
+ #mastra;
816
+ #machines = {};
817
+ logger;
818
+ #steps = {};
819
+ #stepGraph;
820
+ #stepSubscriberGraph = {};
821
+ #retryConfig;
822
+ #runId;
823
+ #state = null;
824
+ #executionSpan;
825
+ #onStepTransition = /* @__PURE__ */ new Set();
826
+ #onFinish;
827
+ // indexed by stepId
828
+ #suspendedMachines = {};
829
+ constructor({
830
+ name,
831
+ logger,
832
+ steps,
833
+ runId,
834
+ retryConfig,
835
+ mastra,
836
+ stepGraph,
837
+ stepSubscriberGraph,
838
+ onStepTransition,
839
+ onFinish
840
+ }) {
841
+ this.name = name;
842
+ this.logger = logger;
843
+ this.#steps = steps;
844
+ this.#stepGraph = stepGraph;
845
+ this.#stepSubscriberGraph = stepSubscriberGraph;
846
+ this.#retryConfig = retryConfig;
847
+ this.#mastra = mastra;
848
+ this.#runId = runId ?? crypto.randomUUID();
849
+ this.#onStepTransition = onStepTransition;
850
+ this.#onFinish = onFinish;
851
+ }
852
+ setState(state) {
853
+ this.#state = state;
854
+ }
855
+ get runId() {
856
+ return this.#runId;
857
+ }
858
+ get executionSpan() {
859
+ return this.#executionSpan;
860
+ }
861
+ async start({ triggerData } = {}) {
862
+ const results = await this.execute({ triggerData });
863
+ if (this.#onFinish) {
864
+ this.#onFinish();
865
+ }
866
+ return {
867
+ ...results,
868
+ runId: this.runId
869
+ };
870
+ }
871
+ async execute({
872
+ triggerData,
873
+ snapshot,
874
+ stepId
875
+ } = {}) {
876
+ this.#executionSpan = this.#mastra?.telemetry?.tracer.startSpan(`workflow.${this.name}.execute`, {
877
+ attributes: { componentName: this.name, runId: this.runId }
878
+ });
879
+ let machineInput = {
880
+ // Maintain the original step results and their output
881
+ steps: {},
882
+ triggerData: triggerData || {},
883
+ attempts: Object.keys(this.#steps).reduce(
884
+ (acc, stepKey) => {
885
+ acc[stepKey] = this.#steps[stepKey]?.retryConfig?.attempts || this.#retryConfig?.attempts || 3;
886
+ return acc;
887
+ },
888
+ {}
889
+ )
890
+ };
891
+ let stepGraph = this.#stepGraph;
892
+ let startStepId = "trigger";
893
+ if (snapshot) {
894
+ const runState = snapshot;
895
+ machineInput = runState.context;
896
+ if (stepId && runState?.suspendedSteps?.[stepId]) {
897
+ startStepId = runState.suspendedSteps[stepId];
898
+ stepGraph = this.#stepSubscriberGraph[startStepId] ?? this.#stepGraph;
899
+ }
900
+ }
901
+ const defaultMachine = new Machine({
902
+ logger: this.logger,
903
+ mastra: this.#mastra,
904
+ workflowInstance: this,
905
+ name: this.name,
906
+ runId: this.runId,
907
+ steps: this.#steps,
908
+ stepGraph,
909
+ executionSpan: this.#executionSpan,
910
+ startStepId
911
+ });
912
+ this.#machines[startStepId] = defaultMachine;
913
+ const stateUpdateHandler = (startStepId2, state, context) => {
914
+ if (startStepId2 === "trigger") {
915
+ this.#state = state;
916
+ } else {
917
+ this.#state = mergeChildValue(startStepId2, this.#state, state);
918
+ }
919
+ const now = Date.now();
920
+ if (this.#onStepTransition) {
921
+ this.#onStepTransition.forEach((onTransition) => {
922
+ void onTransition({
923
+ runId: this.#runId,
924
+ value: this.#state,
925
+ context,
926
+ activePaths: getActivePathsAndStatus(this.#state),
927
+ timestamp: now
928
+ });
929
+ });
930
+ }
931
+ };
932
+ defaultMachine.on("state-update", stateUpdateHandler);
933
+ const { results } = await defaultMachine.execute({ snapshot, stepId, input: machineInput });
934
+ await this.persistWorkflowSnapshot();
935
+ return { results };
936
+ }
937
+ async runMachine(parentStepId, input) {
938
+ if (!this.#stepSubscriberGraph[parentStepId]) {
939
+ return;
940
+ }
941
+ const stateUpdateHandler = (startStepId, state, context) => {
942
+ if (startStepId === "trigger") {
943
+ this.#state = state;
944
+ } else {
945
+ this.#state = mergeChildValue(startStepId, this.#state, state);
946
+ }
947
+ const now = Date.now();
948
+ if (this.#onStepTransition) {
949
+ this.#onStepTransition.forEach((onTransition) => {
950
+ void onTransition({
951
+ runId: this.#runId,
952
+ value: this.#state,
953
+ context,
954
+ activePaths: getActivePathsAndStatus(this.#state),
955
+ timestamp: now
956
+ });
957
+ });
958
+ }
959
+ };
960
+ const machine = new Machine({
961
+ logger: this.logger,
962
+ mastra: this.#mastra,
963
+ workflowInstance: this,
964
+ name: parentStepId === "trigger" ? this.name : `${this.name}-${parentStepId}`,
965
+ runId: this.runId,
966
+ steps: this.#steps,
967
+ stepGraph: this.#stepSubscriberGraph[parentStepId],
968
+ executionSpan: this.#executionSpan,
969
+ startStepId: parentStepId
970
+ });
971
+ machine.on("state-update", stateUpdateHandler);
972
+ this.#machines[parentStepId] = machine;
973
+ return await machine.execute({ input });
974
+ }
975
+ async suspend(stepId, machine) {
976
+ this.#suspendedMachines[stepId] = machine;
977
+ }
978
+ /**
979
+ * Persists the workflow state to the database
980
+ */
981
+ async persistWorkflowSnapshot() {
982
+ const existingSnapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
983
+ workflowName: this.name,
984
+ runId: this.#runId
985
+ });
986
+ const machineSnapshots = {};
987
+ for (const [stepId, machine] of Object.entries(this.#machines)) {
988
+ const machineSnapshot = machine?.getSnapshot();
989
+ if (machineSnapshot) {
990
+ machineSnapshots[stepId] = { ...machineSnapshot };
991
+ }
992
+ }
993
+ let snapshot = machineSnapshots["trigger"];
994
+ delete machineSnapshots["trigger"];
995
+ const suspendedSteps = Object.entries(this.#suspendedMachines).reduce(
996
+ (acc, [stepId, machine]) => {
997
+ acc[stepId] = machine.startStepId;
998
+ return acc;
999
+ },
1000
+ {}
1001
+ );
1002
+ if (!snapshot && existingSnapshot) {
1003
+ existingSnapshot.childStates = { ...existingSnapshot.childStates, ...machineSnapshots };
1004
+ existingSnapshot.suspendedSteps = { ...existingSnapshot.suspendedSteps, ...suspendedSteps };
1005
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
1006
+ workflowName: this.name,
1007
+ runId: this.#runId,
1008
+ snapshot: existingSnapshot
1009
+ });
1010
+ return;
1011
+ } else if (snapshot && !existingSnapshot) {
1012
+ snapshot.suspendedSteps = suspendedSteps;
1013
+ snapshot.childStates = { ...machineSnapshots };
1014
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
1015
+ workflowName: this.name,
1016
+ runId: this.#runId,
1017
+ snapshot
1018
+ });
1019
+ return;
1020
+ } else if (!snapshot) {
1021
+ this.logger.debug("Snapshot cannot be persisted. No snapshot received.", { runId: this.#runId });
1022
+ return;
1023
+ }
1024
+ snapshot.suspendedSteps = { ...existingSnapshot.suspendedSteps, ...suspendedSteps };
1025
+ if (!existingSnapshot || snapshot === existingSnapshot) {
1026
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
1027
+ workflowName: this.name,
1028
+ runId: this.#runId,
1029
+ snapshot
1030
+ });
1031
+ return;
1032
+ }
1033
+ if (existingSnapshot?.childStates) {
1034
+ snapshot.childStates = { ...existingSnapshot.childStates, ...machineSnapshots };
1035
+ } else {
1036
+ snapshot.childStates = machineSnapshots;
1037
+ }
1038
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
1039
+ workflowName: this.name,
1040
+ runId: this.#runId,
1041
+ snapshot
1042
+ });
1043
+ }
1044
+ async getState() {
1045
+ const storedSnapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
1046
+ workflowName: this.name,
1047
+ runId: this.runId
1048
+ });
1049
+ const prevSnapshot = storedSnapshot ? {
1050
+ trigger: storedSnapshot,
1051
+ ...Object.entries(storedSnapshot?.childStates ?? {}).reduce(
1052
+ (acc, [stepId, snapshot2]) => ({ ...acc, [stepId]: snapshot2 }),
1053
+ {}
1054
+ )
1055
+ } : {};
1056
+ const currentSnapshot = Object.entries(this.#machines).reduce(
1057
+ (acc, [stepId, machine]) => {
1058
+ const snapshot2 = machine.getSnapshot();
1059
+ if (!snapshot2) {
1060
+ return acc;
1061
+ }
1062
+ return {
1063
+ ...acc,
1064
+ [stepId]: snapshot2
1065
+ };
1066
+ },
1067
+ {}
1068
+ );
1069
+ Object.assign(prevSnapshot, currentSnapshot);
1070
+ const trigger = prevSnapshot.trigger;
1071
+ delete prevSnapshot.trigger;
1072
+ const snapshot = { ...trigger};
1073
+ const m = getActivePathsAndStatus(prevSnapshot.value);
1074
+ return {
1075
+ runId: this.runId,
1076
+ value: snapshot.value,
1077
+ context: snapshot.context,
1078
+ activePaths: m,
1079
+ timestamp: Date.now()
1080
+ };
1081
+ }
1082
+ };
1083
+
1084
+ // src/workflows/workflow.ts
1085
+ var Workflow = class extends MastraBase {
1086
+ name;
1087
+ triggerSchema;
1088
+ #retryConfig;
1089
+ #mastra;
1090
+ #runs = /* @__PURE__ */ new Map();
1091
+ // registers stepIds on `after` calls
1092
+ #afterStepStack = [];
1093
+ #lastStepStack = [];
1094
+ #stepGraph = { initial: [] };
1095
+ #stepSubscriberGraph = {};
1096
+ #steps = {};
1097
+ #onStepTransition = /* @__PURE__ */ new Set();
1098
+ /**
1099
+ * Creates a new Workflow instance
1100
+ * @param name - Identifier for the workflow (not necessarily unique)
1101
+ * @param logger - Optional logger instance
1102
+ */
1103
+ constructor({ name, triggerSchema, retryConfig, mastra }) {
1104
+ super({ component: "WORKFLOW", name });
1105
+ this.name = name;
1106
+ this.#retryConfig = retryConfig;
1107
+ this.triggerSchema = triggerSchema;
1108
+ this.#mastra = mastra;
1109
+ if (mastra?.logger) {
1110
+ this.logger = mastra?.logger;
1111
+ }
1112
+ }
1113
+ step(step, config) {
1114
+ const { variables = {} } = config || {};
1115
+ const requiredData = {};
1116
+ for (const [key, variable] of Object.entries(variables)) {
1117
+ if (variable && isVariableReference(variable)) {
1118
+ requiredData[key] = variable;
1119
+ }
1120
+ }
1121
+ const stepKey = this.#makeStepKey(step);
1122
+ const graphEntry = {
1123
+ step,
1124
+ config: {
1125
+ ...this.#makeStepDef(stepKey),
1126
+ ...config,
1127
+ data: requiredData
1128
+ }
1129
+ };
1130
+ this.#steps[stepKey] = step;
1131
+ const parentStepKey = this.#afterStepStack[this.#afterStepStack.length - 1];
1132
+ const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
1133
+ if (parentStepKey && stepGraph) {
1134
+ if (!stepGraph.initial.some((step2) => step2.step.id === stepKey)) {
1135
+ stepGraph.initial.push(graphEntry);
1136
+ }
1137
+ stepGraph[stepKey] = [];
1138
+ } else {
1139
+ if (!this.#stepGraph[stepKey]) this.#stepGraph[stepKey] = [];
1140
+ this.#stepGraph.initial.push(graphEntry);
1141
+ }
1142
+ this.#lastStepStack.push(stepKey);
1143
+ return this;
1144
+ }
1145
+ #makeStepKey(step) {
1146
+ return `${step.id}`;
1147
+ }
1148
+ then(step, config) {
1149
+ const { variables = {} } = config || {};
1150
+ const requiredData = {};
1151
+ for (const [key, variable] of Object.entries(variables)) {
1152
+ if (variable && isVariableReference(variable)) {
1153
+ requiredData[key] = variable;
1154
+ }
1155
+ }
1156
+ const lastStepKey = this.#lastStepStack[this.#lastStepStack.length - 1];
1157
+ const stepKey = this.#makeStepKey(step);
1158
+ const graphEntry = {
1159
+ step,
1160
+ config: {
1161
+ ...this.#makeStepDef(stepKey),
1162
+ ...config,
1163
+ data: requiredData
1164
+ }
1165
+ };
1166
+ this.#steps[stepKey] = step;
1167
+ if (!lastStepKey) return this;
1168
+ const parentStepKey = this.#afterStepStack[this.#afterStepStack.length - 1];
1169
+ const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
1170
+ if (parentStepKey && stepGraph && stepGraph[lastStepKey]) {
1171
+ stepGraph[lastStepKey].push(graphEntry);
1172
+ } else {
1173
+ if (!this.#stepGraph[lastStepKey]) this.#stepGraph[lastStepKey] = [];
1174
+ this.#stepGraph[lastStepKey].push(graphEntry);
1175
+ }
1176
+ return this;
1177
+ }
1178
+ after(step) {
1179
+ const stepKey = this.#makeStepKey(step);
1180
+ this.#afterStepStack.push(stepKey);
1181
+ if (!this.#stepSubscriberGraph[stepKey]) {
1182
+ this.#stepSubscriberGraph[stepKey] = { initial: [] };
1183
+ }
1184
+ return this;
1185
+ }
1186
+ /**
1187
+ * Executes the workflow with the given trigger data
1188
+ * @param triggerData - Initial data to start the workflow with
1189
+ * @returns Promise resolving to workflow results or rejecting with error
1190
+ * @throws Error if trigger schema validation fails
1191
+ */
1192
+ createRun() {
1193
+ const run = new WorkflowInstance({
1194
+ logger: this.logger,
1195
+ name: this.name,
1196
+ mastra: this.#mastra,
1197
+ retryConfig: this.#retryConfig,
1198
+ steps: this.#steps,
1199
+ stepGraph: this.#stepGraph,
1200
+ stepSubscriberGraph: this.#stepSubscriberGraph,
1201
+ onStepTransition: this.#onStepTransition,
1202
+ onFinish: () => {
1203
+ this.#runs.delete(run.runId);
1204
+ }
1205
+ });
1206
+ this.#runs.set(run.runId, run);
1207
+ return {
1208
+ start: run.start.bind(run),
1209
+ runId: run.runId
1210
+ };
1211
+ }
1212
+ /**
1213
+ * Rebuilds the machine with the current steps configuration and validates the workflow
1214
+ *
1215
+ * This is the last step of a workflow builder method chain
1216
+ * @throws Error if validation fails
1217
+ *
1218
+ * @returns this instance for method chaining
1219
+ */
1220
+ commit() {
1221
+ return this;
1222
+ }
1223
+ // record all object paths that leads to a suspended state
1224
+ #getSuspendedPaths({
1225
+ value,
1226
+ path,
1227
+ suspendedPaths
1228
+ }) {
1229
+ if (typeof value === "string") {
1230
+ if (value === "suspended") {
1231
+ suspendedPaths.add(path);
1232
+ }
1233
+ } else {
1234
+ Object.keys(value).forEach(
1235
+ (key) => this.#getSuspendedPaths({ value: value[key], path: path ? `${path}.${key}` : key, suspendedPaths })
1236
+ );
1237
+ }
1238
+ }
1239
+ async #loadWorkflowSnapshot(runId) {
1240
+ if (!this.#mastra?.storage) {
1241
+ this.logger.debug("Snapshot cannot be loaded. Mastra engine is not initialized", { runId });
1242
+ return;
1243
+ }
1244
+ const activeRun = this.#runs.get(runId);
1245
+ if (activeRun) {
1246
+ await activeRun.persistWorkflowSnapshot();
1247
+ }
1248
+ return this.#mastra.storage.loadWorkflowSnapshot({ runId, workflowName: this.name });
1249
+ }
1250
+ getExecutionSpan(runId) {
1251
+ return this.#runs.get(runId)?.executionSpan;
1252
+ }
1253
+ #makeStepDef(stepId) {
1254
+ const executeStep = (handler2, spanName, attributes) => {
1255
+ return async (data) => {
1256
+ return await context.with(
1257
+ trace.setSpan(context.active(), this.getExecutionSpan(attributes?.runId ?? data?.runId)),
1258
+ async () => {
1259
+ return this.#mastra.telemetry.traceMethod(handler2, {
1260
+ spanName,
1261
+ attributes
1262
+ })(data);
1263
+ }
1264
+ );
1265
+ };
1266
+ };
1267
+ const handler = async ({ context, ...rest }) => {
1268
+ const targetStep = this.#steps[stepId];
1269
+ if (!targetStep) throw new Error(`Step not found`);
1270
+ const { payload = {}, execute = async () => {
1271
+ } } = targetStep;
1272
+ const mergedData = {
1273
+ ...payload,
1274
+ ...context
1275
+ };
1276
+ const finalAction = this.#mastra?.telemetry ? executeStep(execute, `workflow.${this.name}.action.${stepId}`, {
1277
+ componentName: this.name,
1278
+ runId: rest.runId
1279
+ }) : execute;
1280
+ return finalAction ? await finalAction({ context: mergedData, ...rest }) : {};
1281
+ };
1282
+ const finalHandler = ({ context, ...rest }) => {
1283
+ if (this.getExecutionSpan(rest?.runId)) {
1284
+ return executeStep(handler, `workflow.${this.name}.step.${stepId}`, {
1285
+ componentName: this.name,
1286
+ runId: rest?.runId
1287
+ })({ context, ...rest });
1288
+ }
1289
+ return handler({ context, ...rest });
1290
+ };
1291
+ return {
1292
+ handler: finalHandler,
1293
+ data: {}
1294
+ };
1295
+ }
1296
+ #getActivePathsAndStatus(value) {
1297
+ const paths = [];
1298
+ const traverse = (current, path = []) => {
1299
+ for (const [key, value2] of Object.entries(current)) {
1300
+ const currentPath = [...path, key];
1301
+ if (typeof value2 === "string") {
1302
+ paths.push({
1303
+ stepPath: currentPath,
1304
+ stepId: key,
1305
+ status: value2
1306
+ });
1307
+ } else if (typeof value2 === "object" && value2 !== null) {
1308
+ traverse(value2, currentPath);
1309
+ }
1310
+ }
1311
+ };
1312
+ traverse(value);
1313
+ return paths;
1314
+ }
1315
+ async getState(runId) {
1316
+ const run = this.#runs.get(runId);
1317
+ if (run) {
1318
+ return run.getState();
1319
+ }
1320
+ const storedSnapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
1321
+ runId,
1322
+ workflowName: this.name
1323
+ });
1324
+ if (storedSnapshot) {
1325
+ const parsed = storedSnapshot;
1326
+ const m = this.#getActivePathsAndStatus(parsed.value);
1327
+ return {
1328
+ runId,
1329
+ value: parsed.value,
1330
+ context: parsed.context,
1331
+ activePaths: m,
1332
+ timestamp: Date.now()
1333
+ };
1334
+ }
1335
+ return null;
1336
+ }
1337
+ watch(onTransition) {
1338
+ this.#onStepTransition.add(onTransition);
1339
+ return () => {
1340
+ this.#onStepTransition.delete(onTransition);
1341
+ };
1342
+ }
1343
+ async resume({
1344
+ runId,
1345
+ stepId,
1346
+ context: resumeContext
1347
+ }) {
1348
+ await setTimeout(0);
1349
+ return this._resume({ runId, stepId, context: resumeContext });
1350
+ }
1351
+ async _resume({
1352
+ runId,
1353
+ stepId,
1354
+ context: resumeContext
1355
+ }) {
1356
+ const snapshot = await this.#loadWorkflowSnapshot(runId);
1357
+ if (!snapshot) {
1358
+ throw new Error(`No snapshot found for workflow run ${runId}`);
1359
+ }
1360
+ let parsedSnapshot;
1361
+ try {
1362
+ parsedSnapshot = typeof snapshot === "string" ? JSON.parse(snapshot) : snapshot;
1363
+ } catch (error) {
1364
+ this.logger.debug("Failed to parse workflow snapshot for resume", { error, runId });
1365
+ throw new Error("Failed to parse workflow snapshot");
1366
+ }
1367
+ const origSnapshot = parsedSnapshot;
1368
+ const startStepId = parsedSnapshot.suspendedSteps?.[stepId];
1369
+ if (!startStepId) {
1370
+ return;
1371
+ }
1372
+ parsedSnapshot = startStepId === "trigger" ? parsedSnapshot : { ...parsedSnapshot?.childStates?.[startStepId], ...{ suspendedSteps: parsedSnapshot.suspendedSteps } };
1373
+ if (!parsedSnapshot) {
1374
+ throw new Error(`No snapshot found for step: ${stepId} starting at ${startStepId}`);
1375
+ }
1376
+ if (resumeContext) {
1377
+ parsedSnapshot.context.steps[stepId] = {
1378
+ status: "success",
1379
+ output: {
1380
+ ...parsedSnapshot?.context?.steps?.[stepId]?.output || {},
1381
+ ...resumeContext
1382
+ }
1383
+ };
1384
+ }
1385
+ if (parsedSnapshot.children) {
1386
+ Object.entries(parsedSnapshot.children).forEach(([_childId, child]) => {
1387
+ if (child.snapshot?.input?.stepNode) {
1388
+ const stepDef = this.#makeStepDef(child.snapshot.input.stepNode.step.id);
1389
+ child.snapshot.input.stepNode.config = {
1390
+ ...child.snapshot.input.stepNode.config,
1391
+ ...stepDef
1392
+ };
1393
+ child.snapshot.input.context = parsedSnapshot.context;
1394
+ }
1395
+ });
1396
+ }
1397
+ parsedSnapshot.value = updateStepInHierarchy(parsedSnapshot.value, stepId);
1398
+ if (parsedSnapshot.context?.attempts) {
1399
+ parsedSnapshot.context.attempts[stepId] = this.#steps[stepId]?.retryConfig?.attempts || this.#retryConfig?.attempts || 3;
1400
+ }
1401
+ this.logger.debug("Resuming workflow with updated snapshot", {
1402
+ updatedSnapshot: parsedSnapshot,
1403
+ runId,
1404
+ stepId
1405
+ });
1406
+ const run = this.#runs.get(runId) ?? new WorkflowInstance({
1407
+ logger: this.logger,
1408
+ name: this.name,
1409
+ mastra: this.#mastra,
1410
+ retryConfig: this.#retryConfig,
1411
+ steps: this.#steps,
1412
+ stepGraph: this.#stepGraph,
1413
+ stepSubscriberGraph: this.#stepSubscriberGraph,
1414
+ onStepTransition: this.#onStepTransition,
1415
+ runId,
1416
+ onFinish: () => {
1417
+ this.#runs.delete(run.runId);
1418
+ }
1419
+ });
1420
+ run.setState(origSnapshot?.value);
1421
+ this.#runs.set(run.runId, run);
1422
+ return run?.execute({
1423
+ snapshot: parsedSnapshot,
1424
+ stepId
1425
+ });
1426
+ }
1427
+ __registerPrimitives(p) {
1428
+ if (p.telemetry) {
1429
+ this.__setTelemetry(p.telemetry);
1430
+ }
1431
+ if (p.logger) {
1432
+ this.__setLogger(p.logger);
1433
+ }
1434
+ this.#mastra = p;
1435
+ }
1436
+ get stepGraph() {
1437
+ return this.#stepGraph;
1438
+ }
1439
+ get stepSubscriberGraph() {
1440
+ return this.#stepSubscriberGraph;
1441
+ }
1442
+ get steps() {
1443
+ return this.#steps;
1444
+ }
1445
+ };
1446
+
1447
+ // src/workflows/step.ts
1448
+ var Step = class {
1449
+ id;
1450
+ description;
1451
+ inputSchema;
1452
+ outputSchema;
1453
+ payload;
1454
+ execute;
1455
+ retryConfig;
1456
+ mastra;
1457
+ constructor({
1458
+ id,
1459
+ description,
1460
+ execute,
1461
+ payload,
1462
+ outputSchema,
1463
+ inputSchema,
1464
+ retryConfig
1465
+ }) {
1466
+ this.id = id;
1467
+ this.description = description ?? "";
1468
+ this.inputSchema = inputSchema;
1469
+ this.payload = payload;
1470
+ this.outputSchema = outputSchema;
1471
+ this.execute = execute;
1472
+ this.retryConfig = retryConfig;
1473
+ }
1474
+ };
1475
+ function createStep(opts) {
1476
+ return new Step(opts);
1477
+ }
1478
+
1479
+ export { Step, Workflow, createStep, getActivePathsAndStatus, getStepResult, getSuspendedPaths, isErrorEvent, isFinalState, isTransitionEvent, isVariableReference, mergeChildValue, recursivelyCheckForFinalState, updateStepInHierarchy };