@mastra/inngest 0.0.0-roamin-openaivoice-speak-options-passing-20250926163614 → 0.0.0-safe-stringify-telemetry-20251205024938
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 +323 -3
- package/dist/index.cjs +664 -217
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +112 -36
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +665 -218
- package/dist/index.js.map +1 -1
- package/package.json +20 -13
package/dist/index.cjs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
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 aiTracing = require('@mastra/core/ai-tracing');
|
|
6
7
|
var di = require('@mastra/core/di');
|
|
8
|
+
var stream = require('@mastra/core/stream');
|
|
7
9
|
var tools = require('@mastra/core/tools');
|
|
8
10
|
var workflows = require('@mastra/core/workflows');
|
|
9
11
|
var _constants = require('@mastra/core/workflows/_constants');
|
|
12
|
+
var inngest = require('inngest');
|
|
10
13
|
var hono = require('inngest/hono');
|
|
11
14
|
var zod = require('zod');
|
|
12
15
|
|
|
@@ -60,8 +63,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
60
63
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
61
64
|
runs = await this.getRuns(eventId);
|
|
62
65
|
if (runs?.[0]?.status === "Failed") {
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
67
|
+
workflowName: this.workflowId,
|
|
68
|
+
runId: this.runId
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (runs?.[0]?.status === "Cancelled") {
|
|
65
75
|
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
66
76
|
workflowName: this.workflowId,
|
|
67
77
|
runId: this.runId
|
|
@@ -95,13 +105,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
95
105
|
resourceId: this.resourceId,
|
|
96
106
|
snapshot: {
|
|
97
107
|
...snapshot,
|
|
98
|
-
status: "canceled"
|
|
108
|
+
status: "canceled",
|
|
109
|
+
value: snapshot.value
|
|
99
110
|
}
|
|
100
111
|
});
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
async start({
|
|
104
|
-
inputData
|
|
115
|
+
inputData,
|
|
116
|
+
initialState
|
|
105
117
|
}) {
|
|
106
118
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
107
119
|
workflowName: this.workflowId,
|
|
@@ -110,20 +122,24 @@ var InngestRun = class extends workflows.Run {
|
|
|
110
122
|
snapshot: {
|
|
111
123
|
runId: this.runId,
|
|
112
124
|
serializedStepGraph: this.serializedStepGraph,
|
|
125
|
+
status: "running",
|
|
113
126
|
value: {},
|
|
114
127
|
context: {},
|
|
115
128
|
activePaths: [],
|
|
116
129
|
suspendedPaths: {},
|
|
130
|
+
activeStepsPath: {},
|
|
131
|
+
resumeLabels: {},
|
|
117
132
|
waitingPaths: {},
|
|
118
|
-
timestamp: Date.now()
|
|
119
|
-
status: "running"
|
|
133
|
+
timestamp: Date.now()
|
|
120
134
|
}
|
|
121
135
|
});
|
|
122
136
|
const inputDataToUse = await this._validateInput(inputData);
|
|
137
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
123
138
|
const eventOutput = await this.inngest.send({
|
|
124
139
|
name: `workflow.${this.workflowId}`,
|
|
125
140
|
data: {
|
|
126
141
|
inputData: inputDataToUse,
|
|
142
|
+
initialState: initialStateToUse,
|
|
127
143
|
runId: this.runId,
|
|
128
144
|
resourceId: this.resourceId
|
|
129
145
|
}
|
|
@@ -154,10 +170,16 @@ var InngestRun = class extends workflows.Run {
|
|
|
154
170
|
return p;
|
|
155
171
|
}
|
|
156
172
|
async _resume(params) {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
)
|
|
160
|
-
|
|
173
|
+
const storage = this.#mastra?.getStorage();
|
|
174
|
+
let steps = [];
|
|
175
|
+
if (typeof params.step === "string") {
|
|
176
|
+
steps = params.step.split(".");
|
|
177
|
+
} else {
|
|
178
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
179
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
161
183
|
workflowName: this.workflowId,
|
|
162
184
|
runId: this.runId
|
|
163
185
|
});
|
|
@@ -167,6 +189,7 @@ var InngestRun = class extends workflows.Run {
|
|
|
167
189
|
name: `workflow.${this.workflowId}`,
|
|
168
190
|
data: {
|
|
169
191
|
inputData: resumeDataToUse,
|
|
192
|
+
initialState: snapshot?.value ?? {},
|
|
170
193
|
runId: this.runId,
|
|
171
194
|
workflowId: this.workflowId,
|
|
172
195
|
stepResults: snapshot?.context,
|
|
@@ -213,7 +236,98 @@ var InngestRun = class extends workflows.Run {
|
|
|
213
236
|
});
|
|
214
237
|
};
|
|
215
238
|
}
|
|
216
|
-
|
|
239
|
+
async timeTravel(params) {
|
|
240
|
+
const p = this._timeTravel(params).then((result) => {
|
|
241
|
+
if (result.status !== "suspended") {
|
|
242
|
+
this.closeStreamAction?.().catch(() => {
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
return result;
|
|
246
|
+
});
|
|
247
|
+
this.executionResults = p;
|
|
248
|
+
return p;
|
|
249
|
+
}
|
|
250
|
+
async _timeTravel(params) {
|
|
251
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
252
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
253
|
+
}
|
|
254
|
+
let steps = [];
|
|
255
|
+
if (typeof params.step === "string") {
|
|
256
|
+
steps = params.step.split(".");
|
|
257
|
+
} else {
|
|
258
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
259
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (steps.length === 0) {
|
|
263
|
+
throw new Error("No steps provided to timeTravel");
|
|
264
|
+
}
|
|
265
|
+
const storage = this.#mastra?.getStorage();
|
|
266
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
267
|
+
workflowName: this.workflowId,
|
|
268
|
+
runId: this.runId
|
|
269
|
+
});
|
|
270
|
+
if (!snapshot) {
|
|
271
|
+
await storage?.persistWorkflowSnapshot({
|
|
272
|
+
workflowName: this.workflowId,
|
|
273
|
+
runId: this.runId,
|
|
274
|
+
resourceId: this.resourceId,
|
|
275
|
+
snapshot: {
|
|
276
|
+
runId: this.runId,
|
|
277
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
278
|
+
status: "pending",
|
|
279
|
+
value: {},
|
|
280
|
+
context: {},
|
|
281
|
+
activePaths: [],
|
|
282
|
+
suspendedPaths: {},
|
|
283
|
+
activeStepsPath: {},
|
|
284
|
+
resumeLabels: {},
|
|
285
|
+
waitingPaths: {},
|
|
286
|
+
timestamp: Date.now()
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
if (snapshot?.status === "running") {
|
|
291
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
292
|
+
}
|
|
293
|
+
let inputDataToUse = params.inputData;
|
|
294
|
+
if (inputDataToUse && steps.length === 1) {
|
|
295
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
296
|
+
}
|
|
297
|
+
const timeTravelData = workflows.createTimeTravelExecutionParams({
|
|
298
|
+
steps,
|
|
299
|
+
inputData: inputDataToUse,
|
|
300
|
+
resumeData: params.resumeData,
|
|
301
|
+
context: params.context,
|
|
302
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
303
|
+
snapshot: snapshot ?? { context: {} },
|
|
304
|
+
graph: this.executionGraph,
|
|
305
|
+
initialState: params.initialState
|
|
306
|
+
});
|
|
307
|
+
const eventOutput = await this.inngest.send({
|
|
308
|
+
name: `workflow.${this.workflowId}`,
|
|
309
|
+
data: {
|
|
310
|
+
initialState: timeTravelData.state,
|
|
311
|
+
runId: this.runId,
|
|
312
|
+
workflowId: this.workflowId,
|
|
313
|
+
stepResults: timeTravelData.stepResults,
|
|
314
|
+
timeTravel: timeTravelData,
|
|
315
|
+
tracingOptions: params.tracingOptions,
|
|
316
|
+
outputOptions: params.outputOptions
|
|
317
|
+
}
|
|
318
|
+
});
|
|
319
|
+
const eventId = eventOutput.ids[0];
|
|
320
|
+
if (!eventId) {
|
|
321
|
+
throw new Error("Event ID is not set");
|
|
322
|
+
}
|
|
323
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
324
|
+
const result = runOutput?.output?.result;
|
|
325
|
+
if (result.status === "failed") {
|
|
326
|
+
result.error = new Error(result.error);
|
|
327
|
+
}
|
|
328
|
+
return result;
|
|
329
|
+
}
|
|
330
|
+
streamLegacy({ inputData, runtimeContext } = {}) {
|
|
217
331
|
const { readable, writable } = new TransformStream();
|
|
218
332
|
const writer = writable.getWriter();
|
|
219
333
|
const unwatch = this.watch(async (event) => {
|
|
@@ -248,6 +362,126 @@ var InngestRun = class extends workflows.Run {
|
|
|
248
362
|
getWorkflowState: () => this.executionResults
|
|
249
363
|
};
|
|
250
364
|
}
|
|
365
|
+
stream({
|
|
366
|
+
inputData,
|
|
367
|
+
runtimeContext,
|
|
368
|
+
closeOnSuspend = true
|
|
369
|
+
} = {}) {
|
|
370
|
+
const self = this;
|
|
371
|
+
let streamOutput;
|
|
372
|
+
const stream$1 = new web.ReadableStream({
|
|
373
|
+
async start(controller) {
|
|
374
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
375
|
+
controller.enqueue({
|
|
376
|
+
type,
|
|
377
|
+
runId: self.runId,
|
|
378
|
+
from,
|
|
379
|
+
payload: {
|
|
380
|
+
stepName: payload.id,
|
|
381
|
+
...payload
|
|
382
|
+
}
|
|
383
|
+
});
|
|
384
|
+
}, "watch-v2");
|
|
385
|
+
self.closeStreamAction = async () => {
|
|
386
|
+
unwatch();
|
|
387
|
+
try {
|
|
388
|
+
await controller.close();
|
|
389
|
+
} catch (err) {
|
|
390
|
+
console.error("Error closing stream:", err);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
const executionResultsPromise = self.start({
|
|
394
|
+
inputData,
|
|
395
|
+
runtimeContext
|
|
396
|
+
});
|
|
397
|
+
const executionResults = await executionResultsPromise;
|
|
398
|
+
if (closeOnSuspend) {
|
|
399
|
+
self.closeStreamAction?.().catch(() => {
|
|
400
|
+
});
|
|
401
|
+
} else if (executionResults.status !== "suspended") {
|
|
402
|
+
self.closeStreamAction?.().catch(() => {
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
if (streamOutput) {
|
|
406
|
+
streamOutput.updateResults(executionResults);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
streamOutput = new stream.WorkflowRunOutput({
|
|
411
|
+
runId: this.runId,
|
|
412
|
+
workflowId: this.workflowId,
|
|
413
|
+
stream: stream$1
|
|
414
|
+
});
|
|
415
|
+
return streamOutput;
|
|
416
|
+
}
|
|
417
|
+
timeTravelStream({
|
|
418
|
+
inputData,
|
|
419
|
+
resumeData,
|
|
420
|
+
initialState,
|
|
421
|
+
step,
|
|
422
|
+
context,
|
|
423
|
+
nestedStepsContext,
|
|
424
|
+
runtimeContext,
|
|
425
|
+
tracingOptions,
|
|
426
|
+
outputOptions
|
|
427
|
+
}) {
|
|
428
|
+
const self = this;
|
|
429
|
+
let streamOutput;
|
|
430
|
+
const stream$1 = new web.ReadableStream({
|
|
431
|
+
async start(controller) {
|
|
432
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
433
|
+
controller.enqueue({
|
|
434
|
+
type,
|
|
435
|
+
runId: self.runId,
|
|
436
|
+
from,
|
|
437
|
+
payload: {
|
|
438
|
+
stepName: payload?.id,
|
|
439
|
+
...payload
|
|
440
|
+
}
|
|
441
|
+
});
|
|
442
|
+
}, "watch-v2");
|
|
443
|
+
self.closeStreamAction = async () => {
|
|
444
|
+
unwatch();
|
|
445
|
+
try {
|
|
446
|
+
await controller.close();
|
|
447
|
+
} catch (err) {
|
|
448
|
+
console.error("Error closing stream:", err);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
const executionResultsPromise = self._timeTravel({
|
|
452
|
+
inputData,
|
|
453
|
+
step,
|
|
454
|
+
context,
|
|
455
|
+
nestedStepsContext,
|
|
456
|
+
resumeData,
|
|
457
|
+
initialState,
|
|
458
|
+
runtimeContext,
|
|
459
|
+
tracingOptions,
|
|
460
|
+
outputOptions
|
|
461
|
+
});
|
|
462
|
+
self.executionResults = executionResultsPromise;
|
|
463
|
+
let executionResults;
|
|
464
|
+
try {
|
|
465
|
+
executionResults = await executionResultsPromise;
|
|
466
|
+
self.closeStreamAction?.().catch(() => {
|
|
467
|
+
});
|
|
468
|
+
if (streamOutput) {
|
|
469
|
+
streamOutput.updateResults(executionResults);
|
|
470
|
+
}
|
|
471
|
+
} catch (err) {
|
|
472
|
+
streamOutput?.rejectResults(err);
|
|
473
|
+
self.closeStreamAction?.().catch(() => {
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
streamOutput = new stream.WorkflowRunOutput({
|
|
479
|
+
runId: this.runId,
|
|
480
|
+
workflowId: this.workflowId,
|
|
481
|
+
stream: stream$1
|
|
482
|
+
});
|
|
483
|
+
return streamOutput;
|
|
484
|
+
}
|
|
251
485
|
};
|
|
252
486
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
253
487
|
#mastra;
|
|
@@ -257,6 +491,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
257
491
|
constructor(params, inngest) {
|
|
258
492
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
259
493
|
super(workflowParams);
|
|
494
|
+
this.engineType = "inngest";
|
|
260
495
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
261
496
|
([_, value]) => value !== void 0
|
|
262
497
|
);
|
|
@@ -321,13 +556,19 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
321
556
|
mastra: this.#mastra,
|
|
322
557
|
retryConfig: this.retryConfig,
|
|
323
558
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
324
|
-
workflowSteps: this.steps
|
|
559
|
+
workflowSteps: this.steps,
|
|
560
|
+
workflowEngineType: this.engineType,
|
|
561
|
+
validateInputs: this.options.validateInputs
|
|
325
562
|
},
|
|
326
563
|
this.inngest
|
|
327
564
|
);
|
|
328
565
|
this.runs.set(runIdToUse, run);
|
|
566
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
|
|
567
|
+
workflowStatus: run.workflowRunStatus,
|
|
568
|
+
stepResults: {}
|
|
569
|
+
});
|
|
329
570
|
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
330
|
-
if (!workflowSnapshotInStorage) {
|
|
571
|
+
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
331
572
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
332
573
|
workflowName: this.id,
|
|
333
574
|
runId: runIdToUse,
|
|
@@ -338,9 +579,11 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
338
579
|
value: {},
|
|
339
580
|
context: {},
|
|
340
581
|
activePaths: [],
|
|
582
|
+
activeStepsPath: {},
|
|
341
583
|
waitingPaths: {},
|
|
342
584
|
serializedStepGraph: this.serializedStepGraph,
|
|
343
585
|
suspendedPaths: {},
|
|
586
|
+
resumeLabels: {},
|
|
344
587
|
result: void 0,
|
|
345
588
|
error: void 0,
|
|
346
589
|
// @ts-ignore
|
|
@@ -365,7 +608,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
365
608
|
},
|
|
366
609
|
{ event: `workflow.${this.id}` },
|
|
367
610
|
async ({ event, step, attempt, publish }) => {
|
|
368
|
-
let { inputData, runId, resourceId, resume } = event.data;
|
|
611
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, timeTravel } = event.data;
|
|
369
612
|
if (!runId) {
|
|
370
613
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
371
614
|
return crypto.randomUUID();
|
|
@@ -393,7 +636,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
393
636
|
once: (_event, _callback) => {
|
|
394
637
|
}
|
|
395
638
|
};
|
|
396
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
639
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
397
640
|
const result = await engine.execute({
|
|
398
641
|
workflowId: this.id,
|
|
399
642
|
runId,
|
|
@@ -401,14 +644,25 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
401
644
|
graph: this.executionGraph,
|
|
402
645
|
serializedStepGraph: this.serializedStepGraph,
|
|
403
646
|
input: inputData,
|
|
647
|
+
initialState,
|
|
404
648
|
emitter,
|
|
405
649
|
retryConfig: this.retryConfig,
|
|
406
650
|
runtimeContext: new di.RuntimeContext(),
|
|
407
651
|
// TODO
|
|
408
652
|
resume,
|
|
653
|
+
timeTravel,
|
|
409
654
|
abortController: new AbortController(),
|
|
410
|
-
currentSpan: void 0
|
|
655
|
+
currentSpan: void 0,
|
|
411
656
|
// TODO: Pass actual parent AI span from workflow execution context
|
|
657
|
+
outputOptions
|
|
658
|
+
});
|
|
659
|
+
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
660
|
+
if (result.status === "failed") {
|
|
661
|
+
throw new inngest.NonRetriableError(`Workflow failed`, {
|
|
662
|
+
cause: result
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
return result;
|
|
412
666
|
});
|
|
413
667
|
return { result, runId };
|
|
414
668
|
}
|
|
@@ -461,28 +715,55 @@ function createStep(params) {
|
|
|
461
715
|
name: params.name,
|
|
462
716
|
args: inputData
|
|
463
717
|
};
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
718
|
+
if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
|
|
719
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
720
|
+
runtimeContext,
|
|
721
|
+
tracingContext,
|
|
722
|
+
onFinish: (result) => {
|
|
723
|
+
streamPromise.resolve(result.text);
|
|
724
|
+
},
|
|
725
|
+
abortSignal
|
|
726
|
+
});
|
|
727
|
+
if (abortSignal.aborted) {
|
|
728
|
+
return abort();
|
|
729
|
+
}
|
|
730
|
+
await emitter.emit("watch-v2", {
|
|
731
|
+
type: "tool-call-streaming-start",
|
|
732
|
+
...toolData ?? {}
|
|
733
|
+
});
|
|
734
|
+
for await (const chunk of fullStream) {
|
|
735
|
+
if (chunk.type === "text-delta") {
|
|
736
|
+
await emitter.emit("watch-v2", {
|
|
737
|
+
type: "tool-call-delta",
|
|
738
|
+
...toolData ?? {},
|
|
739
|
+
argsTextDelta: chunk.payload.text
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
} else {
|
|
744
|
+
const { fullStream } = await params.streamLegacy(inputData.prompt, {
|
|
745
|
+
runtimeContext,
|
|
746
|
+
tracingContext,
|
|
747
|
+
onFinish: (result) => {
|
|
748
|
+
streamPromise.resolve(result.text);
|
|
749
|
+
},
|
|
750
|
+
abortSignal
|
|
751
|
+
});
|
|
752
|
+
if (abortSignal.aborted) {
|
|
753
|
+
return abort();
|
|
754
|
+
}
|
|
755
|
+
await emitter.emit("watch-v2", {
|
|
756
|
+
type: "tool-call-streaming-start",
|
|
757
|
+
...toolData ?? {}
|
|
758
|
+
});
|
|
759
|
+
for await (const chunk of fullStream) {
|
|
760
|
+
if (chunk.type === "text-delta") {
|
|
761
|
+
await emitter.emit("watch-v2", {
|
|
762
|
+
type: "tool-call-delta",
|
|
763
|
+
...toolData ?? {},
|
|
764
|
+
argsTextDelta: chunk.textDelta
|
|
765
|
+
});
|
|
766
|
+
}
|
|
486
767
|
}
|
|
487
768
|
}
|
|
488
769
|
await emitter.emit("watch-v2", {
|
|
@@ -533,7 +814,10 @@ function createStep(params) {
|
|
|
533
814
|
function init(inngest) {
|
|
534
815
|
return {
|
|
535
816
|
createWorkflow(params) {
|
|
536
|
-
return new InngestWorkflow(
|
|
817
|
+
return new InngestWorkflow(
|
|
818
|
+
params,
|
|
819
|
+
inngest
|
|
820
|
+
);
|
|
537
821
|
},
|
|
538
822
|
createStep,
|
|
539
823
|
cloneStep(step, opts) {
|
|
@@ -542,6 +826,9 @@ function init(inngest) {
|
|
|
542
826
|
description: step.description,
|
|
543
827
|
inputSchema: step.inputSchema,
|
|
544
828
|
outputSchema: step.outputSchema,
|
|
829
|
+
resumeSchema: step.resumeSchema,
|
|
830
|
+
suspendSchema: step.suspendSchema,
|
|
831
|
+
stateSchema: step.stateSchema,
|
|
545
832
|
execute: step.execute,
|
|
546
833
|
component: step.component
|
|
547
834
|
};
|
|
@@ -627,7 +914,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
627
914
|
});
|
|
628
915
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
629
916
|
if (stepResult?.status === "suspended") {
|
|
630
|
-
const nestedPath = stepResult?.
|
|
917
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
631
918
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
632
919
|
}
|
|
633
920
|
return [];
|
|
@@ -672,6 +959,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
672
959
|
mastra: this.mastra,
|
|
673
960
|
runtimeContext,
|
|
674
961
|
inputData: prevOutput,
|
|
962
|
+
state: executionContext.state,
|
|
963
|
+
setState: (state) => {
|
|
964
|
+
executionContext.state = state;
|
|
965
|
+
},
|
|
675
966
|
runCount: -1,
|
|
676
967
|
tracingContext: {
|
|
677
968
|
currentSpan: sleepSpan
|
|
@@ -749,6 +1040,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
749
1040
|
mastra: this.mastra,
|
|
750
1041
|
runtimeContext,
|
|
751
1042
|
inputData: prevOutput,
|
|
1043
|
+
state: executionContext.state,
|
|
1044
|
+
setState: (state) => {
|
|
1045
|
+
executionContext.state = state;
|
|
1046
|
+
},
|
|
752
1047
|
runCount: -1,
|
|
753
1048
|
tracingContext: {
|
|
754
1049
|
currentSpan: sleepUntilSpan
|
|
@@ -816,6 +1111,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
816
1111
|
stepResults,
|
|
817
1112
|
executionContext,
|
|
818
1113
|
resume,
|
|
1114
|
+
timeTravel,
|
|
819
1115
|
prevOutput,
|
|
820
1116
|
emitter,
|
|
821
1117
|
abortController,
|
|
@@ -879,38 +1175,87 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
879
1175
|
const isResume = !!resume?.steps?.length;
|
|
880
1176
|
let result;
|
|
881
1177
|
let runId;
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1178
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
1179
|
+
try {
|
|
1180
|
+
if (isResume) {
|
|
1181
|
+
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1182
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1183
|
+
workflowName: step.id,
|
|
1184
|
+
runId
|
|
1185
|
+
});
|
|
1186
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1187
|
+
function: step.getFunction(),
|
|
1188
|
+
data: {
|
|
1189
|
+
inputData,
|
|
1190
|
+
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
894
1191
|
runId,
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
1192
|
+
resume: {
|
|
1193
|
+
runId,
|
|
1194
|
+
steps: resume.steps.slice(1),
|
|
1195
|
+
stepResults: snapshot?.context,
|
|
1196
|
+
resumePayload: resume.resumePayload,
|
|
1197
|
+
// @ts-ignore
|
|
1198
|
+
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1199
|
+
},
|
|
1200
|
+
outputOptions: { includeState: true }
|
|
900
1201
|
}
|
|
901
|
-
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1202
|
+
});
|
|
1203
|
+
result = invokeResp.result;
|
|
1204
|
+
runId = invokeResp.runId;
|
|
1205
|
+
executionContext.state = invokeResp.result.state;
|
|
1206
|
+
} else if (isTimeTravel) {
|
|
1207
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1208
|
+
workflowName: step.id,
|
|
1209
|
+
runId: executionContext.runId
|
|
1210
|
+
}) ?? { context: {} };
|
|
1211
|
+
const timeTravelParams = workflows.createTimeTravelExecutionParams({
|
|
1212
|
+
steps: timeTravel.steps.slice(1),
|
|
1213
|
+
inputData: timeTravel.inputData,
|
|
1214
|
+
resumeData: timeTravel.resumeData,
|
|
1215
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1216
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1217
|
+
snapshot,
|
|
1218
|
+
graph: step.buildExecutionGraph()
|
|
1219
|
+
});
|
|
1220
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1221
|
+
function: step.getFunction(),
|
|
1222
|
+
data: {
|
|
1223
|
+
timeTravel: timeTravelParams,
|
|
1224
|
+
initialState: executionContext.state ?? {},
|
|
1225
|
+
runId: executionContext.runId,
|
|
1226
|
+
outputOptions: { includeState: true }
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
result = invokeResp.result;
|
|
1230
|
+
runId = invokeResp.runId;
|
|
1231
|
+
executionContext.state = invokeResp.result.state;
|
|
1232
|
+
} else {
|
|
1233
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1234
|
+
function: step.getFunction(),
|
|
1235
|
+
data: {
|
|
1236
|
+
inputData,
|
|
1237
|
+
initialState: executionContext.state ?? {},
|
|
1238
|
+
outputOptions: { includeState: true }
|
|
1239
|
+
}
|
|
1240
|
+
});
|
|
1241
|
+
result = invokeResp.result;
|
|
1242
|
+
runId = invokeResp.runId;
|
|
1243
|
+
executionContext.state = invokeResp.result.state;
|
|
1244
|
+
}
|
|
1245
|
+
} catch (e) {
|
|
1246
|
+
const errorCause = e?.cause;
|
|
1247
|
+
if (errorCause && typeof errorCause === "object") {
|
|
1248
|
+
result = errorCause;
|
|
1249
|
+
runId = errorCause.runId || crypto.randomUUID();
|
|
1250
|
+
} else {
|
|
1251
|
+
runId = crypto.randomUUID();
|
|
1252
|
+
result = {
|
|
1253
|
+
status: "failed",
|
|
1254
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1255
|
+
steps: {},
|
|
1256
|
+
input: inputData
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
914
1259
|
}
|
|
915
1260
|
const res = await this.inngestStep.run(
|
|
916
1261
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
@@ -944,12 +1289,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
944
1289
|
});
|
|
945
1290
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
946
1291
|
} else if (result.status === "suspended") {
|
|
947
|
-
const suspendedSteps = Object.entries(result.steps).filter(([_stepName,
|
|
948
|
-
const stepRes2 =
|
|
1292
|
+
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult2]) => {
|
|
1293
|
+
const stepRes2 = stepResult2;
|
|
949
1294
|
return stepRes2?.status === "suspended";
|
|
950
1295
|
});
|
|
951
|
-
for (const [stepName,
|
|
952
|
-
const suspendPath = [stepName, ...
|
|
1296
|
+
for (const [stepName, stepResult2] of suspendedSteps) {
|
|
1297
|
+
const suspendPath = [stepName, ...stepResult2?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
953
1298
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
954
1299
|
await emitter.emit("watch", {
|
|
955
1300
|
type: "watch",
|
|
@@ -957,7 +1302,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
957
1302
|
currentStep: {
|
|
958
1303
|
id: step.id,
|
|
959
1304
|
status: "suspended",
|
|
960
|
-
payload:
|
|
1305
|
+
payload: stepResult2.payload,
|
|
1306
|
+
suspendPayload: {
|
|
1307
|
+
...stepResult2?.suspendPayload,
|
|
1308
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1309
|
+
}
|
|
961
1310
|
},
|
|
962
1311
|
workflowState: {
|
|
963
1312
|
status: "running",
|
|
@@ -979,7 +1328,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
979
1328
|
executionContext,
|
|
980
1329
|
result: {
|
|
981
1330
|
status: "suspended",
|
|
982
|
-
payload:
|
|
1331
|
+
payload: stepResult2.payload,
|
|
1332
|
+
suspendPayload: {
|
|
1333
|
+
...stepResult2?.suspendPayload,
|
|
1334
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1335
|
+
}
|
|
983
1336
|
}
|
|
984
1337
|
};
|
|
985
1338
|
}
|
|
@@ -1044,132 +1397,206 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1044
1397
|
}
|
|
1045
1398
|
);
|
|
1046
1399
|
Object.assign(executionContext, res.executionContext);
|
|
1047
|
-
|
|
1400
|
+
const stepResult = {
|
|
1401
|
+
...res.result,
|
|
1402
|
+
startedAt,
|
|
1403
|
+
endedAt: Date.now(),
|
|
1404
|
+
payload: inputData,
|
|
1405
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1406
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1407
|
+
};
|
|
1408
|
+
return { result: stepResult, executionContextState: executionContext.state };
|
|
1048
1409
|
}
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1410
|
+
let stepRes;
|
|
1411
|
+
try {
|
|
1412
|
+
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1413
|
+
let execResults;
|
|
1414
|
+
let suspended;
|
|
1415
|
+
let bailed;
|
|
1416
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
|
|
1417
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1418
|
+
step
|
|
1419
|
+
});
|
|
1420
|
+
let resumeDataToUse;
|
|
1421
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1422
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1423
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1424
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1425
|
+
stepId: step.id,
|
|
1426
|
+
error: timeTravelResumeValidationError.message
|
|
1427
|
+
});
|
|
1428
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1429
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1056
1430
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1431
|
+
try {
|
|
1432
|
+
if (validationError) {
|
|
1433
|
+
throw validationError;
|
|
1434
|
+
}
|
|
1435
|
+
const result = await step.execute({
|
|
1436
|
+
runId: executionContext.runId,
|
|
1437
|
+
mastra: this.mastra,
|
|
1438
|
+
runtimeContext,
|
|
1439
|
+
writableStream,
|
|
1440
|
+
state: executionContext?.state ?? {},
|
|
1441
|
+
setState: (state) => {
|
|
1442
|
+
executionContext.state = state;
|
|
1443
|
+
},
|
|
1444
|
+
inputData,
|
|
1445
|
+
resumeData: resumeDataToUse,
|
|
1446
|
+
tracingContext: {
|
|
1447
|
+
currentSpan: stepAISpan
|
|
1448
|
+
},
|
|
1449
|
+
getInitData: () => stepResults?.input,
|
|
1450
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1451
|
+
suspend: async (suspendPayload, suspendOptions) => {
|
|
1452
|
+
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1453
|
+
if (suspendOptions?.resumeLabel) {
|
|
1454
|
+
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
1455
|
+
for (const label of resumeLabel) {
|
|
1456
|
+
executionContext.resumeLabels[label] = {
|
|
1457
|
+
stepId: step.id,
|
|
1458
|
+
foreachIndex: executionContext.foreachIndex
|
|
1459
|
+
};
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
suspended = { payload: suspendPayload };
|
|
1463
|
+
},
|
|
1464
|
+
bail: (result2) => {
|
|
1465
|
+
bailed = { payload: result2 };
|
|
1466
|
+
},
|
|
1467
|
+
resume: {
|
|
1468
|
+
steps: resume?.steps?.slice(1) || [],
|
|
1469
|
+
resumePayload: resume?.resumePayload,
|
|
1470
|
+
// @ts-ignore
|
|
1471
|
+
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1472
|
+
},
|
|
1473
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1474
|
+
engine: {
|
|
1475
|
+
step: this.inngestStep
|
|
1476
|
+
},
|
|
1477
|
+
abortSignal: abortController.signal
|
|
1478
|
+
});
|
|
1479
|
+
const endedAt = Date.now();
|
|
1480
|
+
execResults = {
|
|
1481
|
+
status: "success",
|
|
1482
|
+
output: result,
|
|
1483
|
+
startedAt,
|
|
1484
|
+
endedAt,
|
|
1485
|
+
payload: inputData,
|
|
1486
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1487
|
+
resumePayload: resumeDataToUse
|
|
1488
|
+
};
|
|
1489
|
+
} catch (e) {
|
|
1490
|
+
const stepFailure = {
|
|
1491
|
+
status: "failed",
|
|
1492
|
+
payload: inputData,
|
|
1493
|
+
error: e instanceof Error ? e.stack ?? e.message : String(e),
|
|
1494
|
+
endedAt: Date.now(),
|
|
1495
|
+
startedAt,
|
|
1496
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1497
|
+
resumePayload: resumeDataToUse
|
|
1498
|
+
};
|
|
1499
|
+
execResults = stepFailure;
|
|
1500
|
+
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1501
|
+
stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1502
|
+
throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1503
|
+
cause: execResults
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
if (suspended) {
|
|
1507
|
+
execResults = {
|
|
1508
|
+
status: "suspended",
|
|
1509
|
+
suspendPayload: suspended.payload,
|
|
1510
|
+
payload: inputData,
|
|
1511
|
+
suspendedAt: Date.now(),
|
|
1512
|
+
startedAt,
|
|
1513
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1514
|
+
resumePayload: resumeDataToUse
|
|
1515
|
+
};
|
|
1516
|
+
} else if (bailed) {
|
|
1517
|
+
execResults = {
|
|
1518
|
+
status: "bailed",
|
|
1519
|
+
output: bailed.payload,
|
|
1520
|
+
payload: inputData,
|
|
1521
|
+
endedAt: Date.now(),
|
|
1522
|
+
startedAt
|
|
1523
|
+
};
|
|
1524
|
+
}
|
|
1525
|
+
await emitter.emit("watch", {
|
|
1526
|
+
type: "watch",
|
|
1527
|
+
payload: {
|
|
1528
|
+
currentStep: {
|
|
1529
|
+
id: step.id,
|
|
1530
|
+
...execResults
|
|
1531
|
+
},
|
|
1532
|
+
workflowState: {
|
|
1533
|
+
status: "running",
|
|
1534
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
1535
|
+
result: null,
|
|
1536
|
+
error: null
|
|
1537
|
+
}
|
|
1085
1538
|
},
|
|
1086
|
-
|
|
1539
|
+
eventTimestamp: Date.now()
|
|
1087
1540
|
});
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
status: "suspended",
|
|
1112
|
-
suspendedPayload: suspended.payload,
|
|
1113
|
-
payload: inputData,
|
|
1114
|
-
suspendedAt: Date.now(),
|
|
1115
|
-
startedAt,
|
|
1116
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1117
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1118
|
-
};
|
|
1119
|
-
} else if (bailed) {
|
|
1120
|
-
execResults = { status: "bailed", output: bailed.payload, payload: inputData, endedAt: Date.now(), startedAt };
|
|
1121
|
-
}
|
|
1122
|
-
if (execResults.status === "failed") {
|
|
1123
|
-
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
1124
|
-
const error = new Error(execResults.error);
|
|
1125
|
-
stepAISpan?.error({ error });
|
|
1126
|
-
throw error;
|
|
1541
|
+
if (execResults.status === "suspended") {
|
|
1542
|
+
await emitter.emit("watch-v2", {
|
|
1543
|
+
type: "workflow-step-suspended",
|
|
1544
|
+
payload: {
|
|
1545
|
+
id: step.id,
|
|
1546
|
+
...execResults
|
|
1547
|
+
}
|
|
1548
|
+
});
|
|
1549
|
+
} else {
|
|
1550
|
+
await emitter.emit("watch-v2", {
|
|
1551
|
+
type: "workflow-step-result",
|
|
1552
|
+
payload: {
|
|
1553
|
+
id: step.id,
|
|
1554
|
+
...execResults
|
|
1555
|
+
}
|
|
1556
|
+
});
|
|
1557
|
+
await emitter.emit("watch-v2", {
|
|
1558
|
+
type: "workflow-step-finish",
|
|
1559
|
+
payload: {
|
|
1560
|
+
id: step.id,
|
|
1561
|
+
metadata: {}
|
|
1562
|
+
}
|
|
1563
|
+
});
|
|
1127
1564
|
}
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1565
|
+
stepAISpan?.end({ output: execResults });
|
|
1566
|
+
return { result: execResults, executionContext, stepResults };
|
|
1567
|
+
});
|
|
1568
|
+
} catch (e) {
|
|
1569
|
+
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1570
|
+
status: "failed",
|
|
1571
|
+
error: e instanceof Error ? e.stack ?? e.message : String(e),
|
|
1572
|
+
payload: inputData,
|
|
1573
|
+
startedAt,
|
|
1574
|
+
endedAt: Date.now()
|
|
1575
|
+
};
|
|
1576
|
+
await emitter.emit("watch-v2", {
|
|
1577
|
+
type: "workflow-step-result",
|
|
1131
1578
|
payload: {
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
},
|
|
1136
|
-
workflowState: {
|
|
1137
|
-
status: "running",
|
|
1138
|
-
steps: { ...stepResults, [step.id]: execResults },
|
|
1139
|
-
result: null,
|
|
1140
|
-
error: null
|
|
1141
|
-
}
|
|
1142
|
-
},
|
|
1143
|
-
eventTimestamp: Date.now()
|
|
1579
|
+
id: step.id,
|
|
1580
|
+
...stepFailure
|
|
1581
|
+
}
|
|
1144
1582
|
});
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
type: "workflow-step-finish",
|
|
1163
|
-
payload: {
|
|
1164
|
-
id: step.id,
|
|
1165
|
-
metadata: {}
|
|
1166
|
-
}
|
|
1167
|
-
});
|
|
1168
|
-
}
|
|
1169
|
-
stepAISpan?.end({ output: execResults });
|
|
1170
|
-
return { result: execResults, executionContext, stepResults };
|
|
1171
|
-
});
|
|
1172
|
-
if (disableScorers !== false) {
|
|
1583
|
+
await emitter.emit("watch-v2", {
|
|
1584
|
+
type: "workflow-step-finish",
|
|
1585
|
+
payload: {
|
|
1586
|
+
id: step.id,
|
|
1587
|
+
metadata: {}
|
|
1588
|
+
}
|
|
1589
|
+
});
|
|
1590
|
+
stepRes = {
|
|
1591
|
+
result: stepFailure,
|
|
1592
|
+
executionContext,
|
|
1593
|
+
stepResults: {
|
|
1594
|
+
...stepResults,
|
|
1595
|
+
[step.id]: stepFailure
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
}
|
|
1599
|
+
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1173
1600
|
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1174
1601
|
if (step.scorers) {
|
|
1175
1602
|
await this.runScorers({
|
|
@@ -1187,8 +1614,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1187
1614
|
});
|
|
1188
1615
|
}
|
|
1189
1616
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1190
|
-
|
|
1191
|
-
return
|
|
1617
|
+
executionContext.state = stepRes.executionContext.state;
|
|
1618
|
+
return {
|
|
1619
|
+
result: stepRes.result,
|
|
1620
|
+
executionContextState: stepRes.executionContext.state
|
|
1621
|
+
};
|
|
1192
1622
|
}
|
|
1193
1623
|
async persistStepUpdate({
|
|
1194
1624
|
workflowId,
|
|
@@ -1204,19 +1634,25 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1204
1634
|
await this.inngestStep.run(
|
|
1205
1635
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1206
1636
|
async () => {
|
|
1637
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1638
|
+
if (!shouldPersistSnapshot) {
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1207
1641
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1208
1642
|
workflowName: workflowId,
|
|
1209
1643
|
runId,
|
|
1210
1644
|
resourceId,
|
|
1211
1645
|
snapshot: {
|
|
1212
1646
|
runId,
|
|
1213
|
-
|
|
1647
|
+
status: workflowStatus,
|
|
1648
|
+
value: executionContext.state,
|
|
1214
1649
|
context: stepResults,
|
|
1215
|
-
activePaths:
|
|
1650
|
+
activePaths: executionContext.executionPath,
|
|
1651
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1216
1652
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1653
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1217
1654
|
waitingPaths: {},
|
|
1218
1655
|
serializedStepGraph,
|
|
1219
|
-
status: workflowStatus,
|
|
1220
1656
|
result,
|
|
1221
1657
|
error,
|
|
1222
1658
|
// @ts-ignore
|
|
@@ -1231,9 +1667,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1231
1667
|
runId,
|
|
1232
1668
|
entry,
|
|
1233
1669
|
prevOutput,
|
|
1234
|
-
prevStep,
|
|
1235
1670
|
stepResults,
|
|
1236
|
-
|
|
1671
|
+
timeTravel,
|
|
1237
1672
|
resume,
|
|
1238
1673
|
executionContext,
|
|
1239
1674
|
emitter,
|
|
@@ -1273,6 +1708,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1273
1708
|
runtimeContext,
|
|
1274
1709
|
runCount: -1,
|
|
1275
1710
|
inputData: prevOutput,
|
|
1711
|
+
state: executionContext.state,
|
|
1712
|
+
setState: (state) => {
|
|
1713
|
+
executionContext.state = state;
|
|
1714
|
+
},
|
|
1276
1715
|
tracingContext: {
|
|
1277
1716
|
currentSpan: evalSpan
|
|
1278
1717
|
},
|
|
@@ -1330,22 +1769,27 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1330
1769
|
}
|
|
1331
1770
|
});
|
|
1332
1771
|
const results = await Promise.all(
|
|
1333
|
-
stepsToRun.map(
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1772
|
+
stepsToRun.map(async (step, index) => {
|
|
1773
|
+
const currStepResult = stepResults[step.step.id];
|
|
1774
|
+
if (currStepResult && currStepResult.status === "success") {
|
|
1775
|
+
return currStepResult;
|
|
1776
|
+
}
|
|
1777
|
+
const result = await this.executeStep({
|
|
1778
|
+
step: step.step,
|
|
1779
|
+
prevOutput,
|
|
1340
1780
|
stepResults,
|
|
1341
1781
|
resume,
|
|
1782
|
+
timeTravel,
|
|
1342
1783
|
executionContext: {
|
|
1343
1784
|
workflowId,
|
|
1344
1785
|
runId,
|
|
1345
1786
|
executionPath: [...executionContext.executionPath, index],
|
|
1787
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1346
1788
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1789
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1347
1790
|
retryConfig: executionContext.retryConfig,
|
|
1348
|
-
executionSpan: executionContext.executionSpan
|
|
1791
|
+
executionSpan: executionContext.executionSpan,
|
|
1792
|
+
state: executionContext.state
|
|
1349
1793
|
},
|
|
1350
1794
|
emitter,
|
|
1351
1795
|
abortController,
|
|
@@ -1355,20 +1799,23 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1355
1799
|
tracingContext: {
|
|
1356
1800
|
currentSpan: conditionalSpan
|
|
1357
1801
|
}
|
|
1358
|
-
})
|
|
1359
|
-
|
|
1802
|
+
});
|
|
1803
|
+
stepResults[step.step.id] = result.result;
|
|
1804
|
+
executionContext.state = result.executionContextState;
|
|
1805
|
+
return result.result;
|
|
1806
|
+
})
|
|
1360
1807
|
);
|
|
1361
|
-
const hasFailed = results.find((result) => result.
|
|
1362
|
-
const hasSuspended = results.find((result) => result.
|
|
1808
|
+
const hasFailed = results.find((result) => result.status === "failed");
|
|
1809
|
+
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1363
1810
|
if (hasFailed) {
|
|
1364
|
-
execResults = { status: "failed", error: hasFailed.
|
|
1811
|
+
execResults = { status: "failed", error: hasFailed.error };
|
|
1365
1812
|
} else if (hasSuspended) {
|
|
1366
|
-
execResults = { status: "suspended",
|
|
1813
|
+
execResults = { status: "suspended", suspendPayload: hasSuspended.suspendPayload };
|
|
1367
1814
|
} else {
|
|
1368
1815
|
execResults = {
|
|
1369
1816
|
status: "success",
|
|
1370
1817
|
output: results.reduce((acc, result, index) => {
|
|
1371
|
-
if (result.
|
|
1818
|
+
if (result.status === "success") {
|
|
1372
1819
|
acc[stepsToRun[index].step.id] = result.output;
|
|
1373
1820
|
}
|
|
1374
1821
|
return acc;
|