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