@mastra/inngest 0.0.0-main-test-05-11-2025-2-20251106025330 → 0.0.0-main-test-2-20251127211532
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 +266 -3
- package/dist/index.cjs +314 -54
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +56 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +316 -56
- package/dist/index.js.map +1 -1
- package/package.json +15 -13
package/dist/index.cjs
CHANGED
|
@@ -101,7 +101,8 @@ var InngestRun = class extends workflows.Run {
|
|
|
101
101
|
resourceId: this.resourceId,
|
|
102
102
|
snapshot: {
|
|
103
103
|
...snapshot,
|
|
104
|
-
status: "canceled"
|
|
104
|
+
status: "canceled",
|
|
105
|
+
value: snapshot.value
|
|
105
106
|
}
|
|
106
107
|
});
|
|
107
108
|
}
|
|
@@ -123,14 +124,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
123
124
|
snapshot: {
|
|
124
125
|
runId: this.runId,
|
|
125
126
|
serializedStepGraph: this.serializedStepGraph,
|
|
127
|
+
status: "running",
|
|
126
128
|
value: {},
|
|
127
129
|
context: {},
|
|
128
130
|
activePaths: [],
|
|
129
131
|
suspendedPaths: {},
|
|
132
|
+
activeStepsPath: {},
|
|
130
133
|
resumeLabels: {},
|
|
131
134
|
waitingPaths: {},
|
|
132
|
-
timestamp: Date.now()
|
|
133
|
-
status: "running"
|
|
135
|
+
timestamp: Date.now()
|
|
134
136
|
}
|
|
135
137
|
});
|
|
136
138
|
const inputDataToUse = await this._validateInput(inputData);
|
|
@@ -174,9 +176,14 @@ var InngestRun = class extends workflows.Run {
|
|
|
174
176
|
}
|
|
175
177
|
async _resume(params) {
|
|
176
178
|
const storage = this.#mastra?.getStorage();
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
+
}
|
|
180
187
|
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
181
188
|
workflowName: this.workflowId,
|
|
182
189
|
runId: this.runId
|
|
@@ -195,8 +202,7 @@ var InngestRun = class extends workflows.Run {
|
|
|
195
202
|
steps,
|
|
196
203
|
stepResults: snapshot?.context,
|
|
197
204
|
resumePayload: resumeDataToUse,
|
|
198
|
-
|
|
199
|
-
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
205
|
+
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
});
|
|
@@ -211,6 +217,97 @@ var InngestRun = class extends workflows.Run {
|
|
|
211
217
|
}
|
|
212
218
|
return result;
|
|
213
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()
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
if (snapshot?.status === "running") {
|
|
272
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
273
|
+
}
|
|
274
|
+
let inputDataToUse = params.inputData;
|
|
275
|
+
if (inputDataToUse && steps.length === 1) {
|
|
276
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
277
|
+
}
|
|
278
|
+
const timeTravelData = workflows.createTimeTravelExecutionParams({
|
|
279
|
+
steps,
|
|
280
|
+
inputData: inputDataToUse,
|
|
281
|
+
resumeData: params.resumeData,
|
|
282
|
+
context: params.context,
|
|
283
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
284
|
+
snapshot: snapshot ?? { context: {} },
|
|
285
|
+
graph: this.executionGraph,
|
|
286
|
+
initialState: params.initialState
|
|
287
|
+
});
|
|
288
|
+
const eventOutput = await this.inngest.send({
|
|
289
|
+
name: `workflow.${this.workflowId}`,
|
|
290
|
+
data: {
|
|
291
|
+
initialState: timeTravelData.state,
|
|
292
|
+
runId: this.runId,
|
|
293
|
+
workflowId: this.workflowId,
|
|
294
|
+
stepResults: timeTravelData.stepResults,
|
|
295
|
+
timeTravel: timeTravelData,
|
|
296
|
+
tracingOptions: params.tracingOptions,
|
|
297
|
+
outputOptions: params.outputOptions
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
const eventId = eventOutput.ids[0];
|
|
301
|
+
if (!eventId) {
|
|
302
|
+
throw new Error("Event ID is not set");
|
|
303
|
+
}
|
|
304
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
305
|
+
const result = runOutput?.output?.result;
|
|
306
|
+
if (result.status === "failed") {
|
|
307
|
+
result.error = new Error(result.error);
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
214
311
|
watch(cb) {
|
|
215
312
|
let active = true;
|
|
216
313
|
const streamPromise = realtime.subscribe(
|
|
@@ -237,14 +334,14 @@ var InngestRun = class extends workflows.Run {
|
|
|
237
334
|
streamLegacy({ inputData, requestContext } = {}) {
|
|
238
335
|
const { readable, writable } = new TransformStream();
|
|
239
336
|
const writer = writable.getWriter();
|
|
337
|
+
void writer.write({
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
type: "start",
|
|
340
|
+
// @ts-ignore
|
|
341
|
+
payload: { runId: this.runId }
|
|
342
|
+
});
|
|
240
343
|
const unwatch = this.watch(async (event) => {
|
|
241
344
|
try {
|
|
242
|
-
await writer.write({
|
|
243
|
-
// @ts-ignore
|
|
244
|
-
type: "start",
|
|
245
|
-
// @ts-ignore
|
|
246
|
-
payload: { runId: this.runId }
|
|
247
|
-
});
|
|
248
345
|
const e = {
|
|
249
346
|
...event,
|
|
250
347
|
type: event.type.replace("workflow-", "")
|
|
@@ -360,6 +457,75 @@ var InngestRun = class extends workflows.Run {
|
|
|
360
457
|
streamVNext(args = {}) {
|
|
361
458
|
return this.stream(args);
|
|
362
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
|
+
}
|
|
363
529
|
};
|
|
364
530
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
365
531
|
#mastra;
|
|
@@ -369,6 +535,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
369
535
|
constructor(params, inngest) {
|
|
370
536
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
371
537
|
super(workflowParams);
|
|
538
|
+
this.engineType = "inngest";
|
|
372
539
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
373
540
|
([_, value]) => value !== void 0
|
|
374
541
|
);
|
|
@@ -424,7 +591,9 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
424
591
|
mastra: this.#mastra,
|
|
425
592
|
retryConfig: this.retryConfig,
|
|
426
593
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
427
|
-
workflowSteps: this.steps
|
|
594
|
+
workflowSteps: this.steps,
|
|
595
|
+
workflowEngineType: this.engineType,
|
|
596
|
+
validateInputs: this.options.validateInputs
|
|
428
597
|
},
|
|
429
598
|
this.inngest
|
|
430
599
|
);
|
|
@@ -445,13 +614,13 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
445
614
|
value: {},
|
|
446
615
|
context: {},
|
|
447
616
|
activePaths: [],
|
|
617
|
+
activeStepsPath: {},
|
|
448
618
|
waitingPaths: {},
|
|
449
619
|
serializedStepGraph: this.serializedStepGraph,
|
|
450
620
|
suspendedPaths: {},
|
|
451
621
|
resumeLabels: {},
|
|
452
622
|
result: void 0,
|
|
453
623
|
error: void 0,
|
|
454
|
-
// @ts-ignore
|
|
455
624
|
timestamp: Date.now()
|
|
456
625
|
}
|
|
457
626
|
});
|
|
@@ -465,15 +634,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
465
634
|
this.function = this.inngest.createFunction(
|
|
466
635
|
{
|
|
467
636
|
id: `workflow.${this.id}`,
|
|
468
|
-
|
|
469
|
-
retries: this.retryConfig?.attempts ?? 0,
|
|
637
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
470
638
|
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
471
639
|
// Spread flow control configuration
|
|
472
640
|
...this.flowControlConfig
|
|
473
641
|
},
|
|
474
642
|
{ event: `workflow.${this.id}` },
|
|
475
643
|
async ({ event, step, attempt, publish }) => {
|
|
476
|
-
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
644
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
477
645
|
if (!runId) {
|
|
478
646
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
479
647
|
return crypto.randomUUID();
|
|
@@ -515,11 +683,12 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
515
683
|
requestContext: new di.RequestContext(),
|
|
516
684
|
// TODO
|
|
517
685
|
resume,
|
|
686
|
+
timeTravel,
|
|
518
687
|
format,
|
|
519
688
|
abortController: new AbortController(),
|
|
520
689
|
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
521
690
|
outputOptions,
|
|
522
|
-
writableStream: new WritableStream({
|
|
691
|
+
writableStream: new web.WritableStream({
|
|
523
692
|
write(chunk) {
|
|
524
693
|
void emitter.emit("watch", chunk).catch(() => {
|
|
525
694
|
});
|
|
@@ -567,13 +736,11 @@ function createStep(params, agentOptions) {
|
|
|
567
736
|
return {
|
|
568
737
|
id: params.name,
|
|
569
738
|
description: params.getDescription(),
|
|
570
|
-
// @ts-ignore
|
|
571
739
|
inputSchema: zod.z.object({
|
|
572
740
|
prompt: zod.z.string()
|
|
573
741
|
// resourceId: z.string().optional(),
|
|
574
742
|
// threadId: z.string().optional(),
|
|
575
743
|
}),
|
|
576
|
-
// @ts-ignore
|
|
577
744
|
outputSchema: zod.z.object({
|
|
578
745
|
text: zod.z.string()
|
|
579
746
|
}),
|
|
@@ -663,20 +830,38 @@ function createStep(params, agentOptions) {
|
|
|
663
830
|
}
|
|
664
831
|
return {
|
|
665
832
|
// TODO: tool probably should have strong id type
|
|
666
|
-
// @ts-ignore
|
|
667
833
|
id: params.id,
|
|
668
834
|
description: params.description,
|
|
669
835
|
inputSchema: params.inputSchema,
|
|
670
836
|
outputSchema: params.outputSchema,
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
837
|
+
suspendSchema: params.suspendSchema,
|
|
838
|
+
resumeSchema: params.resumeSchema,
|
|
839
|
+
execute: async ({
|
|
840
|
+
inputData,
|
|
841
|
+
mastra,
|
|
842
|
+
requestContext,
|
|
843
|
+
tracingContext,
|
|
844
|
+
suspend,
|
|
845
|
+
resumeData,
|
|
846
|
+
runId,
|
|
847
|
+
workflowId,
|
|
848
|
+
state,
|
|
849
|
+
setState
|
|
850
|
+
}) => {
|
|
851
|
+
const toolContext = {
|
|
852
|
+
mastra,
|
|
675
853
|
requestContext,
|
|
676
854
|
tracingContext,
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
855
|
+
workflow: {
|
|
856
|
+
runId,
|
|
857
|
+
resumeData,
|
|
858
|
+
suspend,
|
|
859
|
+
workflowId,
|
|
860
|
+
state,
|
|
861
|
+
setState
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
return params.execute(inputData, toolContext);
|
|
680
865
|
},
|
|
681
866
|
component: "TOOL"
|
|
682
867
|
};
|
|
@@ -710,6 +895,8 @@ function init(inngest) {
|
|
|
710
895
|
suspendSchema: step.suspendSchema,
|
|
711
896
|
stateSchema: step.stateSchema,
|
|
712
897
|
execute: step.execute,
|
|
898
|
+
retries: step.retries,
|
|
899
|
+
scorers: step.scorers,
|
|
713
900
|
component: step.component
|
|
714
901
|
};
|
|
715
902
|
},
|
|
@@ -719,7 +906,8 @@ function init(inngest) {
|
|
|
719
906
|
inputSchema: workflow.inputSchema,
|
|
720
907
|
outputSchema: workflow.outputSchema,
|
|
721
908
|
steps: workflow.stepDefs,
|
|
722
|
-
mastra: workflow.mastra
|
|
909
|
+
mastra: workflow.mastra,
|
|
910
|
+
options: workflow.options
|
|
723
911
|
});
|
|
724
912
|
wf.setStepFlow(workflow.stepGraph);
|
|
725
913
|
wf.commit();
|
|
@@ -949,6 +1137,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
949
1137
|
stepResults,
|
|
950
1138
|
executionContext,
|
|
951
1139
|
resume,
|
|
1140
|
+
timeTravel,
|
|
952
1141
|
prevOutput,
|
|
953
1142
|
emitter,
|
|
954
1143
|
abortController,
|
|
@@ -969,7 +1158,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
969
1158
|
const { inputData, validationError } = await workflows.validateStepInput({
|
|
970
1159
|
prevOutput,
|
|
971
1160
|
step,
|
|
972
|
-
validateInputs: this.options?.validateInputs ??
|
|
1161
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
973
1162
|
});
|
|
974
1163
|
const startedAt = await this.inngestStep.run(
|
|
975
1164
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
@@ -991,9 +1180,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
991
1180
|
const isResume = !!resume?.steps?.length;
|
|
992
1181
|
let result;
|
|
993
1182
|
let runId;
|
|
1183
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
994
1184
|
try {
|
|
995
1185
|
if (isResume) {
|
|
996
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1186
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
997
1187
|
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
998
1188
|
workflowName: step.id,
|
|
999
1189
|
runId
|
|
@@ -1009,8 +1199,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1009
1199
|
steps: resume.steps.slice(1),
|
|
1010
1200
|
stepResults: snapshot?.context,
|
|
1011
1201
|
resumePayload: resume.resumePayload,
|
|
1012
|
-
|
|
1013
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1202
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1014
1203
|
},
|
|
1015
1204
|
outputOptions: { includeState: true }
|
|
1016
1205
|
}
|
|
@@ -1018,6 +1207,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1018
1207
|
result = invokeResp.result;
|
|
1019
1208
|
runId = invokeResp.runId;
|
|
1020
1209
|
executionContext.state = invokeResp.result.state;
|
|
1210
|
+
} else if (isTimeTravel) {
|
|
1211
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1212
|
+
workflowName: step.id,
|
|
1213
|
+
runId: executionContext.runId
|
|
1214
|
+
}) ?? { context: {} };
|
|
1215
|
+
const timeTravelParams = workflows.createTimeTravelExecutionParams({
|
|
1216
|
+
steps: timeTravel.steps.slice(1),
|
|
1217
|
+
inputData: timeTravel.inputData,
|
|
1218
|
+
resumeData: timeTravel.resumeData,
|
|
1219
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1220
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1221
|
+
snapshot,
|
|
1222
|
+
graph: step.buildExecutionGraph()
|
|
1223
|
+
});
|
|
1224
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1225
|
+
function: step.getFunction(),
|
|
1226
|
+
data: {
|
|
1227
|
+
timeTravel: timeTravelParams,
|
|
1228
|
+
initialState: executionContext.state ?? {},
|
|
1229
|
+
runId: executionContext.runId,
|
|
1230
|
+
outputOptions: { includeState: true }
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
result = invokeResp.result;
|
|
1234
|
+
runId = invokeResp.runId;
|
|
1235
|
+
executionContext.state = invokeResp.result.state;
|
|
1021
1236
|
} else {
|
|
1022
1237
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1023
1238
|
function: step.getFunction(),
|
|
@@ -1130,14 +1345,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1130
1345
|
let execResults;
|
|
1131
1346
|
let suspended;
|
|
1132
1347
|
let bailed;
|
|
1348
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await workflows.validateStepResumeData({
|
|
1349
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1350
|
+
step
|
|
1351
|
+
});
|
|
1352
|
+
let resumeDataToUse;
|
|
1353
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1354
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1355
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1356
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1357
|
+
stepId: step.id,
|
|
1358
|
+
error: timeTravelResumeValidationError.message
|
|
1359
|
+
});
|
|
1360
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1361
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1362
|
+
}
|
|
1133
1363
|
try {
|
|
1134
1364
|
if (validationError) {
|
|
1135
1365
|
throw validationError;
|
|
1136
1366
|
}
|
|
1367
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1137
1368
|
const result = await step.execute({
|
|
1138
1369
|
runId: executionContext.runId,
|
|
1370
|
+
workflowId: executionContext.workflowId,
|
|
1139
1371
|
mastra: this.mastra,
|
|
1140
1372
|
requestContext,
|
|
1373
|
+
retryCount,
|
|
1141
1374
|
writer: new tools.ToolStream(
|
|
1142
1375
|
{
|
|
1143
1376
|
prefix: "workflow-step",
|
|
@@ -1152,13 +1385,20 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1152
1385
|
executionContext.state = state;
|
|
1153
1386
|
},
|
|
1154
1387
|
inputData,
|
|
1155
|
-
resumeData:
|
|
1388
|
+
resumeData: resumeDataToUse,
|
|
1156
1389
|
tracingContext: {
|
|
1157
1390
|
currentSpan: stepSpan
|
|
1158
1391
|
},
|
|
1159
1392
|
getInitData: () => stepResults?.input,
|
|
1160
1393
|
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1161
1394
|
suspend: async (suspendPayload, suspendOptions) => {
|
|
1395
|
+
const { suspendData, validationError: validationError2 } = await workflows.validateStepSuspendData({
|
|
1396
|
+
suspendData: suspendPayload,
|
|
1397
|
+
step
|
|
1398
|
+
});
|
|
1399
|
+
if (validationError2) {
|
|
1400
|
+
throw validationError2;
|
|
1401
|
+
}
|
|
1162
1402
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1163
1403
|
if (suspendOptions?.resumeLabel) {
|
|
1164
1404
|
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
@@ -1169,16 +1409,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1169
1409
|
};
|
|
1170
1410
|
}
|
|
1171
1411
|
}
|
|
1172
|
-
suspended = { payload:
|
|
1412
|
+
suspended = { payload: suspendData };
|
|
1173
1413
|
},
|
|
1174
1414
|
bail: (result2) => {
|
|
1175
1415
|
bailed = { payload: result2 };
|
|
1176
1416
|
},
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
resumePayload: resume?.resumePayload,
|
|
1180
|
-
// @ts-ignore
|
|
1181
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1417
|
+
abort: () => {
|
|
1418
|
+
abortController?.abort();
|
|
1182
1419
|
},
|
|
1183
1420
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1184
1421
|
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
@@ -1194,8 +1431,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1194
1431
|
startedAt,
|
|
1195
1432
|
endedAt,
|
|
1196
1433
|
payload: inputData,
|
|
1197
|
-
resumedAt:
|
|
1198
|
-
resumePayload:
|
|
1434
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1435
|
+
resumePayload: resumeDataToUse
|
|
1199
1436
|
};
|
|
1200
1437
|
} catch (e) {
|
|
1201
1438
|
const stepFailure = {
|
|
@@ -1204,8 +1441,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1204
1441
|
error: e instanceof Error ? e.message : String(e),
|
|
1205
1442
|
endedAt: Date.now(),
|
|
1206
1443
|
startedAt,
|
|
1207
|
-
resumedAt:
|
|
1208
|
-
resumePayload:
|
|
1444
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1445
|
+
resumePayload: resumeDataToUse
|
|
1209
1446
|
};
|
|
1210
1447
|
execResults = stepFailure;
|
|
1211
1448
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
@@ -1218,11 +1455,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1218
1455
|
execResults = {
|
|
1219
1456
|
status: "suspended",
|
|
1220
1457
|
suspendPayload: suspended.payload,
|
|
1458
|
+
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1221
1459
|
payload: inputData,
|
|
1222
1460
|
suspendedAt: Date.now(),
|
|
1223
1461
|
startedAt,
|
|
1224
|
-
resumedAt:
|
|
1225
|
-
resumePayload:
|
|
1462
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1463
|
+
resumePayload: resumeDataToUse
|
|
1226
1464
|
};
|
|
1227
1465
|
} else if (bailed) {
|
|
1228
1466
|
execResults = {
|
|
@@ -1268,6 +1506,20 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1268
1506
|
startedAt,
|
|
1269
1507
|
endedAt: Date.now()
|
|
1270
1508
|
};
|
|
1509
|
+
await emitter.emit("watch", {
|
|
1510
|
+
type: "workflow-step-result",
|
|
1511
|
+
payload: {
|
|
1512
|
+
id: step.id,
|
|
1513
|
+
...stepFailure
|
|
1514
|
+
}
|
|
1515
|
+
});
|
|
1516
|
+
await emitter.emit("watch", {
|
|
1517
|
+
type: "workflow-step-finish",
|
|
1518
|
+
payload: {
|
|
1519
|
+
id: step.id,
|
|
1520
|
+
metadata: {}
|
|
1521
|
+
}
|
|
1522
|
+
});
|
|
1271
1523
|
stepRes = {
|
|
1272
1524
|
result: stepFailure,
|
|
1273
1525
|
executionContext,
|
|
@@ -1295,7 +1547,6 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1295
1547
|
});
|
|
1296
1548
|
}
|
|
1297
1549
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1298
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1299
1550
|
executionContext.state = stepRes.executionContext.state;
|
|
1300
1551
|
return stepRes.result;
|
|
1301
1552
|
}
|
|
@@ -1323,17 +1574,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1323
1574
|
resourceId,
|
|
1324
1575
|
snapshot: {
|
|
1325
1576
|
runId,
|
|
1577
|
+
status: workflowStatus,
|
|
1326
1578
|
value: executionContext.state,
|
|
1327
1579
|
context: stepResults,
|
|
1328
|
-
activePaths:
|
|
1580
|
+
activePaths: executionContext.executionPath,
|
|
1581
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1329
1582
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1330
1583
|
resumeLabels: executionContext.resumeLabels,
|
|
1331
1584
|
waitingPaths: {},
|
|
1332
1585
|
serializedStepGraph,
|
|
1333
|
-
status: workflowStatus,
|
|
1334
1586
|
result,
|
|
1335
1587
|
error,
|
|
1336
|
-
// @ts-ignore
|
|
1337
1588
|
timestamp: Date.now()
|
|
1338
1589
|
}
|
|
1339
1590
|
});
|
|
@@ -1346,6 +1597,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1346
1597
|
entry,
|
|
1347
1598
|
prevOutput,
|
|
1348
1599
|
stepResults,
|
|
1600
|
+
timeTravel,
|
|
1349
1601
|
resume,
|
|
1350
1602
|
executionContext,
|
|
1351
1603
|
emitter,
|
|
@@ -1464,10 +1716,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1464
1716
|
prevOutput,
|
|
1465
1717
|
stepResults,
|
|
1466
1718
|
resume,
|
|
1719
|
+
timeTravel,
|
|
1467
1720
|
executionContext: {
|
|
1468
1721
|
workflowId,
|
|
1469
1722
|
runId,
|
|
1470
1723
|
executionPath: [...executionContext.executionPath, index],
|
|
1724
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1471
1725
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1472
1726
|
resumeLabels: executionContext.resumeLabels,
|
|
1473
1727
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1491,13 +1745,19 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1491
1745
|
if (hasFailed) {
|
|
1492
1746
|
execResults = { status: "failed", error: hasFailed.error };
|
|
1493
1747
|
} else if (hasSuspended) {
|
|
1494
|
-
execResults = {
|
|
1748
|
+
execResults = {
|
|
1749
|
+
status: "suspended",
|
|
1750
|
+
suspendPayload: hasSuspended.suspendPayload,
|
|
1751
|
+
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1752
|
+
};
|
|
1495
1753
|
} else {
|
|
1496
1754
|
execResults = {
|
|
1497
1755
|
status: "success",
|
|
1498
1756
|
output: results.reduce((acc, result, index) => {
|
|
1499
1757
|
if (result.status === "success") {
|
|
1500
|
-
|
|
1758
|
+
if ("step" in stepsToRun[index]) {
|
|
1759
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1760
|
+
}
|
|
1501
1761
|
}
|
|
1502
1762
|
return acc;
|
|
1503
1763
|
}, {})
|