@mastra/inngest 0.0.0-vnext-20251104230439 → 0.0.0-vnext-20251119160359
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 +236 -3
- package/dist/index.cjs +293 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +56 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +295 -75
- package/dist/index.js.map +1 -1
- package/package.json +18 -13
package/dist/index.cjs
CHANGED
|
@@ -82,12 +82,6 @@ var InngestRun = class extends workflows.Run {
|
|
|
82
82
|
}
|
|
83
83
|
return runs?.[0];
|
|
84
84
|
}
|
|
85
|
-
async sendEvent(event, data) {
|
|
86
|
-
await this.inngest.send({
|
|
87
|
-
name: `user-event-${event}`,
|
|
88
|
-
data
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
85
|
async cancel() {
|
|
92
86
|
const storage = this.#mastra?.getStorage();
|
|
93
87
|
await this.inngest.send({
|
|
@@ -107,7 +101,8 @@ var InngestRun = class extends workflows.Run {
|
|
|
107
101
|
resourceId: this.resourceId,
|
|
108
102
|
snapshot: {
|
|
109
103
|
...snapshot,
|
|
110
|
-
status: "canceled"
|
|
104
|
+
status: "canceled",
|
|
105
|
+
value: snapshot.value
|
|
111
106
|
}
|
|
112
107
|
});
|
|
113
108
|
}
|
|
@@ -129,14 +124,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
129
124
|
snapshot: {
|
|
130
125
|
runId: this.runId,
|
|
131
126
|
serializedStepGraph: this.serializedStepGraph,
|
|
127
|
+
status: "running",
|
|
132
128
|
value: {},
|
|
133
129
|
context: {},
|
|
134
130
|
activePaths: [],
|
|
135
131
|
suspendedPaths: {},
|
|
132
|
+
activeStepsPath: {},
|
|
136
133
|
resumeLabels: {},
|
|
137
134
|
waitingPaths: {},
|
|
138
|
-
timestamp: Date.now()
|
|
139
|
-
status: "running"
|
|
135
|
+
timestamp: Date.now()
|
|
140
136
|
}
|
|
141
137
|
});
|
|
142
138
|
const inputDataToUse = await this._validateInput(inputData);
|
|
@@ -180,9 +176,14 @@ var InngestRun = class extends workflows.Run {
|
|
|
180
176
|
}
|
|
181
177
|
async _resume(params) {
|
|
182
178
|
const storage = this.#mastra?.getStorage();
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
179
|
+
let steps = [];
|
|
180
|
+
if (typeof params.step === "string") {
|
|
181
|
+
steps = params.step.split(".");
|
|
182
|
+
} else {
|
|
183
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
184
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
185
|
+
);
|
|
186
|
+
}
|
|
186
187
|
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
187
188
|
workflowName: this.workflowId,
|
|
188
189
|
runId: this.runId
|
|
@@ -201,9 +202,99 @@ var InngestRun = class extends workflows.Run {
|
|
|
201
202
|
steps,
|
|
202
203
|
stepResults: snapshot?.context,
|
|
203
204
|
resumePayload: resumeDataToUse,
|
|
204
|
-
|
|
205
|
-
|
|
205
|
+
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
const eventId = eventOutput.ids[0];
|
|
210
|
+
if (!eventId) {
|
|
211
|
+
throw new Error("Event ID is not set");
|
|
212
|
+
}
|
|
213
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
214
|
+
const result = runOutput?.output?.result;
|
|
215
|
+
if (result.status === "failed") {
|
|
216
|
+
result.error = new Error(result.error);
|
|
217
|
+
}
|
|
218
|
+
return result;
|
|
219
|
+
}
|
|
220
|
+
async timeTravel(params) {
|
|
221
|
+
const p = this._timeTravel(params).then((result) => {
|
|
222
|
+
if (result.status !== "suspended") {
|
|
223
|
+
this.closeStreamAction?.().catch(() => {
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return result;
|
|
227
|
+
});
|
|
228
|
+
this.executionResults = p;
|
|
229
|
+
return p;
|
|
230
|
+
}
|
|
231
|
+
async _timeTravel(params) {
|
|
232
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
233
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
234
|
+
}
|
|
235
|
+
let steps = [];
|
|
236
|
+
if (typeof params.step === "string") {
|
|
237
|
+
steps = params.step.split(".");
|
|
238
|
+
} else {
|
|
239
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
240
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
if (steps.length === 0) {
|
|
244
|
+
throw new Error("No steps provided to timeTravel");
|
|
245
|
+
}
|
|
246
|
+
const storage = this.#mastra?.getStorage();
|
|
247
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
248
|
+
workflowName: this.workflowId,
|
|
249
|
+
runId: this.runId
|
|
250
|
+
});
|
|
251
|
+
if (!snapshot) {
|
|
252
|
+
await storage?.persistWorkflowSnapshot({
|
|
253
|
+
workflowName: this.workflowId,
|
|
254
|
+
runId: this.runId,
|
|
255
|
+
resourceId: this.resourceId,
|
|
256
|
+
snapshot: {
|
|
257
|
+
runId: this.runId,
|
|
258
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
259
|
+
status: "pending",
|
|
260
|
+
value: {},
|
|
261
|
+
context: {},
|
|
262
|
+
activePaths: [],
|
|
263
|
+
suspendedPaths: {},
|
|
264
|
+
activeStepsPath: {},
|
|
265
|
+
resumeLabels: {},
|
|
266
|
+
waitingPaths: {},
|
|
267
|
+
timestamp: Date.now()
|
|
206
268
|
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (snapshot?.status === "running") {
|
|
272
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
273
|
+
}
|
|
274
|
+
let inputDataToUse = params.inputData;
|
|
275
|
+
if (inputDataToUse && steps.length === 1) {
|
|
276
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
277
|
+
}
|
|
278
|
+
const timeTravelData = workflows.createTimeTravelExecutionParams({
|
|
279
|
+
steps,
|
|
280
|
+
inputData: inputDataToUse,
|
|
281
|
+
resumeData: params.resumeData,
|
|
282
|
+
context: params.context,
|
|
283
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
284
|
+
snapshot: snapshot ?? { context: {} },
|
|
285
|
+
graph: this.executionGraph,
|
|
286
|
+
initialState: params.initialState
|
|
287
|
+
});
|
|
288
|
+
const eventOutput = await this.inngest.send({
|
|
289
|
+
name: `workflow.${this.workflowId}`,
|
|
290
|
+
data: {
|
|
291
|
+
initialState: timeTravelData.state,
|
|
292
|
+
runId: this.runId,
|
|
293
|
+
workflowId: this.workflowId,
|
|
294
|
+
stepResults: timeTravelData.stepResults,
|
|
295
|
+
timeTravel: timeTravelData,
|
|
296
|
+
tracingOptions: params.tracingOptions,
|
|
297
|
+
outputOptions: params.outputOptions
|
|
207
298
|
}
|
|
208
299
|
});
|
|
209
300
|
const eventId = eventOutput.ids[0];
|
|
@@ -366,6 +457,75 @@ var InngestRun = class extends workflows.Run {
|
|
|
366
457
|
streamVNext(args = {}) {
|
|
367
458
|
return this.stream(args);
|
|
368
459
|
}
|
|
460
|
+
timeTravelStream({
|
|
461
|
+
inputData,
|
|
462
|
+
resumeData,
|
|
463
|
+
initialState,
|
|
464
|
+
step,
|
|
465
|
+
context,
|
|
466
|
+
nestedStepsContext,
|
|
467
|
+
requestContext,
|
|
468
|
+
tracingOptions,
|
|
469
|
+
outputOptions
|
|
470
|
+
}) {
|
|
471
|
+
this.closeStreamAction = async () => {
|
|
472
|
+
};
|
|
473
|
+
const self = this;
|
|
474
|
+
const stream$1 = new web.ReadableStream({
|
|
475
|
+
async start(controller) {
|
|
476
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
477
|
+
controller.enqueue({
|
|
478
|
+
type,
|
|
479
|
+
runId: self.runId,
|
|
480
|
+
from,
|
|
481
|
+
payload: {
|
|
482
|
+
stepName: payload?.id,
|
|
483
|
+
...payload
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
self.closeStreamAction = async () => {
|
|
488
|
+
unwatch();
|
|
489
|
+
try {
|
|
490
|
+
await controller.close();
|
|
491
|
+
} catch (err) {
|
|
492
|
+
console.error("Error closing stream:", err);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
const executionResultsPromise = self._timeTravel({
|
|
496
|
+
inputData,
|
|
497
|
+
step,
|
|
498
|
+
context,
|
|
499
|
+
nestedStepsContext,
|
|
500
|
+
resumeData,
|
|
501
|
+
initialState,
|
|
502
|
+
requestContext,
|
|
503
|
+
tracingOptions,
|
|
504
|
+
outputOptions
|
|
505
|
+
});
|
|
506
|
+
self.executionResults = executionResultsPromise;
|
|
507
|
+
let executionResults;
|
|
508
|
+
try {
|
|
509
|
+
executionResults = await executionResultsPromise;
|
|
510
|
+
self.closeStreamAction?.().catch(() => {
|
|
511
|
+
});
|
|
512
|
+
if (self.streamOutput) {
|
|
513
|
+
self.streamOutput.updateResults(executionResults);
|
|
514
|
+
}
|
|
515
|
+
} catch (err) {
|
|
516
|
+
self.streamOutput?.rejectResults(err);
|
|
517
|
+
self.closeStreamAction?.().catch(() => {
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
});
|
|
522
|
+
this.streamOutput = new stream.WorkflowRunOutput({
|
|
523
|
+
runId: this.runId,
|
|
524
|
+
workflowId: this.workflowId,
|
|
525
|
+
stream: stream$1
|
|
526
|
+
});
|
|
527
|
+
return this.streamOutput;
|
|
528
|
+
}
|
|
369
529
|
};
|
|
370
530
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
371
531
|
#mastra;
|
|
@@ -375,6 +535,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
375
535
|
constructor(params, inngest) {
|
|
376
536
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
377
537
|
super(workflowParams);
|
|
538
|
+
this.engineType = "inngest";
|
|
378
539
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
379
540
|
([_, value]) => value !== void 0
|
|
380
541
|
);
|
|
@@ -430,7 +591,9 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
430
591
|
mastra: this.#mastra,
|
|
431
592
|
retryConfig: this.retryConfig,
|
|
432
593
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
433
|
-
workflowSteps: this.steps
|
|
594
|
+
workflowSteps: this.steps,
|
|
595
|
+
workflowEngineType: this.engineType,
|
|
596
|
+
validateInputs: this.options.validateInputs
|
|
434
597
|
},
|
|
435
598
|
this.inngest
|
|
436
599
|
);
|
|
@@ -451,13 +614,13 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
451
614
|
value: {},
|
|
452
615
|
context: {},
|
|
453
616
|
activePaths: [],
|
|
617
|
+
activeStepsPath: {},
|
|
454
618
|
waitingPaths: {},
|
|
455
619
|
serializedStepGraph: this.serializedStepGraph,
|
|
456
620
|
suspendedPaths: {},
|
|
457
621
|
resumeLabels: {},
|
|
458
622
|
result: void 0,
|
|
459
623
|
error: void 0,
|
|
460
|
-
// @ts-ignore
|
|
461
624
|
timestamp: Date.now()
|
|
462
625
|
}
|
|
463
626
|
});
|
|
@@ -471,15 +634,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
471
634
|
this.function = this.inngest.createFunction(
|
|
472
635
|
{
|
|
473
636
|
id: `workflow.${this.id}`,
|
|
474
|
-
|
|
475
|
-
retries: this.retryConfig?.attempts ?? 0,
|
|
637
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
476
638
|
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
477
639
|
// Spread flow control configuration
|
|
478
640
|
...this.flowControlConfig
|
|
479
641
|
},
|
|
480
642
|
{ event: `workflow.${this.id}` },
|
|
481
643
|
async ({ event, step, attempt, publish }) => {
|
|
482
|
-
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
644
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
483
645
|
if (!runId) {
|
|
484
646
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
485
647
|
return crypto.randomUUID();
|
|
@@ -521,11 +683,12 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
521
683
|
requestContext: new di.RequestContext(),
|
|
522
684
|
// TODO
|
|
523
685
|
resume,
|
|
686
|
+
timeTravel,
|
|
524
687
|
format,
|
|
525
688
|
abortController: new AbortController(),
|
|
526
|
-
// currentSpan: undefined, // TODO: Pass actual parent
|
|
689
|
+
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
527
690
|
outputOptions,
|
|
528
|
-
writableStream: new WritableStream({
|
|
691
|
+
writableStream: new web.WritableStream({
|
|
529
692
|
write(chunk) {
|
|
530
693
|
void emitter.emit("watch", chunk).catch(() => {
|
|
531
694
|
});
|
|
@@ -573,13 +736,11 @@ function createStep(params, agentOptions) {
|
|
|
573
736
|
return {
|
|
574
737
|
id: params.name,
|
|
575
738
|
description: params.getDescription(),
|
|
576
|
-
// @ts-ignore
|
|
577
739
|
inputSchema: zod.z.object({
|
|
578
740
|
prompt: zod.z.string()
|
|
579
741
|
// resourceId: z.string().optional(),
|
|
580
742
|
// threadId: z.string().optional(),
|
|
581
743
|
}),
|
|
582
|
-
// @ts-ignore
|
|
583
744
|
outputSchema: zod.z.object({
|
|
584
745
|
text: zod.z.string()
|
|
585
746
|
}),
|
|
@@ -669,20 +830,36 @@ function createStep(params, agentOptions) {
|
|
|
669
830
|
}
|
|
670
831
|
return {
|
|
671
832
|
// TODO: tool probably should have strong id type
|
|
672
|
-
// @ts-ignore
|
|
673
833
|
id: params.id,
|
|
674
834
|
description: params.description,
|
|
675
835
|
inputSchema: params.inputSchema,
|
|
676
836
|
outputSchema: params.outputSchema,
|
|
677
|
-
execute: async ({
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
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 = {
|
|
850
|
+
mastra,
|
|
681
851
|
requestContext,
|
|
682
852
|
tracingContext,
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
853
|
+
resumeData,
|
|
854
|
+
workflow: {
|
|
855
|
+
runId,
|
|
856
|
+
suspend,
|
|
857
|
+
workflowId,
|
|
858
|
+
state,
|
|
859
|
+
setState
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
return params.execute(inputData, toolContext);
|
|
686
863
|
},
|
|
687
864
|
component: "TOOL"
|
|
688
865
|
};
|
|
@@ -716,6 +893,8 @@ function init(inngest) {
|
|
|
716
893
|
suspendSchema: step.suspendSchema,
|
|
717
894
|
stateSchema: step.stateSchema,
|
|
718
895
|
execute: step.execute,
|
|
896
|
+
retries: step.retries,
|
|
897
|
+
scorers: step.scorers,
|
|
719
898
|
component: step.component
|
|
720
899
|
};
|
|
721
900
|
},
|
|
@@ -780,7 +959,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
780
959
|
}) {
|
|
781
960
|
let { duration, fn } = entry;
|
|
782
961
|
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
783
|
-
type: observability.
|
|
962
|
+
type: observability.SpanType.WORKFLOW_SLEEP,
|
|
784
963
|
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
785
964
|
attributes: {
|
|
786
965
|
durationMs: duration,
|
|
@@ -868,7 +1047,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
868
1047
|
}) {
|
|
869
1048
|
let { date, fn } = entry;
|
|
870
1049
|
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
871
|
-
type: observability.
|
|
1050
|
+
type: observability.SpanType.WORKFLOW_SLEEP,
|
|
872
1051
|
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
873
1052
|
attributes: {
|
|
874
1053
|
untilDate: date,
|
|
@@ -950,21 +1129,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
950
1129
|
throw e;
|
|
951
1130
|
}
|
|
952
1131
|
}
|
|
953
|
-
async executeWaitForEvent({ event, timeout }) {
|
|
954
|
-
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
955
|
-
event: `user-event-${event}`,
|
|
956
|
-
timeout: timeout ?? 5e3
|
|
957
|
-
});
|
|
958
|
-
if (eventData === null) {
|
|
959
|
-
throw "Timeout waiting for event";
|
|
960
|
-
}
|
|
961
|
-
return eventData?.data;
|
|
962
|
-
}
|
|
963
1132
|
async executeStep({
|
|
964
1133
|
step,
|
|
965
1134
|
stepResults,
|
|
966
1135
|
executionContext,
|
|
967
1136
|
resume,
|
|
1137
|
+
timeTravel,
|
|
968
1138
|
prevOutput,
|
|
969
1139
|
emitter,
|
|
970
1140
|
abortController,
|
|
@@ -973,9 +1143,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
973
1143
|
writableStream,
|
|
974
1144
|
disableScorers
|
|
975
1145
|
}) {
|
|
976
|
-
const
|
|
1146
|
+
const stepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
977
1147
|
name: `workflow step: '${step.id}'`,
|
|
978
|
-
type: observability.
|
|
1148
|
+
type: observability.SpanType.WORKFLOW_STEP,
|
|
979
1149
|
input: prevOutput,
|
|
980
1150
|
attributes: {
|
|
981
1151
|
stepId: step.id
|
|
@@ -985,7 +1155,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
985
1155
|
const { inputData, validationError } = await workflows.validateStepInput({
|
|
986
1156
|
prevOutput,
|
|
987
1157
|
step,
|
|
988
|
-
validateInputs: this.options?.validateInputs ??
|
|
1158
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
989
1159
|
});
|
|
990
1160
|
const startedAt = await this.inngestStep.run(
|
|
991
1161
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
@@ -1007,9 +1177,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1007
1177
|
const isResume = !!resume?.steps?.length;
|
|
1008
1178
|
let result;
|
|
1009
1179
|
let runId;
|
|
1180
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
1010
1181
|
try {
|
|
1011
1182
|
if (isResume) {
|
|
1012
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1183
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1013
1184
|
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1014
1185
|
workflowName: step.id,
|
|
1015
1186
|
runId
|
|
@@ -1025,8 +1196,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1025
1196
|
steps: resume.steps.slice(1),
|
|
1026
1197
|
stepResults: snapshot?.context,
|
|
1027
1198
|
resumePayload: resume.resumePayload,
|
|
1028
|
-
|
|
1029
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1199
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1030
1200
|
},
|
|
1031
1201
|
outputOptions: { includeState: true }
|
|
1032
1202
|
}
|
|
@@ -1034,6 +1204,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1034
1204
|
result = invokeResp.result;
|
|
1035
1205
|
runId = invokeResp.runId;
|
|
1036
1206
|
executionContext.state = invokeResp.result.state;
|
|
1207
|
+
} else if (isTimeTravel) {
|
|
1208
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1209
|
+
workflowName: step.id,
|
|
1210
|
+
runId: executionContext.runId
|
|
1211
|
+
}) ?? { context: {} };
|
|
1212
|
+
const timeTravelParams = workflows.createTimeTravelExecutionParams({
|
|
1213
|
+
steps: timeTravel.steps.slice(1),
|
|
1214
|
+
inputData: timeTravel.inputData,
|
|
1215
|
+
resumeData: timeTravel.resumeData,
|
|
1216
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1217
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1218
|
+
snapshot,
|
|
1219
|
+
graph: step.buildExecutionGraph()
|
|
1220
|
+
});
|
|
1221
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1222
|
+
function: step.getFunction(),
|
|
1223
|
+
data: {
|
|
1224
|
+
timeTravel: timeTravelParams,
|
|
1225
|
+
initialState: executionContext.state ?? {},
|
|
1226
|
+
runId: executionContext.runId,
|
|
1227
|
+
outputOptions: { includeState: true }
|
|
1228
|
+
}
|
|
1229
|
+
});
|
|
1230
|
+
result = invokeResp.result;
|
|
1231
|
+
runId = invokeResp.runId;
|
|
1232
|
+
executionContext.state = invokeResp.result.state;
|
|
1037
1233
|
} else {
|
|
1038
1234
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1039
1235
|
function: step.getFunction(),
|
|
@@ -1146,14 +1342,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1146
1342
|
let execResults;
|
|
1147
1343
|
let suspended;
|
|
1148
1344
|
let bailed;
|
|
1345
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
|
|
1346
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1347
|
+
step
|
|
1348
|
+
});
|
|
1349
|
+
let resumeDataToUse;
|
|
1350
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1351
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1352
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1353
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1354
|
+
stepId: step.id,
|
|
1355
|
+
error: timeTravelResumeValidationError.message
|
|
1356
|
+
});
|
|
1357
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1358
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1359
|
+
}
|
|
1149
1360
|
try {
|
|
1150
1361
|
if (validationError) {
|
|
1151
1362
|
throw validationError;
|
|
1152
1363
|
}
|
|
1364
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1153
1365
|
const result = await step.execute({
|
|
1154
1366
|
runId: executionContext.runId,
|
|
1367
|
+
workflowId: executionContext.workflowId,
|
|
1155
1368
|
mastra: this.mastra,
|
|
1156
1369
|
requestContext,
|
|
1370
|
+
retryCount,
|
|
1157
1371
|
writer: new tools.ToolStream(
|
|
1158
1372
|
{
|
|
1159
1373
|
prefix: "workflow-step",
|
|
@@ -1168,9 +1382,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1168
1382
|
executionContext.state = state;
|
|
1169
1383
|
},
|
|
1170
1384
|
inputData,
|
|
1171
|
-
resumeData:
|
|
1385
|
+
resumeData: resumeDataToUse,
|
|
1172
1386
|
tracingContext: {
|
|
1173
|
-
currentSpan:
|
|
1387
|
+
currentSpan: stepSpan
|
|
1174
1388
|
},
|
|
1175
1389
|
getInitData: () => stepResults?.input,
|
|
1176
1390
|
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
@@ -1190,11 +1404,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1190
1404
|
bail: (result2) => {
|
|
1191
1405
|
bailed = { payload: result2 };
|
|
1192
1406
|
},
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
resumePayload: resume?.resumePayload,
|
|
1196
|
-
// @ts-ignore
|
|
1197
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1407
|
+
abort: () => {
|
|
1408
|
+
abortController?.abort();
|
|
1198
1409
|
},
|
|
1199
1410
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1200
1411
|
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
@@ -1210,8 +1421,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1210
1421
|
startedAt,
|
|
1211
1422
|
endedAt,
|
|
1212
1423
|
payload: inputData,
|
|
1213
|
-
resumedAt:
|
|
1214
|
-
resumePayload:
|
|
1424
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1425
|
+
resumePayload: resumeDataToUse
|
|
1215
1426
|
};
|
|
1216
1427
|
} catch (e) {
|
|
1217
1428
|
const stepFailure = {
|
|
@@ -1220,12 +1431,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1220
1431
|
error: e instanceof Error ? e.message : String(e),
|
|
1221
1432
|
endedAt: Date.now(),
|
|
1222
1433
|
startedAt,
|
|
1223
|
-
resumedAt:
|
|
1224
|
-
resumePayload:
|
|
1434
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1435
|
+
resumePayload: resumeDataToUse
|
|
1225
1436
|
};
|
|
1226
1437
|
execResults = stepFailure;
|
|
1227
1438
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1228
|
-
|
|
1439
|
+
stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1229
1440
|
throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1230
1441
|
cause: execResults
|
|
1231
1442
|
});
|
|
@@ -1234,11 +1445,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1234
1445
|
execResults = {
|
|
1235
1446
|
status: "suspended",
|
|
1236
1447
|
suspendPayload: suspended.payload,
|
|
1448
|
+
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1237
1449
|
payload: inputData,
|
|
1238
1450
|
suspendedAt: Date.now(),
|
|
1239
1451
|
startedAt,
|
|
1240
|
-
resumedAt:
|
|
1241
|
-
resumePayload:
|
|
1452
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1453
|
+
resumePayload: resumeDataToUse
|
|
1242
1454
|
};
|
|
1243
1455
|
} else if (bailed) {
|
|
1244
1456
|
execResults = {
|
|
@@ -1273,7 +1485,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1273
1485
|
}
|
|
1274
1486
|
});
|
|
1275
1487
|
}
|
|
1276
|
-
|
|
1488
|
+
stepSpan?.end({ output: execResults });
|
|
1277
1489
|
return { result: execResults, executionContext, stepResults };
|
|
1278
1490
|
});
|
|
1279
1491
|
} catch (e) {
|
|
@@ -1305,13 +1517,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1305
1517
|
stepId: step.id,
|
|
1306
1518
|
requestContext,
|
|
1307
1519
|
disableScorers,
|
|
1308
|
-
tracingContext: { currentSpan:
|
|
1520
|
+
tracingContext: { currentSpan: stepSpan }
|
|
1309
1521
|
});
|
|
1310
1522
|
}
|
|
1311
1523
|
});
|
|
1312
1524
|
}
|
|
1313
1525
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1314
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1315
1526
|
executionContext.state = stepRes.executionContext.state;
|
|
1316
1527
|
return stepRes.result;
|
|
1317
1528
|
}
|
|
@@ -1339,17 +1550,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1339
1550
|
resourceId,
|
|
1340
1551
|
snapshot: {
|
|
1341
1552
|
runId,
|
|
1553
|
+
status: workflowStatus,
|
|
1342
1554
|
value: executionContext.state,
|
|
1343
1555
|
context: stepResults,
|
|
1344
|
-
activePaths:
|
|
1556
|
+
activePaths: executionContext.executionPath,
|
|
1557
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1345
1558
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1346
1559
|
resumeLabels: executionContext.resumeLabels,
|
|
1347
1560
|
waitingPaths: {},
|
|
1348
1561
|
serializedStepGraph,
|
|
1349
|
-
status: workflowStatus,
|
|
1350
1562
|
result,
|
|
1351
1563
|
error,
|
|
1352
|
-
// @ts-ignore
|
|
1353
1564
|
timestamp: Date.now()
|
|
1354
1565
|
}
|
|
1355
1566
|
});
|
|
@@ -1362,6 +1573,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1362
1573
|
entry,
|
|
1363
1574
|
prevOutput,
|
|
1364
1575
|
stepResults,
|
|
1576
|
+
timeTravel,
|
|
1365
1577
|
resume,
|
|
1366
1578
|
executionContext,
|
|
1367
1579
|
emitter,
|
|
@@ -1372,7 +1584,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1372
1584
|
tracingContext
|
|
1373
1585
|
}) {
|
|
1374
1586
|
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1375
|
-
type: observability.
|
|
1587
|
+
type: observability.SpanType.WORKFLOW_CONDITIONAL,
|
|
1376
1588
|
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1377
1589
|
input: prevOutput,
|
|
1378
1590
|
attributes: {
|
|
@@ -1385,7 +1597,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1385
1597
|
entry.conditions.map(
|
|
1386
1598
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1387
1599
|
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1388
|
-
type: observability.
|
|
1600
|
+
type: observability.SpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1389
1601
|
name: `condition: '${index}'`,
|
|
1390
1602
|
input: prevOutput,
|
|
1391
1603
|
attributes: {
|
|
@@ -1480,10 +1692,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1480
1692
|
prevOutput,
|
|
1481
1693
|
stepResults,
|
|
1482
1694
|
resume,
|
|
1695
|
+
timeTravel,
|
|
1483
1696
|
executionContext: {
|
|
1484
1697
|
workflowId,
|
|
1485
1698
|
runId,
|
|
1486
1699
|
executionPath: [...executionContext.executionPath, index],
|
|
1700
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1487
1701
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1488
1702
|
resumeLabels: executionContext.resumeLabels,
|
|
1489
1703
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1507,13 +1721,19 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1507
1721
|
if (hasFailed) {
|
|
1508
1722
|
execResults = { status: "failed", error: hasFailed.error };
|
|
1509
1723
|
} else if (hasSuspended) {
|
|
1510
|
-
execResults = {
|
|
1724
|
+
execResults = {
|
|
1725
|
+
status: "suspended",
|
|
1726
|
+
suspendPayload: hasSuspended.suspendPayload,
|
|
1727
|
+
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1728
|
+
};
|
|
1511
1729
|
} else {
|
|
1512
1730
|
execResults = {
|
|
1513
1731
|
status: "success",
|
|
1514
1732
|
output: results.reduce((acc, result, index) => {
|
|
1515
1733
|
if (result.status === "success") {
|
|
1516
|
-
|
|
1734
|
+
if ("step" in stepsToRun[index]) {
|
|
1735
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1736
|
+
}
|
|
1517
1737
|
}
|
|
1518
1738
|
return acc;
|
|
1519
1739
|
}, {})
|