@mastra/inngest 1.0.0-beta.1 → 1.0.0-beta.3
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 +54 -0
- package/dist/index.cjs +286 -46
- 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 +288 -48
- package/dist/index.js.map +1 -1
- package/package.json +12 -10
package/dist/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
-
import { ReadableStream } from 'stream/web';
|
|
2
|
+
import { ReadableStream, WritableStream } from 'stream/web';
|
|
3
3
|
import { subscribe } from '@inngest/realtime';
|
|
4
4
|
import { RequestContext } from '@mastra/core/di';
|
|
5
|
-
import {
|
|
5
|
+
import { SpanType } from '@mastra/core/observability';
|
|
6
6
|
import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
|
|
7
7
|
import { ToolStream, Tool } from '@mastra/core/tools';
|
|
8
|
-
import { Run, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput } from '@mastra/core/workflows';
|
|
8
|
+
import { Run, createTimeTravelExecutionParams, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput, validateStepResumeData, validateStepSuspendData } from '@mastra/core/workflows';
|
|
9
9
|
import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
10
10
|
import { NonRetriableError, RetryAfterError } from 'inngest';
|
|
11
11
|
import { serve as serve$1 } from 'inngest/hono';
|
|
@@ -99,7 +99,8 @@ var InngestRun = class extends Run {
|
|
|
99
99
|
resourceId: this.resourceId,
|
|
100
100
|
snapshot: {
|
|
101
101
|
...snapshot,
|
|
102
|
-
status: "canceled"
|
|
102
|
+
status: "canceled",
|
|
103
|
+
value: snapshot.value
|
|
103
104
|
}
|
|
104
105
|
});
|
|
105
106
|
}
|
|
@@ -121,14 +122,15 @@ var InngestRun = class extends Run {
|
|
|
121
122
|
snapshot: {
|
|
122
123
|
runId: this.runId,
|
|
123
124
|
serializedStepGraph: this.serializedStepGraph,
|
|
125
|
+
status: "running",
|
|
124
126
|
value: {},
|
|
125
127
|
context: {},
|
|
126
128
|
activePaths: [],
|
|
127
129
|
suspendedPaths: {},
|
|
130
|
+
activeStepsPath: {},
|
|
128
131
|
resumeLabels: {},
|
|
129
132
|
waitingPaths: {},
|
|
130
|
-
timestamp: Date.now()
|
|
131
|
-
status: "running"
|
|
133
|
+
timestamp: Date.now()
|
|
132
134
|
}
|
|
133
135
|
});
|
|
134
136
|
const inputDataToUse = await this._validateInput(inputData);
|
|
@@ -172,9 +174,14 @@ var InngestRun = class extends Run {
|
|
|
172
174
|
}
|
|
173
175
|
async _resume(params) {
|
|
174
176
|
const storage = this.#mastra?.getStorage();
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
let steps = [];
|
|
178
|
+
if (typeof params.step === "string") {
|
|
179
|
+
steps = params.step.split(".");
|
|
180
|
+
} else {
|
|
181
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
182
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
183
|
+
);
|
|
184
|
+
}
|
|
178
185
|
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
179
186
|
workflowName: this.workflowId,
|
|
180
187
|
runId: this.runId
|
|
@@ -193,8 +200,7 @@ var InngestRun = class extends Run {
|
|
|
193
200
|
steps,
|
|
194
201
|
stepResults: snapshot?.context,
|
|
195
202
|
resumePayload: resumeDataToUse,
|
|
196
|
-
|
|
197
|
-
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
203
|
+
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
198
204
|
}
|
|
199
205
|
}
|
|
200
206
|
});
|
|
@@ -209,6 +215,97 @@ var InngestRun = class extends Run {
|
|
|
209
215
|
}
|
|
210
216
|
return result;
|
|
211
217
|
}
|
|
218
|
+
async timeTravel(params) {
|
|
219
|
+
const p = this._timeTravel(params).then((result) => {
|
|
220
|
+
if (result.status !== "suspended") {
|
|
221
|
+
this.closeStreamAction?.().catch(() => {
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
});
|
|
226
|
+
this.executionResults = p;
|
|
227
|
+
return p;
|
|
228
|
+
}
|
|
229
|
+
async _timeTravel(params) {
|
|
230
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
231
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
232
|
+
}
|
|
233
|
+
let steps = [];
|
|
234
|
+
if (typeof params.step === "string") {
|
|
235
|
+
steps = params.step.split(".");
|
|
236
|
+
} else {
|
|
237
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
238
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
if (steps.length === 0) {
|
|
242
|
+
throw new Error("No steps provided to timeTravel");
|
|
243
|
+
}
|
|
244
|
+
const storage = this.#mastra?.getStorage();
|
|
245
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
246
|
+
workflowName: this.workflowId,
|
|
247
|
+
runId: this.runId
|
|
248
|
+
});
|
|
249
|
+
if (!snapshot) {
|
|
250
|
+
await storage?.persistWorkflowSnapshot({
|
|
251
|
+
workflowName: this.workflowId,
|
|
252
|
+
runId: this.runId,
|
|
253
|
+
resourceId: this.resourceId,
|
|
254
|
+
snapshot: {
|
|
255
|
+
runId: this.runId,
|
|
256
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
257
|
+
status: "pending",
|
|
258
|
+
value: {},
|
|
259
|
+
context: {},
|
|
260
|
+
activePaths: [],
|
|
261
|
+
suspendedPaths: {},
|
|
262
|
+
activeStepsPath: {},
|
|
263
|
+
resumeLabels: {},
|
|
264
|
+
waitingPaths: {},
|
|
265
|
+
timestamp: Date.now()
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
if (snapshot?.status === "running") {
|
|
270
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
271
|
+
}
|
|
272
|
+
let inputDataToUse = params.inputData;
|
|
273
|
+
if (inputDataToUse && steps.length === 1) {
|
|
274
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
275
|
+
}
|
|
276
|
+
const timeTravelData = createTimeTravelExecutionParams({
|
|
277
|
+
steps,
|
|
278
|
+
inputData: inputDataToUse,
|
|
279
|
+
resumeData: params.resumeData,
|
|
280
|
+
context: params.context,
|
|
281
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
282
|
+
snapshot: snapshot ?? { context: {} },
|
|
283
|
+
graph: this.executionGraph,
|
|
284
|
+
initialState: params.initialState
|
|
285
|
+
});
|
|
286
|
+
const eventOutput = await this.inngest.send({
|
|
287
|
+
name: `workflow.${this.workflowId}`,
|
|
288
|
+
data: {
|
|
289
|
+
initialState: timeTravelData.state,
|
|
290
|
+
runId: this.runId,
|
|
291
|
+
workflowId: this.workflowId,
|
|
292
|
+
stepResults: timeTravelData.stepResults,
|
|
293
|
+
timeTravel: timeTravelData,
|
|
294
|
+
tracingOptions: params.tracingOptions,
|
|
295
|
+
outputOptions: params.outputOptions
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
const eventId = eventOutput.ids[0];
|
|
299
|
+
if (!eventId) {
|
|
300
|
+
throw new Error("Event ID is not set");
|
|
301
|
+
}
|
|
302
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
303
|
+
const result = runOutput?.output?.result;
|
|
304
|
+
if (result.status === "failed") {
|
|
305
|
+
result.error = new Error(result.error);
|
|
306
|
+
}
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
212
309
|
watch(cb) {
|
|
213
310
|
let active = true;
|
|
214
311
|
const streamPromise = subscribe(
|
|
@@ -358,6 +455,75 @@ var InngestRun = class extends Run {
|
|
|
358
455
|
streamVNext(args = {}) {
|
|
359
456
|
return this.stream(args);
|
|
360
457
|
}
|
|
458
|
+
timeTravelStream({
|
|
459
|
+
inputData,
|
|
460
|
+
resumeData,
|
|
461
|
+
initialState,
|
|
462
|
+
step,
|
|
463
|
+
context,
|
|
464
|
+
nestedStepsContext,
|
|
465
|
+
requestContext,
|
|
466
|
+
tracingOptions,
|
|
467
|
+
outputOptions
|
|
468
|
+
}) {
|
|
469
|
+
this.closeStreamAction = async () => {
|
|
470
|
+
};
|
|
471
|
+
const self = this;
|
|
472
|
+
const stream = new ReadableStream({
|
|
473
|
+
async start(controller) {
|
|
474
|
+
const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
|
|
475
|
+
controller.enqueue({
|
|
476
|
+
type,
|
|
477
|
+
runId: self.runId,
|
|
478
|
+
from,
|
|
479
|
+
payload: {
|
|
480
|
+
stepName: payload?.id,
|
|
481
|
+
...payload
|
|
482
|
+
}
|
|
483
|
+
});
|
|
484
|
+
});
|
|
485
|
+
self.closeStreamAction = async () => {
|
|
486
|
+
unwatch();
|
|
487
|
+
try {
|
|
488
|
+
await controller.close();
|
|
489
|
+
} catch (err) {
|
|
490
|
+
console.error("Error closing stream:", err);
|
|
491
|
+
}
|
|
492
|
+
};
|
|
493
|
+
const executionResultsPromise = self._timeTravel({
|
|
494
|
+
inputData,
|
|
495
|
+
step,
|
|
496
|
+
context,
|
|
497
|
+
nestedStepsContext,
|
|
498
|
+
resumeData,
|
|
499
|
+
initialState,
|
|
500
|
+
requestContext,
|
|
501
|
+
tracingOptions,
|
|
502
|
+
outputOptions
|
|
503
|
+
});
|
|
504
|
+
self.executionResults = executionResultsPromise;
|
|
505
|
+
let executionResults;
|
|
506
|
+
try {
|
|
507
|
+
executionResults = await executionResultsPromise;
|
|
508
|
+
self.closeStreamAction?.().catch(() => {
|
|
509
|
+
});
|
|
510
|
+
if (self.streamOutput) {
|
|
511
|
+
self.streamOutput.updateResults(executionResults);
|
|
512
|
+
}
|
|
513
|
+
} catch (err) {
|
|
514
|
+
self.streamOutput?.rejectResults(err);
|
|
515
|
+
self.closeStreamAction?.().catch(() => {
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
this.streamOutput = new WorkflowRunOutput({
|
|
521
|
+
runId: this.runId,
|
|
522
|
+
workflowId: this.workflowId,
|
|
523
|
+
stream
|
|
524
|
+
});
|
|
525
|
+
return this.streamOutput;
|
|
526
|
+
}
|
|
361
527
|
};
|
|
362
528
|
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
363
529
|
#mastra;
|
|
@@ -367,6 +533,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
367
533
|
constructor(params, inngest) {
|
|
368
534
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
369
535
|
super(workflowParams);
|
|
536
|
+
this.engineType = "inngest";
|
|
370
537
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
371
538
|
([_, value]) => value !== void 0
|
|
372
539
|
);
|
|
@@ -422,7 +589,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
422
589
|
mastra: this.#mastra,
|
|
423
590
|
retryConfig: this.retryConfig,
|
|
424
591
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
425
|
-
workflowSteps: this.steps
|
|
592
|
+
workflowSteps: this.steps,
|
|
593
|
+
workflowEngineType: this.engineType,
|
|
594
|
+
validateInputs: this.options.validateInputs
|
|
426
595
|
},
|
|
427
596
|
this.inngest
|
|
428
597
|
);
|
|
@@ -443,13 +612,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
443
612
|
value: {},
|
|
444
613
|
context: {},
|
|
445
614
|
activePaths: [],
|
|
615
|
+
activeStepsPath: {},
|
|
446
616
|
waitingPaths: {},
|
|
447
617
|
serializedStepGraph: this.serializedStepGraph,
|
|
448
618
|
suspendedPaths: {},
|
|
449
619
|
resumeLabels: {},
|
|
450
620
|
result: void 0,
|
|
451
621
|
error: void 0,
|
|
452
|
-
// @ts-ignore
|
|
453
622
|
timestamp: Date.now()
|
|
454
623
|
}
|
|
455
624
|
});
|
|
@@ -463,15 +632,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
463
632
|
this.function = this.inngest.createFunction(
|
|
464
633
|
{
|
|
465
634
|
id: `workflow.${this.id}`,
|
|
466
|
-
|
|
467
|
-
retries: this.retryConfig?.attempts ?? 0,
|
|
635
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
468
636
|
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
469
637
|
// Spread flow control configuration
|
|
470
638
|
...this.flowControlConfig
|
|
471
639
|
},
|
|
472
640
|
{ event: `workflow.${this.id}` },
|
|
473
641
|
async ({ event, step, attempt, publish }) => {
|
|
474
|
-
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
642
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
475
643
|
if (!runId) {
|
|
476
644
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
477
645
|
return randomUUID();
|
|
@@ -513,6 +681,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
513
681
|
requestContext: new RequestContext(),
|
|
514
682
|
// TODO
|
|
515
683
|
resume,
|
|
684
|
+
timeTravel,
|
|
516
685
|
format,
|
|
517
686
|
abortController: new AbortController(),
|
|
518
687
|
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
@@ -565,13 +734,11 @@ function createStep(params, agentOptions) {
|
|
|
565
734
|
return {
|
|
566
735
|
id: params.name,
|
|
567
736
|
description: params.getDescription(),
|
|
568
|
-
// @ts-ignore
|
|
569
737
|
inputSchema: z.object({
|
|
570
738
|
prompt: z.string()
|
|
571
739
|
// resourceId: z.string().optional(),
|
|
572
740
|
// threadId: z.string().optional(),
|
|
573
741
|
}),
|
|
574
|
-
// @ts-ignore
|
|
575
742
|
outputSchema: z.object({
|
|
576
743
|
text: z.string()
|
|
577
744
|
}),
|
|
@@ -661,20 +828,38 @@ function createStep(params, agentOptions) {
|
|
|
661
828
|
}
|
|
662
829
|
return {
|
|
663
830
|
// TODO: tool probably should have strong id type
|
|
664
|
-
// @ts-ignore
|
|
665
831
|
id: params.id,
|
|
666
832
|
description: params.description,
|
|
667
833
|
inputSchema: params.inputSchema,
|
|
668
834
|
outputSchema: params.outputSchema,
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
835
|
+
suspendSchema: params.suspendSchema,
|
|
836
|
+
resumeSchema: params.resumeSchema,
|
|
837
|
+
execute: async ({
|
|
838
|
+
inputData,
|
|
839
|
+
mastra,
|
|
840
|
+
requestContext,
|
|
841
|
+
tracingContext,
|
|
842
|
+
suspend,
|
|
843
|
+
resumeData,
|
|
844
|
+
runId,
|
|
845
|
+
workflowId,
|
|
846
|
+
state,
|
|
847
|
+
setState
|
|
848
|
+
}) => {
|
|
849
|
+
const toolContext = {
|
|
850
|
+
mastra,
|
|
673
851
|
requestContext,
|
|
674
852
|
tracingContext,
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
853
|
+
workflow: {
|
|
854
|
+
runId,
|
|
855
|
+
resumeData,
|
|
856
|
+
suspend,
|
|
857
|
+
workflowId,
|
|
858
|
+
state,
|
|
859
|
+
setState
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
return params.execute(inputData, toolContext);
|
|
678
863
|
},
|
|
679
864
|
component: "TOOL"
|
|
680
865
|
};
|
|
@@ -708,6 +893,8 @@ function init(inngest) {
|
|
|
708
893
|
suspendSchema: step.suspendSchema,
|
|
709
894
|
stateSchema: step.stateSchema,
|
|
710
895
|
execute: step.execute,
|
|
896
|
+
retries: step.retries,
|
|
897
|
+
scorers: step.scorers,
|
|
711
898
|
component: step.component
|
|
712
899
|
};
|
|
713
900
|
},
|
|
@@ -947,6 +1134,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
947
1134
|
stepResults,
|
|
948
1135
|
executionContext,
|
|
949
1136
|
resume,
|
|
1137
|
+
timeTravel,
|
|
950
1138
|
prevOutput,
|
|
951
1139
|
emitter,
|
|
952
1140
|
abortController,
|
|
@@ -967,7 +1155,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
967
1155
|
const { inputData, validationError } = await validateStepInput({
|
|
968
1156
|
prevOutput,
|
|
969
1157
|
step,
|
|
970
|
-
validateInputs: this.options?.validateInputs ??
|
|
1158
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
971
1159
|
});
|
|
972
1160
|
const startedAt = await this.inngestStep.run(
|
|
973
1161
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
@@ -989,9 +1177,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
989
1177
|
const isResume = !!resume?.steps?.length;
|
|
990
1178
|
let result;
|
|
991
1179
|
let runId;
|
|
1180
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
992
1181
|
try {
|
|
993
1182
|
if (isResume) {
|
|
994
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
1183
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
995
1184
|
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
996
1185
|
workflowName: step.id,
|
|
997
1186
|
runId
|
|
@@ -1007,8 +1196,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1007
1196
|
steps: resume.steps.slice(1),
|
|
1008
1197
|
stepResults: snapshot?.context,
|
|
1009
1198
|
resumePayload: resume.resumePayload,
|
|
1010
|
-
|
|
1011
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1199
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1012
1200
|
},
|
|
1013
1201
|
outputOptions: { includeState: true }
|
|
1014
1202
|
}
|
|
@@ -1016,6 +1204,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1016
1204
|
result = invokeResp.result;
|
|
1017
1205
|
runId = invokeResp.runId;
|
|
1018
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 = 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;
|
|
1019
1233
|
} else {
|
|
1020
1234
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1021
1235
|
function: step.getFunction(),
|
|
@@ -1128,14 +1342,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1128
1342
|
let execResults;
|
|
1129
1343
|
let suspended;
|
|
1130
1344
|
let bailed;
|
|
1345
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await 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
|
+
}
|
|
1131
1360
|
try {
|
|
1132
1361
|
if (validationError) {
|
|
1133
1362
|
throw validationError;
|
|
1134
1363
|
}
|
|
1364
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1135
1365
|
const result = await step.execute({
|
|
1136
1366
|
runId: executionContext.runId,
|
|
1367
|
+
workflowId: executionContext.workflowId,
|
|
1137
1368
|
mastra: this.mastra,
|
|
1138
1369
|
requestContext,
|
|
1370
|
+
retryCount,
|
|
1139
1371
|
writer: new ToolStream(
|
|
1140
1372
|
{
|
|
1141
1373
|
prefix: "workflow-step",
|
|
@@ -1150,13 +1382,20 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1150
1382
|
executionContext.state = state;
|
|
1151
1383
|
},
|
|
1152
1384
|
inputData,
|
|
1153
|
-
resumeData:
|
|
1385
|
+
resumeData: resumeDataToUse,
|
|
1154
1386
|
tracingContext: {
|
|
1155
1387
|
currentSpan: stepSpan
|
|
1156
1388
|
},
|
|
1157
1389
|
getInitData: () => stepResults?.input,
|
|
1158
1390
|
getStepResult: getStepResult.bind(this, stepResults),
|
|
1159
1391
|
suspend: async (suspendPayload, suspendOptions) => {
|
|
1392
|
+
const { suspendData, validationError: validationError2 } = await validateStepSuspendData({
|
|
1393
|
+
suspendData: suspendPayload,
|
|
1394
|
+
step
|
|
1395
|
+
});
|
|
1396
|
+
if (validationError2) {
|
|
1397
|
+
throw validationError2;
|
|
1398
|
+
}
|
|
1160
1399
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1161
1400
|
if (suspendOptions?.resumeLabel) {
|
|
1162
1401
|
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
@@ -1167,16 +1406,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1167
1406
|
};
|
|
1168
1407
|
}
|
|
1169
1408
|
}
|
|
1170
|
-
suspended = { payload:
|
|
1409
|
+
suspended = { payload: suspendData };
|
|
1171
1410
|
},
|
|
1172
1411
|
bail: (result2) => {
|
|
1173
1412
|
bailed = { payload: result2 };
|
|
1174
1413
|
},
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
resumePayload: resume?.resumePayload,
|
|
1178
|
-
// @ts-ignore
|
|
1179
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1414
|
+
abort: () => {
|
|
1415
|
+
abortController?.abort();
|
|
1180
1416
|
},
|
|
1181
1417
|
[EMITTER_SYMBOL]: emitter,
|
|
1182
1418
|
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
@@ -1192,8 +1428,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1192
1428
|
startedAt,
|
|
1193
1429
|
endedAt,
|
|
1194
1430
|
payload: inputData,
|
|
1195
|
-
resumedAt:
|
|
1196
|
-
resumePayload:
|
|
1431
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1432
|
+
resumePayload: resumeDataToUse
|
|
1197
1433
|
};
|
|
1198
1434
|
} catch (e) {
|
|
1199
1435
|
const stepFailure = {
|
|
@@ -1202,8 +1438,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1202
1438
|
error: e instanceof Error ? e.message : String(e),
|
|
1203
1439
|
endedAt: Date.now(),
|
|
1204
1440
|
startedAt,
|
|
1205
|
-
resumedAt:
|
|
1206
|
-
resumePayload:
|
|
1441
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1442
|
+
resumePayload: resumeDataToUse
|
|
1207
1443
|
};
|
|
1208
1444
|
execResults = stepFailure;
|
|
1209
1445
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
@@ -1220,8 +1456,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1220
1456
|
payload: inputData,
|
|
1221
1457
|
suspendedAt: Date.now(),
|
|
1222
1458
|
startedAt,
|
|
1223
|
-
resumedAt:
|
|
1224
|
-
resumePayload:
|
|
1459
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1460
|
+
resumePayload: resumeDataToUse
|
|
1225
1461
|
};
|
|
1226
1462
|
} else if (bailed) {
|
|
1227
1463
|
execResults = {
|
|
@@ -1294,7 +1530,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1294
1530
|
});
|
|
1295
1531
|
}
|
|
1296
1532
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1297
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1298
1533
|
executionContext.state = stepRes.executionContext.state;
|
|
1299
1534
|
return stepRes.result;
|
|
1300
1535
|
}
|
|
@@ -1322,17 +1557,17 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1322
1557
|
resourceId,
|
|
1323
1558
|
snapshot: {
|
|
1324
1559
|
runId,
|
|
1560
|
+
status: workflowStatus,
|
|
1325
1561
|
value: executionContext.state,
|
|
1326
1562
|
context: stepResults,
|
|
1327
|
-
activePaths:
|
|
1563
|
+
activePaths: executionContext.executionPath,
|
|
1564
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1328
1565
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1329
1566
|
resumeLabels: executionContext.resumeLabels,
|
|
1330
1567
|
waitingPaths: {},
|
|
1331
1568
|
serializedStepGraph,
|
|
1332
|
-
status: workflowStatus,
|
|
1333
1569
|
result,
|
|
1334
1570
|
error,
|
|
1335
|
-
// @ts-ignore
|
|
1336
1571
|
timestamp: Date.now()
|
|
1337
1572
|
}
|
|
1338
1573
|
});
|
|
@@ -1345,6 +1580,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1345
1580
|
entry,
|
|
1346
1581
|
prevOutput,
|
|
1347
1582
|
stepResults,
|
|
1583
|
+
timeTravel,
|
|
1348
1584
|
resume,
|
|
1349
1585
|
executionContext,
|
|
1350
1586
|
emitter,
|
|
@@ -1463,10 +1699,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1463
1699
|
prevOutput,
|
|
1464
1700
|
stepResults,
|
|
1465
1701
|
resume,
|
|
1702
|
+
timeTravel,
|
|
1466
1703
|
executionContext: {
|
|
1467
1704
|
workflowId,
|
|
1468
1705
|
runId,
|
|
1469
1706
|
executionPath: [...executionContext.executionPath, index],
|
|
1707
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1470
1708
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1471
1709
|
resumeLabels: executionContext.resumeLabels,
|
|
1472
1710
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1500,7 +1738,9 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1500
1738
|
status: "success",
|
|
1501
1739
|
output: results.reduce((acc, result, index) => {
|
|
1502
1740
|
if (result.status === "success") {
|
|
1503
|
-
|
|
1741
|
+
if ("step" in stepsToRun[index]) {
|
|
1742
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1743
|
+
}
|
|
1504
1744
|
}
|
|
1505
1745
|
return acc;
|
|
1506
1746
|
}, {})
|