@mastra/inngest 0.0.0-mssql-store-20250804200341 → 0.0.0-netlify-no-bundle-20251127120354
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/CHANGELOG.md +1032 -2
- package/dist/index.cjs +1101 -616
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +178 -112
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1104 -619
- package/dist/index.js.map +1 -1
- package/package.json +38 -19
- package/docker-compose.yaml +0 -10
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -7815
- package/src/index.ts +0 -1784
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -22
- package/vitest.config.ts +0 -14
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,27 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
|
+
var web = require('stream/web');
|
|
4
5
|
var realtime = require('@inngest/realtime');
|
|
5
6
|
var di = require('@mastra/core/di');
|
|
7
|
+
var observability = require('@mastra/core/observability');
|
|
8
|
+
var stream = require('@mastra/core/stream');
|
|
6
9
|
var tools = require('@mastra/core/tools');
|
|
7
10
|
var workflows = require('@mastra/core/workflows');
|
|
8
11
|
var _constants = require('@mastra/core/workflows/_constants');
|
|
12
|
+
var inngest = require('inngest');
|
|
9
13
|
var hono = require('inngest/hono');
|
|
10
14
|
var zod = require('zod');
|
|
11
15
|
|
|
12
16
|
// src/index.ts
|
|
13
|
-
function serve({
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
function serve({
|
|
18
|
+
mastra,
|
|
19
|
+
inngest,
|
|
20
|
+
functions: userFunctions = [],
|
|
21
|
+
registerOptions
|
|
22
|
+
}) {
|
|
23
|
+
const wfs = mastra.listWorkflows();
|
|
24
|
+
const workflowFunctions = Array.from(
|
|
16
25
|
new Set(
|
|
17
26
|
Object.values(wfs).flatMap((wf) => {
|
|
18
27
|
if (wf instanceof InngestWorkflow) {
|
|
@@ -24,8 +33,9 @@ function serve({ mastra, inngest }) {
|
|
|
24
33
|
)
|
|
25
34
|
);
|
|
26
35
|
return hono.serve({
|
|
36
|
+
...registerOptions,
|
|
27
37
|
client: inngest,
|
|
28
|
-
functions
|
|
38
|
+
functions: [...workflowFunctions, ...userFunctions]
|
|
29
39
|
});
|
|
30
40
|
}
|
|
31
41
|
var InngestRun = class extends workflows.Run {
|
|
@@ -49,14 +59,21 @@ var InngestRun = class extends workflows.Run {
|
|
|
49
59
|
}
|
|
50
60
|
async getRunOutput(eventId) {
|
|
51
61
|
let runs = await this.getRuns(eventId);
|
|
62
|
+
const storage = this.#mastra?.getStorage();
|
|
52
63
|
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
53
64
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
54
65
|
runs = await this.getRuns(eventId);
|
|
55
66
|
if (runs?.[0]?.status === "Failed") {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
68
|
+
workflowName: this.workflowId,
|
|
69
|
+
runId: this.runId
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (runs?.[0]?.status === "Cancelled") {
|
|
76
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
60
77
|
workflowName: this.workflowId,
|
|
61
78
|
runId: this.runId
|
|
62
79
|
});
|
|
@@ -65,56 +82,71 @@ var InngestRun = class extends workflows.Run {
|
|
|
65
82
|
}
|
|
66
83
|
return runs?.[0];
|
|
67
84
|
}
|
|
68
|
-
async sendEvent(event, data) {
|
|
69
|
-
await this.inngest.send({
|
|
70
|
-
name: `user-event-${event}`,
|
|
71
|
-
data
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
85
|
async cancel() {
|
|
86
|
+
const storage = this.#mastra?.getStorage();
|
|
75
87
|
await this.inngest.send({
|
|
76
88
|
name: `cancel.workflow.${this.workflowId}`,
|
|
77
89
|
data: {
|
|
78
90
|
runId: this.runId
|
|
79
91
|
}
|
|
80
92
|
});
|
|
81
|
-
const snapshot = await
|
|
93
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
82
94
|
workflowName: this.workflowId,
|
|
83
95
|
runId: this.runId
|
|
84
96
|
});
|
|
85
97
|
if (snapshot) {
|
|
86
|
-
await
|
|
98
|
+
await storage?.persistWorkflowSnapshot({
|
|
87
99
|
workflowName: this.workflowId,
|
|
88
100
|
runId: this.runId,
|
|
101
|
+
resourceId: this.resourceId,
|
|
89
102
|
snapshot: {
|
|
90
103
|
...snapshot,
|
|
91
|
-
status: "canceled"
|
|
104
|
+
status: "canceled",
|
|
105
|
+
value: snapshot.value
|
|
92
106
|
}
|
|
93
107
|
});
|
|
94
108
|
}
|
|
95
109
|
}
|
|
96
|
-
async start({
|
|
97
|
-
|
|
110
|
+
async start(params) {
|
|
111
|
+
return this._start(params);
|
|
112
|
+
}
|
|
113
|
+
async _start({
|
|
114
|
+
inputData,
|
|
115
|
+
initialState,
|
|
116
|
+
outputOptions,
|
|
117
|
+
tracingOptions,
|
|
118
|
+
format
|
|
98
119
|
}) {
|
|
99
120
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
100
121
|
workflowName: this.workflowId,
|
|
101
122
|
runId: this.runId,
|
|
123
|
+
resourceId: this.resourceId,
|
|
102
124
|
snapshot: {
|
|
103
125
|
runId: this.runId,
|
|
104
126
|
serializedStepGraph: this.serializedStepGraph,
|
|
127
|
+
status: "running",
|
|
105
128
|
value: {},
|
|
106
129
|
context: {},
|
|
107
130
|
activePaths: [],
|
|
108
131
|
suspendedPaths: {},
|
|
109
|
-
|
|
110
|
-
|
|
132
|
+
activeStepsPath: {},
|
|
133
|
+
resumeLabels: {},
|
|
134
|
+
waitingPaths: {},
|
|
135
|
+
timestamp: Date.now()
|
|
111
136
|
}
|
|
112
137
|
});
|
|
138
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
139
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
113
140
|
const eventOutput = await this.inngest.send({
|
|
114
141
|
name: `workflow.${this.workflowId}`,
|
|
115
142
|
data: {
|
|
116
|
-
inputData,
|
|
117
|
-
|
|
143
|
+
inputData: inputDataToUse,
|
|
144
|
+
initialState: initialStateToUse,
|
|
145
|
+
runId: this.runId,
|
|
146
|
+
resourceId: this.resourceId,
|
|
147
|
+
outputOptions,
|
|
148
|
+
tracingOptions,
|
|
149
|
+
format
|
|
118
150
|
}
|
|
119
151
|
});
|
|
120
152
|
const eventId = eventOutput.ids[0];
|
|
@@ -143,26 +175,34 @@ var InngestRun = class extends workflows.Run {
|
|
|
143
175
|
return p;
|
|
144
176
|
}
|
|
145
177
|
async _resume(params) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
|
|
178
|
+
const storage = this.#mastra?.getStorage();
|
|
179
|
+
let steps = [];
|
|
180
|
+
if (typeof params.step === "string") {
|
|
181
|
+
steps = params.step.split(".");
|
|
182
|
+
} else {
|
|
183
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
184
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
150
188
|
workflowName: this.workflowId,
|
|
151
189
|
runId: this.runId
|
|
152
190
|
});
|
|
191
|
+
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
192
|
+
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
153
193
|
const eventOutput = await this.inngest.send({
|
|
154
194
|
name: `workflow.${this.workflowId}`,
|
|
155
195
|
data: {
|
|
156
|
-
inputData:
|
|
196
|
+
inputData: resumeDataToUse,
|
|
197
|
+
initialState: snapshot?.value ?? {},
|
|
157
198
|
runId: this.runId,
|
|
158
199
|
workflowId: this.workflowId,
|
|
159
200
|
stepResults: snapshot?.context,
|
|
160
201
|
resume: {
|
|
161
202
|
steps,
|
|
162
203
|
stepResults: snapshot?.context,
|
|
163
|
-
resumePayload:
|
|
164
|
-
|
|
165
|
-
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
204
|
+
resumePayload: resumeDataToUse,
|
|
205
|
+
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
166
206
|
}
|
|
167
207
|
}
|
|
168
208
|
});
|
|
@@ -177,12 +217,103 @@ var InngestRun = class extends workflows.Run {
|
|
|
177
217
|
}
|
|
178
218
|
return result;
|
|
179
219
|
}
|
|
180
|
-
|
|
220
|
+
async timeTravel(params) {
|
|
221
|
+
const p = this._timeTravel(params).then((result) => {
|
|
222
|
+
if (result.status !== "suspended") {
|
|
223
|
+
this.closeStreamAction?.().catch(() => {
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
});
|
|
228
|
+
this.executionResults = p;
|
|
229
|
+
return p;
|
|
230
|
+
}
|
|
231
|
+
async _timeTravel(params) {
|
|
232
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
233
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
234
|
+
}
|
|
235
|
+
let steps = [];
|
|
236
|
+
if (typeof params.step === "string") {
|
|
237
|
+
steps = params.step.split(".");
|
|
238
|
+
} else {
|
|
239
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
240
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
if (steps.length === 0) {
|
|
244
|
+
throw new Error("No steps provided to timeTravel");
|
|
245
|
+
}
|
|
246
|
+
const storage = this.#mastra?.getStorage();
|
|
247
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
248
|
+
workflowName: this.workflowId,
|
|
249
|
+
runId: this.runId
|
|
250
|
+
});
|
|
251
|
+
if (!snapshot) {
|
|
252
|
+
await storage?.persistWorkflowSnapshot({
|
|
253
|
+
workflowName: this.workflowId,
|
|
254
|
+
runId: this.runId,
|
|
255
|
+
resourceId: this.resourceId,
|
|
256
|
+
snapshot: {
|
|
257
|
+
runId: this.runId,
|
|
258
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
259
|
+
status: "pending",
|
|
260
|
+
value: {},
|
|
261
|
+
context: {},
|
|
262
|
+
activePaths: [],
|
|
263
|
+
suspendedPaths: {},
|
|
264
|
+
activeStepsPath: {},
|
|
265
|
+
resumeLabels: {},
|
|
266
|
+
waitingPaths: {},
|
|
267
|
+
timestamp: Date.now()
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (snapshot?.status === "running") {
|
|
272
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
273
|
+
}
|
|
274
|
+
let inputDataToUse = params.inputData;
|
|
275
|
+
if (inputDataToUse && steps.length === 1) {
|
|
276
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
277
|
+
}
|
|
278
|
+
const timeTravelData = workflows.createTimeTravelExecutionParams({
|
|
279
|
+
steps,
|
|
280
|
+
inputData: inputDataToUse,
|
|
281
|
+
resumeData: params.resumeData,
|
|
282
|
+
context: params.context,
|
|
283
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
284
|
+
snapshot: snapshot ?? { context: {} },
|
|
285
|
+
graph: this.executionGraph,
|
|
286
|
+
initialState: params.initialState
|
|
287
|
+
});
|
|
288
|
+
const eventOutput = await this.inngest.send({
|
|
289
|
+
name: `workflow.${this.workflowId}`,
|
|
290
|
+
data: {
|
|
291
|
+
initialState: timeTravelData.state,
|
|
292
|
+
runId: this.runId,
|
|
293
|
+
workflowId: this.workflowId,
|
|
294
|
+
stepResults: timeTravelData.stepResults,
|
|
295
|
+
timeTravel: timeTravelData,
|
|
296
|
+
tracingOptions: params.tracingOptions,
|
|
297
|
+
outputOptions: params.outputOptions
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
const eventId = eventOutput.ids[0];
|
|
301
|
+
if (!eventId) {
|
|
302
|
+
throw new Error("Event ID is not set");
|
|
303
|
+
}
|
|
304
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
305
|
+
const result = runOutput?.output?.result;
|
|
306
|
+
if (result.status === "failed") {
|
|
307
|
+
result.error = new Error(result.error);
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
watch(cb) {
|
|
181
312
|
let active = true;
|
|
182
313
|
const streamPromise = realtime.subscribe(
|
|
183
314
|
{
|
|
184
315
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
185
|
-
topics: [
|
|
316
|
+
topics: ["watch"],
|
|
186
317
|
app: this.inngest
|
|
187
318
|
},
|
|
188
319
|
(message) => {
|
|
@@ -200,16 +331,35 @@ var InngestRun = class extends workflows.Run {
|
|
|
200
331
|
});
|
|
201
332
|
};
|
|
202
333
|
}
|
|
203
|
-
|
|
334
|
+
streamLegacy({ inputData, requestContext } = {}) {
|
|
204
335
|
const { readable, writable } = new TransformStream();
|
|
205
336
|
const writer = writable.getWriter();
|
|
337
|
+
void writer.write({
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
type: "start",
|
|
340
|
+
// @ts-ignore
|
|
341
|
+
payload: { runId: this.runId }
|
|
342
|
+
});
|
|
206
343
|
const unwatch = this.watch(async (event) => {
|
|
207
344
|
try {
|
|
208
|
-
|
|
345
|
+
const e = {
|
|
346
|
+
...event,
|
|
347
|
+
type: event.type.replace("workflow-", "")
|
|
348
|
+
};
|
|
349
|
+
if (e.type === "step-output") {
|
|
350
|
+
e.type = e.payload.output.type;
|
|
351
|
+
e.payload = e.payload.output.payload;
|
|
352
|
+
}
|
|
353
|
+
await writer.write(e);
|
|
209
354
|
} catch {
|
|
210
355
|
}
|
|
211
|
-
}
|
|
356
|
+
});
|
|
212
357
|
this.closeStreamAction = async () => {
|
|
358
|
+
await writer.write({
|
|
359
|
+
type: "finish",
|
|
360
|
+
// @ts-ignore
|
|
361
|
+
payload: { runId: this.runId }
|
|
362
|
+
});
|
|
213
363
|
unwatch();
|
|
214
364
|
try {
|
|
215
365
|
await writer.close();
|
|
@@ -219,7 +369,7 @@ var InngestRun = class extends workflows.Run {
|
|
|
219
369
|
writer.releaseLock();
|
|
220
370
|
}
|
|
221
371
|
};
|
|
222
|
-
this.executionResults = this.
|
|
372
|
+
this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
|
|
223
373
|
if (result.status !== "suspended") {
|
|
224
374
|
this.closeStreamAction?.().catch(() => {
|
|
225
375
|
});
|
|
@@ -231,23 +381,175 @@ var InngestRun = class extends workflows.Run {
|
|
|
231
381
|
getWorkflowState: () => this.executionResults
|
|
232
382
|
};
|
|
233
383
|
}
|
|
384
|
+
stream({
|
|
385
|
+
inputData,
|
|
386
|
+
requestContext,
|
|
387
|
+
tracingOptions,
|
|
388
|
+
closeOnSuspend = true,
|
|
389
|
+
initialState,
|
|
390
|
+
outputOptions
|
|
391
|
+
} = {}) {
|
|
392
|
+
if (this.closeStreamAction && this.streamOutput) {
|
|
393
|
+
return this.streamOutput;
|
|
394
|
+
}
|
|
395
|
+
this.closeStreamAction = async () => {
|
|
396
|
+
};
|
|
397
|
+
const self = this;
|
|
398
|
+
const stream$1 = new web.ReadableStream({
|
|
399
|
+
async start(controller) {
|
|
400
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
401
|
+
controller.enqueue({
|
|
402
|
+
type,
|
|
403
|
+
runId: self.runId,
|
|
404
|
+
from,
|
|
405
|
+
payload: {
|
|
406
|
+
stepName: payload?.id,
|
|
407
|
+
...payload
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
self.closeStreamAction = async () => {
|
|
412
|
+
unwatch();
|
|
413
|
+
try {
|
|
414
|
+
await controller.close();
|
|
415
|
+
} catch (err) {
|
|
416
|
+
console.error("Error closing stream:", err);
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
const executionResultsPromise = self._start({
|
|
420
|
+
inputData,
|
|
421
|
+
requestContext,
|
|
422
|
+
// tracingContext, // We are not able to pass a reference to a span here, what to do?
|
|
423
|
+
initialState,
|
|
424
|
+
tracingOptions,
|
|
425
|
+
outputOptions,
|
|
426
|
+
format: "vnext"
|
|
427
|
+
});
|
|
428
|
+
let executionResults;
|
|
429
|
+
try {
|
|
430
|
+
executionResults = await executionResultsPromise;
|
|
431
|
+
if (closeOnSuspend) {
|
|
432
|
+
self.closeStreamAction?.().catch(() => {
|
|
433
|
+
});
|
|
434
|
+
} else if (executionResults.status !== "suspended") {
|
|
435
|
+
self.closeStreamAction?.().catch(() => {
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
if (self.streamOutput) {
|
|
439
|
+
self.streamOutput.updateResults(
|
|
440
|
+
executionResults
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
} catch (err) {
|
|
444
|
+
self.streamOutput?.rejectResults(err);
|
|
445
|
+
self.closeStreamAction?.().catch(() => {
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
this.streamOutput = new stream.WorkflowRunOutput({
|
|
451
|
+
runId: this.runId,
|
|
452
|
+
workflowId: this.workflowId,
|
|
453
|
+
stream: stream$1
|
|
454
|
+
});
|
|
455
|
+
return this.streamOutput;
|
|
456
|
+
}
|
|
457
|
+
streamVNext(args = {}) {
|
|
458
|
+
return this.stream(args);
|
|
459
|
+
}
|
|
460
|
+
timeTravelStream({
|
|
461
|
+
inputData,
|
|
462
|
+
resumeData,
|
|
463
|
+
initialState,
|
|
464
|
+
step,
|
|
465
|
+
context,
|
|
466
|
+
nestedStepsContext,
|
|
467
|
+
requestContext,
|
|
468
|
+
tracingOptions,
|
|
469
|
+
outputOptions
|
|
470
|
+
}) {
|
|
471
|
+
this.closeStreamAction = async () => {
|
|
472
|
+
};
|
|
473
|
+
const self = this;
|
|
474
|
+
const stream$1 = new web.ReadableStream({
|
|
475
|
+
async start(controller) {
|
|
476
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
477
|
+
controller.enqueue({
|
|
478
|
+
type,
|
|
479
|
+
runId: self.runId,
|
|
480
|
+
from,
|
|
481
|
+
payload: {
|
|
482
|
+
stepName: payload?.id,
|
|
483
|
+
...payload
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
self.closeStreamAction = async () => {
|
|
488
|
+
unwatch();
|
|
489
|
+
try {
|
|
490
|
+
await controller.close();
|
|
491
|
+
} catch (err) {
|
|
492
|
+
console.error("Error closing stream:", err);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
const executionResultsPromise = self._timeTravel({
|
|
496
|
+
inputData,
|
|
497
|
+
step,
|
|
498
|
+
context,
|
|
499
|
+
nestedStepsContext,
|
|
500
|
+
resumeData,
|
|
501
|
+
initialState,
|
|
502
|
+
requestContext,
|
|
503
|
+
tracingOptions,
|
|
504
|
+
outputOptions
|
|
505
|
+
});
|
|
506
|
+
self.executionResults = executionResultsPromise;
|
|
507
|
+
let executionResults;
|
|
508
|
+
try {
|
|
509
|
+
executionResults = await executionResultsPromise;
|
|
510
|
+
self.closeStreamAction?.().catch(() => {
|
|
511
|
+
});
|
|
512
|
+
if (self.streamOutput) {
|
|
513
|
+
self.streamOutput.updateResults(executionResults);
|
|
514
|
+
}
|
|
515
|
+
} catch (err) {
|
|
516
|
+
self.streamOutput?.rejectResults(err);
|
|
517
|
+
self.closeStreamAction?.().catch(() => {
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
this.streamOutput = new stream.WorkflowRunOutput({
|
|
523
|
+
runId: this.runId,
|
|
524
|
+
workflowId: this.workflowId,
|
|
525
|
+
stream: stream$1
|
|
526
|
+
});
|
|
527
|
+
return this.streamOutput;
|
|
528
|
+
}
|
|
234
529
|
};
|
|
235
530
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
236
531
|
#mastra;
|
|
237
532
|
inngest;
|
|
238
533
|
function;
|
|
534
|
+
flowControlConfig;
|
|
239
535
|
constructor(params, inngest) {
|
|
240
|
-
|
|
536
|
+
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
537
|
+
super(workflowParams);
|
|
538
|
+
this.engineType = "inngest";
|
|
539
|
+
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
540
|
+
([_, value]) => value !== void 0
|
|
541
|
+
);
|
|
542
|
+
this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
|
|
241
543
|
this.#mastra = params.mastra;
|
|
242
544
|
this.inngest = inngest;
|
|
243
545
|
}
|
|
244
|
-
async
|
|
546
|
+
async listWorkflowRuns(args) {
|
|
245
547
|
const storage = this.#mastra?.getStorage();
|
|
246
548
|
if (!storage) {
|
|
247
549
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
248
550
|
return { runs: [], total: 0 };
|
|
249
551
|
}
|
|
250
|
-
return storage.
|
|
552
|
+
return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
|
|
251
553
|
}
|
|
252
554
|
async getWorkflowRunById(runId) {
|
|
253
555
|
const storage = this.#mastra?.getStorage();
|
|
@@ -258,27 +560,6 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
258
560
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
259
561
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
260
562
|
}
|
|
261
|
-
async getWorkflowRunExecutionResult(runId) {
|
|
262
|
-
const storage = this.#mastra?.getStorage();
|
|
263
|
-
if (!storage) {
|
|
264
|
-
this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
|
|
265
|
-
return null;
|
|
266
|
-
}
|
|
267
|
-
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
268
|
-
if (!run?.snapshot) {
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
if (typeof run.snapshot === "string") {
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
return {
|
|
275
|
-
status: run.snapshot.status,
|
|
276
|
-
result: run.snapshot.result,
|
|
277
|
-
error: run.snapshot.error,
|
|
278
|
-
payload: run.snapshot.context?.input,
|
|
279
|
-
steps: run.snapshot.context
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
563
|
__registerMastra(mastra) {
|
|
283
564
|
this.#mastra = mastra;
|
|
284
565
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -297,56 +578,49 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
297
578
|
}
|
|
298
579
|
}
|
|
299
580
|
}
|
|
300
|
-
createRun(options) {
|
|
301
|
-
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
302
|
-
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
303
|
-
{
|
|
304
|
-
workflowId: this.id,
|
|
305
|
-
runId: runIdToUse,
|
|
306
|
-
executionEngine: this.executionEngine,
|
|
307
|
-
executionGraph: this.executionGraph,
|
|
308
|
-
serializedStepGraph: this.serializedStepGraph,
|
|
309
|
-
mastra: this.#mastra,
|
|
310
|
-
retryConfig: this.retryConfig,
|
|
311
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
312
|
-
},
|
|
313
|
-
this.inngest
|
|
314
|
-
);
|
|
315
|
-
this.runs.set(runIdToUse, run);
|
|
316
|
-
return run;
|
|
317
|
-
}
|
|
318
|
-
async createRunAsync(options) {
|
|
581
|
+
async createRun(options) {
|
|
319
582
|
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
320
583
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
321
584
|
{
|
|
322
585
|
workflowId: this.id,
|
|
323
586
|
runId: runIdToUse,
|
|
587
|
+
resourceId: options?.resourceId,
|
|
324
588
|
executionEngine: this.executionEngine,
|
|
325
589
|
executionGraph: this.executionGraph,
|
|
326
590
|
serializedStepGraph: this.serializedStepGraph,
|
|
327
591
|
mastra: this.#mastra,
|
|
328
592
|
retryConfig: this.retryConfig,
|
|
329
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
593
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
594
|
+
workflowSteps: this.steps,
|
|
595
|
+
workflowEngineType: this.engineType,
|
|
596
|
+
validateInputs: this.options.validateInputs
|
|
330
597
|
},
|
|
331
598
|
this.inngest
|
|
332
599
|
);
|
|
333
600
|
this.runs.set(runIdToUse, run);
|
|
334
|
-
const
|
|
335
|
-
|
|
601
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
|
|
602
|
+
workflowStatus: run.workflowRunStatus,
|
|
603
|
+
stepResults: {}
|
|
604
|
+
});
|
|
605
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
606
|
+
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
336
607
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
337
608
|
workflowName: this.id,
|
|
338
609
|
runId: runIdToUse,
|
|
610
|
+
resourceId: options?.resourceId,
|
|
339
611
|
snapshot: {
|
|
340
612
|
runId: runIdToUse,
|
|
341
613
|
status: "pending",
|
|
342
614
|
value: {},
|
|
343
615
|
context: {},
|
|
344
616
|
activePaths: [],
|
|
617
|
+
activeStepsPath: {},
|
|
618
|
+
waitingPaths: {},
|
|
345
619
|
serializedStepGraph: this.serializedStepGraph,
|
|
346
620
|
suspendedPaths: {},
|
|
621
|
+
resumeLabels: {},
|
|
347
622
|
result: void 0,
|
|
348
623
|
error: void 0,
|
|
349
|
-
// @ts-ignore
|
|
350
624
|
timestamp: Date.now()
|
|
351
625
|
}
|
|
352
626
|
});
|
|
@@ -360,13 +634,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
360
634
|
this.function = this.inngest.createFunction(
|
|
361
635
|
{
|
|
362
636
|
id: `workflow.${this.id}`,
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
637
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
638
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
639
|
+
// Spread flow control configuration
|
|
640
|
+
...this.flowControlConfig
|
|
366
641
|
},
|
|
367
642
|
{ event: `workflow.${this.id}` },
|
|
368
643
|
async ({ event, step, attempt, publish }) => {
|
|
369
|
-
let { inputData, runId, resume } = event.data;
|
|
644
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
370
645
|
if (!runId) {
|
|
371
646
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
372
647
|
return crypto.randomUUID();
|
|
@@ -394,19 +669,39 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
394
669
|
once: (_event, _callback) => {
|
|
395
670
|
}
|
|
396
671
|
};
|
|
397
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
672
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
398
673
|
const result = await engine.execute({
|
|
399
674
|
workflowId: this.id,
|
|
400
675
|
runId,
|
|
676
|
+
resourceId,
|
|
401
677
|
graph: this.executionGraph,
|
|
402
678
|
serializedStepGraph: this.serializedStepGraph,
|
|
403
679
|
input: inputData,
|
|
680
|
+
initialState,
|
|
404
681
|
emitter,
|
|
405
682
|
retryConfig: this.retryConfig,
|
|
406
|
-
|
|
683
|
+
requestContext: new di.RequestContext(),
|
|
407
684
|
// TODO
|
|
408
685
|
resume,
|
|
409
|
-
|
|
686
|
+
timeTravel,
|
|
687
|
+
format,
|
|
688
|
+
abortController: new AbortController(),
|
|
689
|
+
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
690
|
+
outputOptions,
|
|
691
|
+
writableStream: new web.WritableStream({
|
|
692
|
+
write(chunk) {
|
|
693
|
+
void emitter.emit("watch", chunk).catch(() => {
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
})
|
|
697
|
+
});
|
|
698
|
+
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
699
|
+
if (result.status === "failed") {
|
|
700
|
+
throw new inngest.NonRetriableError(`Workflow failed`, {
|
|
701
|
+
cause: result
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
return result;
|
|
410
705
|
});
|
|
411
706
|
return { result, runId };
|
|
412
707
|
}
|
|
@@ -436,21 +731,29 @@ function isAgent(params) {
|
|
|
436
731
|
function isTool(params) {
|
|
437
732
|
return params instanceof tools.Tool;
|
|
438
733
|
}
|
|
439
|
-
function createStep(params) {
|
|
734
|
+
function createStep(params, agentOptions) {
|
|
440
735
|
if (isAgent(params)) {
|
|
441
736
|
return {
|
|
442
737
|
id: params.name,
|
|
443
|
-
|
|
738
|
+
description: params.getDescription(),
|
|
444
739
|
inputSchema: zod.z.object({
|
|
445
740
|
prompt: zod.z.string()
|
|
446
741
|
// resourceId: z.string().optional(),
|
|
447
742
|
// threadId: z.string().optional(),
|
|
448
743
|
}),
|
|
449
|
-
// @ts-ignore
|
|
450
744
|
outputSchema: zod.z.object({
|
|
451
745
|
text: zod.z.string()
|
|
452
746
|
}),
|
|
453
|
-
execute: async ({
|
|
747
|
+
execute: async ({
|
|
748
|
+
inputData,
|
|
749
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
750
|
+
[_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
|
|
751
|
+
requestContext,
|
|
752
|
+
tracingContext,
|
|
753
|
+
abortSignal,
|
|
754
|
+
abort,
|
|
755
|
+
writer
|
|
756
|
+
}) => {
|
|
454
757
|
let streamPromise = {};
|
|
455
758
|
streamPromise.promise = new Promise((resolve, reject) => {
|
|
456
759
|
streamPromise.resolve = resolve;
|
|
@@ -460,50 +763,65 @@ function createStep(params) {
|
|
|
460
763
|
name: params.name,
|
|
461
764
|
args: inputData
|
|
462
765
|
};
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
766
|
+
let stream;
|
|
767
|
+
if ((await params.getModel()).specificationVersion === "v1") {
|
|
768
|
+
const { fullStream } = await params.streamLegacy(inputData.prompt, {
|
|
769
|
+
...agentOptions ?? {},
|
|
770
|
+
// resourceId: inputData.resourceId,
|
|
771
|
+
// threadId: inputData.threadId,
|
|
772
|
+
requestContext,
|
|
773
|
+
tracingContext,
|
|
774
|
+
onFinish: (result) => {
|
|
775
|
+
streamPromise.resolve(result.text);
|
|
776
|
+
void agentOptions?.onFinish?.(result);
|
|
777
|
+
},
|
|
778
|
+
abortSignal
|
|
779
|
+
});
|
|
780
|
+
stream = fullStream;
|
|
781
|
+
} else {
|
|
782
|
+
const modelOutput = await params.stream(inputData.prompt, {
|
|
783
|
+
...agentOptions ?? {},
|
|
784
|
+
requestContext,
|
|
785
|
+
tracingContext,
|
|
786
|
+
onFinish: (result) => {
|
|
787
|
+
streamPromise.resolve(result.text);
|
|
788
|
+
void agentOptions?.onFinish?.(result);
|
|
789
|
+
},
|
|
790
|
+
abortSignal
|
|
791
|
+
});
|
|
792
|
+
stream = modelOutput.fullStream;
|
|
478
793
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
794
|
+
if (streamFormat === "legacy") {
|
|
795
|
+
await emitter.emit("watch", {
|
|
796
|
+
type: "tool-call-streaming-start",
|
|
797
|
+
...toolData ?? {}
|
|
798
|
+
});
|
|
799
|
+
for await (const chunk of stream) {
|
|
800
|
+
if (chunk.type === "text-delta") {
|
|
801
|
+
await emitter.emit("watch", {
|
|
483
802
|
type: "tool-call-delta",
|
|
484
|
-
...toolData,
|
|
803
|
+
...toolData ?? {},
|
|
485
804
|
argsTextDelta: chunk.textDelta
|
|
486
805
|
});
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
case "source":
|
|
497
|
-
case "file":
|
|
498
|
-
default:
|
|
499
|
-
await emitter.emit("watch-v2", chunk);
|
|
500
|
-
break;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
await emitter.emit("watch", {
|
|
809
|
+
type: "tool-call-streaming-finish",
|
|
810
|
+
...toolData ?? {}
|
|
811
|
+
});
|
|
812
|
+
} else {
|
|
813
|
+
for await (const chunk of stream) {
|
|
814
|
+
await writer.write(chunk);
|
|
501
815
|
}
|
|
502
816
|
}
|
|
817
|
+
if (abortSignal.aborted) {
|
|
818
|
+
return abort();
|
|
819
|
+
}
|
|
503
820
|
return {
|
|
504
821
|
text: await streamPromise.promise
|
|
505
822
|
};
|
|
506
|
-
}
|
|
823
|
+
},
|
|
824
|
+
component: params.component
|
|
507
825
|
};
|
|
508
826
|
}
|
|
509
827
|
if (isTool(params)) {
|
|
@@ -512,17 +830,40 @@ function createStep(params) {
|
|
|
512
830
|
}
|
|
513
831
|
return {
|
|
514
832
|
// TODO: tool probably should have strong id type
|
|
515
|
-
// @ts-ignore
|
|
516
833
|
id: params.id,
|
|
834
|
+
description: params.description,
|
|
517
835
|
inputSchema: params.inputSchema,
|
|
518
836
|
outputSchema: params.outputSchema,
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
837
|
+
suspendSchema: params.suspendSchema,
|
|
838
|
+
resumeSchema: params.resumeSchema,
|
|
839
|
+
execute: async ({
|
|
840
|
+
inputData,
|
|
841
|
+
mastra,
|
|
842
|
+
requestContext,
|
|
843
|
+
tracingContext,
|
|
844
|
+
suspend,
|
|
845
|
+
resumeData,
|
|
846
|
+
runId,
|
|
847
|
+
workflowId,
|
|
848
|
+
state,
|
|
849
|
+
setState
|
|
850
|
+
}) => {
|
|
851
|
+
const toolContext = {
|
|
522
852
|
mastra,
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
853
|
+
requestContext,
|
|
854
|
+
tracingContext,
|
|
855
|
+
workflow: {
|
|
856
|
+
runId,
|
|
857
|
+
resumeData,
|
|
858
|
+
suspend,
|
|
859
|
+
workflowId,
|
|
860
|
+
state,
|
|
861
|
+
setState
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
return params.execute(inputData, toolContext);
|
|
865
|
+
},
|
|
866
|
+
component: "TOOL"
|
|
526
867
|
};
|
|
527
868
|
}
|
|
528
869
|
return {
|
|
@@ -538,7 +879,10 @@ function createStep(params) {
|
|
|
538
879
|
function init(inngest) {
|
|
539
880
|
return {
|
|
540
881
|
createWorkflow(params) {
|
|
541
|
-
return new InngestWorkflow(
|
|
882
|
+
return new InngestWorkflow(
|
|
883
|
+
params,
|
|
884
|
+
inngest
|
|
885
|
+
);
|
|
542
886
|
},
|
|
543
887
|
createStep,
|
|
544
888
|
cloneStep(step, opts) {
|
|
@@ -547,7 +891,13 @@ function init(inngest) {
|
|
|
547
891
|
description: step.description,
|
|
548
892
|
inputSchema: step.inputSchema,
|
|
549
893
|
outputSchema: step.outputSchema,
|
|
550
|
-
|
|
894
|
+
resumeSchema: step.resumeSchema,
|
|
895
|
+
suspendSchema: step.suspendSchema,
|
|
896
|
+
stateSchema: step.stateSchema,
|
|
897
|
+
execute: step.execute,
|
|
898
|
+
retries: step.retries,
|
|
899
|
+
scorers: step.scorers,
|
|
900
|
+
component: step.component
|
|
551
901
|
};
|
|
552
902
|
},
|
|
553
903
|
cloneWorkflow(workflow, opts) {
|
|
@@ -556,7 +906,8 @@ function init(inngest) {
|
|
|
556
906
|
inputSchema: workflow.inputSchema,
|
|
557
907
|
outputSchema: workflow.outputSchema,
|
|
558
908
|
steps: workflow.stepDefs,
|
|
559
|
-
mastra: workflow.mastra
|
|
909
|
+
mastra: workflow.mastra,
|
|
910
|
+
options: workflow.options
|
|
560
911
|
});
|
|
561
912
|
wf.setStepFlow(workflow.stepGraph);
|
|
562
913
|
wf.commit();
|
|
@@ -567,107 +918,32 @@ function init(inngest) {
|
|
|
567
918
|
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
568
919
|
inngestStep;
|
|
569
920
|
inngestAttempts;
|
|
570
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
571
|
-
super({ mastra });
|
|
921
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
922
|
+
super({ mastra, options });
|
|
572
923
|
this.inngestStep = inngestStep;
|
|
573
924
|
this.inngestAttempts = inngestAttempts;
|
|
574
925
|
}
|
|
575
|
-
async
|
|
576
|
-
await params.emitter.emit("watch-v2", {
|
|
577
|
-
type: "start",
|
|
578
|
-
payload: { runId: params.runId }
|
|
579
|
-
});
|
|
580
|
-
const result = await super.execute(params);
|
|
581
|
-
await params.emitter.emit("watch-v2", {
|
|
582
|
-
type: "finish",
|
|
583
|
-
payload: { runId: params.runId }
|
|
584
|
-
});
|
|
585
|
-
return result;
|
|
586
|
-
}
|
|
587
|
-
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
926
|
+
async fmtReturnValue(emitter, stepResults, lastOutput, error) {
|
|
588
927
|
const base = {
|
|
589
928
|
status: lastOutput.status,
|
|
590
929
|
steps: stepResults
|
|
591
930
|
};
|
|
592
931
|
if (lastOutput.status === "success") {
|
|
593
|
-
await emitter.emit("watch", {
|
|
594
|
-
type: "watch",
|
|
595
|
-
payload: {
|
|
596
|
-
workflowState: {
|
|
597
|
-
status: lastOutput.status,
|
|
598
|
-
steps: stepResults,
|
|
599
|
-
result: lastOutput.output
|
|
600
|
-
}
|
|
601
|
-
},
|
|
602
|
-
eventTimestamp: Date.now()
|
|
603
|
-
});
|
|
604
932
|
base.result = lastOutput.output;
|
|
605
933
|
} else if (lastOutput.status === "failed") {
|
|
606
934
|
base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
|
|
607
|
-
await emitter.emit("watch", {
|
|
608
|
-
type: "watch",
|
|
609
|
-
payload: {
|
|
610
|
-
workflowState: {
|
|
611
|
-
status: lastOutput.status,
|
|
612
|
-
steps: stepResults,
|
|
613
|
-
result: null,
|
|
614
|
-
error: base.error
|
|
615
|
-
}
|
|
616
|
-
},
|
|
617
|
-
eventTimestamp: Date.now()
|
|
618
|
-
});
|
|
619
935
|
} else if (lastOutput.status === "suspended") {
|
|
620
|
-
await emitter.emit("watch", {
|
|
621
|
-
type: "watch",
|
|
622
|
-
payload: {
|
|
623
|
-
workflowState: {
|
|
624
|
-
status: lastOutput.status,
|
|
625
|
-
steps: stepResults,
|
|
626
|
-
result: null,
|
|
627
|
-
error: null
|
|
628
|
-
}
|
|
629
|
-
},
|
|
630
|
-
eventTimestamp: Date.now()
|
|
631
|
-
});
|
|
632
936
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
633
937
|
if (stepResult?.status === "suspended") {
|
|
634
|
-
const nestedPath = stepResult?.
|
|
938
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
635
939
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
636
940
|
}
|
|
637
941
|
return [];
|
|
638
942
|
});
|
|
639
943
|
base.suspended = suspendedStepIds;
|
|
640
944
|
}
|
|
641
|
-
executionSpan?.end();
|
|
642
945
|
return base;
|
|
643
946
|
}
|
|
644
|
-
async superExecuteStep({
|
|
645
|
-
workflowId,
|
|
646
|
-
runId,
|
|
647
|
-
step,
|
|
648
|
-
stepResults,
|
|
649
|
-
executionContext,
|
|
650
|
-
resume,
|
|
651
|
-
prevOutput,
|
|
652
|
-
emitter,
|
|
653
|
-
abortController,
|
|
654
|
-
runtimeContext,
|
|
655
|
-
writableStream
|
|
656
|
-
}) {
|
|
657
|
-
return super.executeStep({
|
|
658
|
-
workflowId,
|
|
659
|
-
runId,
|
|
660
|
-
step,
|
|
661
|
-
stepResults,
|
|
662
|
-
executionContext,
|
|
663
|
-
resume,
|
|
664
|
-
prevOutput,
|
|
665
|
-
emitter,
|
|
666
|
-
abortController,
|
|
667
|
-
runtimeContext,
|
|
668
|
-
writableStream
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
947
|
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
672
948
|
// await this.inngestStep.sleep(id, duration);
|
|
673
949
|
// }
|
|
@@ -679,55 +955,85 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
679
955
|
stepResults,
|
|
680
956
|
emitter,
|
|
681
957
|
abortController,
|
|
682
|
-
|
|
683
|
-
|
|
958
|
+
requestContext,
|
|
959
|
+
executionContext,
|
|
960
|
+
writableStream,
|
|
961
|
+
tracingContext
|
|
684
962
|
}) {
|
|
685
963
|
let { duration, fn } = entry;
|
|
964
|
+
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
965
|
+
type: observability.SpanType.WORKFLOW_SLEEP,
|
|
966
|
+
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
967
|
+
attributes: {
|
|
968
|
+
durationMs: duration,
|
|
969
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
970
|
+
},
|
|
971
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
972
|
+
});
|
|
686
973
|
if (fn) {
|
|
687
974
|
const stepCallId = crypto.randomUUID();
|
|
688
975
|
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
689
|
-
return await fn(
|
|
690
|
-
|
|
691
|
-
workflowId,
|
|
692
|
-
mastra: this.mastra,
|
|
693
|
-
runtimeContext,
|
|
694
|
-
inputData: prevOutput,
|
|
695
|
-
runCount: -1,
|
|
696
|
-
getInitData: () => stepResults?.input,
|
|
697
|
-
getStepResult: (step) => {
|
|
698
|
-
if (!step?.id) {
|
|
699
|
-
return null;
|
|
700
|
-
}
|
|
701
|
-
const result = stepResults[step.id];
|
|
702
|
-
if (result?.status === "success") {
|
|
703
|
-
return result.output;
|
|
704
|
-
}
|
|
705
|
-
return null;
|
|
706
|
-
},
|
|
707
|
-
// TODO: this function shouldn't have suspend probably?
|
|
708
|
-
suspend: async (_suspendPayload) => {
|
|
709
|
-
},
|
|
710
|
-
bail: () => {
|
|
711
|
-
},
|
|
712
|
-
abort: () => {
|
|
713
|
-
abortController?.abort();
|
|
714
|
-
},
|
|
715
|
-
[_constants.EMITTER_SYMBOL]: emitter,
|
|
716
|
-
engine: { step: this.inngestStep },
|
|
717
|
-
abortSignal: abortController?.signal,
|
|
718
|
-
writer: new tools.ToolStream(
|
|
976
|
+
return await fn(
|
|
977
|
+
workflows.createDeprecationProxy(
|
|
719
978
|
{
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
979
|
+
runId,
|
|
980
|
+
workflowId,
|
|
981
|
+
mastra: this.mastra,
|
|
982
|
+
requestContext,
|
|
983
|
+
inputData: prevOutput,
|
|
984
|
+
state: executionContext.state,
|
|
985
|
+
setState: (state) => {
|
|
986
|
+
executionContext.state = state;
|
|
987
|
+
},
|
|
988
|
+
retryCount: -1,
|
|
989
|
+
tracingContext: {
|
|
990
|
+
currentSpan: sleepSpan
|
|
991
|
+
},
|
|
992
|
+
getInitData: () => stepResults?.input,
|
|
993
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
994
|
+
// TODO: this function shouldn't have suspend probably?
|
|
995
|
+
suspend: async (_suspendPayload) => {
|
|
996
|
+
},
|
|
997
|
+
bail: () => {
|
|
998
|
+
},
|
|
999
|
+
abort: () => {
|
|
1000
|
+
abortController?.abort();
|
|
1001
|
+
},
|
|
1002
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1003
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1004
|
+
engine: { step: this.inngestStep },
|
|
1005
|
+
abortSignal: abortController?.signal,
|
|
1006
|
+
writer: new tools.ToolStream(
|
|
1007
|
+
{
|
|
1008
|
+
prefix: "workflow-step",
|
|
1009
|
+
callId: stepCallId,
|
|
1010
|
+
name: "sleep",
|
|
1011
|
+
runId
|
|
1012
|
+
},
|
|
1013
|
+
writableStream
|
|
1014
|
+
)
|
|
724
1015
|
},
|
|
725
|
-
|
|
1016
|
+
{
|
|
1017
|
+
paramName: "runCount",
|
|
1018
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
1019
|
+
logger: this.logger
|
|
1020
|
+
}
|
|
726
1021
|
)
|
|
727
|
-
|
|
1022
|
+
);
|
|
1023
|
+
});
|
|
1024
|
+
sleepSpan?.update({
|
|
1025
|
+
attributes: {
|
|
1026
|
+
durationMs: duration
|
|
1027
|
+
}
|
|
728
1028
|
});
|
|
729
1029
|
}
|
|
730
|
-
|
|
1030
|
+
try {
|
|
1031
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
1032
|
+
sleepSpan?.end();
|
|
1033
|
+
} catch (e) {
|
|
1034
|
+
sleepSpan?.error({ error: e });
|
|
1035
|
+
throw e;
|
|
1036
|
+
}
|
|
731
1037
|
}
|
|
732
1038
|
async executeSleepUntil({
|
|
733
1039
|
workflowId,
|
|
@@ -737,111 +1043,133 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
737
1043
|
stepResults,
|
|
738
1044
|
emitter,
|
|
739
1045
|
abortController,
|
|
740
|
-
|
|
741
|
-
|
|
1046
|
+
requestContext,
|
|
1047
|
+
executionContext,
|
|
1048
|
+
writableStream,
|
|
1049
|
+
tracingContext
|
|
742
1050
|
}) {
|
|
743
1051
|
let { date, fn } = entry;
|
|
1052
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1053
|
+
type: observability.SpanType.WORKFLOW_SLEEP,
|
|
1054
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
1055
|
+
attributes: {
|
|
1056
|
+
untilDate: date,
|
|
1057
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
1058
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
1059
|
+
},
|
|
1060
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1061
|
+
});
|
|
744
1062
|
if (fn) {
|
|
745
1063
|
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
746
1064
|
const stepCallId = crypto.randomUUID();
|
|
747
|
-
return await fn(
|
|
748
|
-
|
|
749
|
-
workflowId,
|
|
750
|
-
mastra: this.mastra,
|
|
751
|
-
runtimeContext,
|
|
752
|
-
inputData: prevOutput,
|
|
753
|
-
runCount: -1,
|
|
754
|
-
getInitData: () => stepResults?.input,
|
|
755
|
-
getStepResult: (step) => {
|
|
756
|
-
if (!step?.id) {
|
|
757
|
-
return null;
|
|
758
|
-
}
|
|
759
|
-
const result = stepResults[step.id];
|
|
760
|
-
if (result?.status === "success") {
|
|
761
|
-
return result.output;
|
|
762
|
-
}
|
|
763
|
-
return null;
|
|
764
|
-
},
|
|
765
|
-
// TODO: this function shouldn't have suspend probably?
|
|
766
|
-
suspend: async (_suspendPayload) => {
|
|
767
|
-
},
|
|
768
|
-
bail: () => {
|
|
769
|
-
},
|
|
770
|
-
abort: () => {
|
|
771
|
-
abortController?.abort();
|
|
772
|
-
},
|
|
773
|
-
[_constants.EMITTER_SYMBOL]: emitter,
|
|
774
|
-
engine: { step: this.inngestStep },
|
|
775
|
-
abortSignal: abortController?.signal,
|
|
776
|
-
writer: new tools.ToolStream(
|
|
1065
|
+
return await fn(
|
|
1066
|
+
workflows.createDeprecationProxy(
|
|
777
1067
|
{
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
1068
|
+
runId,
|
|
1069
|
+
workflowId,
|
|
1070
|
+
mastra: this.mastra,
|
|
1071
|
+
requestContext,
|
|
1072
|
+
inputData: prevOutput,
|
|
1073
|
+
state: executionContext.state,
|
|
1074
|
+
setState: (state) => {
|
|
1075
|
+
executionContext.state = state;
|
|
1076
|
+
},
|
|
1077
|
+
retryCount: -1,
|
|
1078
|
+
tracingContext: {
|
|
1079
|
+
currentSpan: sleepUntilSpan
|
|
1080
|
+
},
|
|
1081
|
+
getInitData: () => stepResults?.input,
|
|
1082
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1083
|
+
// TODO: this function shouldn't have suspend probably?
|
|
1084
|
+
suspend: async (_suspendPayload) => {
|
|
1085
|
+
},
|
|
1086
|
+
bail: () => {
|
|
1087
|
+
},
|
|
1088
|
+
abort: () => {
|
|
1089
|
+
abortController?.abort();
|
|
1090
|
+
},
|
|
1091
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1092
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1093
|
+
engine: { step: this.inngestStep },
|
|
1094
|
+
abortSignal: abortController?.signal,
|
|
1095
|
+
writer: new tools.ToolStream(
|
|
1096
|
+
{
|
|
1097
|
+
prefix: "workflow-step",
|
|
1098
|
+
callId: stepCallId,
|
|
1099
|
+
name: "sleep",
|
|
1100
|
+
runId
|
|
1101
|
+
},
|
|
1102
|
+
writableStream
|
|
1103
|
+
)
|
|
782
1104
|
},
|
|
783
|
-
|
|
1105
|
+
{
|
|
1106
|
+
paramName: "runCount",
|
|
1107
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
1108
|
+
logger: this.logger
|
|
1109
|
+
}
|
|
784
1110
|
)
|
|
785
|
-
|
|
1111
|
+
);
|
|
1112
|
+
});
|
|
1113
|
+
if (date && !(date instanceof Date)) {
|
|
1114
|
+
date = new Date(date);
|
|
1115
|
+
}
|
|
1116
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
1117
|
+
sleepUntilSpan?.update({
|
|
1118
|
+
attributes: {
|
|
1119
|
+
durationMs: Math.max(0, time)
|
|
1120
|
+
}
|
|
786
1121
|
});
|
|
787
1122
|
}
|
|
788
1123
|
if (!(date instanceof Date)) {
|
|
1124
|
+
sleepUntilSpan?.end();
|
|
789
1125
|
return;
|
|
790
1126
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
});
|
|
798
|
-
if (eventData === null) {
|
|
799
|
-
throw "Timeout waiting for event";
|
|
1127
|
+
try {
|
|
1128
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
1129
|
+
sleepUntilSpan?.end();
|
|
1130
|
+
} catch (e) {
|
|
1131
|
+
sleepUntilSpan?.error({ error: e });
|
|
1132
|
+
throw e;
|
|
800
1133
|
}
|
|
801
|
-
return eventData?.data;
|
|
802
1134
|
}
|
|
803
1135
|
async executeStep({
|
|
804
1136
|
step,
|
|
805
1137
|
stepResults,
|
|
806
1138
|
executionContext,
|
|
807
1139
|
resume,
|
|
1140
|
+
timeTravel,
|
|
808
1141
|
prevOutput,
|
|
809
1142
|
emitter,
|
|
810
1143
|
abortController,
|
|
811
|
-
|
|
812
|
-
|
|
1144
|
+
requestContext,
|
|
1145
|
+
tracingContext,
|
|
1146
|
+
writableStream,
|
|
1147
|
+
disableScorers
|
|
813
1148
|
}) {
|
|
1149
|
+
const stepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1150
|
+
name: `workflow step: '${step.id}'`,
|
|
1151
|
+
type: observability.SpanType.WORKFLOW_STEP,
|
|
1152
|
+
input: prevOutput,
|
|
1153
|
+
attributes: {
|
|
1154
|
+
stepId: step.id
|
|
1155
|
+
},
|
|
1156
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1157
|
+
});
|
|
1158
|
+
const { inputData, validationError } = await workflows.validateStepInput({
|
|
1159
|
+
prevOutput,
|
|
1160
|
+
step,
|
|
1161
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
1162
|
+
});
|
|
814
1163
|
const startedAt = await this.inngestStep.run(
|
|
815
1164
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
816
1165
|
async () => {
|
|
817
1166
|
const startedAt2 = Date.now();
|
|
818
1167
|
await emitter.emit("watch", {
|
|
819
|
-
type: "
|
|
820
|
-
payload: {
|
|
821
|
-
currentStep: {
|
|
822
|
-
id: step.id,
|
|
823
|
-
status: "running"
|
|
824
|
-
},
|
|
825
|
-
workflowState: {
|
|
826
|
-
status: "running",
|
|
827
|
-
steps: {
|
|
828
|
-
...stepResults,
|
|
829
|
-
[step.id]: {
|
|
830
|
-
status: "running"
|
|
831
|
-
}
|
|
832
|
-
},
|
|
833
|
-
result: null,
|
|
834
|
-
error: null
|
|
835
|
-
}
|
|
836
|
-
},
|
|
837
|
-
eventTimestamp: Date.now()
|
|
838
|
-
});
|
|
839
|
-
await emitter.emit("watch-v2", {
|
|
840
|
-
type: "step-start",
|
|
1168
|
+
type: "workflow-step-start",
|
|
841
1169
|
payload: {
|
|
842
1170
|
id: step.id,
|
|
843
1171
|
status: "running",
|
|
844
|
-
payload:
|
|
1172
|
+
payload: inputData,
|
|
845
1173
|
startedAt: startedAt2
|
|
846
1174
|
}
|
|
847
1175
|
});
|
|
@@ -852,62 +1180,93 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
852
1180
|
const isResume = !!resume?.steps?.length;
|
|
853
1181
|
let result;
|
|
854
1182
|
let runId;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1183
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
1184
|
+
try {
|
|
1185
|
+
if (isResume) {
|
|
1186
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1187
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1188
|
+
workflowName: step.id,
|
|
1189
|
+
runId
|
|
1190
|
+
});
|
|
1191
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1192
|
+
function: step.getFunction(),
|
|
1193
|
+
data: {
|
|
1194
|
+
inputData,
|
|
1195
|
+
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
867
1196
|
runId,
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1197
|
+
resume: {
|
|
1198
|
+
runId,
|
|
1199
|
+
steps: resume.steps.slice(1),
|
|
1200
|
+
stepResults: snapshot?.context,
|
|
1201
|
+
resumePayload: resume.resumePayload,
|
|
1202
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1203
|
+
},
|
|
1204
|
+
outputOptions: { includeState: true }
|
|
873
1205
|
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
1206
|
+
});
|
|
1207
|
+
result = invokeResp.result;
|
|
1208
|
+
runId = invokeResp.runId;
|
|
1209
|
+
executionContext.state = invokeResp.result.state;
|
|
1210
|
+
} else if (isTimeTravel) {
|
|
1211
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1212
|
+
workflowName: step.id,
|
|
1213
|
+
runId: executionContext.runId
|
|
1214
|
+
}) ?? { context: {} };
|
|
1215
|
+
const timeTravelParams = workflows.createTimeTravelExecutionParams({
|
|
1216
|
+
steps: timeTravel.steps.slice(1),
|
|
1217
|
+
inputData: timeTravel.inputData,
|
|
1218
|
+
resumeData: timeTravel.resumeData,
|
|
1219
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1220
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1221
|
+
snapshot,
|
|
1222
|
+
graph: step.buildExecutionGraph()
|
|
1223
|
+
});
|
|
1224
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1225
|
+
function: step.getFunction(),
|
|
1226
|
+
data: {
|
|
1227
|
+
timeTravel: timeTravelParams,
|
|
1228
|
+
initialState: executionContext.state ?? {},
|
|
1229
|
+
runId: executionContext.runId,
|
|
1230
|
+
outputOptions: { includeState: true }
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
result = invokeResp.result;
|
|
1234
|
+
runId = invokeResp.runId;
|
|
1235
|
+
executionContext.state = invokeResp.result.state;
|
|
1236
|
+
} else {
|
|
1237
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1238
|
+
function: step.getFunction(),
|
|
1239
|
+
data: {
|
|
1240
|
+
inputData,
|
|
1241
|
+
initialState: executionContext.state ?? {},
|
|
1242
|
+
outputOptions: { includeState: true }
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
result = invokeResp.result;
|
|
1246
|
+
runId = invokeResp.runId;
|
|
1247
|
+
executionContext.state = invokeResp.result.state;
|
|
1248
|
+
}
|
|
1249
|
+
} catch (e) {
|
|
1250
|
+
const errorCause = e?.cause;
|
|
1251
|
+
if (errorCause && typeof errorCause === "object") {
|
|
1252
|
+
result = errorCause;
|
|
1253
|
+
runId = errorCause.runId || crypto.randomUUID();
|
|
1254
|
+
} else {
|
|
1255
|
+
runId = crypto.randomUUID();
|
|
1256
|
+
result = {
|
|
1257
|
+
status: "failed",
|
|
1258
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1259
|
+
steps: {},
|
|
1260
|
+
input: inputData
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
887
1263
|
}
|
|
888
1264
|
const res = await this.inngestStep.run(
|
|
889
1265
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
890
1266
|
async () => {
|
|
891
1267
|
if (result.status === "failed") {
|
|
892
1268
|
await emitter.emit("watch", {
|
|
893
|
-
type: "
|
|
894
|
-
payload: {
|
|
895
|
-
currentStep: {
|
|
896
|
-
id: step.id,
|
|
897
|
-
status: "failed",
|
|
898
|
-
error: result?.error
|
|
899
|
-
},
|
|
900
|
-
workflowState: {
|
|
901
|
-
status: "running",
|
|
902
|
-
steps: stepResults,
|
|
903
|
-
result: null,
|
|
904
|
-
error: null
|
|
905
|
-
}
|
|
906
|
-
},
|
|
907
|
-
eventTimestamp: Date.now()
|
|
908
|
-
});
|
|
909
|
-
await emitter.emit("watch-v2", {
|
|
910
|
-
type: "step-result",
|
|
1269
|
+
type: "workflow-step-result",
|
|
911
1270
|
payload: {
|
|
912
1271
|
id: step.id,
|
|
913
1272
|
status: "failed",
|
|
@@ -922,27 +1281,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
922
1281
|
return stepRes2?.status === "suspended";
|
|
923
1282
|
});
|
|
924
1283
|
for (const [stepName, stepResult] of suspendedSteps) {
|
|
925
|
-
const suspendPath = [stepName, ...stepResult?.
|
|
1284
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
926
1285
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
927
1286
|
await emitter.emit("watch", {
|
|
928
|
-
type: "
|
|
929
|
-
payload: {
|
|
930
|
-
currentStep: {
|
|
931
|
-
id: step.id,
|
|
932
|
-
status: "suspended",
|
|
933
|
-
payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
|
|
934
|
-
},
|
|
935
|
-
workflowState: {
|
|
936
|
-
status: "running",
|
|
937
|
-
steps: stepResults,
|
|
938
|
-
result: null,
|
|
939
|
-
error: null
|
|
940
|
-
}
|
|
941
|
-
},
|
|
942
|
-
eventTimestamp: Date.now()
|
|
943
|
-
});
|
|
944
|
-
await emitter.emit("watch-v2", {
|
|
945
|
-
type: "step-suspended",
|
|
1287
|
+
type: "workflow-step-suspended",
|
|
946
1288
|
payload: {
|
|
947
1289
|
id: step.id,
|
|
948
1290
|
status: "suspended"
|
|
@@ -952,27 +1294,14 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
952
1294
|
executionContext,
|
|
953
1295
|
result: {
|
|
954
1296
|
status: "suspended",
|
|
955
|
-
payload:
|
|
1297
|
+
payload: stepResult.payload,
|
|
1298
|
+
suspendPayload: {
|
|
1299
|
+
...stepResult?.suspendPayload,
|
|
1300
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1301
|
+
}
|
|
956
1302
|
}
|
|
957
1303
|
};
|
|
958
1304
|
}
|
|
959
|
-
await emitter.emit("watch", {
|
|
960
|
-
type: "watch",
|
|
961
|
-
payload: {
|
|
962
|
-
currentStep: {
|
|
963
|
-
id: step.id,
|
|
964
|
-
status: "suspended",
|
|
965
|
-
payload: {}
|
|
966
|
-
},
|
|
967
|
-
workflowState: {
|
|
968
|
-
status: "running",
|
|
969
|
-
steps: stepResults,
|
|
970
|
-
result: null,
|
|
971
|
-
error: null
|
|
972
|
-
}
|
|
973
|
-
},
|
|
974
|
-
eventTimestamp: Date.now()
|
|
975
|
-
});
|
|
976
1305
|
return {
|
|
977
1306
|
executionContext,
|
|
978
1307
|
result: {
|
|
@@ -982,32 +1311,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
982
1311
|
};
|
|
983
1312
|
}
|
|
984
1313
|
await emitter.emit("watch", {
|
|
985
|
-
type: "
|
|
986
|
-
payload: {
|
|
987
|
-
currentStep: {
|
|
988
|
-
id: step.id,
|
|
989
|
-
status: "success",
|
|
990
|
-
output: result?.result
|
|
991
|
-
},
|
|
992
|
-
workflowState: {
|
|
993
|
-
status: "running",
|
|
994
|
-
steps: stepResults,
|
|
995
|
-
result: null,
|
|
996
|
-
error: null
|
|
997
|
-
}
|
|
998
|
-
},
|
|
999
|
-
eventTimestamp: Date.now()
|
|
1000
|
-
});
|
|
1001
|
-
await emitter.emit("watch-v2", {
|
|
1002
|
-
type: "step-result",
|
|
1314
|
+
type: "workflow-step-result",
|
|
1003
1315
|
payload: {
|
|
1004
1316
|
id: step.id,
|
|
1005
1317
|
status: "success",
|
|
1006
1318
|
output: result?.result
|
|
1007
1319
|
}
|
|
1008
1320
|
});
|
|
1009
|
-
await emitter.emit("watch
|
|
1010
|
-
type: "step-finish",
|
|
1321
|
+
await emitter.emit("watch", {
|
|
1322
|
+
type: "workflow-step-finish",
|
|
1011
1323
|
payload: {
|
|
1012
1324
|
id: step.id,
|
|
1013
1325
|
metadata: {}
|
|
@@ -1017,136 +1329,232 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1017
1329
|
}
|
|
1018
1330
|
);
|
|
1019
1331
|
Object.assign(executionContext, res.executionContext);
|
|
1020
|
-
return
|
|
1332
|
+
return {
|
|
1333
|
+
...res.result,
|
|
1334
|
+
startedAt,
|
|
1335
|
+
endedAt: Date.now(),
|
|
1336
|
+
payload: inputData,
|
|
1337
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1338
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1339
|
+
};
|
|
1021
1340
|
}
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
inputData: prevOutput,
|
|
1033
|
-
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1034
|
-
getInitData: () => stepResults?.input,
|
|
1035
|
-
getStepResult: (step2) => {
|
|
1036
|
-
const result2 = stepResults[step2.id];
|
|
1037
|
-
if (result2?.status === "success") {
|
|
1038
|
-
return result2.output;
|
|
1039
|
-
}
|
|
1040
|
-
return null;
|
|
1041
|
-
},
|
|
1042
|
-
suspend: async (suspendPayload) => {
|
|
1043
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1044
|
-
suspended = { payload: suspendPayload };
|
|
1045
|
-
},
|
|
1046
|
-
bail: (result2) => {
|
|
1047
|
-
bailed = { payload: result2 };
|
|
1048
|
-
},
|
|
1049
|
-
resume: {
|
|
1050
|
-
steps: resume?.steps?.slice(1) || [],
|
|
1051
|
-
resumePayload: resume?.resumePayload,
|
|
1052
|
-
// @ts-ignore
|
|
1053
|
-
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
1054
|
-
},
|
|
1055
|
-
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1056
|
-
engine: {
|
|
1057
|
-
step: this.inngestStep
|
|
1058
|
-
},
|
|
1059
|
-
abortSignal: abortController.signal
|
|
1341
|
+
const stepCallId = crypto.randomUUID();
|
|
1342
|
+
let stepRes;
|
|
1343
|
+
try {
|
|
1344
|
+
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1345
|
+
let execResults;
|
|
1346
|
+
let suspended;
|
|
1347
|
+
let bailed;
|
|
1348
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
|
|
1349
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1350
|
+
step
|
|
1060
1351
|
});
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
} catch (e) {
|
|
1072
|
-
execResults = {
|
|
1073
|
-
status: "failed",
|
|
1074
|
-
payload: prevOutput,
|
|
1075
|
-
error: e instanceof Error ? e.message : String(e),
|
|
1076
|
-
endedAt: Date.now(),
|
|
1077
|
-
startedAt,
|
|
1078
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1079
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1080
|
-
};
|
|
1081
|
-
}
|
|
1082
|
-
if (suspended) {
|
|
1083
|
-
execResults = {
|
|
1084
|
-
status: "suspended",
|
|
1085
|
-
suspendedPayload: suspended.payload,
|
|
1086
|
-
payload: prevOutput,
|
|
1087
|
-
suspendedAt: Date.now(),
|
|
1088
|
-
startedAt,
|
|
1089
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1090
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1091
|
-
};
|
|
1092
|
-
} else if (bailed) {
|
|
1093
|
-
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
1094
|
-
}
|
|
1095
|
-
if (execResults.status === "failed") {
|
|
1096
|
-
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
1097
|
-
throw execResults.error;
|
|
1352
|
+
let resumeDataToUse;
|
|
1353
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1354
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1355
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1356
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1357
|
+
stepId: step.id,
|
|
1358
|
+
error: timeTravelResumeValidationError.message
|
|
1359
|
+
});
|
|
1360
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1361
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1098
1362
|
}
|
|
1099
|
-
|
|
1363
|
+
try {
|
|
1364
|
+
if (validationError) {
|
|
1365
|
+
throw validationError;
|
|
1366
|
+
}
|
|
1367
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1368
|
+
const result = await step.execute({
|
|
1369
|
+
runId: executionContext.runId,
|
|
1370
|
+
workflowId: executionContext.workflowId,
|
|
1371
|
+
mastra: this.mastra,
|
|
1372
|
+
requestContext,
|
|
1373
|
+
retryCount,
|
|
1374
|
+
writer: new tools.ToolStream(
|
|
1375
|
+
{
|
|
1376
|
+
prefix: "workflow-step",
|
|
1377
|
+
callId: stepCallId,
|
|
1378
|
+
name: step.id,
|
|
1379
|
+
runId: executionContext.runId
|
|
1380
|
+
},
|
|
1381
|
+
writableStream
|
|
1382
|
+
),
|
|
1383
|
+
state: executionContext?.state ?? {},
|
|
1384
|
+
setState: (state) => {
|
|
1385
|
+
executionContext.state = state;
|
|
1386
|
+
},
|
|
1387
|
+
inputData,
|
|
1388
|
+
resumeData: resumeDataToUse,
|
|
1389
|
+
tracingContext: {
|
|
1390
|
+
currentSpan: stepSpan
|
|
1391
|
+
},
|
|
1392
|
+
getInitData: () => stepResults?.input,
|
|
1393
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1394
|
+
suspend: async (suspendPayload, suspendOptions) => {
|
|
1395
|
+
const { suspendData, validationError: validationError2 } = await workflows.validateStepSuspendData({
|
|
1396
|
+
suspendData: suspendPayload,
|
|
1397
|
+
step
|
|
1398
|
+
});
|
|
1399
|
+
if (validationError2) {
|
|
1400
|
+
throw validationError2;
|
|
1401
|
+
}
|
|
1402
|
+
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1403
|
+
if (suspendOptions?.resumeLabel) {
|
|
1404
|
+
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
1405
|
+
for (const label of resumeLabel) {
|
|
1406
|
+
executionContext.resumeLabels[label] = {
|
|
1407
|
+
stepId: step.id,
|
|
1408
|
+
foreachIndex: executionContext.foreachIndex
|
|
1409
|
+
};
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
suspended = { payload: suspendData };
|
|
1413
|
+
},
|
|
1414
|
+
bail: (result2) => {
|
|
1415
|
+
bailed = { payload: result2 };
|
|
1416
|
+
},
|
|
1417
|
+
abort: () => {
|
|
1418
|
+
abortController?.abort();
|
|
1419
|
+
},
|
|
1420
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1421
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1422
|
+
engine: {
|
|
1423
|
+
step: this.inngestStep
|
|
1424
|
+
},
|
|
1425
|
+
abortSignal: abortController.signal
|
|
1426
|
+
});
|
|
1427
|
+
const endedAt = Date.now();
|
|
1428
|
+
execResults = {
|
|
1429
|
+
status: "success",
|
|
1430
|
+
output: result,
|
|
1431
|
+
startedAt,
|
|
1432
|
+
endedAt,
|
|
1433
|
+
payload: inputData,
|
|
1434
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1435
|
+
resumePayload: resumeDataToUse
|
|
1436
|
+
};
|
|
1437
|
+
} catch (e) {
|
|
1438
|
+
const stepFailure = {
|
|
1439
|
+
status: "failed",
|
|
1440
|
+
payload: inputData,
|
|
1441
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1442
|
+
endedAt: Date.now(),
|
|
1443
|
+
startedAt,
|
|
1444
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1445
|
+
resumePayload: resumeDataToUse
|
|
1446
|
+
};
|
|
1447
|
+
execResults = stepFailure;
|
|
1448
|
+
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1449
|
+
stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1450
|
+
throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1451
|
+
cause: execResults
|
|
1452
|
+
});
|
|
1453
|
+
}
|
|
1454
|
+
if (suspended) {
|
|
1455
|
+
execResults = {
|
|
1456
|
+
status: "suspended",
|
|
1457
|
+
suspendPayload: suspended.payload,
|
|
1458
|
+
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1459
|
+
payload: inputData,
|
|
1460
|
+
suspendedAt: Date.now(),
|
|
1461
|
+
startedAt,
|
|
1462
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1463
|
+
resumePayload: resumeDataToUse
|
|
1464
|
+
};
|
|
1465
|
+
} else if (bailed) {
|
|
1466
|
+
execResults = {
|
|
1467
|
+
status: "bailed",
|
|
1468
|
+
output: bailed.payload,
|
|
1469
|
+
payload: inputData,
|
|
1470
|
+
endedAt: Date.now(),
|
|
1471
|
+
startedAt
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
if (execResults.status === "suspended") {
|
|
1475
|
+
await emitter.emit("watch", {
|
|
1476
|
+
type: "workflow-step-suspended",
|
|
1477
|
+
payload: {
|
|
1478
|
+
id: step.id,
|
|
1479
|
+
...execResults
|
|
1480
|
+
}
|
|
1481
|
+
});
|
|
1482
|
+
} else {
|
|
1483
|
+
await emitter.emit("watch", {
|
|
1484
|
+
type: "workflow-step-result",
|
|
1485
|
+
payload: {
|
|
1486
|
+
id: step.id,
|
|
1487
|
+
...execResults
|
|
1488
|
+
}
|
|
1489
|
+
});
|
|
1490
|
+
await emitter.emit("watch", {
|
|
1491
|
+
type: "workflow-step-finish",
|
|
1492
|
+
payload: {
|
|
1493
|
+
id: step.id,
|
|
1494
|
+
metadata: {}
|
|
1495
|
+
}
|
|
1496
|
+
});
|
|
1497
|
+
}
|
|
1498
|
+
stepSpan?.end({ output: execResults });
|
|
1499
|
+
return { result: execResults, executionContext, stepResults };
|
|
1500
|
+
});
|
|
1501
|
+
} catch (e) {
|
|
1502
|
+
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1503
|
+
status: "failed",
|
|
1504
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1505
|
+
payload: inputData,
|
|
1506
|
+
startedAt,
|
|
1507
|
+
endedAt: Date.now()
|
|
1508
|
+
};
|
|
1100
1509
|
await emitter.emit("watch", {
|
|
1101
|
-
type: "
|
|
1510
|
+
type: "workflow-step-result",
|
|
1102
1511
|
payload: {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
},
|
|
1107
|
-
workflowState: {
|
|
1108
|
-
status: "running",
|
|
1109
|
-
steps: { ...stepResults, [step.id]: execResults },
|
|
1110
|
-
result: null,
|
|
1111
|
-
error: null
|
|
1112
|
-
}
|
|
1113
|
-
},
|
|
1114
|
-
eventTimestamp: Date.now()
|
|
1512
|
+
id: step.id,
|
|
1513
|
+
...stepFailure
|
|
1514
|
+
}
|
|
1115
1515
|
});
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1516
|
+
await emitter.emit("watch", {
|
|
1517
|
+
type: "workflow-step-finish",
|
|
1518
|
+
payload: {
|
|
1519
|
+
id: step.id,
|
|
1520
|
+
metadata: {}
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1523
|
+
stepRes = {
|
|
1524
|
+
result: stepFailure,
|
|
1525
|
+
executionContext,
|
|
1526
|
+
stepResults: {
|
|
1527
|
+
...stepResults,
|
|
1528
|
+
[step.id]: stepFailure
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
}
|
|
1532
|
+
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1533
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1534
|
+
if (step.scorers) {
|
|
1535
|
+
await this.runScorers({
|
|
1536
|
+
scorers: step.scorers,
|
|
1537
|
+
runId: executionContext.runId,
|
|
1538
|
+
input: inputData,
|
|
1539
|
+
output: stepRes.result,
|
|
1540
|
+
workflowId: executionContext.workflowId,
|
|
1541
|
+
stepId: step.id,
|
|
1542
|
+
requestContext,
|
|
1543
|
+
disableScorers,
|
|
1544
|
+
tracingContext: { currentSpan: stepSpan }
|
|
1545
|
+
});
|
|
1546
|
+
}
|
|
1547
|
+
});
|
|
1548
|
+
}
|
|
1142
1549
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1143
|
-
|
|
1550
|
+
executionContext.state = stepRes.executionContext.state;
|
|
1144
1551
|
return stepRes.result;
|
|
1145
1552
|
}
|
|
1146
1553
|
async persistStepUpdate({
|
|
1147
1554
|
workflowId,
|
|
1148
1555
|
runId,
|
|
1149
1556
|
stepResults,
|
|
1557
|
+
resourceId,
|
|
1150
1558
|
executionContext,
|
|
1151
1559
|
serializedStepGraph,
|
|
1152
1560
|
workflowStatus,
|
|
@@ -1156,20 +1564,27 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1156
1564
|
await this.inngestStep.run(
|
|
1157
1565
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1158
1566
|
async () => {
|
|
1567
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1568
|
+
if (!shouldPersistSnapshot) {
|
|
1569
|
+
return;
|
|
1570
|
+
}
|
|
1159
1571
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1160
1572
|
workflowName: workflowId,
|
|
1161
1573
|
runId,
|
|
1574
|
+
resourceId,
|
|
1162
1575
|
snapshot: {
|
|
1163
1576
|
runId,
|
|
1164
|
-
|
|
1577
|
+
status: workflowStatus,
|
|
1578
|
+
value: executionContext.state,
|
|
1165
1579
|
context: stepResults,
|
|
1166
|
-
activePaths:
|
|
1580
|
+
activePaths: executionContext.executionPath,
|
|
1581
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1167
1582
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1583
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1584
|
+
waitingPaths: {},
|
|
1168
1585
|
serializedStepGraph,
|
|
1169
|
-
status: workflowStatus,
|
|
1170
1586
|
result,
|
|
1171
1587
|
error,
|
|
1172
|
-
// @ts-ignore
|
|
1173
1588
|
timestamp: Date.now()
|
|
1174
1589
|
}
|
|
1175
1590
|
});
|
|
@@ -1181,112 +1596,182 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1181
1596
|
runId,
|
|
1182
1597
|
entry,
|
|
1183
1598
|
prevOutput,
|
|
1184
|
-
prevStep,
|
|
1185
1599
|
stepResults,
|
|
1186
|
-
|
|
1600
|
+
timeTravel,
|
|
1187
1601
|
resume,
|
|
1188
1602
|
executionContext,
|
|
1189
1603
|
emitter,
|
|
1190
1604
|
abortController,
|
|
1191
|
-
|
|
1192
|
-
writableStream
|
|
1605
|
+
requestContext,
|
|
1606
|
+
writableStream,
|
|
1607
|
+
disableScorers,
|
|
1608
|
+
tracingContext
|
|
1193
1609
|
}) {
|
|
1610
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1611
|
+
type: observability.SpanType.WORKFLOW_CONDITIONAL,
|
|
1612
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1613
|
+
input: prevOutput,
|
|
1614
|
+
attributes: {
|
|
1615
|
+
conditionCount: entry.conditions.length
|
|
1616
|
+
},
|
|
1617
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1618
|
+
});
|
|
1194
1619
|
let execResults;
|
|
1195
1620
|
const truthyIndexes = (await Promise.all(
|
|
1196
1621
|
entry.conditions.map(
|
|
1197
1622
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1623
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1624
|
+
type: observability.SpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1625
|
+
name: `condition: '${index}'`,
|
|
1626
|
+
input: prevOutput,
|
|
1627
|
+
attributes: {
|
|
1628
|
+
conditionIndex: index
|
|
1629
|
+
},
|
|
1630
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1631
|
+
});
|
|
1198
1632
|
try {
|
|
1199
|
-
const result = await cond(
|
|
1200
|
-
|
|
1201
|
-
workflowId,
|
|
1202
|
-
mastra: this.mastra,
|
|
1203
|
-
runtimeContext,
|
|
1204
|
-
runCount: -1,
|
|
1205
|
-
inputData: prevOutput,
|
|
1206
|
-
getInitData: () => stepResults?.input,
|
|
1207
|
-
getStepResult: (step) => {
|
|
1208
|
-
if (!step?.id) {
|
|
1209
|
-
return null;
|
|
1210
|
-
}
|
|
1211
|
-
const result2 = stepResults[step.id];
|
|
1212
|
-
if (result2?.status === "success") {
|
|
1213
|
-
return result2.output;
|
|
1214
|
-
}
|
|
1215
|
-
return null;
|
|
1216
|
-
},
|
|
1217
|
-
// TODO: this function shouldn't have suspend probably?
|
|
1218
|
-
suspend: async (_suspendPayload) => {
|
|
1219
|
-
},
|
|
1220
|
-
bail: () => {
|
|
1221
|
-
},
|
|
1222
|
-
abort: () => {
|
|
1223
|
-
abortController.abort();
|
|
1224
|
-
},
|
|
1225
|
-
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1226
|
-
engine: {
|
|
1227
|
-
step: this.inngestStep
|
|
1228
|
-
},
|
|
1229
|
-
abortSignal: abortController.signal,
|
|
1230
|
-
writer: new tools.ToolStream(
|
|
1633
|
+
const result = await cond(
|
|
1634
|
+
workflows.createDeprecationProxy(
|
|
1231
1635
|
{
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1636
|
+
runId,
|
|
1637
|
+
workflowId,
|
|
1638
|
+
mastra: this.mastra,
|
|
1639
|
+
requestContext,
|
|
1640
|
+
retryCount: -1,
|
|
1641
|
+
inputData: prevOutput,
|
|
1642
|
+
state: executionContext.state,
|
|
1643
|
+
setState: (state) => {
|
|
1644
|
+
executionContext.state = state;
|
|
1645
|
+
},
|
|
1646
|
+
tracingContext: {
|
|
1647
|
+
currentSpan: evalSpan
|
|
1648
|
+
},
|
|
1649
|
+
getInitData: () => stepResults?.input,
|
|
1650
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1651
|
+
// TODO: this function shouldn't have suspend probably?
|
|
1652
|
+
suspend: async (_suspendPayload) => {
|
|
1653
|
+
},
|
|
1654
|
+
bail: () => {
|
|
1655
|
+
},
|
|
1656
|
+
abort: () => {
|
|
1657
|
+
abortController.abort();
|
|
1658
|
+
},
|
|
1659
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1660
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1661
|
+
engine: {
|
|
1662
|
+
step: this.inngestStep
|
|
1663
|
+
},
|
|
1664
|
+
abortSignal: abortController.signal,
|
|
1665
|
+
writer: new tools.ToolStream(
|
|
1666
|
+
{
|
|
1667
|
+
prefix: "workflow-step",
|
|
1668
|
+
callId: crypto.randomUUID(),
|
|
1669
|
+
name: "conditional",
|
|
1670
|
+
runId
|
|
1671
|
+
},
|
|
1672
|
+
writableStream
|
|
1673
|
+
)
|
|
1236
1674
|
},
|
|
1237
|
-
|
|
1675
|
+
{
|
|
1676
|
+
paramName: "runCount",
|
|
1677
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
1678
|
+
logger: this.logger
|
|
1679
|
+
}
|
|
1238
1680
|
)
|
|
1681
|
+
);
|
|
1682
|
+
evalSpan?.end({
|
|
1683
|
+
output: result,
|
|
1684
|
+
attributes: {
|
|
1685
|
+
result: !!result
|
|
1686
|
+
}
|
|
1239
1687
|
});
|
|
1240
1688
|
return result ? index : null;
|
|
1241
1689
|
} catch (e) {
|
|
1690
|
+
evalSpan?.error({
|
|
1691
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1692
|
+
attributes: {
|
|
1693
|
+
result: false
|
|
1694
|
+
}
|
|
1695
|
+
});
|
|
1242
1696
|
return null;
|
|
1243
1697
|
}
|
|
1244
1698
|
})
|
|
1245
1699
|
)
|
|
1246
1700
|
)).filter((index) => index !== null);
|
|
1247
1701
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1702
|
+
conditionalSpan?.update({
|
|
1703
|
+
attributes: {
|
|
1704
|
+
truthyIndexes,
|
|
1705
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1248
1708
|
const results = await Promise.all(
|
|
1249
|
-
stepsToRun.map(
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1709
|
+
stepsToRun.map(async (step, index) => {
|
|
1710
|
+
const currStepResult = stepResults[step.step.id];
|
|
1711
|
+
if (currStepResult && currStepResult.status === "success") {
|
|
1712
|
+
return currStepResult;
|
|
1713
|
+
}
|
|
1714
|
+
const result = await this.executeStep({
|
|
1715
|
+
step: step.step,
|
|
1716
|
+
prevOutput,
|
|
1255
1717
|
stepResults,
|
|
1256
1718
|
resume,
|
|
1257
|
-
|
|
1719
|
+
timeTravel,
|
|
1258
1720
|
executionContext: {
|
|
1259
1721
|
workflowId,
|
|
1260
1722
|
runId,
|
|
1261
1723
|
executionPath: [...executionContext.executionPath, index],
|
|
1724
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1262
1725
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1726
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1263
1727
|
retryConfig: executionContext.retryConfig,
|
|
1264
|
-
|
|
1728
|
+
state: executionContext.state
|
|
1265
1729
|
},
|
|
1266
1730
|
emitter,
|
|
1267
1731
|
abortController,
|
|
1268
|
-
|
|
1269
|
-
writableStream
|
|
1270
|
-
|
|
1271
|
-
|
|
1732
|
+
requestContext,
|
|
1733
|
+
writableStream,
|
|
1734
|
+
disableScorers,
|
|
1735
|
+
tracingContext: {
|
|
1736
|
+
currentSpan: conditionalSpan
|
|
1737
|
+
}
|
|
1738
|
+
});
|
|
1739
|
+
stepResults[step.step.id] = result;
|
|
1740
|
+
return result;
|
|
1741
|
+
})
|
|
1272
1742
|
);
|
|
1273
|
-
const hasFailed = results.find((result) => result.
|
|
1274
|
-
const hasSuspended = results.find((result) => result.
|
|
1743
|
+
const hasFailed = results.find((result) => result.status === "failed");
|
|
1744
|
+
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1275
1745
|
if (hasFailed) {
|
|
1276
|
-
execResults = { status: "failed", error: hasFailed.
|
|
1746
|
+
execResults = { status: "failed", error: hasFailed.error };
|
|
1277
1747
|
} else if (hasSuspended) {
|
|
1278
|
-
execResults = {
|
|
1748
|
+
execResults = {
|
|
1749
|
+
status: "suspended",
|
|
1750
|
+
suspendPayload: hasSuspended.suspendPayload,
|
|
1751
|
+
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1752
|
+
};
|
|
1279
1753
|
} else {
|
|
1280
1754
|
execResults = {
|
|
1281
1755
|
status: "success",
|
|
1282
1756
|
output: results.reduce((acc, result, index) => {
|
|
1283
|
-
if (result.
|
|
1284
|
-
|
|
1757
|
+
if (result.status === "success") {
|
|
1758
|
+
if ("step" in stepsToRun[index]) {
|
|
1759
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1760
|
+
}
|
|
1285
1761
|
}
|
|
1286
1762
|
return acc;
|
|
1287
1763
|
}, {})
|
|
1288
1764
|
};
|
|
1289
1765
|
}
|
|
1766
|
+
if (execResults.status === "failed") {
|
|
1767
|
+
conditionalSpan?.error({
|
|
1768
|
+
error: new Error(execResults.error)
|
|
1769
|
+
});
|
|
1770
|
+
} else {
|
|
1771
|
+
conditionalSpan?.end({
|
|
1772
|
+
output: execResults.output || execResults
|
|
1773
|
+
});
|
|
1774
|
+
}
|
|
1290
1775
|
return execResults;
|
|
1291
1776
|
}
|
|
1292
1777
|
};
|