@mastra/core 0.10.13 → 0.10.14

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 (235) hide show
  1. package/a2a.d.ts +1 -0
  2. package/agent.d.ts +1 -0
  3. package/base.d.ts +1 -0
  4. package/bundler.d.ts +1 -0
  5. package/deployer.d.ts +1 -0
  6. package/di.d.ts +1 -0
  7. package/dist/a2a/index.cjs +79 -0
  8. package/dist/a2a/index.d.cts +780 -0
  9. package/dist/a2a/index.d.ts +780 -0
  10. package/dist/a2a/index.js +68 -0
  11. package/dist/agent/index.cjs +15 -0
  12. package/dist/agent/index.d.cts +29 -0
  13. package/dist/agent/index.d.ts +29 -0
  14. package/dist/agent/index.js +2 -0
  15. package/dist/base-B_y9sMg0.d.cts +162 -0
  16. package/dist/base-CS5eSXbL.d.cts +4117 -0
  17. package/dist/base-ClrXcCRx.d.ts +162 -0
  18. package/dist/base-DBhKcre4.d.ts +4117 -0
  19. package/dist/base.cjs +10 -0
  20. package/dist/base.d.cts +6 -0
  21. package/dist/base.d.ts +6 -0
  22. package/dist/base.js +1 -0
  23. package/dist/bundler/index.cjs +10 -0
  24. package/dist/bundler/index.d.cts +30 -0
  25. package/dist/bundler/index.d.ts +30 -0
  26. package/dist/bundler/index.js +1 -0
  27. package/dist/chunk-2GRYVZ2O.cjs +244 -0
  28. package/dist/chunk-2HDFKWFU.js +2249 -0
  29. package/dist/chunk-32C7JDIZ.js +1 -0
  30. package/dist/chunk-4UBOJFSL.js +989 -0
  31. package/dist/chunk-4UWPFBC6.js +88 -0
  32. package/dist/chunk-4Z3OU5RY.cjs +31 -0
  33. package/dist/chunk-5HTMDAXP.js +359 -0
  34. package/dist/chunk-5IEKR756.js +53 -0
  35. package/dist/chunk-5YDTZN2X.js +114 -0
  36. package/dist/chunk-6UNGH46J.js +75 -0
  37. package/dist/chunk-6Y4UL5Z6.cjs +94 -0
  38. package/dist/chunk-7F6BQXE2.cjs +425 -0
  39. package/dist/chunk-7H2GET5Z.cjs +668 -0
  40. package/dist/chunk-7HZ6NIAF.cjs +2 -0
  41. package/dist/chunk-7MZNOW6W.cjs +2263 -0
  42. package/dist/chunk-7XQIPES3.js +668 -0
  43. package/dist/chunk-AKYTYALY.js +70 -0
  44. package/dist/chunk-ATXBSEFT.js +22 -0
  45. package/dist/chunk-B6TOBUS6.cjs +80 -0
  46. package/dist/chunk-B7SQOKEC.cjs +91 -0
  47. package/dist/chunk-BB4KXGBU.js +83 -0
  48. package/dist/chunk-BB6DPGIV.cjs +6 -0
  49. package/dist/chunk-C4LMN2IR.js +27 -0
  50. package/dist/chunk-DFFVEKIG.js +407 -0
  51. package/dist/chunk-E7AX3U6M.cjs +659 -0
  52. package/dist/chunk-EWCOOO3H.js +5007 -0
  53. package/dist/chunk-F2WMR75C.cjs +183 -0
  54. package/dist/chunk-FBKJ3652.cjs +5034 -0
  55. package/dist/chunk-FEYYOBBG.cjs +24 -0
  56. package/dist/chunk-FL5SZ2XU.js +181 -0
  57. package/dist/chunk-GH2KM66J.js +37 -0
  58. package/dist/chunk-GWFS5DAR.cjs +37 -0
  59. package/dist/chunk-HNEE7IF4.js +60 -0
  60. package/dist/chunk-HSVOEWAM.cjs +2 -0
  61. package/dist/chunk-J52TXHZV.cjs +73 -0
  62. package/dist/chunk-JNMQKJH4.js +10 -0
  63. package/dist/chunk-JQOMTERC.js +89 -0
  64. package/dist/chunk-LABUWBKX.cjs +71 -0
  65. package/dist/chunk-LXFZUKP3.cjs +34 -0
  66. package/dist/chunk-MP2QBLUJ.cjs +70 -0
  67. package/dist/chunk-MUNFCOMB.cjs +62 -0
  68. package/dist/chunk-NH5WJNNS.js +1 -0
  69. package/dist/chunk-P3Q73CAW.cjs +55 -0
  70. package/dist/chunk-PA2YIVIT.js +61 -0
  71. package/dist/chunk-QFTBW7ZZ.cjs +2 -0
  72. package/dist/chunk-QQ5K5TZE.cjs +619 -0
  73. package/dist/chunk-QUSEDVYI.cjs +991 -0
  74. package/dist/chunk-R4V75T7J.js +1 -0
  75. package/dist/chunk-SGGPJWRQ.js +69 -0
  76. package/dist/chunk-ST5RMVLG.cjs +87 -0
  77. package/dist/chunk-TC2SCOTE.js +605 -0
  78. package/dist/chunk-U64IJDC5.cjs +109 -0
  79. package/dist/chunk-UX3B6S2I.cjs +65 -0
  80. package/dist/chunk-V5D2LIF5.js +68 -0
  81. package/dist/chunk-VG4OPO2R.js +240 -0
  82. package/dist/chunk-WQNOATKB.js +103 -0
  83. package/dist/chunk-Y7D2JLKS.js +4 -0
  84. package/dist/chunk-YJEHXYK5.js +657 -0
  85. package/dist/chunk-YOQP5T77.js +32 -0
  86. package/dist/chunk-ZIZ3CVHN.cjs +120 -0
  87. package/dist/chunk-ZPOUMTTH.cjs +362 -0
  88. package/dist/chunk-ZZLBNB3U.cjs +12 -0
  89. package/dist/deployer/index.cjs +10 -0
  90. package/dist/deployer/index.d.cts +19 -0
  91. package/dist/deployer/index.d.ts +19 -0
  92. package/dist/deployer/index.js +1 -0
  93. package/dist/di/index.cjs +10 -0
  94. package/dist/di/index.d.cts +1 -0
  95. package/dist/di/index.d.ts +1 -0
  96. package/dist/di/index.js +1 -0
  97. package/dist/error/index.cjs +22 -0
  98. package/dist/error/index.d.cts +86 -0
  99. package/dist/error/index.d.ts +86 -0
  100. package/dist/error/index.js +1 -0
  101. package/dist/eval/index.cjs +14 -0
  102. package/dist/eval/index.d.cts +43 -0
  103. package/dist/eval/index.d.ts +43 -0
  104. package/dist/eval/index.js +1 -0
  105. package/dist/hooks/index.cjs +18 -0
  106. package/dist/hooks/index.d.cts +33 -0
  107. package/dist/hooks/index.d.ts +33 -0
  108. package/dist/hooks/index.js +1 -0
  109. package/dist/index.cjs +281 -0
  110. package/dist/index.d.cts +92 -0
  111. package/dist/index.d.ts +92 -0
  112. package/dist/index.js +112 -0
  113. package/dist/integration/index.cjs +14 -0
  114. package/dist/integration/index.d.cts +65 -0
  115. package/dist/integration/index.d.ts +65 -0
  116. package/dist/integration/index.js +1 -0
  117. package/dist/llm/index.cjs +10 -0
  118. package/dist/llm/index.d.cts +29 -0
  119. package/dist/llm/index.d.ts +29 -0
  120. package/dist/llm/index.js +1 -0
  121. package/dist/logger/index.cjs +43 -0
  122. package/dist/logger/index.d.cts +96 -0
  123. package/dist/logger/index.d.ts +96 -0
  124. package/dist/logger/index.js +2 -0
  125. package/dist/logger-B8XXh6ya.d.cts +159 -0
  126. package/dist/logger-Bpa2oLL4.d.ts +159 -0
  127. package/dist/mastra/index.cjs +10 -0
  128. package/dist/mastra/index.d.cts +29 -0
  129. package/dist/mastra/index.d.ts +29 -0
  130. package/dist/mastra/index.js +1 -0
  131. package/dist/mcp/index.cjs +106 -0
  132. package/dist/mcp/index.d.cts +29 -0
  133. package/dist/mcp/index.d.ts +29 -0
  134. package/dist/mcp/index.js +100 -0
  135. package/dist/memory/index.cjs +18 -0
  136. package/dist/memory/index.d.cts +29 -0
  137. package/dist/memory/index.d.ts +29 -0
  138. package/dist/memory/index.js +1 -0
  139. package/dist/network/index.cjs +311 -0
  140. package/dist/network/index.d.cts +29 -0
  141. package/dist/network/index.d.ts +29 -0
  142. package/dist/network/index.js +309 -0
  143. package/dist/network/vNext/index.cjs +873 -0
  144. package/dist/network/vNext/index.d.cts +29 -0
  145. package/dist/network/vNext/index.d.ts +29 -0
  146. package/dist/network/vNext/index.js +871 -0
  147. package/dist/relevance/index.cjs +18 -0
  148. package/dist/relevance/index.d.cts +49 -0
  149. package/dist/relevance/index.d.ts +49 -0
  150. package/dist/relevance/index.js +1 -0
  151. package/dist/runtime-context/index.cjs +10 -0
  152. package/dist/runtime-context/index.d.cts +52 -0
  153. package/dist/runtime-context/index.d.ts +52 -0
  154. package/dist/runtime-context/index.js +1 -0
  155. package/dist/server/index.cjs +62 -0
  156. package/dist/server/index.d.cts +52 -0
  157. package/dist/server/index.d.ts +52 -0
  158. package/dist/server/index.js +59 -0
  159. package/dist/storage/index.cjs +336 -0
  160. package/dist/storage/index.d.cts +149 -0
  161. package/dist/storage/index.d.ts +149 -0
  162. package/dist/storage/index.js +303 -0
  163. package/dist/telemetry/index.cjs +30 -0
  164. package/dist/telemetry/index.d.cts +75 -0
  165. package/dist/telemetry/index.d.ts +75 -0
  166. package/dist/telemetry/index.js +1 -0
  167. package/dist/telemetry/otel-vendor.cjs +103 -0
  168. package/dist/telemetry/otel-vendor.d.cts +20 -0
  169. package/dist/telemetry/otel-vendor.d.ts +20 -0
  170. package/dist/telemetry/otel-vendor.js +57 -0
  171. package/dist/tools/index.cjs +18 -0
  172. package/dist/tools/index.d.cts +41 -0
  173. package/dist/tools/index.d.ts +41 -0
  174. package/dist/tools/index.js +1 -0
  175. package/dist/tts/index.cjs +10 -0
  176. package/dist/tts/index.d.cts +28 -0
  177. package/dist/tts/index.d.ts +28 -0
  178. package/dist/tts/index.js +1 -0
  179. package/dist/types-Bo1uigWx.d.cts +17 -0
  180. package/dist/types-Bo1uigWx.d.ts +17 -0
  181. package/dist/utils.cjs +58 -0
  182. package/dist/utils.d.cts +149 -0
  183. package/dist/utils.d.ts +149 -0
  184. package/dist/utils.js +1 -0
  185. package/dist/vector/filter/index.cjs +192 -0
  186. package/dist/vector/filter/index.d.cts +128 -0
  187. package/dist/vector/filter/index.d.ts +128 -0
  188. package/dist/vector/filter/index.js +190 -0
  189. package/dist/vector/index.cjs +10 -0
  190. package/dist/vector/index.d.cts +77 -0
  191. package/dist/vector/index.d.ts +77 -0
  192. package/dist/vector/index.js +1 -0
  193. package/dist/voice/index.cjs +18 -0
  194. package/dist/voice/index.d.cts +29 -0
  195. package/dist/voice/index.d.ts +29 -0
  196. package/dist/voice/index.js +1 -0
  197. package/dist/workflows/constants.cjs +10 -0
  198. package/dist/workflows/constants.d.cts +3 -0
  199. package/dist/workflows/constants.d.ts +3 -0
  200. package/dist/workflows/constants.js +1 -0
  201. package/dist/workflows/index.cjs +42 -0
  202. package/dist/workflows/index.d.cts +282 -0
  203. package/dist/workflows/index.d.ts +282 -0
  204. package/dist/workflows/index.js +1 -0
  205. package/dist/workflows/legacy/index.cjs +90 -0
  206. package/dist/workflows/legacy/index.d.cts +91 -0
  207. package/dist/workflows/legacy/index.d.ts +91 -0
  208. package/dist/workflows/legacy/index.js +1 -0
  209. package/error.d.ts +1 -0
  210. package/eval.d.ts +1 -0
  211. package/hooks.d.ts +1 -0
  212. package/integration.d.ts +1 -0
  213. package/llm.d.ts +1 -0
  214. package/logger.d.ts +1 -0
  215. package/mastra.d.ts +1 -0
  216. package/mcp.d.ts +1 -0
  217. package/memory.d.ts +1 -0
  218. package/network/vNext.d.ts +1 -0
  219. package/network.d.ts +1 -0
  220. package/package.json +1 -1
  221. package/relevance.d.ts +1 -0
  222. package/runtime-context.d.ts +1 -0
  223. package/server.d.ts +1 -0
  224. package/storage.d.ts +1 -0
  225. package/telemetry/otel-vendor.d.ts +1 -0
  226. package/telemetry.d.ts +1 -0
  227. package/tools.d.ts +1 -0
  228. package/tts.d.ts +1 -0
  229. package/utils.d.ts +1 -0
  230. package/vector/filter.d.ts +1 -0
  231. package/vector.d.ts +1 -0
  232. package/voice.d.ts +1 -0
  233. package/workflows/_constants.d.ts +1 -0
  234. package/workflows/legacy.d.ts +1 -0
  235. package/workflows.d.ts +1 -0
