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