@mastra/core 0.7.0 → 0.8.0-alpha.1

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