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