@@ -0,0 +1,5007 @@
1
+ import { DefaultVoice } from './chunk-5HTMDAXP.js';
2
+ import { MessageList } from './chunk-4UBOJFSL.js';
3
+ import { executeHook } from './chunk-BB4KXGBU.js';
4
+ import { MastraLLM } from './chunk-YJEHXYK5.js';
5
+ import { InstrumentClass } from './chunk-TC2SCOTE.js';
6
+ import { ensureToolProperties, makeCoreTool, createMastraProxy } from './chunk-DFFVEKIG.js';
7
+ import { MastraError } from './chunk-6UNGH46J.js';
8
+ import { MastraBase } from './chunk-5IEKR756.js';
9
+ import { RegisteredLogger } from './chunk-5YDTZN2X.js';
10
+ import { RuntimeContext } from './chunk-SGGPJWRQ.js';
11
+ import { __commonJS, __toESM, __decoratorStart, __decorateElement, __runInitializers } from './chunk-WQNOATKB.js';
12
+ import { context, trace } from '@opentelemetry/api';
13
+ import { z } from 'zod';
14
+ import { get } from 'radash';
15
+ import { randomUUID } from 'crypto';
16
+ import EventEmitter from 'events';
17
+ import sift from 'sift';
18
+ import { createActor, assign, fromPromise, setup } from 'xstate';
19
+
20
+ // ../../node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js
21
+ var require_fast_deep_equal = __commonJS({
22
+ "../../node_modules/.pnpm/fast-deep-equal@3.1.3/node_modules/fast-deep-equal/index.js"(exports, module) {
23
+
24
+ module.exports = function equal(a, b) {
25
+ if (a === b) return true;
26
+ if (a && b && typeof a == "object" && typeof b == "object") {
27
+ if (a.constructor !== b.constructor) return false;
28
+ var length, i, keys;
29
+ if (Array.isArray(a)) {
30
+ length = a.length;
31
+ if (length != b.length) return false;
32
+ for (i = length; i-- !== 0;) if (!equal(a[i], b[i])) return false;
33
+ return true;
34
+ }
35
+ if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
36
+ if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
37
+ if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
38
+ keys = Object.keys(a);
39
+ length = keys.length;
40
+ if (length !== Object.keys(b).length) return false;
41
+ for (i = length; i-- !== 0;) if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
42
+ for (i = length; i-- !== 0;) {
43
+ var key = keys[i];
44
+ if (!equal(a[key], b[key])) return false;
45
+ }
46
+ return true;
47
+ }
48
+ return a !== a && b !== b;
49
+ };
50
+ }
51
+ });
52
+
53
+ // src/workflows/legacy/step.ts
54
+ var LegacyStep = class {
55
+ id;
56
+ description;
57
+ inputSchema;
58
+ outputSchema;
59
+ payload;
60
+ execute;
61
+ retryConfig;
62
+ mastra;
63
+ constructor({
64
+ id,
65
+ description,
66
+ execute,
67
+ payload,
68
+ outputSchema,
69
+ inputSchema,
70
+ retryConfig
71
+ }) {
72
+ this.id = id;
73
+ this.description = description ?? "";
74
+ this.inputSchema = inputSchema;
75
+ this.payload = payload;
76
+ this.outputSchema = outputSchema;
77
+ this.execute = execute;
78
+ this.retryConfig = retryConfig;
79
+ }
80
+ };
81
+
82
+ // src/workflows/legacy/types.ts
83
+ var WhenConditionReturnValue = /* @__PURE__ */(WhenConditionReturnValue2 => {
84
+ WhenConditionReturnValue2["CONTINUE"] = "continue";
85
+ WhenConditionReturnValue2["CONTINUE_FAILED"] = "continue_failed";
86
+ WhenConditionReturnValue2["ABORT"] = "abort";
87
+ WhenConditionReturnValue2["LIMBO"] = "limbo";
88
+ return WhenConditionReturnValue2;
89
+ })(WhenConditionReturnValue || {});
90
+
91
+ // src/agent/index.ts
92
+ var import_fast_deep_equal = __toESM(require_fast_deep_equal(), 1);
93
+
94
+ // src/agent/save-queue/index.ts
95
+ var SaveQueueManager = class _SaveQueueManager {
96
+ logger;
97
+ debounceMs;
98
+ memory;
99
+ static MAX_STALENESS_MS = 1e3;
100
+ constructor({
101
+ logger,
102
+ debounceMs,
103
+ memory
104
+ }) {
105
+ this.logger = logger;
106
+ this.debounceMs = debounceMs || 100;
107
+ this.memory = memory;
108
+ }
109
+ saveQueues = /* @__PURE__ */new Map();
110
+ saveDebounceTimers = /* @__PURE__ */new Map();
111
+ /**
112
+ * Debounces save operations for a thread, ensuring that consecutive save requests
113
+ * are batched and only the latest is executed after a short delay.
114
+ * @param threadId - The ID of the thread to debounce saves for.
115
+ * @param saveFn - The save function to debounce.
116
+ */
117
+ debounceSave(threadId, messageList, memoryConfig) {
118
+ if (this.saveDebounceTimers.has(threadId)) {
119
+ clearTimeout(this.saveDebounceTimers.get(threadId));
120
+ }
121
+ this.saveDebounceTimers.set(threadId, setTimeout(() => {
122
+ this.enqueueSave(threadId, messageList, memoryConfig).catch(err => {
123
+ this.logger?.error?.("Error in debounceSave", {
124
+ err,
125
+ threadId
126
+ });
127
+ });
128
+ this.saveDebounceTimers.delete(threadId);
129
+ }, this.debounceMs));
130
+ }
131
+ /**
132
+ * Enqueues a save operation for a thread, ensuring that saves are executed in order and
133
+ * only one save runs at a time per thread. If a save is already in progress for the thread,
134
+ * the new save is queued to run after the previous completes.
135
+ *
136
+ * @param threadId - The ID of the thread whose messages should be saved.
137
+ * @param messageList - The MessageList instance containing unsaved messages.
138
+ * @param memoryConfig - Optional memory configuration to use for saving.
139
+ */
140
+ enqueueSave(threadId, messageList, memoryConfig) {
141
+ const prev = this.saveQueues.get(threadId) || Promise.resolve();
142
+ const next = prev.then(() => this.persistUnsavedMessages(messageList, memoryConfig)).catch(err => {
143
+ this.logger?.error?.("Error in enqueueSave", {
144
+ err,
145
+ threadId
146
+ });
147
+ }).then(() => {
148
+ if (this.saveQueues.get(threadId) === next) {
149
+ this.saveQueues.delete(threadId);
150
+ }
151
+ });
152
+ this.saveQueues.set(threadId, next);
153
+ return next;
154
+ }
155
+ /**
156
+ * Clears any pending debounced save for a thread, preventing the scheduled save
157
+ * from executing if it hasn't already fired.
158
+ *
159
+ * @param threadId - The ID of the thread whose debounced save should be cleared.
160
+ */
161
+ clearDebounce(threadId) {
162
+ if (this.saveDebounceTimers.has(threadId)) {
163
+ clearTimeout(this.saveDebounceTimers.get(threadId));
164
+ this.saveDebounceTimers.delete(threadId);
165
+ }
166
+ }
167
+ /**
168
+ * Persists any unsaved messages from the MessageList to memory storage.
169
+ * Drains the list of unsaved messages and writes them using the memory backend.
170
+ * @param messageList - The MessageList instance for the current thread.
171
+ * @param memoryConfig - The memory configuration for saving.
172
+ */
173
+ async persistUnsavedMessages(messageList, memoryConfig) {
174
+ const newMessages = messageList.drainUnsavedMessages();
175
+ if (newMessages.length > 0 && this.memory) {
176
+ await this.memory.saveMessages({
177
+ messages: newMessages,
178
+ memoryConfig
179
+ });
180
+ }
181
+ }
182
+ /**
183
+ * Batches a save of unsaved messages for a thread, using debouncing to batch rapid updates.
184
+ * If the oldest unsaved message is stale (older than MAX_STALENESS_MS), the save is performed immediately.
185
+ * Otherwise, the save is delayed to batch multiple updates and reduce redundant writes.
186
+ *
187
+ * @param messageList - The MessageList instance containing unsaved messages.
188
+ * @param threadId - The ID of the thread whose messages are being saved.
189
+ * @param memoryConfig - Optional memory configuration for saving.
190
+ */
191
+ async batchMessages(messageList, threadId, memoryConfig) {
192
+ if (!threadId) return;
193
+ const earliest = messageList.getEarliestUnsavedMessageTimestamp();
194
+ const now = Date.now();
195
+ if (earliest && now - earliest > _SaveQueueManager.MAX_STALENESS_MS) {
196
+ return this.flushMessages(messageList, threadId, memoryConfig);
197
+ } else {
198
+ return this.debounceSave(threadId, messageList, memoryConfig);
199
+ }
200
+ }
201
+ /**
202
+ * Forces an immediate save of unsaved messages for a thread, bypassing any debounce delay.
203
+ * This is used when a flush to persistent storage is required (e.g., on shutdown or critical transitions).
204
+ *
205
+ * @param messageList - The MessageList instance containing unsaved messages.
206
+ * @param threadId - The ID of the thread whose messages are being saved.
207
+ * @param memoryConfig - Optional memory configuration for saving.
208
+ */
209
+ async flushMessages(messageList, threadId, memoryConfig) {
210
+ if (!threadId) return;
211
+ this.clearDebounce(threadId);
212
+ return this.enqueueSave(threadId, messageList, memoryConfig);
213
+ }
214
+ };
215
+
216
+ // src/agent/index.ts
217
+ function resolveMaybePromise(value, cb) {
218
+ if (value instanceof Promise) {
219
+ return value.then(cb);
220
+ }
221
+ return cb(value);
222
+ }
223
+ function resolveThreadIdFromArgs(args) {
224
+ if (args?.memory?.thread) {
225
+ if (typeof args.memory.thread === "string") return {
226
+ id: args.memory.thread
227
+ };
228
+ if (typeof args.memory.thread === "object" && args.memory.thread.id) return args.memory.thread;
229
+ }
230
+ if (args?.threadId) return {
231
+ id: args.threadId
232
+ };
233
+ return void 0;
234
+ }
235
+ var _Agent_decorators, _init, _a;
236
+ _Agent_decorators = [InstrumentClass({
237
+ prefix: "agent",
238
+ excludeMethods: ["hasOwnMemory", "getMemory", "__primitive", "__registerMastra", "__registerPrimitives", "__setTools", "__setLogger", "__setTelemetry", "log", "getModel", "getInstructions", "getTools", "getLLM", "getWorkflows", "getDefaultGenerateOptions", "getDefaultStreamOptions", "getDescription"]
239
+ })];
240
+ var Agent = class extends (_a = MastraBase) {
241
+ id;
242
+ name;
243
+ #instructions;
244
+ #description;
245
+ model;
246
+ #mastra;
247
+ #memory;
248
+ #workflows;
249
+ #defaultGenerateOptions;
250
+ #defaultStreamOptions;
251
+ #tools;
252
+ /** @deprecated This property is deprecated. Use evals instead. */
253
+ metrics;
254
+ evals;
255
+ #voice;
256
+ constructor(config) {
257
+ super({
258
+ component: RegisteredLogger.AGENT
259
+ });
260
+ this.name = config.name;
261
+ this.id = config.name;
262
+ this.#instructions = config.instructions;
263
+ this.#description = config.description;
264
+ if (!config.model) {
265
+ const mastraError = new MastraError({
266
+ id: "AGENT_CONSTRUCTOR_MODEL_REQUIRED",
267
+ domain: "AGENT" /* AGENT */,
268
+ category: "USER" /* USER */,
269
+ details: {
270
+ agentName: config.name
271
+ },
272
+ text: `LanguageModel is required to create an Agent. Please provide the 'model'.`
273
+ });
274
+ this.logger.trackException(mastraError);
275
+ this.logger.error(mastraError.toString());
276
+ throw mastraError;
277
+ }
278
+ this.model = config.model;
279
+ if (config.workflows) {
280
+ this.#workflows = config.workflows;
281
+ }
282
+ this.#defaultGenerateOptions = config.defaultGenerateOptions || {};
283
+ this.#defaultStreamOptions = config.defaultStreamOptions || {};
284
+ this.#tools = config.tools || {};
285
+ this.metrics = {};
286
+ this.evals = {};
287
+ if (config.mastra) {
288
+ this.__registerMastra(config.mastra);
289
+ this.__registerPrimitives({
290
+ telemetry: config.mastra.getTelemetry(),
291
+ logger: config.mastra.getLogger()
292
+ });
293
+ }
294
+ if (config.metrics) {
295
+ this.logger.warn("The metrics property is deprecated. Please use evals instead to add evaluation metrics.");
296
+ this.metrics = config.metrics;
297
+ this.evals = config.metrics;
298
+ }
299
+ if (config.evals) {
300
+ this.evals = config.evals;
301
+ }
302
+ if (config.memory) {
303
+ this.#memory = config.memory;
304
+ }
305
+ if (config.voice) {
306
+ this.#voice = config.voice;
307
+ if (typeof config.tools !== "function") {
308
+ this.#voice?.addTools(this.tools);
309
+ }
310
+ if (typeof config.instructions === "string") {
311
+ this.#voice?.addInstructions(config.instructions);
312
+ }
313
+ } else {
314
+ this.#voice = new DefaultVoice();
315
+ }
316
+ }
317
+ hasOwnMemory() {
318
+ return Boolean(this.#memory);
319
+ }
320
+ getMemory() {
321
+ const memory = this.#memory;
322
+ if (memory && !memory.hasOwnStorage && this.#mastra) {
323
+ const storage = this.#mastra.getStorage();
324
+ if (storage) {
325
+ memory.setStorage(storage);
326
+ }
327
+ }
328
+ return memory;
329
+ }
330
+ get voice() {
331
+ if (typeof this.#instructions === "function") {
332
+ const mastraError = new MastraError({
333
+ id: "AGENT_VOICE_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",
334
+ domain: "AGENT" /* AGENT */,
335
+ category: "USER" /* USER */,
336
+ details: {
337
+ agentName: this.name
338
+ },
339
+ text: "Voice is not compatible when instructions are a function. Please use getVoice() instead."
340
+ });
341
+ this.logger.trackException(mastraError);
342
+ this.logger.error(mastraError.toString());
343
+ throw mastraError;
344
+ }
345
+ return this.#voice;
346
+ }
347
+ async getWorkflows({
348
+ runtimeContext = new RuntimeContext()
349
+ } = {}) {
350
+ let workflowRecord;
351
+ if (typeof this.#workflows === "function") {
352
+ workflowRecord = await Promise.resolve(this.#workflows({
353
+ runtimeContext
354
+ }));
355
+ } else {
356
+ workflowRecord = this.#workflows ?? {};
357
+ }
358
+ Object.entries(workflowRecord || {}).forEach(([_workflowName, workflow]) => {
359
+ if (this.#mastra) {
360
+ workflow.__registerMastra(this.#mastra);
361
+ }
362
+ });
363
+ return workflowRecord;
364
+ }
365
+ async getVoice({
366
+ runtimeContext
367
+ } = {}) {
368
+ if (this.#voice) {
369
+ const voice = this.#voice;
370
+ voice?.addTools(await this.getTools({
371
+ runtimeContext
372
+ }));
373
+ voice?.addInstructions(await this.getInstructions({
374
+ runtimeContext
375
+ }));
376
+ return voice;
377
+ } else {
378
+ return new DefaultVoice();
379
+ }
380
+ }
381
+ get instructions() {
382
+ this.logger.warn("The instructions property is deprecated. Please use getInstructions() instead.");
383
+ if (typeof this.#instructions === "function") {
384
+ const mastraError = new MastraError({
385
+ id: "AGENT_INSTRUCTIONS_INCOMPATIBLE_WITH_FUNCTION_INSTRUCTIONS",
386
+ domain: "AGENT" /* AGENT */,
387
+ category: "USER" /* USER */,
388
+ details: {
389
+ agentName: this.name
390
+ },
391
+ text: "Instructions are not compatible when instructions are a function. Please use getInstructions() instead."
392
+ });
393
+ this.logger.trackException(mastraError);
394
+ this.logger.error(mastraError.toString());
395
+ throw mastraError;
396
+ }
397
+ return this.#instructions;
398
+ }
399
+ getInstructions({
400
+ runtimeContext = new RuntimeContext()
401
+ } = {}) {
402
+ if (typeof this.#instructions === "string") {
403
+ return this.#instructions;
404
+ }
405
+ const result = this.#instructions({
406
+ runtimeContext
407
+ });
408
+ return resolveMaybePromise(result, instructions => {
409
+ if (!instructions) {
410
+ const mastraError = new MastraError({
411
+ id: "AGENT_GET_INSTRUCTIONS_FUNCTION_EMPTY_RETURN",
412
+ domain: "AGENT" /* AGENT */,
413
+ category: "USER" /* USER */,
414
+ details: {
415
+ agentName: this.name
416
+ },
417
+ text: "Instructions are required to use an Agent. The function-based instructions returned an empty value."
418
+ });
419
+ this.logger.trackException(mastraError);
420
+ this.logger.error(mastraError.toString());
421
+ throw mastraError;
422
+ }
423
+ return instructions;
424
+ });
425
+ }
426
+ getDescription() {
427
+ return this.#description ?? "";
428
+ }
429
+ getDefaultGenerateOptions({
430
+ runtimeContext = new RuntimeContext()
431
+ } = {}) {
432
+ if (typeof this.#defaultGenerateOptions !== "function") {
433
+ return this.#defaultGenerateOptions;
434
+ }
435
+ const result = this.#defaultGenerateOptions({
436
+ runtimeContext
437
+ });
438
+ return resolveMaybePromise(result, options => {
439
+ if (!options) {
440
+ const mastraError = new MastraError({
441
+ id: "AGENT_GET_DEFAULT_GENERATE_OPTIONS_FUNCTION_EMPTY_RETURN",
442
+ domain: "AGENT" /* AGENT */,
443
+ category: "USER" /* USER */,
444
+ details: {
445
+ agentName: this.name
446
+ },
447
+ text: `[Agent:${this.name}] - Function-based default generate options returned empty value`
448
+ });
449
+ this.logger.trackException(mastraError);
450
+ this.logger.error(mastraError.toString());
451
+ throw mastraError;
452
+ }
453
+ return options;
454
+ });
455
+ }
456
+ getDefaultStreamOptions({
457
+ runtimeContext = new RuntimeContext()
458
+ } = {}) {
459
+ if (typeof this.#defaultStreamOptions !== "function") {
460
+ return this.#defaultStreamOptions;
461
+ }
462
+ const result = this.#defaultStreamOptions({
463
+ runtimeContext
464
+ });
465
+ return resolveMaybePromise(result, options => {
466
+ if (!options) {
467
+ const mastraError = new MastraError({
468
+ id: "AGENT_GET_DEFAULT_STREAM_OPTIONS_FUNCTION_EMPTY_RETURN",
469
+ domain: "AGENT" /* AGENT */,
470
+ category: "USER" /* USER */,
471
+ details: {
472
+ agentName: this.name
473
+ },
474
+ text: `[Agent:${this.name}] - Function-based default stream options returned empty value`
475
+ });
476
+ this.logger.trackException(mastraError);
477
+ this.logger.error(mastraError.toString());
478
+ throw mastraError;
479
+ }
480
+ return options;
481
+ });
482
+ }
483
+ get tools() {
484
+ this.logger.warn("The tools property is deprecated. Please use getTools() instead.");
485
+ if (typeof this.#tools === "function") {
486
+ const mastraError = new MastraError({
487
+ id: "AGENT_GET_TOOLS_FUNCTION_INCOMPATIBLE_WITH_TOOL_FUNCTION_TYPE",
488
+ domain: "AGENT" /* AGENT */,
489
+ category: "USER" /* USER */,
490
+ details: {
491
+ agentName: this.name
492
+ },
493
+ text: "Tools are not compatible when tools are a function. Please use getTools() instead."
494
+ });
495
+ this.logger.trackException(mastraError);
496
+ this.logger.error(mastraError.toString());
497
+ throw mastraError;
498
+ }
499
+ return ensureToolProperties(this.#tools);
500
+ }
501
+ getTools({
502
+ runtimeContext = new RuntimeContext()
503
+ } = {}) {
504
+ if (typeof this.#tools !== "function") {
505
+ return ensureToolProperties(this.#tools);
506
+ }
507
+ const result = this.#tools({
508
+ runtimeContext
509
+ });
510
+ return resolveMaybePromise(result, tools => {
511
+ if (!tools) {
512
+ const mastraError = new MastraError({
513
+ id: "AGENT_GET_TOOLS_FUNCTION_EMPTY_RETURN",
514
+ domain: "AGENT" /* AGENT */,
515
+ category: "USER" /* USER */,
516
+ details: {
517
+ agentName: this.name
518
+ },
519
+ text: `[Agent:${this.name}] - Function-based tools returned empty value`
520
+ });
521
+ this.logger.trackException(mastraError);
522
+ this.logger.error(mastraError.toString());
523
+ throw mastraError;
524
+ }
525
+ return ensureToolProperties(tools);
526
+ });
527
+ }
528
+ get llm() {
529
+ this.logger.warn("The llm property is deprecated. Please use getLLM() instead.");
530
+ if (typeof this.model === "function") {
531
+ const mastraError = new MastraError({
532
+ id: "AGENT_LLM_GETTER_INCOMPATIBLE_WITH_FUNCTION_MODEL",
533
+ domain: "AGENT" /* AGENT */,
534
+ category: "USER" /* USER */,
535
+ details: {
536
+ agentName: this.name
537
+ },
538
+ text: "LLM is not compatible when model is a function. Please use getLLM() instead."
539
+ });
540
+ this.logger.trackException(mastraError);
541
+ this.logger.error(mastraError.toString());
542
+ throw mastraError;
543
+ }
544
+ return this.getLLM();
545
+ }
546
+ /**
547
+ * Gets or creates an LLM instance based on the current model
548
+ * @param options Options for getting the LLM
549
+ * @returns A promise that resolves to the LLM instance
550
+ */
551
+ getLLM({
552
+ runtimeContext = new RuntimeContext(),
553
+ model
554
+ } = {}) {
555
+ const modelToUse = model ? typeof model === "function" ? model({
556
+ runtimeContext
557
+ }) : model : this.getModel({
558
+ runtimeContext
559
+ });
560
+ return resolveMaybePromise(modelToUse, resolvedModel => {
561
+ const llm = new MastraLLM({
562
+ model: resolvedModel,
563
+ mastra: this.#mastra
564
+ });
565
+ if (this.#primitives) {
566
+ llm.__registerPrimitives(this.#primitives);
567
+ }
568
+ if (this.#mastra) {
569
+ llm.__registerMastra(this.#mastra);
570
+ }
571
+ return llm;
572
+ });
573
+ }
574
+ /**
575
+ * Gets the model, resolving it if it's a function
576
+ * @param options Options for getting the model
577
+ * @returns A promise that resolves to the model
578
+ */
579
+ getModel({
580
+ runtimeContext = new RuntimeContext()
581
+ } = {}) {
582
+ if (typeof this.model !== "function") {
583
+ if (!this.model) {
584
+ const mastraError = new MastraError({
585
+ id: "AGENT_GET_MODEL_MISSING_MODEL_INSTANCE",
586
+ domain: "AGENT" /* AGENT */,
587
+ category: "USER" /* USER */,
588
+ details: {
589
+ agentName: this.name
590
+ },
591
+ text: `[Agent:${this.name}] - No model provided`
592
+ });
593
+ this.logger.trackException(mastraError);
594
+ this.logger.error(mastraError.toString());
595
+ throw mastraError;
596
+ }
597
+ return this.model;
598
+ }
599
+ const result = this.model({
600
+ runtimeContext
601
+ });
602
+ return resolveMaybePromise(result, model => {
603
+ if (!model) {
604
+ const mastraError = new MastraError({
605
+ id: "AGENT_GET_MODEL_FUNCTION_EMPTY_RETURN",
606
+ domain: "AGENT" /* AGENT */,
607
+ category: "USER" /* USER */,
608
+ details: {
609
+ agentName: this.name
610
+ },
611
+ text: `[Agent:${this.name}] - Function-based model returned empty value`
612
+ });
613
+ this.logger.trackException(mastraError);
614
+ this.logger.error(mastraError.toString());
615
+ throw mastraError;
616
+ }
617
+ return model;
618
+ });
619
+ }
620
+ __updateInstructions(newInstructions) {
621
+ this.#instructions = newInstructions;
622
+ this.logger.debug(`[Agents:${this.name}] Instructions updated.`, {
623
+ model: this.model,
624
+ name: this.name
625
+ });
626
+ }
627
+ #primitives;
628
+ __registerPrimitives(p) {
629
+ if (p.telemetry) {
630
+ this.__setTelemetry(p.telemetry);
631
+ }
632
+ if (p.logger) {
633
+ this.__setLogger(p.logger);
634
+ }
635
+ this.#primitives = p;
636
+ this.logger.debug(`[Agents:${this.name}] initialized.`, {
637
+ model: this.model,
638
+ name: this.name
639
+ });
640
+ }
641
+ __registerMastra(mastra) {
642
+ this.#mastra = mastra;
643
+ }
644
+ /**
645
+ * Set the concrete tools for the agent
646
+ * @param tools
647
+ */
648
+ __setTools(tools) {
649
+ this.#tools = tools;
650
+ this.logger.debug(`[Agents:${this.name}] Tools set for agent ${this.name}`, {
651
+ model: this.model,
652
+ name: this.name
653
+ });
654
+ }
655
+ async generateTitleFromUserMessage({
656
+ message,
657
+ runtimeContext = new RuntimeContext(),
658
+ model,
659
+ instructions
660
+ }) {
661
+ const llm = await this.getLLM({
662
+ runtimeContext,
663
+ model
664
+ });
665
+ const normMessage = new MessageList().add(message, "user").get.all.ui().at(-1);
666
+ if (!normMessage) {
667
+ throw new Error(`Could not generate title from input ${JSON.stringify(message)}`);
668
+ }
669
+ const partsToGen = [];
670
+ for (const part of normMessage.parts) {
671
+ if (part.type === `text`) {
672
+ partsToGen.push(part);
673
+ } else if (part.type === `source`) {
674
+ partsToGen.push({
675
+ type: "text",
676
+ text: `User added URL: ${part.source.url.substring(0, 100)}`
677
+ });
678
+ } else if (part.type === `file`) {
679
+ partsToGen.push({
680
+ type: "text",
681
+ text: `User added ${part.mimeType} file: ${part.data.substring(0, 100)}`
682
+ });
683
+ }
684
+ }
685
+ const systemInstructions = await this.resolveTitleInstructions(runtimeContext, instructions);
686
+ const {
687
+ text
688
+ } = await llm.__text({
689
+ runtimeContext,
690
+ messages: [{
691
+ role: "system",
692
+ content: systemInstructions
693
+ }, {
694
+ role: "user",
695
+ content: JSON.stringify(partsToGen)
696
+ }]
697
+ });
698
+ const cleanedText = text.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
699
+ return cleanedText;
700
+ }
701
+ getMostRecentUserMessage(messages) {
702
+ const userMessages = messages.filter(message => message.role === "user");
703
+ return userMessages.at(-1);
704
+ }
705
+ async genTitle(userMessage, runtimeContext, model, instructions) {
706
+ try {
707
+ if (userMessage) {
708
+ const normMessage = new MessageList().add(userMessage, "user").get.all.ui().at(-1);
709
+ if (normMessage) {
710
+ return await this.generateTitleFromUserMessage({
711
+ message: normMessage,
712
+ runtimeContext,
713
+ model,
714
+ instructions
715
+ });
716
+ }
717
+ }
718
+ return `New Thread ${(/* @__PURE__ */new Date()).toISOString()}`;
719
+ } catch (e) {
720
+ this.logger.error("Error generating title:", e);
721
+ return void 0;
722
+ }
723
+ }
724
+ /* @deprecated use agent.getMemory() and query memory directly */
725
+ async fetchMemory({
726
+ threadId,
727
+ thread: passedThread,
728
+ memoryConfig,
729
+ resourceId,
730
+ runId,
731
+ userMessages,
732
+ systemMessage,
733
+ messageList = new MessageList({
734
+ threadId,
735
+ resourceId
736
+ })
737
+ }) {
738
+ const memory = this.getMemory();
739
+ if (memory) {
740
+ const thread = passedThread ?? (await memory.getThreadById({
741
+ threadId
742
+ }));
743
+ if (!thread) {
744
+ return {
745
+ threadId: threadId || "",
746
+ messages: userMessages || []
747
+ };
748
+ }
749
+ if (userMessages && userMessages.length > 0) {
750
+ messageList.add(userMessages, "memory");
751
+ }
752
+ if (systemMessage?.role === "system") {
753
+ messageList.addSystem(systemMessage, "memory");
754
+ }
755
+ const [memoryMessages, memorySystemMessage] = threadId && memory ? await Promise.all([memory.rememberMessages({
756
+ threadId,
757
+ resourceId,
758
+ config: memoryConfig,
759
+ vectorMessageSearch: messageList.getLatestUserContent() || ""
760
+ }).then(r => r.messagesV2), memory.getSystemMessage({
761
+ threadId,
762
+ memoryConfig
763
+ })]) : [[], null];
764
+ this.logger.debug("Fetched messages from memory", {
765
+ threadId,
766
+ runId,
767
+ fetchedCount: memoryMessages.length
768
+ });
769
+ if (memorySystemMessage) {
770
+ messageList.addSystem(memorySystemMessage, "memory");
771
+ }
772
+ messageList.add(memoryMessages, "memory");
773
+ const systemMessages = messageList.getSystemMessages()?.map(m => m.content)?.join(`
774
+ `) ?? void 0;
775
+ const newMessages = messageList.get.input.v1();
776
+ const processedMemoryMessages = memory.processMessages({
777
+ // these will be processed
778
+ messages: messageList.get.remembered.v1(),
779
+ // these are here for inspecting but shouldn't be returned by the processor
780
+ // - ex TokenLimiter needs to measure all tokens even though it's only processing remembered messages
781
+ newMessages,
782
+ systemMessage: systemMessages,
783
+ memorySystemMessage: memorySystemMessage || void 0
784
+ });
785
+ const returnList = new MessageList().addSystem(systemMessages).add(processedMemoryMessages, "memory").add(newMessages, "user");
786
+ return {
787
+ threadId: thread.id,
788
+ messages: returnList.get.all.prompt()
789
+ };
790
+ }
791
+ return {
792
+ threadId: threadId || "",
793
+ messages: userMessages || []
794
+ };
795
+ }
796
+ async getMemoryTools({
797
+ runId,
798
+ resourceId,
799
+ threadId,
800
+ runtimeContext,
801
+ mastraProxy
802
+ }) {
803
+ let convertedMemoryTools = {};
804
+ const memory = this.getMemory();
805
+ const memoryTools = memory?.getTools?.();
806
+ if (memoryTools) {
807
+ const memoryToolEntries = await Promise.all(Object.entries(memoryTools).map(async ([k, tool]) => {
808
+ return [k, {
809
+ description: tool.description,
810
+ parameters: tool.parameters,
811
+ execute: typeof tool?.execute === "function" ? async (args, options) => {
812
+ try {
813
+ this.logger.debug(`[Agent:${this.name}] - Executing memory tool ${k}`, {
814
+ name: k,
815
+ description: tool.description,
816
+ args,
817
+ runId,
818
+ threadId,
819
+ resourceId
820
+ });
821
+ return tool?.execute?.({
822
+ context: args,
823
+ mastra: mastraProxy,
824
+ memory,
825
+ runId,
826
+ threadId,
827
+ resourceId,
828
+ logger: this.logger,
829
+ agentName: this.name,
830
+ runtimeContext
831
+ }, options) ?? void 0;
832
+ } catch (err) {
833
+ const mastraError = new MastraError({
834
+ id: "AGENT_MEMORY_TOOL_EXECUTION_FAILED",
835
+ domain: "AGENT" /* AGENT */,
836
+ category: "USER" /* USER */,
837
+ details: {
838
+ agentName: this.name,
839
+ runId: runId || "",
840
+ threadId: threadId || "",
841
+ resourceId: resourceId || ""
842
+ },
843
+ text: `[Agent:${this.name}] - Failed memory tool execution`
844
+ }, err);
845
+ this.logger.trackException(mastraError);
846
+ this.logger.error(mastraError.toString());
847
+ throw mastraError;
848
+ }
849
+ } : void 0
850
+ }];
851
+ }));
852
+ convertedMemoryTools = Object.fromEntries(memoryToolEntries.filter(entry => Boolean(entry)));
853
+ }
854
+ return convertedMemoryTools;
855
+ }
856
+ async getMemoryMessages({
857
+ resourceId,
858
+ threadId,
859
+ vectorMessageSearch,
860
+ memoryConfig
861
+ }) {
862
+ const memory = this.getMemory();
863
+ if (!memory) {
864
+ return [];
865
+ }
866
+ return memory.rememberMessages({
867
+ threadId,
868
+ resourceId,
869
+ config: memoryConfig,
870
+ // The new user messages aren't in the list yet cause we add memory messages first to try to make sure ordering is correct (memory comes before new user messages)
871
+ vectorMessageSearch
872
+ }).then(r => r.messagesV2);
873
+ }
874
+ async getAssignedTools({
875
+ runtimeContext,
876
+ runId,
877
+ resourceId,
878
+ threadId,
879
+ mastraProxy
880
+ }) {
881
+ let toolsForRequest = {};
882
+ this.logger.debug(`[Agents:${this.name}] - Assembling assigned tools`, {
883
+ runId,
884
+ threadId,
885
+ resourceId
886
+ });
887
+ const memory = this.getMemory();
888
+ const assignedTools = await this.getTools({
889
+ runtimeContext
890
+ });
891
+ const assignedToolEntries = Object.entries(assignedTools || {});
892
+ const assignedCoreToolEntries = await Promise.all(assignedToolEntries.map(async ([k, tool]) => {
893
+ if (!tool) {
894
+ return;
895
+ }
896
+ const options = {
897
+ name: k,
898
+ runId,
899
+ threadId,
900
+ resourceId,
901
+ logger: this.logger,
902
+ mastra: mastraProxy,
903
+ memory,
904
+ agentName: this.name,
905
+ runtimeContext,
906
+ model: typeof this.model === "function" ? await this.getModel({
907
+ runtimeContext
908
+ }) : this.model
909
+ };
910
+ return [k, makeCoreTool(tool, options)];
911
+ }));
912
+ const assignedToolEntriesConverted = Object.fromEntries(assignedCoreToolEntries.filter(entry => Boolean(entry)));
913
+ toolsForRequest = {
914
+ ...assignedToolEntriesConverted
915
+ };
916
+ return toolsForRequest;
917
+ }
918
+ async getToolsets({
919
+ runId,
920
+ threadId,
921
+ resourceId,
922
+ toolsets,
923
+ runtimeContext,
924
+ mastraProxy
925
+ }) {
926
+ let toolsForRequest = {};
927
+ const memory = this.getMemory();
928
+ const toolsFromToolsets = Object.values(toolsets || {});
929
+ if (toolsFromToolsets.length > 0) {
930
+ this.logger.debug(`[Agent:${this.name}] - Adding tools from toolsets ${Object.keys(toolsets || {}).join(", ")}`, {
931
+ runId
932
+ });
933
+ for (const toolset of toolsFromToolsets) {
934
+ for (const [toolName, tool] of Object.entries(toolset)) {
935
+ const toolObj = tool;
936
+ const options = {
937
+ name: toolName,
938
+ runId,
939
+ threadId,
940
+ resourceId,
941
+ logger: this.logger,
942
+ mastra: mastraProxy,
943
+ memory,
944
+ agentName: this.name,
945
+ runtimeContext,
946
+ model: typeof this.model === "function" ? await this.getModel({
947
+ runtimeContext
948
+ }) : this.model
949
+ };
950
+ const convertedToCoreTool = makeCoreTool(toolObj, options, "toolset");
951
+ toolsForRequest[toolName] = convertedToCoreTool;
952
+ }
953
+ }
954
+ }
955
+ return toolsForRequest;
956
+ }
957
+ async getClientTools({
958
+ runId,
959
+ threadId,
960
+ resourceId,
961
+ runtimeContext,
962
+ mastraProxy,
963
+ clientTools
964
+ }) {
965
+ let toolsForRequest = {};
966
+ const memory = this.getMemory();
967
+ const clientToolsForInput = Object.entries(clientTools || {});
968
+ if (clientToolsForInput.length > 0) {
969
+ this.logger.debug(`[Agent:${this.name}] - Adding client tools ${Object.keys(clientTools || {}).join(", ")}`, {
970
+ runId
971
+ });
972
+ for (const [toolName, tool] of clientToolsForInput) {
973
+ const {
974
+ execute,
975
+ ...rest
976
+ } = tool;
977
+ const options = {
978
+ name: toolName,
979
+ runId,
980
+ threadId,
981
+ resourceId,
982
+ logger: this.logger,
983
+ mastra: mastraProxy,
984
+ memory,
985
+ agentName: this.name,
986
+ runtimeContext,
987
+ model: typeof this.model === "function" ? await this.getModel({
988
+ runtimeContext
989
+ }) : this.model
990
+ };
991
+ const convertedToCoreTool = makeCoreTool(rest, options, "client-tool");
992
+ toolsForRequest[toolName] = convertedToCoreTool;
993
+ }
994
+ }
995
+ return toolsForRequest;
996
+ }
997
+ async getWorkflowTools({
998
+ runId,
999
+ threadId,
1000
+ resourceId,
1001
+ runtimeContext
1002
+ }) {
1003
+ let convertedWorkflowTools = {};
1004
+ const workflows = await this.getWorkflows({
1005
+ runtimeContext
1006
+ });
1007
+ if (Object.keys(workflows).length > 0) {
1008
+ convertedWorkflowTools = Object.entries(workflows).reduce((memo, [workflowName, workflow]) => {
1009
+ memo[workflowName] = {
1010
+ description: workflow.description || `Workflow: ${workflowName}`,
1011
+ parameters: workflow.inputSchema || {
1012
+ type: "object",
1013
+ properties: {}
1014
+ },
1015
+ execute: async args => {
1016
+ try {
1017
+ this.logger.debug(`[Agent:${this.name}] - Executing workflow as tool ${workflowName}`, {
1018
+ name: workflowName,
1019
+ description: workflow.description,
1020
+ args,
1021
+ runId,
1022
+ threadId,
1023
+ resourceId
1024
+ });
1025
+ const run = workflow.createRun();
1026
+ const result = await run.start({
1027
+ inputData: args,
1028
+ runtimeContext
1029
+ });
1030
+ return result;
1031
+ } catch (err) {
1032
+ const mastraError = new MastraError({
1033
+ id: "AGENT_WORKFLOW_TOOL_EXECUTION_FAILED",
1034
+ domain: "AGENT" /* AGENT */,
1035
+ category: "USER" /* USER */,
1036
+ details: {
1037
+ agentName: this.name,
1038
+ runId: runId || "",
1039
+ threadId: threadId || "",
1040
+ resourceId: resourceId || ""
1041
+ },
1042
+ text: `[Agent:${this.name}] - Failed workflow tool execution`
1043
+ }, err);
1044
+ this.logger.trackException(mastraError);
1045
+ this.logger.error(mastraError.toString());
1046
+ throw mastraError;
1047
+ }
1048
+ }
1049
+ };
1050
+ return memo;
1051
+ }, {});
1052
+ }
1053
+ return convertedWorkflowTools;
1054
+ }
1055
+ async convertTools({
1056
+ toolsets,
1057
+ clientTools,
1058
+ threadId,
1059
+ resourceId,
1060
+ runId,
1061
+ runtimeContext
1062
+ }) {
1063
+ let mastraProxy = void 0;
1064
+ const logger = this.logger;
1065
+ if (this.#mastra) {
1066
+ mastraProxy = createMastraProxy({
1067
+ mastra: this.#mastra,
1068
+ logger
1069
+ });
1070
+ }
1071
+ const assignedTools = await this.getAssignedTools({
1072
+ runId,
1073
+ resourceId,
1074
+ threadId,
1075
+ runtimeContext,
1076
+ mastraProxy
1077
+ });
1078
+ const memoryTools = await this.getMemoryTools({
1079
+ runId,
1080
+ resourceId,
1081
+ threadId,
1082
+ runtimeContext,
1083
+ mastraProxy
1084
+ });
1085
+ const toolsetTools = await this.getToolsets({
1086
+ runId,
1087
+ resourceId,
1088
+ threadId,
1089
+ runtimeContext,
1090
+ mastraProxy,
1091
+ toolsets
1092
+ });
1093
+ const clientsideTools = await this.getClientTools({
1094
+ runId,
1095
+ resourceId,
1096
+ threadId,
1097
+ runtimeContext,
1098
+ mastraProxy,
1099
+ clientTools
1100
+ });
1101
+ const workflowTools = await this.getWorkflowTools({
1102
+ runId,
1103
+ resourceId,
1104
+ threadId,
1105
+ runtimeContext
1106
+ });
1107
+ return {
1108
+ ...assignedTools,
1109
+ ...memoryTools,
1110
+ ...toolsetTools,
1111
+ ...clientsideTools,
1112
+ ...workflowTools
1113
+ };
1114
+ }
1115
+ /**
1116
+ * Adds response messages from a step to the MessageList and schedules persistence.
1117
+ * This is used for incremental saving: after each agent step, messages are added to a save queue
1118
+ * and a debounced save operation is triggered to avoid redundant writes.
1119
+ *
1120
+ * @param result - The step result containing response messages.
1121
+ * @param messageList - The MessageList instance for the current thread.
1122
+ * @param threadId - The thread ID.
1123
+ * @param memoryConfig - The memory configuration for saving.
1124
+ * @param runId - (Optional) The run ID for logging.
1125
+ */
1126
+ async saveStepMessages({
1127
+ saveQueueManager,
1128
+ result,
1129
+ messageList,
1130
+ threadId,
1131
+ memoryConfig,
1132
+ runId
1133
+ }) {
1134
+ try {
1135
+ messageList.add(result.response.messages, "response");
1136
+ await saveQueueManager.batchMessages(messageList, threadId, memoryConfig);
1137
+ } catch (e) {
1138
+ await saveQueueManager.flushMessages(messageList, threadId, memoryConfig);
1139
+ this.logger.error("Error saving memory on step finish", {
1140
+ error: e,
1141
+ runId
1142
+ });
1143
+ throw e;
1144
+ }
1145
+ }
1146
+ __primitive({
1147
+ instructions,
1148
+ messages,
1149
+ context,
1150
+ thread,
1151
+ memoryConfig,
1152
+ resourceId,
1153
+ runId,
1154
+ toolsets,
1155
+ clientTools,
1156
+ runtimeContext,
1157
+ generateMessageId,
1158
+ saveQueueManager
1159
+ }) {
1160
+ return {
1161
+ before: async () => {
1162
+ if (process.env.NODE_ENV !== "test") {
1163
+ this.logger.debug(`[Agents:${this.name}] - Starting generation`, {
1164
+ runId
1165
+ });
1166
+ }
1167
+ const memory = this.getMemory();
1168
+ const toolEnhancements = [
1169
+ // toolsets
1170
+ toolsets && Object.keys(toolsets || {}).length > 0 ? `toolsets present (${Object.keys(toolsets || {}).length} tools)` : void 0,
1171
+ // memory tools
1172
+ memory && resourceId ? "memory and resourceId available" : void 0].filter(Boolean).join(", ");
1173
+ this.logger.debug(`[Agent:${this.name}] - Enhancing tools: ${toolEnhancements}`, {
1174
+ runId,
1175
+ toolsets: toolsets ? Object.keys(toolsets) : void 0,
1176
+ clientTools: clientTools ? Object.keys(clientTools) : void 0,
1177
+ hasMemory: !!this.getMemory(),
1178
+ hasResourceId: !!resourceId
1179
+ });
1180
+ const threadId = thread?.id;
1181
+ const convertedTools = await this.convertTools({
1182
+ toolsets,
1183
+ clientTools,
1184
+ threadId,
1185
+ resourceId,
1186
+ runId,
1187
+ runtimeContext
1188
+ });
1189
+ const messageList = new MessageList({
1190
+ threadId,
1191
+ resourceId,
1192
+ generateMessageId
1193
+ }).addSystem({
1194
+ role: "system",
1195
+ content: instructions || `${this.instructions}.`
1196
+ }).add(context || [], "context");
1197
+ if (!memory || !threadId && !resourceId) {
1198
+ messageList.add(messages, "user");
1199
+ return {
1200
+ messageObjects: messageList.get.all.prompt(),
1201
+ convertedTools,
1202
+ messageList
1203
+ };
1204
+ }
1205
+ if (!threadId || !resourceId) {
1206
+ const mastraError = new MastraError({
1207
+ id: "AGENT_MEMORY_MISSING_RESOURCE_ID",
1208
+ domain: "AGENT" /* AGENT */,
1209
+ category: "USER" /* USER */,
1210
+ details: {
1211
+ agentName: this.name,
1212
+ threadId: threadId || "",
1213
+ resourceId: resourceId || ""
1214
+ },
1215
+ text: `A resourceId must be provided when passing a threadId and using Memory. Saw threadId ${threadId} but resourceId is ${resourceId}`
1216
+ });
1217
+ this.logger.trackException(mastraError);
1218
+ this.logger.error(mastraError.toString());
1219
+ throw mastraError;
1220
+ }
1221
+ const store = memory.constructor.name;
1222
+ this.logger.debug(`[Agent:${this.name}] - Memory persistence enabled: store=${store}, resourceId=${resourceId}`, {
1223
+ runId,
1224
+ resourceId,
1225
+ threadId,
1226
+ memoryStore: store
1227
+ });
1228
+ let threadObject = void 0;
1229
+ const existingThread = await memory.getThreadById({
1230
+ threadId
1231
+ });
1232
+ if (existingThread) {
1233
+ if (!existingThread.metadata && thread.metadata || thread.metadata && !(0, import_fast_deep_equal.default)(existingThread.metadata, thread.metadata)) {
1234
+ threadObject = await memory.saveThread({
1235
+ thread: {
1236
+ ...existingThread,
1237
+ metadata: thread.metadata
1238
+ },
1239
+ memoryConfig
1240
+ });
1241
+ } else {
1242
+ threadObject = existingThread;
1243
+ }
1244
+ } else {
1245
+ threadObject = await memory.createThread({
1246
+ threadId,
1247
+ metadata: thread.metadata,
1248
+ title: thread.title,
1249
+ memoryConfig,
1250
+ resourceId
1251
+ });
1252
+ }
1253
+ let [memoryMessages, memorySystemMessage] = thread.id && memory ? await Promise.all([this.getMemoryMessages({
1254
+ resourceId,
1255
+ threadId: threadObject.id,
1256
+ vectorMessageSearch: new MessageList().add(messages, `user`).getLatestUserContent() || "",
1257
+ memoryConfig
1258
+ }), memory.getSystemMessage({
1259
+ threadId: threadObject.id,
1260
+ resourceId,
1261
+ memoryConfig
1262
+ })]) : [[], null];
1263
+ this.logger.debug("Fetched messages from memory", {
1264
+ threadId: threadObject.id,
1265
+ runId,
1266
+ fetchedCount: memoryMessages.length
1267
+ });
1268
+ const resultsFromOtherThreads = memoryMessages.filter(m => m.threadId !== threadObject.id);
1269
+ if (resultsFromOtherThreads.length && !memorySystemMessage) {
1270
+ memorySystemMessage = ``;
1271
+ }
1272
+ if (resultsFromOtherThreads.length) {
1273
+ memorySystemMessage += `
1274
+ The following messages were remembered from a different conversation:
1275
+ <remembered_from_other_conversation>
1276
+ ${JSON.stringify(
1277
+ // get v1 since they're closer to CoreMessages (which get sent to the LLM) but also include timestamps
1278
+ new MessageList().add(resultsFromOtherThreads, "memory").get.all.v1())}
1279
+ <end_remembered_from_other_conversation>`;
1280
+ }
1281
+ if (memorySystemMessage) {
1282
+ messageList.addSystem(memorySystemMessage, "memory");
1283
+ }
1284
+ messageList.add(memoryMessages.filter(m => m.threadId === threadObject.id),
1285
+ // filter out messages from other threads. those are added to system message above
1286
+ "memory").add(messages, "user");
1287
+ const systemMessage = [...messageList.getSystemMessages(), ...messageList.getSystemMessages("memory")]?.map(m => m.content)?.join(`
1288
+ `) ?? void 0;
1289
+ const processedMemoryMessages = memory.processMessages({
1290
+ // these will be processed
1291
+ messages: messageList.get.remembered.v1(),
1292
+ // these are here for inspecting but shouldn't be returned by the processor
1293
+ // - ex TokenLimiter needs to measure all tokens even though it's only processing remembered messages
1294
+ newMessages: messageList.get.input.v1(),
1295
+ systemMessage,
1296
+ memorySystemMessage: memorySystemMessage || void 0
1297
+ });
1298
+ const processedList = new MessageList({
1299
+ threadId: threadObject.id,
1300
+ resourceId
1301
+ }).addSystem(instructions || `${this.instructions}.`).addSystem(memorySystemMessage).add(context || [], "context").add(processedMemoryMessages, "memory").add(messageList.get.input.v2(), "user").get.all.prompt();
1302
+ return {
1303
+ convertedTools,
1304
+ thread: threadObject,
1305
+ messageList,
1306
+ // add old processed messages + new input messages
1307
+ messageObjects: processedList
1308
+ };
1309
+ },
1310
+ after: async ({
1311
+ result,
1312
+ thread: threadAfter,
1313
+ threadId,
1314
+ memoryConfig: memoryConfig2,
1315
+ outputText,
1316
+ runId: runId2,
1317
+ messageList
1318
+ }) => {
1319
+ const resToLog = {
1320
+ text: result?.text,
1321
+ object: result?.object,
1322
+ toolResults: result?.toolResults,
1323
+ toolCalls: result?.toolCalls,
1324
+ usage: result?.usage,
1325
+ steps: result?.steps?.map(s => {
1326
+ return {
1327
+ stepType: s?.stepType,
1328
+ text: result?.text,
1329
+ object: result?.object,
1330
+ toolResults: result?.toolResults,
1331
+ toolCalls: result?.toolCalls,
1332
+ usage: result?.usage
1333
+ };
1334
+ })
1335
+ };
1336
+ this.logger.debug(`[Agent:${this.name}] - Post processing LLM response`, {
1337
+ runId: runId2,
1338
+ result: resToLog,
1339
+ threadId
1340
+ });
1341
+ const memory = this.getMemory();
1342
+ const messageListResponses = new MessageList({
1343
+ threadId,
1344
+ resourceId
1345
+ }).add(result.response.messages, "response").get.all.core();
1346
+ const usedWorkingMemory = messageListResponses?.some(m => m.role === "tool" && m?.content?.some(c => c?.toolName === "updateWorkingMemory"));
1347
+ const thread2 = usedWorkingMemory ? threadId ? await memory?.getThreadById({
1348
+ threadId
1349
+ }) : void 0 : threadAfter;
1350
+ if (memory && resourceId && thread2) {
1351
+ try {
1352
+ let responseMessages = result.response.messages;
1353
+ if (!responseMessages && result.object) {
1354
+ responseMessages = [{
1355
+ role: "assistant",
1356
+ content: [{
1357
+ type: "text",
1358
+ text: outputText
1359
+ // outputText contains the stringified object
1360
+ }]
1361
+ }];
1362
+ }
1363
+ if (responseMessages) {
1364
+ messageList.add(responseMessages, "response");
1365
+ }
1366
+ const promises = [saveQueueManager.flushMessages(messageList, threadId, memoryConfig2)];
1367
+ if (thread2.title?.startsWith("New Thread")) {
1368
+ const config = memory.getMergedThreadConfig(memoryConfig2);
1369
+ const userMessage = this.getMostRecentUserMessage(messageList.get.all.ui());
1370
+ const {
1371
+ shouldGenerate,
1372
+ model: titleModel,
1373
+ instructions: titleInstructions
1374
+ } = this.resolveTitleGenerationConfig(config?.threads?.generateTitle);
1375
+ if (shouldGenerate && userMessage) {
1376
+ promises.push(this.genTitle(userMessage, runtimeContext, titleModel, titleInstructions).then(title => {
1377
+ if (title) {
1378
+ return memory.createThread({
1379
+ threadId: thread2.id,
1380
+ resourceId,
1381
+ memoryConfig: memoryConfig2,
1382
+ title,
1383
+ metadata: thread2.metadata
1384
+ });
1385
+ }
1386
+ }));
1387
+ }
1388
+ }
1389
+ await Promise.all(promises);
1390
+ } catch (e) {
1391
+ await saveQueueManager.flushMessages(messageList, threadId, memoryConfig2);
1392
+ if (e instanceof MastraError) {
1393
+ throw e;
1394
+ }
1395
+ const mastraError = new MastraError({
1396
+ id: "AGENT_MEMORY_PERSIST_RESPONSE_MESSAGES_FAILED",
1397
+ domain: "AGENT" /* AGENT */,
1398
+ category: "SYSTEM" /* SYSTEM */,
1399
+ details: {
1400
+ agentName: this.name,
1401
+ runId: runId2 || "",
1402
+ threadId: threadId || "",
1403
+ result: JSON.stringify(resToLog)
1404
+ }
1405
+ }, e);
1406
+ this.logger.trackException(mastraError);
1407
+ this.logger.error(mastraError.toString());
1408
+ throw mastraError;
1409
+ }
1410
+ }
1411
+ if (Object.keys(this.evals || {}).length > 0) {
1412
+ const userInputMessages = messageList.get.all.ui().filter(m => m.role === "user");
1413
+ const input = userInputMessages.map(message => typeof message.content === "string" ? message.content : "").join("\n");
1414
+ const runIdToUse = runId2 || crypto.randomUUID();
1415
+ for (const metric of Object.values(this.evals || {})) {
1416
+ executeHook("onGeneration" /* ON_GENERATION */, {
1417
+ input,
1418
+ output: outputText,
1419
+ runId: runIdToUse,
1420
+ metric,
1421
+ agentName: this.name,
1422
+ instructions: instructions || this.instructions
1423
+ });
1424
+ }
1425
+ }
1426
+ }
1427
+ };
1428
+ }
1429
+ async generate(messages, generateOptions = {}) {
1430
+ const defaultGenerateOptions = await this.getDefaultGenerateOptions({
1431
+ runtimeContext: generateOptions.runtimeContext
1432
+ });
1433
+ const {
1434
+ context,
1435
+ memoryOptions: memoryConfigFromArgs,
1436
+ resourceId: resourceIdFromArgs,
1437
+ maxSteps,
1438
+ onStepFinish,
1439
+ output,
1440
+ toolsets,
1441
+ clientTools,
1442
+ temperature,
1443
+ toolChoice = "auto",
1444
+ experimental_output,
1445
+ telemetry,
1446
+ runtimeContext = new RuntimeContext(),
1447
+ savePerStep = false,
1448
+ ...args
1449
+ } = Object.assign({}, defaultGenerateOptions, generateOptions);
1450
+ const generateMessageId = `experimental_generateMessageId` in args && typeof args.experimental_generateMessageId === `function` ? args.experimental_generateMessageId : void 0;
1451
+ const threadFromArgs = resolveThreadIdFromArgs({
1452
+ ...args,
1453
+ ...generateOptions
1454
+ });
1455
+ const resourceId = args.memory?.resource || resourceIdFromArgs;
1456
+ const memoryConfig = args.memory?.options || memoryConfigFromArgs;
1457
+ const runId = args.runId || randomUUID();
1458
+ const instructions = args.instructions || (await this.getInstructions({
1459
+ runtimeContext
1460
+ }));
1461
+ const llm = await this.getLLM({
1462
+ runtimeContext
1463
+ });
1464
+ const memory = this.getMemory();
1465
+ const saveQueueManager = new SaveQueueManager({
1466
+ logger: this.logger,
1467
+ memory
1468
+ });
1469
+ const {
1470
+ before,
1471
+ after
1472
+ } = this.__primitive({
1473
+ messages,
1474
+ instructions,
1475
+ context,
1476
+ thread: threadFromArgs,
1477
+ memoryConfig,
1478
+ resourceId,
1479
+ runId,
1480
+ toolsets,
1481
+ clientTools,
1482
+ runtimeContext,
1483
+ generateMessageId,
1484
+ saveQueueManager
1485
+ });
1486
+ const {
1487
+ thread,
1488
+ messageObjects,
1489
+ convertedTools,
1490
+ messageList
1491
+ } = await before();
1492
+ const threadId = thread?.id;
1493
+ if (!output && experimental_output) {
1494
+ const result2 = await llm.__text({
1495
+ messages: messageObjects,
1496
+ tools: convertedTools,
1497
+ onStepFinish: async result3 => {
1498
+ if (savePerStep) {
1499
+ await this.saveStepMessages({
1500
+ saveQueueManager,
1501
+ result: result3,
1502
+ messageList,
1503
+ threadId,
1504
+ memoryConfig,
1505
+ runId
1506
+ });
1507
+ }
1508
+ return onStepFinish?.({
1509
+ ...result3,
1510
+ runId
1511
+ });
1512
+ },
1513
+ maxSteps,
1514
+ runId,
1515
+ temperature,
1516
+ toolChoice: toolChoice || "auto",
1517
+ experimental_output,
1518
+ threadId,
1519
+ resourceId,
1520
+ memory: this.getMemory(),
1521
+ runtimeContext,
1522
+ telemetry,
1523
+ ...args
1524
+ });
1525
+ const outputText2 = result2.text;
1526
+ await after({
1527
+ result: result2,
1528
+ threadId,
1529
+ thread,
1530
+ memoryConfig,
1531
+ outputText: outputText2,
1532
+ runId,
1533
+ messageList
1534
+ });
1535
+ const newResult = result2;
1536
+ newResult.object = result2.experimental_output;
1537
+ return newResult;
1538
+ }
1539
+ if (!output) {
1540
+ const result2 = await llm.__text({
1541
+ messages: messageObjects,
1542
+ tools: convertedTools,
1543
+ onStepFinish: async result3 => {
1544
+ if (savePerStep) {
1545
+ await this.saveStepMessages({
1546
+ saveQueueManager,
1547
+ result: result3,
1548
+ messageList,
1549
+ threadId,
1550
+ memoryConfig,
1551
+ runId
1552
+ });
1553
+ }
1554
+ return onStepFinish?.({
1555
+ ...result3,
1556
+ runId
1557
+ });
1558
+ },
1559
+ maxSteps,
1560
+ runId,
1561
+ temperature,
1562
+ toolChoice,
1563
+ telemetry,
1564
+ threadId,
1565
+ resourceId,
1566
+ memory: this.getMemory(),
1567
+ runtimeContext,
1568
+ ...args
1569
+ });
1570
+ const outputText2 = result2.text;
1571
+ await after({
1572
+ result: result2,
1573
+ thread,
1574
+ threadId,
1575
+ memoryConfig,
1576
+ outputText: outputText2,
1577
+ runId,
1578
+ messageList
1579
+ });
1580
+ return result2;
1581
+ }
1582
+ const result = await llm.__textObject({
1583
+ messages: messageObjects,
1584
+ tools: convertedTools,
1585
+ structuredOutput: output,
1586
+ onStepFinish: async result2 => {
1587
+ if (savePerStep) {
1588
+ await this.saveStepMessages({
1589
+ saveQueueManager,
1590
+ result: result2,
1591
+ messageList,
1592
+ threadId,
1593
+ memoryConfig,
1594
+ runId
1595
+ });
1596
+ }
1597
+ return onStepFinish?.({
1598
+ ...result2,
1599
+ runId
1600
+ });
1601
+ },
1602
+ maxSteps,
1603
+ runId,
1604
+ temperature,
1605
+ toolChoice,
1606
+ telemetry,
1607
+ memory: this.getMemory(),
1608
+ runtimeContext,
1609
+ ...args
1610
+ });
1611
+ const outputText = JSON.stringify(result.object);
1612
+ await after({
1613
+ result,
1614
+ thread,
1615
+ threadId,
1616
+ memoryConfig,
1617
+ outputText,
1618
+ runId,
1619
+ messageList
1620
+ });
1621
+ return result;
1622
+ }
1623
+ async stream(messages, streamOptions = {}) {
1624
+ const defaultStreamOptions = await this.getDefaultStreamOptions({
1625
+ runtimeContext: streamOptions.runtimeContext
1626
+ });
1627
+ const {
1628
+ context,
1629
+ memoryOptions: memoryConfigFromArgs,
1630
+ resourceId: resourceIdFromArgs,
1631
+ maxSteps,
1632
+ onFinish,
1633
+ onStepFinish,
1634
+ toolsets,
1635
+ clientTools,
1636
+ output,
1637
+ temperature,
1638
+ toolChoice = "auto",
1639
+ experimental_output,
1640
+ telemetry,
1641
+ runtimeContext = new RuntimeContext(),
1642
+ savePerStep = false,
1643
+ ...args
1644
+ } = Object.assign({}, defaultStreamOptions, streamOptions);
1645
+ const generateMessageId = `experimental_generateMessageId` in args && typeof args.experimental_generateMessageId === `function` ? args.experimental_generateMessageId : void 0;
1646
+ const threadFromArgs = resolveThreadIdFromArgs({
1647
+ ...args,
1648
+ ...streamOptions
1649
+ });
1650
+ const resourceId = args.memory?.resource || resourceIdFromArgs;
1651
+ const memoryConfig = args.memory?.options || memoryConfigFromArgs;
1652
+ const runId = args.runId || randomUUID();
1653
+ const instructions = args.instructions || (await this.getInstructions({
1654
+ runtimeContext
1655
+ }));
1656
+ const llm = await this.getLLM({
1657
+ runtimeContext
1658
+ });
1659
+ const memory = this.getMemory();
1660
+ const saveQueueManager = new SaveQueueManager({
1661
+ logger: this.logger,
1662
+ memory
1663
+ });
1664
+ const {
1665
+ before,
1666
+ after
1667
+ } = this.__primitive({
1668
+ instructions,
1669
+ messages,
1670
+ context,
1671
+ thread: threadFromArgs,
1672
+ memoryConfig,
1673
+ resourceId,
1674
+ runId,
1675
+ toolsets,
1676
+ clientTools,
1677
+ runtimeContext,
1678
+ generateMessageId,
1679
+ saveQueueManager
1680
+ });
1681
+ const {
1682
+ thread,
1683
+ messageObjects,
1684
+ convertedTools,
1685
+ messageList
1686
+ } = await before();
1687
+ const threadId = thread?.id;
1688
+ if (!output && experimental_output) {
1689
+ this.logger.debug(`Starting agent ${this.name} llm stream call`, {
1690
+ runId
1691
+ });
1692
+ const streamResult = llm.__stream({
1693
+ messages: messageObjects,
1694
+ temperature,
1695
+ tools: convertedTools,
1696
+ onStepFinish: async result => {
1697
+ if (savePerStep) {
1698
+ await this.saveStepMessages({
1699
+ saveQueueManager,
1700
+ result,
1701
+ messageList,
1702
+ threadId,
1703
+ memoryConfig,
1704
+ runId
1705
+ });
1706
+ }
1707
+ return onStepFinish?.({
1708
+ ...result,
1709
+ runId
1710
+ });
1711
+ },
1712
+ onFinish: async result => {
1713
+ try {
1714
+ const outputText = result.text;
1715
+ await after({
1716
+ result,
1717
+ thread,
1718
+ threadId,
1719
+ memoryConfig,
1720
+ outputText,
1721
+ runId,
1722
+ messageList
1723
+ });
1724
+ } catch (e) {
1725
+ this.logger.error("Error saving memory on finish", {
1726
+ error: e,
1727
+ runId
1728
+ });
1729
+ }
1730
+ await onFinish?.({
1731
+ ...result,
1732
+ runId
1733
+ });
1734
+ },
1735
+ maxSteps,
1736
+ runId,
1737
+ toolChoice,
1738
+ experimental_output,
1739
+ telemetry,
1740
+ memory: this.getMemory(),
1741
+ runtimeContext,
1742
+ threadId: thread?.id,
1743
+ resourceId,
1744
+ ...args
1745
+ });
1746
+ const newStreamResult = streamResult;
1747
+ newStreamResult.partialObjectStream = streamResult.experimental_partialOutputStream;
1748
+ return newStreamResult;
1749
+ } else if (!output) {
1750
+ this.logger.debug(`Starting agent ${this.name} llm stream call`, {
1751
+ runId
1752
+ });
1753
+ return llm.__stream({
1754
+ messages: messageObjects,
1755
+ temperature,
1756
+ tools: convertedTools,
1757
+ onStepFinish: async result => {
1758
+ if (savePerStep) {
1759
+ await this.saveStepMessages({
1760
+ saveQueueManager,
1761
+ result,
1762
+ messageList,
1763
+ threadId,
1764
+ memoryConfig,
1765
+ runId
1766
+ });
1767
+ }
1768
+ return onStepFinish?.({
1769
+ ...result,
1770
+ runId
1771
+ });
1772
+ },
1773
+ onFinish: async result => {
1774
+ try {
1775
+ const outputText = result.text;
1776
+ await after({
1777
+ result,
1778
+ thread,
1779
+ threadId,
1780
+ memoryConfig,
1781
+ outputText,
1782
+ runId,
1783
+ messageList
1784
+ });
1785
+ } catch (e) {
1786
+ this.logger.error("Error saving memory on finish", {
1787
+ error: e,
1788
+ runId
1789
+ });
1790
+ }
1791
+ await onFinish?.({
1792
+ ...result,
1793
+ runId
1794
+ });
1795
+ },
1796
+ maxSteps,
1797
+ runId,
1798
+ toolChoice,
1799
+ telemetry,
1800
+ memory: this.getMemory(),
1801
+ runtimeContext,
1802
+ threadId: thread?.id,
1803
+ resourceId,
1804
+ ...args
1805
+ });
1806
+ }
1807
+ this.logger.debug(`Starting agent ${this.name} llm streamObject call`, {
1808
+ runId
1809
+ });
1810
+ return llm.__streamObject({
1811
+ messages: messageObjects,
1812
+ tools: convertedTools,
1813
+ temperature,
1814
+ structuredOutput: output,
1815
+ onStepFinish: async result => {
1816
+ if (savePerStep) {
1817
+ await this.saveStepMessages({
1818
+ saveQueueManager,
1819
+ result,
1820
+ messageList,
1821
+ threadId,
1822
+ memoryConfig,
1823
+ runId
1824
+ });
1825
+ }
1826
+ return onStepFinish?.({
1827
+ ...result,
1828
+ runId
1829
+ });
1830
+ },
1831
+ onFinish: async result => {
1832
+ try {
1833
+ const outputText = JSON.stringify(result.object);
1834
+ await after({
1835
+ result,
1836
+ thread,
1837
+ threadId,
1838
+ memoryConfig,
1839
+ outputText,
1840
+ runId,
1841
+ messageList
1842
+ });
1843
+ } catch (e) {
1844
+ this.logger.error("Error saving memory on finish", {
1845
+ error: e,
1846
+ runId
1847
+ });
1848
+ }
1849
+ await onFinish?.({
1850
+ ...result,
1851
+ runId
1852
+ });
1853
+ },
1854
+ runId,
1855
+ toolChoice,
1856
+ telemetry,
1857
+ memory: this.getMemory(),
1858
+ runtimeContext,
1859
+ threadId: thread?.id,
1860
+ resourceId,
1861
+ ...args
1862
+ });
1863
+ }
1864
+ /**
1865
+ * Convert text to speech using the configured voice provider
1866
+ * @param input Text or text stream to convert to speech
1867
+ * @param options Speech options including speaker and provider-specific options
1868
+ * @returns Audio stream
1869
+ * @deprecated Use agent.voice.speak() instead
1870
+ */
1871
+ async speak(input, options) {
1872
+ if (!this.voice) {
1873
+ const mastraError = new MastraError({
1874
+ id: "AGENT_SPEAK_METHOD_VOICE_NOT_CONFIGURED",
1875
+ domain: "AGENT" /* AGENT */,
1876
+ category: "USER" /* USER */,
1877
+ details: {
1878
+ agentName: this.name
1879
+ },
1880
+ text: "No voice provider configured"
1881
+ });
1882
+ this.logger.trackException(mastraError);
1883
+ this.logger.error(mastraError.toString());
1884
+ throw mastraError;
1885
+ }
1886
+ this.logger.warn("Warning: agent.speak() is deprecated. Please use agent.voice.speak() instead.");
1887
+ try {
1888
+ return this.voice.speak(input, options);
1889
+ } catch (e) {
1890
+ let err;
1891
+ if (e instanceof MastraError) {
1892
+ err = e;
1893
+ } else {
1894
+ err = new MastraError({
1895
+ id: "AGENT_SPEAK_METHOD_ERROR",
1896
+ domain: "AGENT" /* AGENT */,
1897
+ category: "UNKNOWN" /* UNKNOWN */,
1898
+ details: {
1899
+ agentName: this.name
1900
+ },
1901
+ text: "Error during agent speak"
1902
+ }, e);
1903
+ }
1904
+ this.logger.trackException(err);
1905
+ this.logger.error(err.toString());
1906
+ throw err;
1907
+ }
1908
+ }
1909
+ /**
1910
+ * Convert speech to text using the configured voice provider
1911
+ * @param audioStream Audio stream to transcribe
1912
+ * @param options Provider-specific transcription options
1913
+ * @returns Text or text stream
1914
+ * @deprecated Use agent.voice.listen() instead
1915
+ */
1916
+ async listen(audioStream, options) {
1917
+ if (!this.voice) {
1918
+ const mastraError = new MastraError({
1919
+ id: "AGENT_LISTEN_METHOD_VOICE_NOT_CONFIGURED",
1920
+ domain: "AGENT" /* AGENT */,
1921
+ category: "USER" /* USER */,
1922
+ details: {
1923
+ agentName: this.name
1924
+ },
1925
+ text: "No voice provider configured"
1926
+ });
1927
+ this.logger.trackException(mastraError);
1928
+ this.logger.error(mastraError.toString());
1929
+ throw mastraError;
1930
+ }
1931
+ this.logger.warn("Warning: agent.listen() is deprecated. Please use agent.voice.listen() instead");
1932
+ try {
1933
+ return this.voice.listen(audioStream, options);
1934
+ } catch (e) {
1935
+ let err;
1936
+ if (e instanceof MastraError) {
1937
+ err = e;
1938
+ } else {
1939
+ err = new MastraError({
1940
+ id: "AGENT_LISTEN_METHOD_ERROR",
1941
+ domain: "AGENT" /* AGENT */,
1942
+ category: "UNKNOWN" /* UNKNOWN */,
1943
+ details: {
1944
+ agentName: this.name
1945
+ },
1946
+ text: "Error during agent listen"
1947
+ }, e);
1948
+ }
1949
+ this.logger.trackException(err);
1950
+ this.logger.error(err.toString());
1951
+ throw err;
1952
+ }
1953
+ }
1954
+ /**
1955
+ * Get a list of available speakers from the configured voice provider
1956
+ * @throws {Error} If no voice provider is configured
1957
+ * @returns {Promise<Array<{voiceId: string}>>} List of available speakers
1958
+ * @deprecated Use agent.voice.getSpeakers() instead
1959
+ */
1960
+ async getSpeakers() {
1961
+ if (!this.voice) {
1962
+ const mastraError = new MastraError({
1963
+ id: "AGENT_SPEAKERS_METHOD_VOICE_NOT_CONFIGURED",
1964
+ domain: "AGENT" /* AGENT */,
1965
+ category: "USER" /* USER */,
1966
+ details: {
1967
+ agentName: this.name
1968
+ },
1969
+ text: "No voice provider configured"
1970
+ });
1971
+ this.logger.trackException(mastraError);
1972
+ this.logger.error(mastraError.toString());
1973
+ throw mastraError;
1974
+ }
1975
+ this.logger.warn("Warning: agent.getSpeakers() is deprecated. Please use agent.voice.getSpeakers() instead.");
1976
+ try {
1977
+ return await this.voice.getSpeakers();
1978
+ } catch (e) {
1979
+ let err;
1980
+ if (e instanceof MastraError) {
1981
+ err = e;
1982
+ } else {
1983
+ err = new MastraError({
1984
+ id: "AGENT_GET_SPEAKERS_METHOD_ERROR",
1985
+ domain: "AGENT" /* AGENT */,
1986
+ category: "UNKNOWN" /* UNKNOWN */,
1987
+ details: {
1988
+ agentName: this.name
1989
+ },
1990
+ text: "Error during agent getSpeakers"
1991
+ }, e);
1992
+ }
1993
+ this.logger.trackException(err);
1994
+ this.logger.error(err.toString());
1995
+ throw err;
1996
+ }
1997
+ }
1998
+ toStep() {
1999
+ const x = agentToStep(this);
2000
+ return new LegacyStep(x);
2001
+ }
2002
+ /**
2003
+ * Resolves the configuration for title generation.
2004
+ * @private
2005
+ */
2006
+ resolveTitleGenerationConfig(generateTitleConfig) {
2007
+ if (typeof generateTitleConfig === "boolean") {
2008
+ return {
2009
+ shouldGenerate: generateTitleConfig
2010
+ };
2011
+ }
2012
+ if (typeof generateTitleConfig === "object" && generateTitleConfig !== null) {
2013
+ return {
2014
+ shouldGenerate: true,
2015
+ model: generateTitleConfig.model,
2016
+ instructions: generateTitleConfig.instructions
2017
+ };
2018
+ }
2019
+ return {
2020
+ shouldGenerate: false
2021
+ };
2022
+ }
2023
+ /**
2024
+ * Resolves title generation instructions, handling both static strings and dynamic functions
2025
+ * @private
2026
+ */
2027
+ async resolveTitleInstructions(runtimeContext, instructions) {
2028
+ const DEFAULT_TITLE_INSTRUCTIONS = `
2029
+ - you will generate a short title based on the first message a user begins a conversation with
2030
+ - ensure it is not more than 80 characters long
2031
+ - the title should be a summary of the user's message
2032
+ - do not use quotes or colons
2033
+ - the entire text you return will be used as the title`;
2034
+ if (!instructions) {
2035
+ return DEFAULT_TITLE_INSTRUCTIONS;
2036
+ }
2037
+ if (typeof instructions === "string") {
2038
+ return instructions;
2039
+ } else {
2040
+ const result = instructions({
2041
+ runtimeContext
2042
+ });
2043
+ return resolveMaybePromise(result, resolvedInstructions => {
2044
+ return resolvedInstructions || DEFAULT_TITLE_INSTRUCTIONS;
2045
+ });
2046
+ }
2047
+ }
2048
+ };
2049
+ Agent = /*@__PURE__*/(_ => {
2050
+ _init = __decoratorStart(_a);
2051
+ Agent = __decorateElement(_init, 0, "Agent", _Agent_decorators, Agent);
2052
+ __runInitializers(_init, 1, Agent);
2053
+
2054
+ // src/workflows/legacy/utils.ts
2055
+ return Agent;
2056
+ })();
2057
+ // src/workflows/legacy/utils.ts
2058
+ function isErrorEvent(stateEvent) {
2059
+ return stateEvent.type.startsWith("xstate.error.actor.");
2060
+ }
2061
+ function isTransitionEvent(stateEvent) {
2062
+ return stateEvent.type.startsWith("xstate.done.actor.");
2063
+ }
2064
+ function isVariableReference(value) {
2065
+ return typeof value === "object" && "step" in value && "path" in value;
2066
+ }
2067
+ function getStepResult(result) {
2068
+ if (result?.status === "success") return result.output;
2069
+ return void 0;
2070
+ }
2071
+ function getSuspendedPaths({
2072
+ value,
2073
+ path,
2074
+ suspendedPaths
2075
+ }) {
2076
+ if (typeof value === "string") {
2077
+ if (value === "suspended") {
2078
+ suspendedPaths.add(path);
2079
+ }
2080
+ } else {
2081
+ Object.keys(value).forEach(key => getSuspendedPaths({
2082
+ value: value[key],
2083
+ path: path ? `${path}.${key}` : key,
2084
+ suspendedPaths
2085
+ }));
2086
+ }
2087
+ }
2088
+ function isFinalState(status) {
2089
+ return ["completed", "failed"].includes(status);
2090
+ }
2091
+ function isLimboState(status) {
2092
+ return status === "limbo";
2093
+ }
2094
+ function recursivelyCheckForFinalState({
2095
+ value,
2096
+ suspendedPaths,
2097
+ path
2098
+ }) {
2099
+ if (typeof value === "string") {
2100
+ return isFinalState(value) || isLimboState(value) || suspendedPaths.has(path);
2101
+ }
2102
+ return Object.keys(value).every(key => recursivelyCheckForFinalState({
2103
+ value: value[key],
2104
+ suspendedPaths,
2105
+ path: path ? `${path}.${key}` : key
2106
+ }));
2107
+ }
2108
+ function getActivePathsAndStatus(value) {
2109
+ const paths = [];
2110
+ const traverse = (current, path = []) => {
2111
+ for (const [key, value2] of Object.entries(current)) {
2112
+ const currentPath = [...path, key];
2113
+ if (typeof value2 === "string") {
2114
+ paths.push({
2115
+ stepPath: currentPath,
2116
+ stepId: key,
2117
+ status: value2
2118
+ });
2119
+ } else if (typeof value2 === "object" && value2 !== null) {
2120
+ traverse(value2, currentPath);
2121
+ }
2122
+ }
2123
+ };
2124
+ traverse(value);
2125
+ return paths;
2126
+ }
2127
+ function mergeChildValue(startStepId, parent, child) {
2128
+ const traverse = current => {
2129
+ const obj = {};
2130
+ for (const [key, value] of Object.entries(current)) {
2131
+ if (key === startStepId) {
2132
+ obj[key] = {
2133
+ ...child
2134
+ };
2135
+ } else if (typeof value === "string") {
2136
+ obj[key] = value;
2137
+ } else if (typeof value === "object" && value !== null) {
2138
+ obj[key] = traverse(value);
2139
+ }
2140
+ }
2141
+ return obj;
2142
+ };
2143
+ return traverse(parent);
2144
+ }
2145
+ var updateStepInHierarchy = (value, targetStepId) => {
2146
+ const result = {};
2147
+ for (const key of Object.keys(value)) {
2148
+ const currentValue = value[key];
2149
+ if (key === targetStepId) {
2150
+ result[key] = "pending";
2151
+ } else if (typeof currentValue === "object" && currentValue !== null) {
2152
+ result[key] = updateStepInHierarchy(currentValue, targetStepId);
2153
+ } else {
2154
+ result[key] = currentValue;
2155
+ }
2156
+ }
2157
+ return result;
2158
+ };
2159
+ function getResultActivePaths(state) {
2160
+ const activePaths = getActivePathsAndStatus(state.value);
2161
+ const activePathsAndStatus = activePaths.reduce((acc, curr) => {
2162
+ const entry = {
2163
+ status: curr.status,
2164
+ stepPath: curr.stepPath
2165
+ };
2166
+ if (curr.status === "suspended") {
2167
+ entry.suspendPayload = state.context.steps[curr.stepId].suspendPayload;
2168
+ entry.stepPath = curr.stepPath;
2169
+ }
2170
+ acc.set(curr.stepId, entry);
2171
+ return acc;
2172
+ }, /* @__PURE__ */new Map());
2173
+ return activePathsAndStatus;
2174
+ }
2175
+ function isWorkflow(step) {
2176
+ return step instanceof LegacyWorkflow;
2177
+ }
2178
+ function isAgent(step) {
2179
+ return step instanceof Agent;
2180
+ }
2181
+ function resolveVariables({
2182
+ runId,
2183
+ logger,
2184
+ variables,
2185
+ context
2186
+ }) {
2187
+ const resolvedData = {};
2188
+ for (const [key, variable] of Object.entries(variables)) {
2189
+ const sourceData = variable.step === "trigger" ? context.triggerData : getStepResult(context.steps[variable.step.id ?? variable.step.name]);
2190
+ logger.debug(`Got source data for ${key} variable from ${variable.step === "trigger" ? "trigger" : variable.step.id ?? variable.step.name}`, {
2191
+ sourceData,
2192
+ path: variable.path,
2193
+ runId
2194
+ });
2195
+ if (!sourceData && variable.step !== "trigger") {
2196
+ resolvedData[key] = void 0;
2197
+ continue;
2198
+ }
2199
+ const value = variable.path === "" || variable.path === "." ? sourceData : get(sourceData, variable.path);
2200
+ logger.debug(`Resolved variable ${key}`, {
2201
+ value,
2202
+ runId
2203
+ });
2204
+ resolvedData[key] = value;
2205
+ }
2206
+ return resolvedData;
2207
+ }
2208
+ function agentToStep(agent, {
2209
+ mastra
2210
+ } = {}) {
2211
+ return {
2212
+ id: agent.name,
2213
+ inputSchema: z.object({
2214
+ prompt: z.string(),
2215
+ resourceId: z.string().optional(),
2216
+ threadId: z.string().optional()
2217
+ }),
2218
+ outputSchema: z.object({
2219
+ text: z.string()
2220
+ }),
2221
+ execute: async ({
2222
+ context,
2223
+ runId,
2224
+ mastra: mastraFromExecute
2225
+ }) => {
2226
+ const realMastra = mastraFromExecute ?? mastra;
2227
+ if (!realMastra) {
2228
+ throw new Error("Mastra instance not found");
2229
+ }
2230
+ agent.__registerMastra(realMastra);
2231
+ agent.__registerPrimitives({
2232
+ logger: realMastra.getLogger(),
2233
+ telemetry: realMastra.getTelemetry()
2234
+ });
2235
+ const result = await agent.generate(context.inputData.prompt, {
2236
+ runId,
2237
+ resourceId: context.inputData.resourceId,
2238
+ threadId: context.inputData.threadId
2239
+ });
2240
+ return {
2241
+ text: result.text
2242
+ };
2243
+ }
2244
+ };
2245
+ }
2246
+ function workflowToStep(workflow, {
2247
+ mastra
2248
+ }) {
2249
+ workflow.setNested(true);
2250
+ return {
2251
+ id: workflow.name,
2252
+ workflow,
2253
+ workflowId: toCamelCaseWithRandomSuffix(workflow.name),
2254
+ execute: async ({
2255
+ context,
2256
+ suspend,
2257
+ emit,
2258
+ mastra: mastraFromExecute,
2259
+ runtimeContext
2260
+ }) => {
2261
+ const realMastra = mastraFromExecute ?? mastra;
2262
+ if (realMastra) {
2263
+ workflow.__registerMastra(realMastra);
2264
+ workflow.__registerPrimitives({
2265
+ logger: realMastra.getLogger(),
2266
+ telemetry: realMastra.getTelemetry()
2267
+ });
2268
+ }
2269
+ const run = context.isResume ? workflow.createRun({
2270
+ runId: context.isResume.runId
2271
+ }) : workflow.createRun();
2272
+ const unwatch = run.watch(state => {
2273
+ emit("state-update", workflow.name, state.results, {
2274
+ ...context,
2275
+ ...{
2276
+ [workflow.name]: state.results
2277
+ }
2278
+ });
2279
+ });
2280
+ const awaitedResult = context.isResume && context.isResume.stepId.includes(".") ? await run.resume({
2281
+ stepId: context.isResume.stepId.split(".").slice(1).join("."),
2282
+ context: context.inputData,
2283
+ runtimeContext
2284
+ }) : await run.start({
2285
+ triggerData: context.inputData,
2286
+ runtimeContext
2287
+ });
2288
+ unwatch();
2289
+ if (!awaitedResult) {
2290
+ throw new Error("LegacyWorkflow run failed");
2291
+ }
2292
+ if (awaitedResult.activePaths?.size > 0) {
2293
+ const suspendedStep = [...awaitedResult.activePaths.entries()].find(([, {
2294
+ status
2295
+ }]) => {
2296
+ return status === "suspended";
2297
+ });
2298
+ if (suspendedStep) {
2299
+ await suspend(suspendedStep[1].suspendPayload, {
2300
+ ...awaitedResult,
2301
+ runId: run.runId
2302
+ });
2303
+ }
2304
+ }
2305
+ return {
2306
+ ...awaitedResult,
2307
+ runId: run.runId
2308
+ };
2309
+ }
2310
+ };
2311
+ }
2312
+ function toCamelCaseWithRandomSuffix(str) {
2313
+ if (!str) return "";
2314
+ const normalizedStr = str.replace(/[-_]/g, " ");
2315
+ const words = normalizedStr.split(" ").filter(word => word.length > 0);
2316
+ const camelCase = words.map((word, index) => {
2317
+ word = word.replace(/[^a-zA-Z0-9]/g, "");
2318
+ if (index === 0) {
2319
+ return word.toLowerCase();
2320
+ }
2321
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
2322
+ }).join("");
2323
+ const randomString = generateRandomLetters(3);
2324
+ return camelCase + randomString;
2325
+ }
2326
+ function generateRandomLetters(length) {
2327
+ const characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
2328
+ let result = "";
2329
+ for (let i = 0; i < length; i++) {
2330
+ const randomIndex = Math.floor(Math.random() * characters.length);
2331
+ result += characters.charAt(randomIndex);
2332
+ }
2333
+ return result;
2334
+ }
2335
+ function isConditionalKey(key) {
2336
+ return key.startsWith("__") && (key.includes("_if") || key.includes("_else"));
2337
+ }
2338
+ var Machine = class extends EventEmitter {
2339
+ logger;
2340
+ #mastra;
2341
+ #runtimeContext;
2342
+ #workflowInstance;
2343
+ #executionSpan;
2344
+ #stepGraph;
2345
+ #machine;
2346
+ #runId;
2347
+ #startStepId;
2348
+ name;
2349
+ #actor = null;
2350
+ #steps = {};
2351
+ #retryConfig;
2352
+ constructor({
2353
+ logger,
2354
+ mastra,
2355
+ runtimeContext,
2356
+ workflowInstance,
2357
+ executionSpan,
2358
+ name,
2359
+ runId,
2360
+ steps,
2361
+ stepGraph,
2362
+ retryConfig,
2363
+ startStepId
2364
+ }) {
2365
+ super();
2366
+ this.#mastra = mastra;
2367
+ this.#workflowInstance = workflowInstance;
2368
+ this.#runtimeContext = runtimeContext;
2369
+ this.#executionSpan = executionSpan;
2370
+ this.logger = logger;
2371
+ this.#runId = runId;
2372
+ this.#startStepId = startStepId;
2373
+ this.name = name;
2374
+ this.#stepGraph = stepGraph;
2375
+ this.#steps = steps;
2376
+ this.#retryConfig = retryConfig;
2377
+ this.initializeMachine();
2378
+ }
2379
+ get startStepId() {
2380
+ return this.#startStepId;
2381
+ }
2382
+ async execute({
2383
+ stepId,
2384
+ input,
2385
+ snapshot,
2386
+ resumeData
2387
+ } = {}) {
2388
+ if (snapshot) {
2389
+ this.logger.debug(`Workflow snapshot received`, {
2390
+ runId: this.#runId,
2391
+ snapshot
2392
+ });
2393
+ }
2394
+ const origSteps = input.steps;
2395
+ const isResumedInitialStep = this.#stepGraph?.initial[0]?.step?.id === stepId;
2396
+ if (isResumedInitialStep) {
2397
+ snapshot = void 0;
2398
+ input.steps = {};
2399
+ }
2400
+ this.logger.debug(`Machine input prepared`, {
2401
+ runId: this.#runId,
2402
+ input
2403
+ });
2404
+ const actorSnapshot = snapshot ? {
2405
+ ...snapshot,
2406
+ context: {
2407
+ ...input,
2408
+ inputData: {
2409
+ ...(snapshot?.context?.inputData || {}),
2410
+ ...resumeData
2411
+ },
2412
+ // ts-ignore is needed here because our snapshot types don't really match xstate snapshot types right now. We should fix this in general.
2413
+ // @ts-ignore
2414
+ isResume: {
2415
+ runId: snapshot?.context?.steps[stepId.split(".")?.[0]]?.output?.runId || this.#runId,
2416
+ stepId
2417
+ }
2418
+ }
2419
+ } : void 0;
2420
+ this.logger.debug(`Creating actor with configuration`, {
2421
+ input,
2422
+ actorSnapshot,
2423
+ runId: this.#runId,
2424
+ machineStates: this.#machine.config.states
2425
+ });
2426
+ this.#actor = createActor(this.#machine, {
2427
+ inspect: inspectionEvent => {
2428
+ this.logger.debug("XState inspection event", {
2429
+ type: inspectionEvent.type,
2430
+ event: inspectionEvent.event,
2431
+ runId: this.#runId
2432
+ });
2433
+ },
2434
+ input: {
2435
+ ...input,
2436
+ inputData: {
2437
+ ...(snapshot?.context?.inputData || {}),
2438
+ ...resumeData
2439
+ }
2440
+ },
2441
+ snapshot: actorSnapshot
2442
+ });
2443
+ this.#actor.start();
2444
+ if (stepId) {
2445
+ this.#actor.send({
2446
+ type: "RESET_TO_PENDING",
2447
+ stepId
2448
+ });
2449
+ }
2450
+ this.logger.debug("Actor started", {
2451
+ runId: this.#runId
2452
+ });
2453
+ return new Promise((resolve, reject) => {
2454
+ if (!this.#actor) {
2455
+ this.logger.error("Actor not initialized", {
2456
+ runId: this.#runId
2457
+ });
2458
+ const e = new Error("Actor not initialized");
2459
+ this.#executionSpan?.recordException(e);
2460
+ this.#executionSpan?.end();
2461
+ reject(e);
2462
+ return;
2463
+ }
2464
+ const suspendedPaths = /* @__PURE__ */new Set();
2465
+ this.#actor.subscribe(async state => {
2466
+ this.emit("state-update", this.#startStepId, state);
2467
+ getSuspendedPaths({
2468
+ value: state.value,
2469
+ path: "",
2470
+ suspendedPaths
2471
+ });
2472
+ const allStatesValue = state.value;
2473
+ const allStatesComplete = recursivelyCheckForFinalState({
2474
+ value: allStatesValue,
2475
+ suspendedPaths,
2476
+ path: ""
2477
+ });
2478
+ this.logger.debug("State completion check", {
2479
+ allStatesComplete,
2480
+ suspendedPaths: Array.from(suspendedPaths),
2481
+ runId: this.#runId
2482
+ });
2483
+ if (!allStatesComplete) {
2484
+ this.logger.debug("Not all states complete", {
2485
+ allStatesComplete,
2486
+ suspendedPaths: Array.from(suspendedPaths),
2487
+ runId: this.#runId
2488
+ });
2489
+ return;
2490
+ }
2491
+ try {
2492
+ this.logger.debug("All states complete", {
2493
+ runId: this.#runId
2494
+ });
2495
+ await this.#workflowInstance.persistWorkflowSnapshot();
2496
+ this.#cleanup();
2497
+ this.#executionSpan?.end();
2498
+ resolve({
2499
+ runId: this.#runId,
2500
+ results: isResumedInitialStep ? {
2501
+ ...origSteps,
2502
+ ...state.context.steps
2503
+ } : state.context.steps,
2504
+ activePaths: getResultActivePaths(state),
2505
+ timestamp: Date.now()
2506
+ });
2507
+ } catch (error) {
2508
+ this.logger.debug("Failed to persist final snapshot", {
2509
+ error
2510
+ });
2511
+ this.#cleanup();
2512
+ this.#executionSpan?.end();
2513
+ resolve({
2514
+ runId: this.#runId,
2515
+ results: isResumedInitialStep ? {
2516
+ ...origSteps,
2517
+ ...state.context.steps
2518
+ } : state.context.steps,
2519
+ activePaths: getResultActivePaths(state),
2520
+ timestamp: Date.now()
2521
+ });
2522
+ }
2523
+ });
2524
+ });
2525
+ }
2526
+ #cleanup() {
2527
+ if (this.#actor) {
2528
+ this.#actor.stop();
2529
+ this.#actor = null;
2530
+ }
2531
+ this.removeAllListeners();
2532
+ }
2533
+ #makeDelayMap() {
2534
+ const delayMap = {};
2535
+ Object.keys(this.#steps).forEach(stepId => {
2536
+ delayMap[stepId] = this.#steps[stepId]?.step?.retryConfig?.delay || this.#retryConfig?.delay || 1e3;
2537
+ });
2538
+ return delayMap;
2539
+ }
2540
+ #getDefaultActions() {
2541
+ return {
2542
+ updateStepResult: assign({
2543
+ steps: ({
2544
+ context,
2545
+ event
2546
+ }) => {
2547
+ if (!isTransitionEvent(event)) return context.steps;
2548
+ const {
2549
+ stepId,
2550
+ result
2551
+ } = event.output;
2552
+ return {
2553
+ ...context.steps,
2554
+ [stepId]: {
2555
+ status: "success",
2556
+ output: result
2557
+ }
2558
+ };
2559
+ }
2560
+ }),
2561
+ setStepError: assign({
2562
+ steps: ({
2563
+ context,
2564
+ event
2565
+ }, params) => {
2566
+ if (!isErrorEvent(event)) return context.steps;
2567
+ const {
2568
+ stepId
2569
+ } = params;
2570
+ if (!stepId) return context.steps;
2571
+ return {
2572
+ ...context.steps,
2573
+ [stepId]: {
2574
+ status: "failed",
2575
+ error: event.error.message
2576
+ }
2577
+ };
2578
+ }
2579
+ }),
2580
+ notifyStepCompletion: async (_, params) => {
2581
+ const {
2582
+ stepId
2583
+ } = params;
2584
+ this.logger.debug(`Step ${stepId} completed`);
2585
+ },
2586
+ snapshotStep: assign({
2587
+ _snapshot: ({}, params) => {
2588
+ const {
2589
+ stepId
2590
+ } = params;
2591
+ return {
2592
+ stepId
2593
+ };
2594
+ }
2595
+ }),
2596
+ persistSnapshot: async ({
2597
+ context
2598
+ }) => {
2599
+ if (context._snapshot) {
2600
+ await this.#workflowInstance.persistWorkflowSnapshot();
2601
+ }
2602
+ return;
2603
+ },
2604
+ decrementAttemptCount: assign({
2605
+ attempts: ({
2606
+ context,
2607
+ event
2608
+ }, params) => {
2609
+ if (!isTransitionEvent(event)) return context.attempts;
2610
+ const {
2611
+ stepId
2612
+ } = params;
2613
+ const attemptCount = context.attempts[stepId];
2614
+ if (attemptCount === void 0) return context.attempts;
2615
+ return {
2616
+ ...context.attempts,
2617
+ [stepId]: attemptCount - 1
2618
+ };
2619
+ }
2620
+ })
2621
+ };
2622
+ }
2623
+ #getDefaultActors() {
2624
+ return {
2625
+ resolverFunction: fromPromise(async ({
2626
+ input
2627
+ }) => {
2628
+ const {
2629
+ stepNode,
2630
+ context
2631
+ } = input;
2632
+ const attemptCount = context.attempts[stepNode.id];
2633
+ const resolvedData = this.#resolveVariables({
2634
+ stepConfig: stepNode.config,
2635
+ context,
2636
+ stepId: stepNode.id
2637
+ });
2638
+ this.logger.debug(`Resolved variables for ${stepNode.id}`, {
2639
+ resolvedData,
2640
+ runId: this.#runId
2641
+ });
2642
+ const logger = this.logger;
2643
+ let mastraProxy = void 0;
2644
+ if (this.#mastra) {
2645
+ mastraProxy = createMastraProxy({
2646
+ mastra: this.#mastra,
2647
+ logger
2648
+ });
2649
+ }
2650
+ let result = void 0;
2651
+ try {
2652
+ result = await stepNode.config.handler({
2653
+ context: {
2654
+ ...context,
2655
+ inputData: {
2656
+ ...(context?.inputData || {}),
2657
+ ...resolvedData
2658
+ },
2659
+ getStepResult: stepId => {
2660
+ const resolvedStepId = typeof stepId === "string" ? stepId : stepId.id;
2661
+ if (resolvedStepId === "trigger") {
2662
+ return context.triggerData;
2663
+ }
2664
+ const result2 = context.steps[resolvedStepId];
2665
+ if (result2 && result2.status === "success") {
2666
+ return result2.output;
2667
+ }
2668
+ return void 0;
2669
+ }
2670
+ },
2671
+ emit: (event, ...args) => {
2672
+ this.emit(event, ...args);
2673
+ },
2674
+ suspend: async (payload, softSuspend) => {
2675
+ await this.#workflowInstance.suspend(stepNode.id, this);
2676
+ if (this.#actor) {
2677
+ context.steps[stepNode.id] = {
2678
+ status: "suspended",
2679
+ suspendPayload: payload,
2680
+ output: softSuspend
2681
+ };
2682
+ this.logger.debug(`Sending SUSPENDED event for step ${stepNode.id}`);
2683
+ this.#actor?.send({
2684
+ type: "SUSPENDED",
2685
+ suspendPayload: payload,
2686
+ stepId: stepNode.id,
2687
+ softSuspend
2688
+ });
2689
+ } else {
2690
+ this.logger.debug(`Actor not available for step ${stepNode.id}`);
2691
+ }
2692
+ },
2693
+ runId: this.#runId,
2694
+ mastra: mastraProxy,
2695
+ runtimeContext: this.#runtimeContext
2696
+ });
2697
+ } catch (error) {
2698
+ this.logger.debug(`Step ${stepNode.id} failed`, {
2699
+ stepId: stepNode.id,
2700
+ error,
2701
+ runId: this.#runId
2702
+ });
2703
+ this.logger.debug(`Attempt count for step ${stepNode.id}`, {
2704
+ attemptCount,
2705
+ attempts: context.attempts,
2706
+ runId: this.#runId,
2707
+ stepId: stepNode.id
2708
+ });
2709
+ if (!attemptCount || attemptCount < 0) {
2710
+ return {
2711
+ type: "STEP_FAILED",
2712
+ error: error instanceof Error ? error.message : `Step:${stepNode.id} failed with error: ${error}`,
2713
+ stepId: stepNode.id
2714
+ };
2715
+ }
2716
+ return {
2717
+ type: "STEP_WAITING",
2718
+ stepId: stepNode.id
2719
+ };
2720
+ }
2721
+ this.logger.debug(`Step ${stepNode.id} result`, {
2722
+ stepId: stepNode.id,
2723
+ result,
2724
+ runId: this.#runId
2725
+ });
2726
+ return {
2727
+ type: "STEP_SUCCESS",
2728
+ result,
2729
+ stepId: stepNode.id
2730
+ };
2731
+ }),
2732
+ conditionCheck: fromPromise(async ({
2733
+ input
2734
+ }) => {
2735
+ const {
2736
+ context,
2737
+ stepNode
2738
+ } = input;
2739
+ const stepConfig = stepNode.config;
2740
+ this.logger.debug(`Checking conditions for step ${stepNode.id}`, {
2741
+ stepId: stepNode.id,
2742
+ runId: this.#runId
2743
+ });
2744
+ if (!stepConfig?.when) {
2745
+ return {
2746
+ type: "CONDITIONS_MET"
2747
+ };
2748
+ }
2749
+ this.logger.debug(`Checking conditions for step ${stepNode.id}`, {
2750
+ stepId: stepNode.id,
2751
+ runId: this.#runId
2752
+ });
2753
+ if (typeof stepConfig?.when === "function") {
2754
+ let conditionMet = await stepConfig.when({
2755
+ context: {
2756
+ ...context,
2757
+ getStepResult: stepId => {
2758
+ const resolvedStepId = typeof stepId === "string" ? stepId : stepId.id;
2759
+ if (resolvedStepId === "trigger") {
2760
+ return context.triggerData;
2761
+ }
2762
+ const result = context.steps[resolvedStepId];
2763
+ if (result && result.status === "success") {
2764
+ return result.output;
2765
+ }
2766
+ return void 0;
2767
+ }
2768
+ },
2769
+ mastra: this.#mastra
2770
+ });
2771
+ if (conditionMet === "abort" /* ABORT */) {
2772
+ conditionMet = false;
2773
+ } else if (conditionMet === "continue_failed" /* CONTINUE_FAILED */) {
2774
+ return {
2775
+ type: "CONDITIONS_SKIP_TO_COMPLETED"
2776
+ };
2777
+ } else if (conditionMet === "limbo" /* LIMBO */) {
2778
+ return {
2779
+ type: "CONDITIONS_LIMBO"
2780
+ };
2781
+ } else if (conditionMet) {
2782
+ this.logger.debug(`Condition met for step ${stepNode.id}`, {
2783
+ stepId: stepNode.id,
2784
+ runId: this.#runId
2785
+ });
2786
+ return {
2787
+ type: "CONDITIONS_MET"
2788
+ };
2789
+ }
2790
+ if (isConditionalKey(stepNode.id)) {
2791
+ return {
2792
+ type: "CONDITIONS_LIMBO"
2793
+ };
2794
+ }
2795
+ return this.#workflowInstance.hasSubscribers(stepNode.id) ? {
2796
+ type: "CONDITIONS_SKIPPED"
2797
+ } : {
2798
+ type: "CONDITIONS_LIMBO"
2799
+ };
2800
+ } else {
2801
+ const conditionMet = this.#evaluateCondition(stepConfig.when, context);
2802
+ if (!conditionMet) {
2803
+ return {
2804
+ type: "CONDITION_FAILED",
2805
+ error: `Step:${stepNode.id} condition check failed`
2806
+ };
2807
+ }
2808
+ }
2809
+ return {
2810
+ type: "CONDITIONS_MET"
2811
+ };
2812
+ }),
2813
+ spawnSubscriberFunction: fromPromise(async ({
2814
+ input
2815
+ }) => {
2816
+ const {
2817
+ parentStepId,
2818
+ context
2819
+ } = input;
2820
+ const result = await this.#workflowInstance.runMachine(parentStepId, context, this.#runtimeContext);
2821
+ return Promise.resolve({
2822
+ steps: result.reduce((acc, r) => {
2823
+ return {
2824
+ ...acc,
2825
+ ...r?.results
2826
+ };
2827
+ }, {})
2828
+ });
2829
+ })
2830
+ };
2831
+ }
2832
+ #resolveVariables({
2833
+ stepConfig,
2834
+ context,
2835
+ stepId
2836
+ }) {
2837
+ this.logger.debug(`Resolving variables for step ${stepId}`, {
2838
+ stepId,
2839
+ runId: this.#runId
2840
+ });
2841
+ const resolvedData = {};
2842
+ for (const [key, variable] of Object.entries(stepConfig.data)) {
2843
+ const sourceData = variable.step === "trigger" ? context.triggerData : getStepResult(context.steps[variable.step.id]);
2844
+ this.logger.debug(`Got source data for ${key} variable from ${variable.step === "trigger" ? "trigger" : variable.step.id}`, {
2845
+ sourceData,
2846
+ path: variable.path,
2847
+ runId: this.#runId
2848
+ });
2849
+ if (!sourceData && variable.step !== "trigger") {
2850
+ resolvedData[key] = void 0;
2851
+ continue;
2852
+ }
2853
+ const value = variable.path === "" || variable.path === "." ? sourceData : get(sourceData, variable.path);
2854
+ this.logger.debug(`Resolved variable ${key}`, {
2855
+ value,
2856
+ runId: this.#runId
2857
+ });
2858
+ resolvedData[key] = value;
2859
+ }
2860
+ return resolvedData;
2861
+ }
2862
+ initializeMachine() {
2863
+ const machine = setup({
2864
+ types: {},
2865
+ delays: this.#makeDelayMap(),
2866
+ actions: this.#getDefaultActions(),
2867
+ actors: this.#getDefaultActors()
2868
+ }).createMachine({
2869
+ id: this.name,
2870
+ type: "parallel",
2871
+ context: ({
2872
+ input
2873
+ }) => ({
2874
+ ...input
2875
+ }),
2876
+ states: this.#buildStateHierarchy(this.#stepGraph)
2877
+ });
2878
+ this.#machine = machine;
2879
+ return machine;
2880
+ }
2881
+ #buildStateHierarchy(stepGraph) {
2882
+ const states = {};
2883
+ stepGraph.initial.forEach(stepNode => {
2884
+ const nextSteps = [...(stepGraph[stepNode.id] || [])];
2885
+ states[stepNode.id] = {
2886
+ ...this.#buildBaseState(stepNode, nextSteps)
2887
+ };
2888
+ });
2889
+ return states;
2890
+ }
2891
+ #buildBaseState(stepNode, nextSteps = []) {
2892
+ const nextStep = nextSteps.shift();
2893
+ return {
2894
+ initial: "pending",
2895
+ on: {
2896
+ RESET_TO_PENDING: {
2897
+ target: ".pending"
2898
+ // Note the dot to target child state
2899
+ }
2900
+ },
2901
+ states: {
2902
+ pending: {
2903
+ entry: () => {
2904
+ this.logger.debug(`Step ${stepNode.id} pending`, {
2905
+ stepId: stepNode.id,
2906
+ runId: this.#runId
2907
+ });
2908
+ },
2909
+ exit: () => {
2910
+ this.logger.debug(`Step ${stepNode.id} finished pending`, {
2911
+ stepId: stepNode.id,
2912
+ runId: this.#runId
2913
+ });
2914
+ },
2915
+ invoke: {
2916
+ src: "conditionCheck",
2917
+ input: ({
2918
+ context
2919
+ }) => {
2920
+ return {
2921
+ context,
2922
+ stepNode
2923
+ };
2924
+ },
2925
+ onDone: [{
2926
+ guard: ({
2927
+ event
2928
+ }) => {
2929
+ return event.output.type === "SUSPENDED";
2930
+ },
2931
+ target: "suspended",
2932
+ actions: [assign({
2933
+ steps: ({
2934
+ context,
2935
+ event
2936
+ }) => {
2937
+ if (event.output.type !== "SUSPENDED") return context.steps;
2938
+ if (event.output.softSuspend) {
2939
+ return {
2940
+ ...context.steps,
2941
+ [stepNode.id]: {
2942
+ status: "suspended",
2943
+ ...(context.steps?.[stepNode.id] || {}),
2944
+ output: event.output.softSuspend
2945
+ }
2946
+ };
2947
+ }
2948
+ return {
2949
+ ...context.steps,
2950
+ [stepNode.id]: {
2951
+ status: "suspended",
2952
+ ...(context.steps?.[stepNode.id] || {})
2953
+ }
2954
+ };
2955
+ },
2956
+ attempts: ({
2957
+ context,
2958
+ event
2959
+ }) => {
2960
+ if (event.output.type !== "SUSPENDED") return context.attempts;
2961
+ return {
2962
+ ...context.attempts,
2963
+ [stepNode.id]: stepNode.step.retryConfig?.attempts || 0
2964
+ };
2965
+ }
2966
+ })]
2967
+ }, {
2968
+ guard: ({
2969
+ event
2970
+ }) => {
2971
+ return event.output.type === "WAITING";
2972
+ },
2973
+ target: "waiting",
2974
+ actions: [{
2975
+ type: "decrementAttemptCount",
2976
+ params: {
2977
+ stepId: stepNode.id
2978
+ }
2979
+ }, assign({
2980
+ steps: ({
2981
+ context,
2982
+ event
2983
+ }) => {
2984
+ if (event.output.type !== "WAITING") return context.steps;
2985
+ return {
2986
+ ...context.steps,
2987
+ [stepNode.id]: {
2988
+ status: "waiting"
2989
+ }
2990
+ };
2991
+ }
2992
+ })]
2993
+ }, {
2994
+ guard: ({
2995
+ event
2996
+ }) => {
2997
+ return event.output.type === "CONDITIONS_MET";
2998
+ },
2999
+ target: "executing"
3000
+ }, {
3001
+ guard: ({
3002
+ event
3003
+ }) => {
3004
+ return event.output.type === "CONDITIONS_SKIP_TO_COMPLETED";
3005
+ },
3006
+ target: "completed"
3007
+ }, {
3008
+ guard: ({
3009
+ event
3010
+ }) => {
3011
+ return event.output.type === "CONDITIONS_SKIPPED";
3012
+ },
3013
+ actions: assign({
3014
+ steps: ({
3015
+ context
3016
+ }) => {
3017
+ const newStep = {
3018
+ ...context.steps,
3019
+ [stepNode.id]: {
3020
+ status: "skipped"
3021
+ }
3022
+ };
3023
+ this.logger.debug(`Step ${stepNode.id} skipped`, {
3024
+ stepId: stepNode.id,
3025
+ runId: this.#runId
3026
+ });
3027
+ return newStep;
3028
+ }
3029
+ }),
3030
+ target: "runningSubscribers"
3031
+ }, {
3032
+ guard: ({
3033
+ event
3034
+ }) => {
3035
+ return event.output.type === "CONDITIONS_LIMBO";
3036
+ },
3037
+ target: "limbo",
3038
+ actions: assign({
3039
+ steps: ({
3040
+ context
3041
+ }) => {
3042
+ const newStep = {
3043
+ ...context.steps,
3044
+ [stepNode.id]: {
3045
+ status: "skipped"
3046
+ }
3047
+ };
3048
+ this.logger.debug(`Step ${stepNode.id} skipped`, {
3049
+ stepId: stepNode.id,
3050
+ runId: this.#runId
3051
+ });
3052
+ return newStep;
3053
+ }
3054
+ })
3055
+ }, {
3056
+ guard: ({
3057
+ event
3058
+ }) => {
3059
+ return event.output.type === "CONDITION_FAILED";
3060
+ },
3061
+ target: "failed",
3062
+ actions: assign({
3063
+ steps: ({
3064
+ context,
3065
+ event
3066
+ }) => {
3067
+ if (event.output.type !== "CONDITION_FAILED") return context.steps;
3068
+ this.logger.debug(`Workflow condition check failed`, {
3069
+ error: event.output.error,
3070
+ stepId: stepNode.id
3071
+ });
3072
+ return {
3073
+ ...context.steps,
3074
+ [stepNode.id]: {
3075
+ status: "failed",
3076
+ error: event.output.error
3077
+ }
3078
+ };
3079
+ }
3080
+ })
3081
+ }]
3082
+ }
3083
+ },
3084
+ waiting: {
3085
+ entry: () => {
3086
+ this.logger.debug(`Step ${stepNode.id} waiting`, {
3087
+ stepId: stepNode.id,
3088
+ timestamp: (/* @__PURE__ */new Date()).toISOString(),
3089
+ runId: this.#runId
3090
+ });
3091
+ },
3092
+ exit: () => {
3093
+ this.logger.debug(`Step ${stepNode.id} finished waiting`, {
3094
+ stepId: stepNode.id,
3095
+ timestamp: (/* @__PURE__ */new Date()).toISOString(),
3096
+ runId: this.#runId
3097
+ });
3098
+ },
3099
+ after: {
3100
+ [stepNode.id]: {
3101
+ target: "pending"
3102
+ }
3103
+ }
3104
+ },
3105
+ limbo: {
3106
+ // no target, will stay in limbo indefinitely
3107
+ entry: () => {
3108
+ this.logger.debug(`Step ${stepNode.id} limbo`, {
3109
+ stepId: stepNode.id,
3110
+ timestamp: (/* @__PURE__ */new Date()).toISOString(),
3111
+ runId: this.#runId
3112
+ });
3113
+ },
3114
+ exit: () => {
3115
+ this.logger.debug(`Step ${stepNode.id} finished limbo`, {
3116
+ stepId: stepNode.id,
3117
+ timestamp: (/* @__PURE__ */new Date()).toISOString(),
3118
+ runId: this.#runId
3119
+ });
3120
+ }
3121
+ },
3122
+ suspended: {
3123
+ type: "final",
3124
+ entry: [() => {
3125
+ this.logger.debug(`Step ${stepNode.id} suspended`, {
3126
+ stepId: stepNode.id,
3127
+ runId: this.#runId
3128
+ });
3129
+ }, assign({
3130
+ steps: ({
3131
+ context,
3132
+ event
3133
+ }) => {
3134
+ return {
3135
+ ...context.steps,
3136
+ [stepNode.id]: {
3137
+ ...(context?.steps?.[stepNode.id] || {}),
3138
+ status: "suspended",
3139
+ suspendPayload: event.type === "SUSPENDED" ? event.suspendPayload : void 0,
3140
+ output: event.type === "SUSPENDED" ? event.softSuspend : void 0
3141
+ }
3142
+ };
3143
+ }
3144
+ })]
3145
+ },
3146
+ executing: {
3147
+ entry: () => {
3148
+ this.logger.debug(`Step ${stepNode.id} executing`, {
3149
+ stepId: stepNode.id,
3150
+ runId: this.#runId
3151
+ });
3152
+ },
3153
+ on: {
3154
+ SUSPENDED: {
3155
+ target: "suspended",
3156
+ actions: [assign({
3157
+ steps: ({
3158
+ context,
3159
+ event
3160
+ }) => {
3161
+ return {
3162
+ ...context.steps,
3163
+ [stepNode.id]: {
3164
+ status: "suspended",
3165
+ suspendPayload: event.type === "SUSPENDED" ? event.suspendPayload : void 0,
3166
+ output: event.type === "SUSPENDED" ? event.softSuspend : void 0
3167
+ }
3168
+ };
3169
+ }
3170
+ })]
3171
+ }
3172
+ },
3173
+ invoke: {
3174
+ src: "resolverFunction",
3175
+ input: ({
3176
+ context
3177
+ }) => ({
3178
+ context,
3179
+ stepNode
3180
+ }),
3181
+ onDone: [{
3182
+ guard: ({
3183
+ event
3184
+ }) => {
3185
+ return event.output.type === "STEP_FAILED";
3186
+ },
3187
+ target: "failed",
3188
+ actions: assign({
3189
+ steps: ({
3190
+ context,
3191
+ event
3192
+ }) => {
3193
+ if (event.output.type !== "STEP_FAILED") return context.steps;
3194
+ const newStep = {
3195
+ ...context.steps,
3196
+ [stepNode.id]: {
3197
+ status: "failed",
3198
+ error: event.output.error
3199
+ }
3200
+ };
3201
+ this.logger.debug(`Step ${stepNode.id} failed`, {
3202
+ error: event.output.error,
3203
+ stepId: stepNode.id
3204
+ });
3205
+ return newStep;
3206
+ }
3207
+ })
3208
+ }, {
3209
+ guard: ({
3210
+ event
3211
+ }) => {
3212
+ return event.output.type === "STEP_SUCCESS";
3213
+ },
3214
+ actions: [({
3215
+ event
3216
+ }) => {
3217
+ this.logger.debug(`Step ${stepNode.id} finished executing`, {
3218
+ stepId: stepNode.id,
3219
+ output: event.output,
3220
+ runId: this.#runId
3221
+ });
3222
+ }, {
3223
+ type: "updateStepResult",
3224
+ params: {
3225
+ stepId: stepNode.id
3226
+ }
3227
+ }, {
3228
+ type: "spawnSubscribers",
3229
+ params: {
3230
+ stepId: stepNode.id
3231
+ }
3232
+ }],
3233
+ target: "runningSubscribers"
3234
+ }, {
3235
+ guard: ({
3236
+ event
3237
+ }) => {
3238
+ return event.output.type === "STEP_WAITING";
3239
+ },
3240
+ target: "waiting",
3241
+ actions: [{
3242
+ type: "decrementAttemptCount",
3243
+ params: {
3244
+ stepId: stepNode.id
3245
+ }
3246
+ }, assign({
3247
+ steps: ({
3248
+ context,
3249
+ event
3250
+ }) => {
3251
+ if (event.output.type !== "STEP_WAITING") return context.steps;
3252
+ return {
3253
+ ...context.steps,
3254
+ [stepNode.id]: {
3255
+ status: "waiting"
3256
+ }
3257
+ };
3258
+ }
3259
+ })]
3260
+ }],
3261
+ onError: {
3262
+ target: "failed",
3263
+ actions: [{
3264
+ type: "setStepError",
3265
+ params: {
3266
+ stepId: stepNode.id
3267
+ }
3268
+ }]
3269
+ }
3270
+ }
3271
+ },
3272
+ runningSubscribers: {
3273
+ entry: () => {
3274
+ this.logger.debug(`Step ${stepNode.id} running subscribers`, {
3275
+ stepId: stepNode.id,
3276
+ runId: this.#runId
3277
+ });
3278
+ },
3279
+ exit: () => {
3280
+ this.logger.debug(`Step ${stepNode.id} finished running subscribers`, {
3281
+ stepId: stepNode.id,
3282
+ runId: this.#runId
3283
+ });
3284
+ },
3285
+ invoke: {
3286
+ src: "spawnSubscriberFunction",
3287
+ input: ({
3288
+ context
3289
+ }) => ({
3290
+ parentStepId: stepNode.id,
3291
+ context
3292
+ }),
3293
+ onDone: {
3294
+ target: nextStep ? nextStep.id : "completed",
3295
+ actions: [assign({
3296
+ steps: ({
3297
+ context,
3298
+ event
3299
+ }) => ({
3300
+ ...context.steps,
3301
+ ...event.output.steps
3302
+ })
3303
+ }), () => this.logger.debug(`Subscriber execution completed`, {
3304
+ stepId: stepNode.id
3305
+ })]
3306
+ },
3307
+ onError: {
3308
+ target: nextStep ? nextStep.id : "completed",
3309
+ actions: ({
3310
+ event
3311
+ }) => {
3312
+ this.logger.debug(`Subscriber execution failed`, {
3313
+ error: event.error,
3314
+ stepId: stepNode.id
3315
+ });
3316
+ }
3317
+ }
3318
+ }
3319
+ },
3320
+ completed: {
3321
+ type: "final",
3322
+ entry: [{
3323
+ type: "notifyStepCompletion",
3324
+ params: {
3325
+ stepId: stepNode.id
3326
+ }
3327
+ }, {
3328
+ type: "snapshotStep",
3329
+ params: {
3330
+ stepId: stepNode.id
3331
+ }
3332
+ }, {
3333
+ type: "persistSnapshot"
3334
+ }]
3335
+ },
3336
+ failed: {
3337
+ type: "final",
3338
+ entry: [{
3339
+ type: "notifyStepCompletion",
3340
+ params: {
3341
+ stepId: stepNode.id
3342
+ }
3343
+ }, {
3344
+ type: "snapshotStep",
3345
+ params: {
3346
+ stepId: stepNode.id
3347
+ }
3348
+ }, {
3349
+ type: "persistSnapshot"
3350
+ }]
3351
+ },
3352
+ // build chain of next steps recursively
3353
+ ...(nextStep ? {
3354
+ [nextStep.id]: {
3355
+ ...this.#buildBaseState(nextStep, nextSteps)
3356
+ }
3357
+ } : {})
3358
+ }
3359
+ };
3360
+ }
3361
+ #evaluateCondition(condition, context) {
3362
+ let andBranchResult = true;
3363
+ let baseResult = true;
3364
+ let orBranchResult = true;
3365
+ const simpleCondition = Object.entries(condition).find(([key]) => key.includes("."));
3366
+ if (simpleCondition) {
3367
+ const [key, queryValue] = simpleCondition;
3368
+ const [stepId, ...pathParts] = key.split(".");
3369
+ const path = pathParts.join(".");
3370
+ const sourceData = stepId === "trigger" ? context.triggerData : getStepResult(context.steps[stepId]);
3371
+ this.logger.debug(`Got condition data from step ${stepId}`, {
3372
+ stepId,
3373
+ sourceData,
3374
+ runId: this.#runId
3375
+ });
3376
+ if (!sourceData) {
3377
+ return false;
3378
+ }
3379
+ let value = get(sourceData, path);
3380
+ if (stepId !== "trigger" && path === "status" && !value) {
3381
+ value = "success";
3382
+ }
3383
+ if (typeof queryValue === "object" && queryValue !== null) {
3384
+ baseResult = sift(queryValue)(value);
3385
+ } else {
3386
+ baseResult = value === queryValue;
3387
+ }
3388
+ }
3389
+ if ("ref" in condition) {
3390
+ const {
3391
+ ref,
3392
+ query
3393
+ } = condition;
3394
+ const sourceData = ref.step === "trigger" ? context.triggerData : getStepResult(context.steps[ref.step.id]);
3395
+ this.logger.debug(`Got condition data from ${ref.step === "trigger" ? "trigger" : ref.step.id}`, {
3396
+ sourceData,
3397
+ runId: this.#runId
3398
+ });
3399
+ if (!sourceData) {
3400
+ return false;
3401
+ }
3402
+ let value = get(sourceData, ref.path);
3403
+ if (ref.step !== "trigger" && ref.path === "status" && !value) {
3404
+ value = "success";
3405
+ }
3406
+ baseResult = sift(query)(value);
3407
+ }
3408
+ if ("and" in condition) {
3409
+ andBranchResult = condition.and.every(cond => this.#evaluateCondition(cond, context));
3410
+ this.logger.debug(`Evaluated AND condition`, {
3411
+ andBranchResult,
3412
+ runId: this.#runId
3413
+ });
3414
+ }
3415
+ if ("or" in condition) {
3416
+ orBranchResult = condition.or.some(cond => this.#evaluateCondition(cond, context));
3417
+ this.logger.debug(`Evaluated OR condition`, {
3418
+ orBranchResult,
3419
+ runId: this.#runId
3420
+ });
3421
+ }
3422
+ if ("not" in condition) {
3423
+ baseResult = !this.#evaluateCondition(condition.not, context);
3424
+ this.logger.debug(`Evaluated NOT condition`, {
3425
+ baseResult,
3426
+ runId: this.#runId
3427
+ });
3428
+ }
3429
+ const finalResult = baseResult && andBranchResult && orBranchResult;
3430
+ this.logger.debug(`Evaluated condition`, {
3431
+ finalResult,
3432
+ runId: this.#runId
3433
+ });
3434
+ return finalResult;
3435
+ }
3436
+ getSnapshot() {
3437
+ const snapshot = this.#actor?.getSnapshot();
3438
+ return snapshot;
3439
+ }
3440
+ };
3441
+
3442
+ // src/workflows/legacy/workflow-instance.ts
3443
+ var WorkflowInstance = class {
3444
+ name;
3445
+ #mastra;
3446
+ #machines = {};
3447
+ logger;
3448
+ #steps = {};
3449
+ #stepGraph;
3450
+ #stepSubscriberGraph = {};
3451
+ #retryConfig;
3452
+ events;
3453
+ #runId;
3454
+ #state = null;
3455
+ #executionSpan;
3456
+ #onStepTransition = /* @__PURE__ */new Set();
3457
+ #onFinish;
3458
+ #resultMapping;
3459
+ // indexed by stepId
3460
+ #suspendedMachines = {};
3461
+ // {step1&&step2: {step1: true, step2: true}}
3462
+ #compoundDependencies = {};
3463
+ constructor({
3464
+ name,
3465
+ logger,
3466
+ steps,
3467
+ runId,
3468
+ retryConfig,
3469
+ mastra,
3470
+ stepGraph,
3471
+ stepSubscriberGraph,
3472
+ onFinish,
3473
+ onStepTransition,
3474
+ resultMapping,
3475
+ events
3476
+ }) {
3477
+ this.name = name;
3478
+ this.logger = logger;
3479
+ this.#steps = steps;
3480
+ this.#stepGraph = stepGraph;
3481
+ this.#stepSubscriberGraph = stepSubscriberGraph;
3482
+ this.#retryConfig = retryConfig;
3483
+ this.#mastra = mastra;
3484
+ this.#runId = runId ?? crypto.randomUUID();
3485
+ this.#onFinish = onFinish;
3486
+ this.#resultMapping = resultMapping;
3487
+ this.events = events;
3488
+ onStepTransition?.forEach(handler => this.#onStepTransition.add(handler));
3489
+ this.#initializeCompoundDependencies();
3490
+ }
3491
+ setState(state) {
3492
+ this.#state = state;
3493
+ }
3494
+ get runId() {
3495
+ return this.#runId;
3496
+ }
3497
+ get executionSpan() {
3498
+ return this.#executionSpan;
3499
+ }
3500
+ watch(onTransition) {
3501
+ this.#onStepTransition.add(onTransition);
3502
+ return () => {
3503
+ this.#onStepTransition.delete(onTransition);
3504
+ };
3505
+ }
3506
+ async start({
3507
+ triggerData,
3508
+ runtimeContext
3509
+ } = {}) {
3510
+ const results = await this.execute({
3511
+ triggerData,
3512
+ runtimeContext: runtimeContext ?? new RuntimeContext()
3513
+ });
3514
+ if (this.#onFinish) {
3515
+ const activePathsObj = Object.fromEntries(results.activePaths);
3516
+ const hasSuspendedActivePaths = Object.values(activePathsObj).some(value => value.status === "suspended");
3517
+ if (!hasSuspendedActivePaths) {
3518
+ this.#onFinish();
3519
+ }
3520
+ }
3521
+ return {
3522
+ ...results,
3523
+ runId: this.runId
3524
+ };
3525
+ }
3526
+ isCompoundDependencyMet(stepKey) {
3527
+ if (!this.#isCompoundKey(stepKey)) return true;
3528
+ const dependencies = this.#compoundDependencies[stepKey];
3529
+ return dependencies ? Object.values(dependencies).every(status => status === true) : true;
3530
+ }
3531
+ async execute({
3532
+ triggerData,
3533
+ snapshot,
3534
+ stepId,
3535
+ resumeData,
3536
+ runtimeContext
3537
+ } = {
3538
+ runtimeContext: new RuntimeContext()
3539
+ }) {
3540
+ this.#executionSpan = this.#mastra?.getTelemetry()?.tracer.startSpan(`workflow.${this.name}.execute`, {
3541
+ attributes: {
3542
+ componentName: this.name,
3543
+ runId: this.runId
3544
+ }
3545
+ });
3546
+ let machineInput = {
3547
+ // Maintain the original step results and their output
3548
+ steps: {},
3549
+ triggerData: triggerData || {},
3550
+ attempts: Object.keys(this.#steps).reduce((acc, stepKey) => {
3551
+ acc[stepKey] = this.#steps[stepKey]?.step?.retryConfig?.attempts || this.#retryConfig?.attempts || 0;
3552
+ return acc;
3553
+ }, {})
3554
+ };
3555
+ let stepGraph = this.#stepGraph;
3556
+ let startStepId = "trigger";
3557
+ if (snapshot) {
3558
+ const runState = snapshot;
3559
+ if (stepId && runState?.suspendedSteps?.[stepId]) {
3560
+ startStepId = runState.suspendedSteps[stepId];
3561
+ stepGraph = this.#stepSubscriberGraph[startStepId] ?? this.#stepGraph;
3562
+ machineInput = runState.context;
3563
+ }
3564
+ }
3565
+ const defaultMachine = new Machine({
3566
+ logger: this.logger,
3567
+ mastra: this.#mastra,
3568
+ runtimeContext,
3569
+ workflowInstance: this,
3570
+ name: this.name,
3571
+ runId: this.runId,
3572
+ steps: this.#steps,
3573
+ stepGraph,
3574
+ executionSpan: this.#executionSpan,
3575
+ startStepId,
3576
+ retryConfig: this.#retryConfig
3577
+ });
3578
+ this.#machines[startStepId] = defaultMachine;
3579
+ const stateUpdateHandler = (startStepId2, state, ctx) => {
3580
+ let fullState = {
3581
+ value: {},
3582
+ context: {}
3583
+ };
3584
+ if (ctx) {
3585
+ fullState["value"] = state;
3586
+ fullState["context"] = ctx;
3587
+ } else {
3588
+ fullState = state;
3589
+ }
3590
+ if (startStepId2 === "trigger") {
3591
+ this.#state = fullState.value;
3592
+ } else {
3593
+ this.#state = mergeChildValue(startStepId2, this.#state, fullState.value);
3594
+ }
3595
+ const now = Date.now();
3596
+ if (this.#onStepTransition) {
3597
+ this.#onStepTransition.forEach(onTransition => {
3598
+ void onTransition({
3599
+ runId: this.#runId,
3600
+ results: fullState.context.steps,
3601
+ activePaths: getResultActivePaths(fullState),
3602
+ timestamp: now
3603
+ });
3604
+ });
3605
+ }
3606
+ };
3607
+ defaultMachine.on("state-update", stateUpdateHandler);
3608
+ const {
3609
+ results,
3610
+ activePaths
3611
+ } = await defaultMachine.execute({
3612
+ snapshot,
3613
+ stepId,
3614
+ input: machineInput,
3615
+ resumeData
3616
+ });
3617
+ await this.persistWorkflowSnapshot();
3618
+ const result = {
3619
+ results,
3620
+ activePaths,
3621
+ timestamp: Date.now()
3622
+ };
3623
+ if (this.#resultMapping) {
3624
+ result.result = resolveVariables({
3625
+ runId: this.#runId,
3626
+ logger: this.logger,
3627
+ variables: this.#resultMapping,
3628
+ context: {
3629
+ steps: results,
3630
+ triggerData}
3631
+ });
3632
+ }
3633
+ return result;
3634
+ }
3635
+ hasSubscribers(stepId) {
3636
+ return Object.keys(this.#stepSubscriberGraph).some(key => key.split("&&").includes(stepId));
3637
+ }
3638
+ async runMachine(parentStepId, input, runtimeContext = new RuntimeContext()) {
3639
+ const stepStatus = input.steps[parentStepId]?.status;
3640
+ const subscriberKeys = Object.keys(this.#stepSubscriberGraph).filter(key => key.split("&&").includes(parentStepId));
3641
+ subscriberKeys.forEach(key => {
3642
+ if (["success", "failure", "skipped"].includes(stepStatus) && this.#isCompoundKey(key)) {
3643
+ this.#compoundDependencies[key][parentStepId] = true;
3644
+ }
3645
+ });
3646
+ const stateUpdateHandler = (startStepId, state, ctx) => {
3647
+ let fullState = {
3648
+ value: {},
3649
+ context: {}
3650
+ };
3651
+ if (ctx) {
3652
+ fullState["value"] = state;
3653
+ fullState["context"] = ctx;
3654
+ } else {
3655
+ fullState = state;
3656
+ }
3657
+ if (startStepId === "trigger") {
3658
+ this.#state = fullState.value;
3659
+ } else {
3660
+ this.#state = mergeChildValue(startStepId, this.#state, fullState.value);
3661
+ }
3662
+ const now = Date.now();
3663
+ if (this.#onStepTransition) {
3664
+ this.#onStepTransition.forEach(onTransition => {
3665
+ void onTransition({
3666
+ runId: this.#runId,
3667
+ results: fullState.context.steps,
3668
+ activePaths: getResultActivePaths(fullState),
3669
+ timestamp: now
3670
+ });
3671
+ });
3672
+ }
3673
+ };
3674
+ const results = await Promise.all(subscriberKeys.map(async key => {
3675
+ if (!this.#stepSubscriberGraph[key] || !this.isCompoundDependencyMet(key)) {
3676
+ return;
3677
+ }
3678
+ this.#resetCompoundDependency(key);
3679
+ const machine = new Machine({
3680
+ logger: this.logger,
3681
+ mastra: this.#mastra,
3682
+ runtimeContext,
3683
+ workflowInstance: this,
3684
+ name: parentStepId === "trigger" ? this.name : `${this.name}-${parentStepId}`,
3685
+ runId: this.runId,
3686
+ steps: this.#steps,
3687
+ stepGraph: this.#stepSubscriberGraph[key],
3688
+ executionSpan: this.#executionSpan,
3689
+ startStepId: parentStepId
3690
+ });
3691
+ machine.on("state-update", stateUpdateHandler);
3692
+ this.#machines[parentStepId] = machine;
3693
+ return machine.execute({
3694
+ input
3695
+ });
3696
+ }));
3697
+ return results;
3698
+ }
3699
+ async suspend(stepId, machine) {
3700
+ this.#suspendedMachines[stepId] = machine;
3701
+ }
3702
+ /**
3703
+ * Persists the workflow state to the database
3704
+ */
3705
+ async persistWorkflowSnapshot() {
3706
+ const storage = this.#mastra?.getStorage();
3707
+ if (!storage) {
3708
+ this.logger.debug("Snapshot cannot be persisted. Mastra engine is not initialized", {
3709
+ runId: this.#runId
3710
+ });
3711
+ return;
3712
+ }
3713
+ const existingSnapshot = await storage.loadWorkflowSnapshot({
3714
+ workflowName: this.name,
3715
+ runId: this.#runId
3716
+ });
3717
+ const machineSnapshots = {};
3718
+ for (const [stepId, machine] of Object.entries(this.#machines)) {
3719
+ const machineSnapshot = machine?.getSnapshot();
3720
+ if (machineSnapshot) {
3721
+ machineSnapshots[stepId] = {
3722
+ ...machineSnapshot
3723
+ };
3724
+ }
3725
+ }
3726
+ let snapshot = machineSnapshots["trigger"];
3727
+ delete machineSnapshots["trigger"];
3728
+ const suspendedSteps = Object.entries(this.#suspendedMachines).reduce((acc, [stepId, machine]) => {
3729
+ acc[stepId] = machine.startStepId;
3730
+ return acc;
3731
+ }, {});
3732
+ if (!snapshot && existingSnapshot) {
3733
+ existingSnapshot.childStates = {
3734
+ ...existingSnapshot.childStates,
3735
+ ...machineSnapshots
3736
+ };
3737
+ existingSnapshot.suspendedSteps = {
3738
+ ...existingSnapshot.suspendedSteps,
3739
+ ...suspendedSteps
3740
+ };
3741
+ await storage.persistWorkflowSnapshot({
3742
+ workflowName: this.name,
3743
+ runId: this.#runId,
3744
+ snapshot: existingSnapshot
3745
+ });
3746
+ return;
3747
+ } else if (snapshot && !existingSnapshot) {
3748
+ snapshot.suspendedSteps = suspendedSteps;
3749
+ snapshot.childStates = {
3750
+ ...machineSnapshots
3751
+ };
3752
+ await storage.persistWorkflowSnapshot({
3753
+ workflowName: this.name,
3754
+ runId: this.#runId,
3755
+ snapshot
3756
+ });
3757
+ return;
3758
+ } else if (!snapshot) {
3759
+ this.logger.debug("Snapshot cannot be persisted. No snapshot received.", {
3760
+ runId: this.#runId
3761
+ });
3762
+ return;
3763
+ }
3764
+ snapshot.suspendedSteps = {
3765
+ ...existingSnapshot.suspendedSteps,
3766
+ ...suspendedSteps
3767
+ };
3768
+ if (!existingSnapshot || snapshot === existingSnapshot) {
3769
+ await storage.persistWorkflowSnapshot({
3770
+ workflowName: this.name,
3771
+ runId: this.#runId,
3772
+ snapshot
3773
+ });
3774
+ return;
3775
+ }
3776
+ if (existingSnapshot?.childStates) {
3777
+ snapshot.childStates = {
3778
+ ...existingSnapshot.childStates,
3779
+ ...machineSnapshots
3780
+ };
3781
+ } else {
3782
+ snapshot.childStates = machineSnapshots;
3783
+ }
3784
+ await storage.persistWorkflowSnapshot({
3785
+ workflowName: this.name,
3786
+ runId: this.#runId,
3787
+ snapshot
3788
+ });
3789
+ }
3790
+ async getState() {
3791
+ const storedSnapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
3792
+ workflowName: this.name,
3793
+ runId: this.runId
3794
+ });
3795
+ const prevSnapshot = storedSnapshot ? {
3796
+ trigger: storedSnapshot,
3797
+ ...Object.entries(storedSnapshot?.childStates ?? {}).reduce((acc, [stepId, snapshot2]) => ({
3798
+ ...acc,
3799
+ [stepId]: snapshot2
3800
+ }), {})
3801
+ } : {};
3802
+ const currentSnapshot = Object.entries(this.#machines).reduce((acc, [stepId, machine]) => {
3803
+ const snapshot2 = machine.getSnapshot();
3804
+ if (!snapshot2) {
3805
+ return acc;
3806
+ }
3807
+ return {
3808
+ ...acc,
3809
+ [stepId]: snapshot2
3810
+ };
3811
+ }, {});
3812
+ Object.assign(prevSnapshot, currentSnapshot);
3813
+ const trigger = prevSnapshot.trigger;
3814
+ delete prevSnapshot.trigger;
3815
+ const snapshot = {
3816
+ ...trigger};
3817
+ const m = getActivePathsAndStatus(prevSnapshot.value);
3818
+ return {
3819
+ runId: this.runId,
3820
+ value: snapshot.value,
3821
+ context: snapshot.context,
3822
+ activePaths: m,
3823
+ timestamp: Date.now()
3824
+ };
3825
+ }
3826
+ async resumeWithEvent(eventName, data, runtimeContext = new RuntimeContext()) {
3827
+ const event = this.events?.[eventName];
3828
+ if (!event) {
3829
+ throw new Error(`Event ${eventName} not found`);
3830
+ }
3831
+ const results = await this.resume({
3832
+ stepId: `__${eventName}_event`,
3833
+ context: {
3834
+ resumedEvent: data
3835
+ },
3836
+ runtimeContext
3837
+ });
3838
+ return results;
3839
+ }
3840
+ async resume({
3841
+ stepId,
3842
+ context: resumeContext,
3843
+ runtimeContext = new RuntimeContext()
3844
+ }) {
3845
+ await new Promise(resolve => setTimeout(resolve, 0));
3846
+ return this._resume({
3847
+ stepId,
3848
+ context: resumeContext,
3849
+ runtimeContext
3850
+ });
3851
+ }
3852
+ async #loadWorkflowSnapshot(runId) {
3853
+ const storage = this.#mastra?.getStorage();
3854
+ if (!storage) {
3855
+ this.logger.debug("Snapshot cannot be loaded. Mastra engine is not initialized", {
3856
+ runId
3857
+ });
3858
+ return;
3859
+ }
3860
+ await this.persistWorkflowSnapshot();
3861
+ return storage.loadWorkflowSnapshot({
3862
+ runId,
3863
+ workflowName: this.name
3864
+ });
3865
+ }
3866
+ async _resume({
3867
+ stepId,
3868
+ context: resumeContext,
3869
+ runtimeContext
3870
+ }) {
3871
+ const snapshot = await this.#loadWorkflowSnapshot(this.runId);
3872
+ if (!snapshot) {
3873
+ throw new Error(`No snapshot found for workflow run ${this.runId}`);
3874
+ }
3875
+ const stepParts = stepId.split(".");
3876
+ const stepPath = stepParts.join(".");
3877
+ if (stepParts.length > 1) {
3878
+ stepId = stepParts[0] ?? stepId;
3879
+ }
3880
+ let parsedSnapshot;
3881
+ try {
3882
+ parsedSnapshot = typeof snapshot === "string" ? JSON.parse(snapshot) : snapshot;
3883
+ } catch (error) {
3884
+ this.logger.debug("Failed to parse workflow snapshot for resume", {
3885
+ error,
3886
+ runId: this.runId
3887
+ });
3888
+ throw new Error("Failed to parse workflow snapshot");
3889
+ }
3890
+ const startStepId = parsedSnapshot.suspendedSteps?.[stepId];
3891
+ if (!startStepId) {
3892
+ return;
3893
+ }
3894
+ parsedSnapshot = startStepId === "trigger" ? parsedSnapshot : {
3895
+ ...parsedSnapshot?.childStates?.[startStepId],
3896
+ ...{
3897
+ suspendedSteps: parsedSnapshot.suspendedSteps
3898
+ }
3899
+ };
3900
+ if (!parsedSnapshot) {
3901
+ throw new Error(`No snapshot found for step: ${stepId} starting at ${startStepId}`);
3902
+ }
3903
+ if (resumeContext) {
3904
+ parsedSnapshot.context.steps[stepId] = {
3905
+ status: "success",
3906
+ output: {
3907
+ ...(parsedSnapshot?.context?.steps?.[stepId]?.output || {}),
3908
+ ...resumeContext
3909
+ }
3910
+ };
3911
+ }
3912
+ if (parsedSnapshot.children) {
3913
+ Object.entries(parsedSnapshot.children).forEach(([, child]) => {
3914
+ if (child.snapshot?.input?.stepNode) {
3915
+ const stepDef = this.#makeStepDef(child.snapshot.input.stepNode.step.id);
3916
+ child.snapshot.input.stepNode.config = {
3917
+ ...child.snapshot.input.stepNode.config,
3918
+ ...stepDef
3919
+ };
3920
+ child.snapshot.input.context = parsedSnapshot.context;
3921
+ }
3922
+ });
3923
+ }
3924
+ parsedSnapshot.value = updateStepInHierarchy(parsedSnapshot.value, stepId);
3925
+ if (parsedSnapshot.context?.attempts) {
3926
+ parsedSnapshot.context.attempts[stepId] = this.#steps[stepId]?.step?.retryConfig?.attempts || this.#retryConfig?.attempts || 0;
3927
+ }
3928
+ this.logger.debug("Resuming workflow with updated snapshot", {
3929
+ updatedSnapshot: parsedSnapshot,
3930
+ runId: this.runId,
3931
+ stepId
3932
+ });
3933
+ return this.execute({
3934
+ snapshot: parsedSnapshot,
3935
+ stepId: stepPath,
3936
+ resumeData: resumeContext,
3937
+ runtimeContext
3938
+ });
3939
+ }
3940
+ #initializeCompoundDependencies() {
3941
+ Object.keys(this.#stepSubscriberGraph).forEach(stepKey => {
3942
+ if (this.#isCompoundKey(stepKey)) {
3943
+ const requiredSteps = stepKey.split("&&");
3944
+ this.#compoundDependencies[stepKey] = requiredSteps.reduce((acc, step) => {
3945
+ acc[step] = false;
3946
+ return acc;
3947
+ }, {});
3948
+ }
3949
+ });
3950
+ }
3951
+ #resetCompoundDependency(key) {
3952
+ if (this.#isCompoundKey(key)) {
3953
+ const requiredSteps = key.split("&&");
3954
+ this.#compoundDependencies[key] = requiredSteps.reduce((acc, step) => {
3955
+ acc[step] = false;
3956
+ return acc;
3957
+ }, {});
3958
+ }
3959
+ }
3960
+ #makeStepDef(stepId) {
3961
+ const executeStep = (handler2, spanName, attributes) => {
3962
+ return async data => {
3963
+ return await context.with(trace.setSpan(context.active(), this.#executionSpan), async () => {
3964
+ if (this.#mastra?.getTelemetry()) {
3965
+ return this.#mastra.getTelemetry()?.traceMethod(handler2, {
3966
+ spanName,
3967
+ attributes
3968
+ })(data);
3969
+ } else {
3970
+ return handler2(data);
3971
+ }
3972
+ });
3973
+ };
3974
+ };
3975
+ const handler = async ({
3976
+ context,
3977
+ ...rest
3978
+ }) => {
3979
+ const targetStep = this.#steps[stepId];
3980
+ if (!targetStep) throw new Error(`Step not found`);
3981
+ const {
3982
+ payload = {},
3983
+ execute = async () => {}
3984
+ } = targetStep.step;
3985
+ const mergedData = {
3986
+ ...payload,
3987
+ ...context
3988
+ };
3989
+ const finalAction = this.#mastra?.getTelemetry() ? executeStep(execute, `workflow.${this.name}.action.${stepId}`, {
3990
+ componentName: this.name,
3991
+ runId: rest.runId
3992
+ }) : execute;
3993
+ return finalAction ? await finalAction({
3994
+ context: mergedData,
3995
+ ...rest
3996
+ }) : {};
3997
+ };
3998
+ const finalHandler = ({
3999
+ context,
4000
+ ...rest
4001
+ }) => {
4002
+ if (this.#executionSpan) {
4003
+ return executeStep(handler, `workflow.${this.name}.step.${stepId}`, {
4004
+ componentName: this.name,
4005
+ runId: rest?.runId
4006
+ })({
4007
+ context,
4008
+ ...rest
4009
+ });
4010
+ }
4011
+ return handler({
4012
+ context,
4013
+ ...rest
4014
+ });
4015
+ };
4016
+ return {
4017
+ handler: finalHandler,
4018
+ data: {}
4019
+ };
4020
+ }
4021
+ #isCompoundKey(key) {
4022
+ return key.includes("&&");
4023
+ }
4024
+ };
4025
+
4026
+ // src/workflows/legacy/workflow.ts
4027
+ var LegacyWorkflow = class extends MastraBase {
4028
+ name;
4029
+ triggerSchema;
4030
+ resultSchema;
4031
+ resultMapping;
4032
+ events;
4033
+ #retryConfig;
4034
+ #mastra;
4035
+ #runs = /* @__PURE__ */new Map();
4036
+ isNested = false;
4037
+ #onStepTransition = /* @__PURE__ */new Set();
4038
+ // registers stepIds on `after` calls
4039
+ #afterStepStack = [];
4040
+ #lastStepStack = [];
4041
+ #lastBuilderType = null;
4042
+ #ifStack = [];
4043
+ #stepGraph = {
4044
+ initial: []
4045
+ };
4046
+ #serializedStepGraph = {
4047
+ initial: []
4048
+ };
4049
+ #stepSubscriberGraph = {};
4050
+ #serializedStepSubscriberGraph = {};
4051
+ #steps = {};
4052
+ #ifCount = 0;
4053
+ /**
4054
+ * Creates a new LegacyWorkflow instance
4055
+ * @param name - Identifier for the workflow (not necessarily unique)
4056
+ * @param logger - Optional logger instance
4057
+ */
4058
+ constructor({
4059
+ name,
4060
+ triggerSchema,
4061
+ result,
4062
+ retryConfig,
4063
+ mastra,
4064
+ events
4065
+ }) {
4066
+ super({
4067
+ component: "WORKFLOW",
4068
+ name
4069
+ });
4070
+ this.name = name;
4071
+ this.#retryConfig = retryConfig;
4072
+ this.triggerSchema = triggerSchema;
4073
+ this.resultSchema = result?.schema;
4074
+ this.resultMapping = result?.mapping;
4075
+ this.events = events;
4076
+ if (mastra) {
4077
+ this.__registerPrimitives({
4078
+ telemetry: mastra.getTelemetry(),
4079
+ logger: mastra.getLogger()
4080
+ });
4081
+ this.#mastra = mastra;
4082
+ }
4083
+ }
4084
+ step(next, config) {
4085
+ const that = this;
4086
+ if (Array.isArray(next)) {
4087
+ const nextSteps = next.map(step2 => {
4088
+ if (isWorkflow(step2)) {
4089
+ const asStep = step2.toStep();
4090
+ return asStep;
4091
+ } else if (isAgent(step2)) {
4092
+ return agentToStep(step2);
4093
+ } else {
4094
+ return step2;
4095
+ }
4096
+ });
4097
+ nextSteps.forEach(step2 => this.step(step2, config));
4098
+ this.after(nextSteps);
4099
+ this.step(new LegacyStep({
4100
+ id: `__after_${next.map(step2 => config?.id ?? step2?.id ?? step2?.name).join("_")}`,
4101
+ execute: async () => {
4102
+ return {
4103
+ success: true
4104
+ };
4105
+ }
4106
+ }));
4107
+ return this;
4108
+ }
4109
+ const {
4110
+ variables = {}
4111
+ } = config || {};
4112
+ const requiredData = {};
4113
+ for (const [key, variable] of Object.entries(variables)) {
4114
+ if (variable && isVariableReference(variable)) {
4115
+ requiredData[key] = variable;
4116
+ }
4117
+ }
4118
+ const step = isWorkflow(next) ?
4119
+ // @ts-ignore
4120
+ workflowToStep(next, {
4121
+ mastra: this.#mastra
4122
+ }) : isAgent(next) ?
4123
+ // @ts-ignore
4124
+ agentToStep(next, {
4125
+ mastra: this.#mastra
4126
+ }) : next;
4127
+ const stepKey = this.#makeStepKey(step, config);
4128
+ const when = config?.["#internal"]?.when || config?.when;
4129
+ const graphEntry = {
4130
+ step,
4131
+ config: {
4132
+ ...this.#makeStepDef(stepKey),
4133
+ ...config,
4134
+ loopLabel: config?.["#internal"]?.loopLabel,
4135
+ loopType: config?.["#internal"]?.loopType,
4136
+ serializedWhen: typeof when === "function" ? when.toString() : when,
4137
+ data: requiredData
4138
+ },
4139
+ get id() {
4140
+ return that.#makeStepKey(this.step, this.config);
4141
+ }
4142
+ };
4143
+ this.#steps[stepKey] = graphEntry;
4144
+ const parentStepKey = this.#getParentStepKey({
4145
+ loop_check: true
4146
+ });
4147
+ const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
4148
+ const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
4149
+ if (parentStepKey && stepGraph) {
4150
+ if (!stepGraph.initial.some(step2 => step2.config.id === stepKey || step2.step.id === stepKey)) {
4151
+ stepGraph.initial.push(graphEntry);
4152
+ if (serializedStepGraph) serializedStepGraph.initial.push(graphEntry);
4153
+ }
4154
+ stepGraph[stepKey] = [];
4155
+ if (serializedStepGraph) serializedStepGraph[stepKey] = [];
4156
+ } else {
4157
+ if (!this.#stepGraph[stepKey]) this.#stepGraph[stepKey] = [];
4158
+ this.#stepGraph.initial.push(graphEntry);
4159
+ this.#serializedStepGraph.initial.push(graphEntry);
4160
+ }
4161
+ this.#lastStepStack.push(stepKey);
4162
+ this.#lastBuilderType = "step";
4163
+ return this;
4164
+ }
4165
+ #__internalStep(next, config, internalUse) {
4166
+ const that = this;
4167
+ if (Array.isArray(next)) {
4168
+ const nextSteps = next.map(step2 => {
4169
+ if (isWorkflow(step2)) {
4170
+ const asStep = step2.toStep();
4171
+ return asStep;
4172
+ } else {
4173
+ return step2;
4174
+ }
4175
+ });
4176
+ nextSteps.forEach(step2 => this.#__internalStep(step2, config, internalUse));
4177
+ this.after(nextSteps);
4178
+ this.#__internalStep(new LegacyStep({
4179
+ id: `__after_${next.map(step2 => step2?.id ?? step2?.name).join("_")}`,
4180
+ execute: async () => {
4181
+ return {
4182
+ success: true
4183
+ };
4184
+ }
4185
+ }), void 0, internalUse);
4186
+ return this;
4187
+ }
4188
+ const {
4189
+ variables = {}
4190
+ } = config || {};
4191
+ const requiredData = {};
4192
+ for (const [key, variable] of Object.entries(variables)) {
4193
+ if (variable && isVariableReference(variable)) {
4194
+ requiredData[key] = variable;
4195
+ }
4196
+ }
4197
+ const step = isWorkflow(next) ?
4198
+ // @ts-ignore
4199
+ workflowToStep(next, {
4200
+ mastra: this.#mastra
4201
+ }) : next;
4202
+ const stepKey = this.#makeStepKey(step, config);
4203
+ const when = config?.["#internal"]?.when || config?.when;
4204
+ const graphEntry = {
4205
+ step,
4206
+ config: {
4207
+ ...this.#makeStepDef(stepKey),
4208
+ ...config,
4209
+ loopLabel: config?.["#internal"]?.loopLabel,
4210
+ loopType: config?.["#internal"]?.loopType,
4211
+ serializedWhen: typeof when === "function" ? when.toString() : when,
4212
+ data: requiredData
4213
+ },
4214
+ get id() {
4215
+ return that.#makeStepKey(this.step, this.config);
4216
+ }
4217
+ };
4218
+ this.#steps[stepKey] = graphEntry;
4219
+ const parentStepKey = this.#getParentStepKey();
4220
+ const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
4221
+ const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
4222
+ if (parentStepKey && stepGraph) {
4223
+ if (!stepGraph.initial.some(step2 => step2.step.id === stepKey)) {
4224
+ stepGraph.initial.push(graphEntry);
4225
+ if (serializedStepGraph) serializedStepGraph.initial.push(graphEntry);
4226
+ }
4227
+ stepGraph[stepKey] = [];
4228
+ if (serializedStepGraph) serializedStepGraph[stepKey] = [];
4229
+ } else {
4230
+ if (!this.#stepGraph[stepKey]) this.#stepGraph[stepKey] = [];
4231
+ this.#stepGraph.initial.push(graphEntry);
4232
+ this.#serializedStepGraph.initial.push(graphEntry);
4233
+ }
4234
+ this.#lastStepStack.push(stepKey);
4235
+ this.#lastBuilderType = "step";
4236
+ return this;
4237
+ }
4238
+ #makeStepKey(step, config) {
4239
+ if (typeof step === "string") return step;
4240
+ return `${config?.id ?? step.id ?? step.name}`;
4241
+ }
4242
+ then(next, config) {
4243
+ const that = this;
4244
+ if (Array.isArray(next)) {
4245
+ const lastStep = this.#steps[this.#lastStepStack[this.#lastStepStack.length - 1] ?? ""];
4246
+ if (!lastStep) {
4247
+ throw new Error("Condition requires a step to be executed after");
4248
+ }
4249
+ this.after(lastStep.step);
4250
+ const nextSteps = next.map(step2 => {
4251
+ if (isWorkflow(step2)) {
4252
+ return workflowToStep(step2, {
4253
+ mastra: this.#mastra
4254
+ });
4255
+ }
4256
+ if (isAgent(step2)) {
4257
+ return agentToStep(step2);
4258
+ }
4259
+ return step2;
4260
+ });
4261
+ nextSteps.forEach(step2 => this.step(step2, config));
4262
+ this.step(new LegacyStep({
4263
+ // @ts-ignore
4264
+ id: `__after_${next.map(step2 => step2?.id ?? step2?.name).join("_")}`,
4265
+ execute: async () => {
4266
+ return {
4267
+ success: true
4268
+ };
4269
+ }
4270
+ }));
4271
+ return this;
4272
+ }
4273
+ const {
4274
+ variables = {}
4275
+ } = config || {};
4276
+ const requiredData = {};
4277
+ for (const [key, variable] of Object.entries(variables)) {
4278
+ if (variable && isVariableReference(variable)) {
4279
+ requiredData[key] = variable;
4280
+ }
4281
+ }
4282
+ const lastStepKey = this.#lastStepStack[this.#lastStepStack.length - 1];
4283
+ const step = isWorkflow(next) ? workflowToStep(next, {
4284
+ mastra: this.#mastra
4285
+ }) : isAgent(next) ? agentToStep(next) : next;
4286
+ const stepKey = this.#makeStepKey(step, config);
4287
+ const when = config?.["#internal"]?.when || config?.when;
4288
+ const graphEntry = {
4289
+ step,
4290
+ config: {
4291
+ ...this.#makeStepDef(stepKey),
4292
+ ...config,
4293
+ loopLabel: config?.["#internal"]?.loopLabel,
4294
+ loopType: config?.["#internal"]?.loopType,
4295
+ serializedWhen: typeof when === "function" ? when.toString() : when,
4296
+ data: requiredData
4297
+ },
4298
+ get id() {
4299
+ return that.#makeStepKey(this.step, this.config);
4300
+ }
4301
+ };
4302
+ this.#steps[stepKey] = graphEntry;
4303
+ if (!lastStepKey) return this;
4304
+ const parentStepKey = this.#getParentStepKey();
4305
+ const stepGraph = this.#stepSubscriberGraph[parentStepKey || ""];
4306
+ const serializedStepGraph = this.#serializedStepSubscriberGraph[parentStepKey || ""];
4307
+ if (parentStepKey && this.#lastBuilderType === "after") {
4308
+ return this.step(step, config);
4309
+ }
4310
+ if (parentStepKey && stepGraph && stepGraph[lastStepKey]) {
4311
+ stepGraph[lastStepKey].push(graphEntry);
4312
+ if (serializedStepGraph && serializedStepGraph[lastStepKey]) serializedStepGraph[lastStepKey].push(graphEntry);
4313
+ } else {
4314
+ if (!this.#stepGraph[lastStepKey]) this.#stepGraph[lastStepKey] = [];
4315
+ if (!this.#serializedStepGraph[lastStepKey]) this.#serializedStepGraph[lastStepKey] = [];
4316
+ this.#stepGraph[lastStepKey].push(graphEntry);
4317
+ this.#serializedStepGraph[lastStepKey].push(graphEntry);
4318
+ }
4319
+ this.#lastBuilderType = "then";
4320
+ return this;
4321
+ }
4322
+ loop(applyOperator, condition, fallbackStep, loopType, variables) {
4323
+ const lastStepKey = this.#lastStepStack[this.#lastStepStack.length - 1];
4324
+ if (!lastStepKey) return this;
4325
+ const fallbackStepKey = this.#makeStepKey(fallbackStep);
4326
+ const fallbackStepNode = {
4327
+ step: fallbackStep,
4328
+ config: {
4329
+ ...this.#makeStepDef(fallbackStepKey)
4330
+ },
4331
+ get id() {
4332
+ return fallbackStepKey;
4333
+ }
4334
+ };
4335
+ this.#steps[fallbackStepKey] = fallbackStepNode;
4336
+ const checkStepKey = `__${fallbackStepKey}_${loopType}_loop_check`;
4337
+ const checkStep = {
4338
+ id: checkStepKey,
4339
+ execute: async ({
4340
+ context
4341
+ }) => {
4342
+ if (typeof condition === "function") {
4343
+ const result = await condition({
4344
+ context
4345
+ });
4346
+ switch (loopType) {
4347
+ case "while":
4348
+ return {
4349
+ status: result ? "continue" : "complete"
4350
+ };
4351
+ case "until":
4352
+ return {
4353
+ status: result ? "complete" : "continue"
4354
+ };
4355
+ default:
4356
+ throw new Error(`Invalid loop type: ${loopType}`);
4357
+ }
4358
+ }
4359
+ if (condition && "ref" in condition) {
4360
+ const {
4361
+ ref,
4362
+ query
4363
+ } = condition;
4364
+ const stepId = typeof ref.step === "string" ? ref.step : "id" in ref.step ? ref.step.id : null;
4365
+ if (!stepId) {
4366
+ return {
4367
+ status: "continue"
4368
+ };
4369
+ }
4370
+ const stepOutput = context.steps?.[stepId]?.output;
4371
+ if (!stepOutput) {
4372
+ return {
4373
+ status: "continue"
4374
+ };
4375
+ }
4376
+ const value = ref.path.split(".").reduce((obj, key) => obj?.[key], stepOutput);
4377
+ const operator = Object.keys(query)[0];
4378
+ const target = query[operator];
4379
+ return applyOperator(operator, value, target);
4380
+ }
4381
+ return {
4382
+ status: "continue"
4383
+ };
4384
+ },
4385
+ outputSchema: z.object({
4386
+ status: z.enum(["continue", "complete"])
4387
+ })
4388
+ };
4389
+ const checkStepNode = {
4390
+ step: checkStep,
4391
+ config: {
4392
+ ...this.#makeStepDef(checkStepKey)
4393
+ },
4394
+ get id() {
4395
+ return checkStepKey;
4396
+ }
4397
+ };
4398
+ this.#steps[checkStepKey] = checkStepNode;
4399
+ const loopFinishedStepKey = `__${fallbackStepKey}_${loopType}_loop_finished`;
4400
+ const loopFinishedStep = {
4401
+ id: loopFinishedStepKey,
4402
+ execute: async () => {
4403
+ return {
4404
+ success: true
4405
+ };
4406
+ }
4407
+ };
4408
+ const loopFinishedStepNode = {
4409
+ step: loopFinishedStep,
4410
+ config: {
4411
+ ...this.#makeStepDef(loopFinishedStepKey)
4412
+ },
4413
+ get id() {
4414
+ return loopFinishedStepKey;
4415
+ }
4416
+ };
4417
+ this.#steps[loopFinishedStepKey] = loopFinishedStepNode;
4418
+ this.then(checkStep, {
4419
+ id: checkStepKey,
4420
+ "#internal": {
4421
+ loopLabel: `${fallbackStepKey} ${loopType} loop check`
4422
+ }
4423
+ });
4424
+ this.after(checkStep);
4425
+ this.#__internalStep(fallbackStep, {
4426
+ when: async ({
4427
+ context
4428
+ }) => {
4429
+ const checkStepResult = context.steps?.[checkStepKey];
4430
+ if (checkStepResult?.status !== "success") {
4431
+ return "abort" /* ABORT */;
4432
+ }
4433
+ const status = checkStepResult?.output?.status;
4434
+ return status === "continue" ? "continue" /* CONTINUE */ : "continue_failed" /* CONTINUE_FAILED */;
4435
+ },
4436
+ variables,
4437
+ "#internal": {
4438
+ // @ts-ignore
4439
+ when: condition,
4440
+ loopType
4441
+ }
4442
+ }).then(checkStep, {
4443
+ id: checkStepKey,
4444
+ "#internal": {
4445
+ loopLabel: `${fallbackStepKey} ${loopType} loop check`
4446
+ }
4447
+ });
4448
+ this.#__internalStep(loopFinishedStep, {
4449
+ id: loopFinishedStepKey,
4450
+ when: async ({
4451
+ context
4452
+ }) => {
4453
+ const checkStepResult = context.steps?.[checkStepKey];
4454
+ if (checkStepResult?.status !== "success") {
4455
+ return "continue_failed" /* CONTINUE_FAILED */;
4456
+ }
4457
+ const status = checkStepResult?.output?.status;
4458
+ return status === "complete" ? "continue" /* CONTINUE */ : "continue_failed" /* CONTINUE_FAILED */;
4459
+ },
4460
+ "#internal": {
4461
+ loopLabel: `${fallbackStepKey} ${loopType} loop finished`,
4462
+ //@ts-ignore
4463
+ loopType
4464
+ }
4465
+ });
4466
+ return this;
4467
+ }
4468
+ while(condition, fallbackStep, variables) {
4469
+ const applyOperator = (operator, value, target) => {
4470
+ switch (operator) {
4471
+ case "$eq":
4472
+ return {
4473
+ status: value !== target ? "complete" : "continue"
4474
+ };
4475
+ case "$ne":
4476
+ return {
4477
+ status: value === target ? "complete" : "continue"
4478
+ };
4479
+ case "$gt":
4480
+ return {
4481
+ status: value <= target ? "complete" : "continue"
4482
+ };
4483
+ case "$gte":
4484
+ return {
4485
+ status: value < target ? "complete" : "continue"
4486
+ };
4487
+ case "$lt":
4488
+ return {
4489
+ status: value >= target ? "complete" : "continue"
4490
+ };
4491
+ case "$lte":
4492
+ return {
4493
+ status: value > target ? "complete" : "continue"
4494
+ };
4495
+ default:
4496
+ return {
4497
+ status: "continue"
4498
+ };
4499
+ }
4500
+ };
4501
+ const res = this.loop(applyOperator, condition, fallbackStep, "while", variables);
4502
+ this.#lastBuilderType = "while";
4503
+ return res;
4504
+ }
4505
+ until(condition, fallbackStep, variables) {
4506
+ const applyOperator = (operator, value, target) => {
4507
+ switch (operator) {
4508
+ case "$eq":
4509
+ return {
4510
+ status: value === target ? "complete" : "continue"
4511
+ };
4512
+ case "$ne":
4513
+ return {
4514
+ status: value !== target ? "complete" : "continue"
4515
+ };
4516
+ case "$gt":
4517
+ return {
4518
+ status: value > target ? "complete" : "continue"
4519
+ };
4520
+ case "$gte":
4521
+ return {
4522
+ status: value >= target ? "complete" : "continue"
4523
+ };
4524
+ case "$lt":
4525
+ return {
4526
+ status: value < target ? "complete" : "continue"
4527
+ };
4528
+ case "$lte":
4529
+ return {
4530
+ status: value <= target ? "complete" : "continue"
4531
+ };
4532
+ default:
4533
+ return {
4534
+ status: "continue"
4535
+ };
4536
+ }
4537
+ };
4538
+ const res = this.loop(applyOperator, condition, fallbackStep, "until", variables);
4539
+ this.#lastBuilderType = "until";
4540
+ return res;
4541
+ }
4542
+ if(condition, ifStep, elseStep) {
4543
+ this.#ifCount++;
4544
+ const lastStep = this.#getLastStep({
4545
+ if_else_check: this.#lastBuilderType !== "else"
4546
+ });
4547
+ if (!lastStep) {
4548
+ throw new Error("Condition requires a step to be executed after");
4549
+ }
4550
+ this.after(lastStep.step);
4551
+ if (ifStep) {
4552
+ const _ifStep = isWorkflow(ifStep) ? workflowToStep(ifStep, {
4553
+ mastra: this.#mastra
4554
+ }) : ifStep;
4555
+ this.step(_ifStep, {
4556
+ id: _ifStep.id,
4557
+ when: condition
4558
+ });
4559
+ if (elseStep) {
4560
+ const _elseStep = isWorkflow(elseStep) ? workflowToStep(elseStep, {
4561
+ mastra: this.#mastra
4562
+ }) : elseStep;
4563
+ this.step(_elseStep, {
4564
+ id: _elseStep.id,
4565
+ when: typeof condition === "function" ? async payload => {
4566
+ const result = await condition(payload);
4567
+ return !result;
4568
+ } : {
4569
+ not: condition
4570
+ }
4571
+ });
4572
+ this.after([_ifStep, _elseStep]);
4573
+ } else {
4574
+ this.after(_ifStep);
4575
+ }
4576
+ this.step(new LegacyStep({
4577
+ id: `${lastStep.id}_if_else`,
4578
+ execute: async () => {
4579
+ return {
4580
+ executed: true
4581
+ };
4582
+ }
4583
+ }));
4584
+ return this;
4585
+ }
4586
+ const ifStepKey = `__${lastStep.id}_if_${this.#ifCount}`;
4587
+ this.step({
4588
+ id: ifStepKey,
4589
+ execute: async () => {
4590
+ return {
4591
+ executed: true
4592
+ };
4593
+ }
4594
+ }, {
4595
+ id: ifStepKey,
4596
+ when: condition
4597
+ });
4598
+ const elseStepKey = `__${lastStep.id}_else_${this.#ifCount}`;
4599
+ this.#ifStack.push({
4600
+ condition,
4601
+ elseStepKey,
4602
+ condStep: lastStep.step
4603
+ });
4604
+ this.#lastBuilderType = "if";
4605
+ return this;
4606
+ }
4607
+ else() {
4608
+ const activeCondition = this.#ifStack.pop();
4609
+ if (!activeCondition) {
4610
+ throw new Error("No active condition found");
4611
+ }
4612
+ this.after(activeCondition.condStep).step({
4613
+ id: activeCondition.elseStepKey,
4614
+ execute: async () => {
4615
+ return {
4616
+ executed: true
4617
+ };
4618
+ }
4619
+ }, {
4620
+ id: activeCondition.elseStepKey,
4621
+ when: typeof activeCondition.condition === "function" ? async payload => {
4622
+ const result = await activeCondition.condition(payload);
4623
+ return !result;
4624
+ } : {
4625
+ not: activeCondition.condition
4626
+ }
4627
+ });
4628
+ this.#lastBuilderType = "else";
4629
+ return this;
4630
+ }
4631
+ after(steps) {
4632
+ const stepsArray = Array.isArray(steps) ? steps : [steps];
4633
+ const stepKeys = stepsArray.map(step => this.#makeStepKey(step));
4634
+ const compoundKey = stepKeys.join("&&");
4635
+ this.#afterStepStack.push(compoundKey);
4636
+ if (!this.#stepSubscriberGraph[compoundKey]) {
4637
+ this.#stepSubscriberGraph[compoundKey] = {
4638
+ initial: []
4639
+ };
4640
+ this.#serializedStepSubscriberGraph[compoundKey] = {
4641
+ initial: []
4642
+ };
4643
+ }
4644
+ this.#lastBuilderType = "after";
4645
+ return this;
4646
+ }
4647
+ afterEvent(eventName) {
4648
+ const event = this.events?.[eventName];
4649
+ if (!event) {
4650
+ throw new Error(`Event ${eventName} not found`);
4651
+ }
4652
+ const lastStep = this.#steps[this.#lastStepStack[this.#lastStepStack.length - 1] ?? ""];
4653
+ if (!lastStep) {
4654
+ throw new Error("Condition requires a step to be executed after");
4655
+ }
4656
+ const eventStepKey = `__${eventName}_event`;
4657
+ const eventStep = new LegacyStep({
4658
+ id: eventStepKey,
4659
+ execute: async ({
4660
+ context,
4661
+ suspend
4662
+ }) => {
4663
+ if (context.inputData?.resumedEvent) {
4664
+ return {
4665
+ executed: true,
4666
+ resumedEvent: context.inputData?.resumedEvent
4667
+ };
4668
+ }
4669
+ await suspend();
4670
+ return {
4671
+ executed: false
4672
+ };
4673
+ }
4674
+ });
4675
+ this.after(lastStep.step).step(eventStep).after(eventStep);
4676
+ this.#lastBuilderType = "afterEvent";
4677
+ return this;
4678
+ }
4679
+ /**
4680
+ * Executes the workflow with the given trigger data
4681
+ * @param triggerData - Initial data to start the workflow with
4682
+ * @returns Promise resolving to workflow results or rejecting with error
4683
+ * @throws Error if trigger schema validation fails
4684
+ */
4685
+ createRun({
4686
+ runId,
4687
+ events
4688
+ } = {}) {
4689
+ const run = new WorkflowInstance({
4690
+ logger: this.logger,
4691
+ name: this.name,
4692
+ mastra: this.#mastra,
4693
+ retryConfig: this.#retryConfig,
4694
+ steps: this.#steps,
4695
+ runId,
4696
+ stepGraph: this.#stepGraph,
4697
+ stepSubscriberGraph: this.#stepSubscriberGraph,
4698
+ onStepTransition: this.#onStepTransition,
4699
+ resultMapping: this.resultMapping,
4700
+ onFinish: () => {
4701
+ this.#runs.delete(run.runId);
4702
+ },
4703
+ events
4704
+ });
4705
+ this.#runs.set(run.runId, run);
4706
+ return {
4707
+ start: run.start.bind(run),
4708
+ runId: run.runId,
4709
+ watch: run.watch.bind(run),
4710
+ resume: run.resume.bind(run),
4711
+ resumeWithEvent: run.resumeWithEvent.bind(run)
4712
+ };
4713
+ }
4714
+ /**
4715
+ * Gets a workflow run instance by ID
4716
+ * @param runId - ID of the run to retrieve
4717
+ * @returns The workflow run instance if found, undefined otherwise
4718
+ */
4719
+ async getRun(runId) {
4720
+ const inMemoryRun = this.#runs.get(runId);
4721
+ if (inMemoryRun) {
4722
+ return inMemoryRun;
4723
+ }
4724
+ const storage = this.#mastra?.getStorage();
4725
+ if (!storage) {
4726
+ this.logger.debug("Cannot get workflow run. Mastra engine is not initialized");
4727
+ return null;
4728
+ }
4729
+ return await storage.getWorkflowRunById({
4730
+ runId,
4731
+ workflowName: this.name
4732
+ });
4733
+ }
4734
+ /**
4735
+ * Gets a workflow run instance by ID, from memory
4736
+ * @param runId - ID of the run to retrieve
4737
+ * @returns The workflow run instance if found, undefined otherwise
4738
+ */
4739
+ getMemoryRun(runId) {
4740
+ return this.#runs.get(runId);
4741
+ }
4742
+ /**
4743
+ * Rebuilds the machine with the current steps configuration and validates the workflow
4744
+ *
4745
+ * This is the last step of a workflow builder method chain
4746
+ * @throws Error if validation fails
4747
+ *
4748
+ * @returns this instance for method chaining
4749
+ */
4750
+ commit() {
4751
+ return this;
4752
+ }
4753
+ // record all object paths that leads to a suspended state
4754
+ #getSuspendedPaths({
4755
+ value,
4756
+ path,
4757
+ suspendedPaths
4758
+ }) {
4759
+ if (typeof value === "string") {
4760
+ if (value === "suspended") {
4761
+ suspendedPaths.add(path);
4762
+ }
4763
+ } else {
4764
+ Object.keys(value).forEach(key => this.#getSuspendedPaths({
4765
+ value: value[key],
4766
+ path: path ? `${path}.${key}` : key,
4767
+ suspendedPaths
4768
+ }));
4769
+ }
4770
+ }
4771
+ async getWorkflowRuns(args) {
4772
+ const storage = this.#mastra?.getStorage();
4773
+ if (!storage) {
4774
+ this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
4775
+ return {
4776
+ runs: [],
4777
+ total: 0
4778
+ };
4779
+ }
4780
+ return storage.getWorkflowRuns({
4781
+ workflowName: this.name,
4782
+ ...(args ?? {})
4783
+ });
4784
+ }
4785
+ getExecutionSpan(runId) {
4786
+ return this.#runs.get(runId)?.executionSpan;
4787
+ }
4788
+ #getParentStepKey({
4789
+ loop_check = false,
4790
+ if_else_check = false
4791
+ } = {}) {
4792
+ for (let i = this.#afterStepStack.length - 1; i >= 0; i--) {
4793
+ const stepKey = this.#afterStepStack[i];
4794
+ if (!stepKey) continue;
4795
+ const isValidStep = this.#stepSubscriberGraph[stepKey] && (!loop_check || !stepKey.includes("loop_check")) && (!if_else_check || !isConditionalKey(stepKey));
4796
+ if (isValidStep) {
4797
+ return stepKey;
4798
+ }
4799
+ }
4800
+ return void 0;
4801
+ }
4802
+ #getLastStep({
4803
+ if_else_check
4804
+ }) {
4805
+ for (let i = this.#lastStepStack.length - 1; i >= 0; i--) {
4806
+ const stepKey = this.#lastStepStack[i];
4807
+ if (!stepKey) continue;
4808
+ const step = this.#steps[stepKey];
4809
+ const isInvalidStep = !step || if_else_check && isConditionalKey(stepKey);
4810
+ if (isInvalidStep) continue;
4811
+ return step;
4812
+ }
4813
+ return void 0;
4814
+ }
4815
+ #makeStepDef(stepId) {
4816
+ const executeStep = (handler2, spanName, attributes) => {
4817
+ return async data => {
4818
+ return await context.with(trace.setSpan(context.active(), this.getExecutionSpan(attributes?.runId ?? data?.runId)), async () => {
4819
+ if (this?.telemetry) {
4820
+ return this.telemetry.traceMethod(handler2, {
4821
+ spanName,
4822
+ attributes
4823
+ })(data);
4824
+ } else {
4825
+ return handler2(data);
4826
+ }
4827
+ });
4828
+ };
4829
+ };
4830
+ const handler = async ({
4831
+ context,
4832
+ ...rest
4833
+ }) => {
4834
+ const targetStep = this.#steps[stepId];
4835
+ if (!targetStep) throw new Error(`Step not found`);
4836
+ const {
4837
+ payload = {},
4838
+ execute = async () => {}
4839
+ } = targetStep.step;
4840
+ const finalAction = this.telemetry ? executeStep(execute, `workflow.${this.name}.action.${stepId}`, {
4841
+ componentName: this.name,
4842
+ runId: rest.runId
4843
+ }) : execute;
4844
+ return finalAction ? await finalAction({
4845
+ context: {
4846
+ ...context,
4847
+ inputData: {
4848
+ ...(context?.inputData || {}),
4849
+ ...payload
4850
+ }
4851
+ },
4852
+ ...rest
4853
+ }) : {};
4854
+ };
4855
+ const finalHandler = ({
4856
+ context,
4857
+ ...rest
4858
+ }) => {
4859
+ if (this.getExecutionSpan(rest?.runId)) {
4860
+ return executeStep(handler, `workflow.${this.name}.step.${stepId}`, {
4861
+ componentName: this.name,
4862
+ runId: rest?.runId
4863
+ })({
4864
+ context,
4865
+ ...rest
4866
+ });
4867
+ }
4868
+ return handler({
4869
+ context,
4870
+ ...rest
4871
+ });
4872
+ };
4873
+ return {
4874
+ handler: finalHandler,
4875
+ data: {}
4876
+ };
4877
+ }
4878
+ #getActivePathsAndStatus(value) {
4879
+ const paths = [];
4880
+ const traverse = (current, path = []) => {
4881
+ for (const [key, value2] of Object.entries(current)) {
4882
+ const currentPath = [...path, key];
4883
+ if (typeof value2 === "string") {
4884
+ paths.push({
4885
+ stepPath: currentPath,
4886
+ stepId: key,
4887
+ status: value2
4888
+ });
4889
+ } else if (typeof value2 === "object" && value2 !== null) {
4890
+ traverse(value2, currentPath);
4891
+ }
4892
+ }
4893
+ };
4894
+ traverse(value);
4895
+ return paths;
4896
+ }
4897
+ async getState(runId) {
4898
+ const run = this.#runs.get(runId);
4899
+ if (run) {
4900
+ return run.getState();
4901
+ }
4902
+ const storage = this.#mastra?.getStorage();
4903
+ const storedSnapshot = await storage?.loadWorkflowSnapshot({
4904
+ runId,
4905
+ workflowName: this.name
4906
+ });
4907
+ if (storedSnapshot) {
4908
+ const parsed = storedSnapshot;
4909
+ const m = this.#getActivePathsAndStatus(parsed.value);
4910
+ return {
4911
+ runId,
4912
+ value: parsed.value,
4913
+ context: parsed.context,
4914
+ activePaths: m,
4915
+ timestamp: Date.now()
4916
+ };
4917
+ }
4918
+ return null;
4919
+ }
4920
+ async resume({
4921
+ runId,
4922
+ stepId,
4923
+ context: resumeContext,
4924
+ runtimeContext = new RuntimeContext()
4925
+ }) {
4926
+ this.logger.warn(`Please use 'resume' on the 'createRun' call instead, resume is deprecated`);
4927
+ const activeRun = this.#runs.get(runId);
4928
+ if (activeRun) {
4929
+ return activeRun.resume({
4930
+ stepId,
4931
+ context: resumeContext,
4932
+ runtimeContext
4933
+ });
4934
+ }
4935
+ const run = this.createRun({
4936
+ runId
4937
+ });
4938
+ return run.resume({
4939
+ stepId,
4940
+ context: resumeContext,
4941
+ runtimeContext
4942
+ });
4943
+ }
4944
+ watch(onTransition) {
4945
+ this.logger.warn(`Please use 'watch' on the 'createRun' call instead, watch is deprecated`);
4946
+ this.#onStepTransition.add(onTransition);
4947
+ return () => {
4948
+ this.#onStepTransition.delete(onTransition);
4949
+ };
4950
+ }
4951
+ async resumeWithEvent(runId, eventName, data) {
4952
+ this.logger.warn(`Please use 'resumeWithEvent' on the 'createRun' call instead, resumeWithEvent is deprecated`);
4953
+ const event = this.events?.[eventName];
4954
+ if (!event) {
4955
+ throw new Error(`Event ${eventName} not found`);
4956
+ }
4957
+ const results = await this.resume({
4958
+ runId,
4959
+ stepId: `__${eventName}_event`,
4960
+ context: {
4961
+ resumedEvent: data
4962
+ },
4963
+ runtimeContext: new RuntimeContext()
4964
+ });
4965
+ return results;
4966
+ }
4967
+ __registerMastra(mastra) {
4968
+ this.#mastra = mastra;
4969
+ }
4970
+ __registerPrimitives(p) {
4971
+ if (p.telemetry) {
4972
+ this.__setTelemetry(p.telemetry);
4973
+ }
4974
+ if (p.logger) {
4975
+ this.__setLogger(p.logger);
4976
+ }
4977
+ }
4978
+ get stepGraph() {
4979
+ return this.#stepGraph;
4980
+ }
4981
+ get stepSubscriberGraph() {
4982
+ return this.#stepSubscriberGraph;
4983
+ }
4984
+ get serializedStepGraph() {
4985
+ return this.#serializedStepGraph;
4986
+ }
4987
+ get serializedStepSubscriberGraph() {
4988
+ return this.#serializedStepSubscriberGraph;
4989
+ }
4990
+ get steps() {
4991
+ return Object.entries(this.#steps).reduce((acc, [key, step]) => {
4992
+ acc[key] = step.step;
4993
+ return acc;
4994
+ }, {});
4995
+ }
4996
+ setNested(isNested) {
4997
+ this.isNested = isNested;
4998
+ }
4999
+ toStep() {
5000
+ const x = workflowToStep(this, {
5001
+ mastra: this.#mastra
5002
+ });
5003
+ return new LegacyStep(x);
5004
+ }
5005
+ };
5006
+
5007
+ export { Agent, LegacyStep, LegacyWorkflow, WhenConditionReturnValue, agentToStep, getActivePathsAndStatus, getResultActivePaths, getStepResult, getSuspendedPaths, isAgent, isConditionalKey, isErrorEvent, isFinalState, isLimboState, isTransitionEvent, isVariableReference, isWorkflow, mergeChildValue, recursivelyCheckForFinalState, resolveVariables, updateStepInHierarchy, workflowToStep };