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