@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.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(
|
|
@@ -235,14 +332,14 @@ var InngestRun = class extends Run {
|
|
|
235
332
|
streamLegacy({ inputData, requestContext } = {}) {
|
|
236
333
|
const { readable, writable } = new TransformStream();
|
|
237
334
|
const writer = writable.getWriter();
|
|
335
|
+
void writer.write({
|
|
336
|
+
// @ts-ignore
|
|
337
|
+
type: "start",
|
|
338
|
+
// @ts-ignore
|
|
339
|
+
payload: { runId: this.runId }
|
|
340
|
+
});
|
|
238
341
|
const unwatch = this.watch(async (event) => {
|
|
239
342
|
try {
|
|
240
|
-
await writer.write({
|
|
241
|
-
// @ts-ignore
|
|
242
|
-
type: "start",
|
|
243
|
-
// @ts-ignore
|
|
244
|
-
payload: { runId: this.runId }
|
|
245
|
-
});
|
|
246
343
|
const e = {
|
|
247
344
|
...event,
|
|
248
345
|
type: event.type.replace("workflow-", "")
|
|
@@ -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
|
},
|
|
@@ -717,7 +904,8 @@ function init(inngest) {
|
|
|
717
904
|
inputSchema: workflow.inputSchema,
|
|
718
905
|
outputSchema: workflow.outputSchema,
|
|
719
906
|
steps: workflow.stepDefs,
|
|
720
|
-
mastra: workflow.mastra
|
|
907
|
+
mastra: workflow.mastra,
|
|
908
|
+
options: workflow.options
|
|
721
909
|
});
|
|
722
910
|
wf.setStepFlow(workflow.stepGraph);
|
|
723
911
|
wf.commit();
|
|
@@ -947,6 +1135,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
947
1135
|
stepResults,
|
|
948
1136
|
executionContext,
|
|
949
1137
|
resume,
|
|
1138
|
+
timeTravel,
|
|
950
1139
|
prevOutput,
|
|
951
1140
|
emitter,
|
|
952
1141
|
abortController,
|
|
@@ -967,7 +1156,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
967
1156
|
const { inputData, validationError } = await validateStepInput({
|
|
968
1157
|
prevOutput,
|
|
969
1158
|
step,
|
|
970
|
-
validateInputs: this.options?.validateInputs ??
|
|
1159
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
971
1160
|
});
|
|
972
1161
|
const startedAt = await this.inngestStep.run(
|
|
973
1162
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
@@ -989,9 +1178,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
989
1178
|
const isResume = !!resume?.steps?.length;
|
|
990
1179
|
let result;
|
|
991
1180
|
let runId;
|
|
1181
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
992
1182
|
try {
|
|
993
1183
|
if (isResume) {
|
|
994
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
1184
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
995
1185
|
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
996
1186
|
workflowName: step.id,
|
|
997
1187
|
runId
|
|
@@ -1007,8 +1197,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1007
1197
|
steps: resume.steps.slice(1),
|
|
1008
1198
|
stepResults: snapshot?.context,
|
|
1009
1199
|
resumePayload: resume.resumePayload,
|
|
1010
|
-
|
|
1011
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1200
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1012
1201
|
},
|
|
1013
1202
|
outputOptions: { includeState: true }
|
|
1014
1203
|
}
|
|
@@ -1016,6 +1205,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1016
1205
|
result = invokeResp.result;
|
|
1017
1206
|
runId = invokeResp.runId;
|
|
1018
1207
|
executionContext.state = invokeResp.result.state;
|
|
1208
|
+
} else if (isTimeTravel) {
|
|
1209
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1210
|
+
workflowName: step.id,
|
|
1211
|
+
runId: executionContext.runId
|
|
1212
|
+
}) ?? { context: {} };
|
|
1213
|
+
const timeTravelParams = createTimeTravelExecutionParams({
|
|
1214
|
+
steps: timeTravel.steps.slice(1),
|
|
1215
|
+
inputData: timeTravel.inputData,
|
|
1216
|
+
resumeData: timeTravel.resumeData,
|
|
1217
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1218
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1219
|
+
snapshot,
|
|
1220
|
+
graph: step.buildExecutionGraph()
|
|
1221
|
+
});
|
|
1222
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1223
|
+
function: step.getFunction(),
|
|
1224
|
+
data: {
|
|
1225
|
+
timeTravel: timeTravelParams,
|
|
1226
|
+
initialState: executionContext.state ?? {},
|
|
1227
|
+
runId: executionContext.runId,
|
|
1228
|
+
outputOptions: { includeState: true }
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
result = invokeResp.result;
|
|
1232
|
+
runId = invokeResp.runId;
|
|
1233
|
+
executionContext.state = invokeResp.result.state;
|
|
1019
1234
|
} else {
|
|
1020
1235
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1021
1236
|
function: step.getFunction(),
|
|
@@ -1128,14 +1343,32 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1128
1343
|
let execResults;
|
|
1129
1344
|
let suspended;
|
|
1130
1345
|
let bailed;
|
|
1346
|
+
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await validateStepResumeData({
|
|
1347
|
+
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1348
|
+
step
|
|
1349
|
+
});
|
|
1350
|
+
let resumeDataToUse;
|
|
1351
|
+
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1352
|
+
resumeDataToUse = timeTravelResumeData;
|
|
1353
|
+
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1354
|
+
this.logger.warn("Time travel resume data validation failed", {
|
|
1355
|
+
stepId: step.id,
|
|
1356
|
+
error: timeTravelResumeValidationError.message
|
|
1357
|
+
});
|
|
1358
|
+
} else if (resume?.steps[0] === step.id) {
|
|
1359
|
+
resumeDataToUse = resume?.resumePayload;
|
|
1360
|
+
}
|
|
1131
1361
|
try {
|
|
1132
1362
|
if (validationError) {
|
|
1133
1363
|
throw validationError;
|
|
1134
1364
|
}
|
|
1365
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1135
1366
|
const result = await step.execute({
|
|
1136
1367
|
runId: executionContext.runId,
|
|
1368
|
+
workflowId: executionContext.workflowId,
|
|
1137
1369
|
mastra: this.mastra,
|
|
1138
1370
|
requestContext,
|
|
1371
|
+
retryCount,
|
|
1139
1372
|
writer: new ToolStream(
|
|
1140
1373
|
{
|
|
1141
1374
|
prefix: "workflow-step",
|
|
@@ -1150,13 +1383,20 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1150
1383
|
executionContext.state = state;
|
|
1151
1384
|
},
|
|
1152
1385
|
inputData,
|
|
1153
|
-
resumeData:
|
|
1386
|
+
resumeData: resumeDataToUse,
|
|
1154
1387
|
tracingContext: {
|
|
1155
1388
|
currentSpan: stepSpan
|
|
1156
1389
|
},
|
|
1157
1390
|
getInitData: () => stepResults?.input,
|
|
1158
1391
|
getStepResult: getStepResult.bind(this, stepResults),
|
|
1159
1392
|
suspend: async (suspendPayload, suspendOptions) => {
|
|
1393
|
+
const { suspendData, validationError: validationError2 } = await validateStepSuspendData({
|
|
1394
|
+
suspendData: suspendPayload,
|
|
1395
|
+
step
|
|
1396
|
+
});
|
|
1397
|
+
if (validationError2) {
|
|
1398
|
+
throw validationError2;
|
|
1399
|
+
}
|
|
1160
1400
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1161
1401
|
if (suspendOptions?.resumeLabel) {
|
|
1162
1402
|
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
@@ -1167,16 +1407,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1167
1407
|
};
|
|
1168
1408
|
}
|
|
1169
1409
|
}
|
|
1170
|
-
suspended = { payload:
|
|
1410
|
+
suspended = { payload: suspendData };
|
|
1171
1411
|
},
|
|
1172
1412
|
bail: (result2) => {
|
|
1173
1413
|
bailed = { payload: result2 };
|
|
1174
1414
|
},
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
resumePayload: resume?.resumePayload,
|
|
1178
|
-
// @ts-ignore
|
|
1179
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1415
|
+
abort: () => {
|
|
1416
|
+
abortController?.abort();
|
|
1180
1417
|
},
|
|
1181
1418
|
[EMITTER_SYMBOL]: emitter,
|
|
1182
1419
|
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
@@ -1192,8 +1429,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1192
1429
|
startedAt,
|
|
1193
1430
|
endedAt,
|
|
1194
1431
|
payload: inputData,
|
|
1195
|
-
resumedAt:
|
|
1196
|
-
resumePayload:
|
|
1432
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1433
|
+
resumePayload: resumeDataToUse
|
|
1197
1434
|
};
|
|
1198
1435
|
} catch (e) {
|
|
1199
1436
|
const stepFailure = {
|
|
@@ -1202,8 +1439,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1202
1439
|
error: e instanceof Error ? e.message : String(e),
|
|
1203
1440
|
endedAt: Date.now(),
|
|
1204
1441
|
startedAt,
|
|
1205
|
-
resumedAt:
|
|
1206
|
-
resumePayload:
|
|
1442
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1443
|
+
resumePayload: resumeDataToUse
|
|
1207
1444
|
};
|
|
1208
1445
|
execResults = stepFailure;
|
|
1209
1446
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
@@ -1216,11 +1453,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1216
1453
|
execResults = {
|
|
1217
1454
|
status: "suspended",
|
|
1218
1455
|
suspendPayload: suspended.payload,
|
|
1456
|
+
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1219
1457
|
payload: inputData,
|
|
1220
1458
|
suspendedAt: Date.now(),
|
|
1221
1459
|
startedAt,
|
|
1222
|
-
resumedAt:
|
|
1223
|
-
resumePayload:
|
|
1460
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1461
|
+
resumePayload: resumeDataToUse
|
|
1224
1462
|
};
|
|
1225
1463
|
} else if (bailed) {
|
|
1226
1464
|
execResults = {
|
|
@@ -1266,6 +1504,20 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1266
1504
|
startedAt,
|
|
1267
1505
|
endedAt: Date.now()
|
|
1268
1506
|
};
|
|
1507
|
+
await emitter.emit("watch", {
|
|
1508
|
+
type: "workflow-step-result",
|
|
1509
|
+
payload: {
|
|
1510
|
+
id: step.id,
|
|
1511
|
+
...stepFailure
|
|
1512
|
+
}
|
|
1513
|
+
});
|
|
1514
|
+
await emitter.emit("watch", {
|
|
1515
|
+
type: "workflow-step-finish",
|
|
1516
|
+
payload: {
|
|
1517
|
+
id: step.id,
|
|
1518
|
+
metadata: {}
|
|
1519
|
+
}
|
|
1520
|
+
});
|
|
1269
1521
|
stepRes = {
|
|
1270
1522
|
result: stepFailure,
|
|
1271
1523
|
executionContext,
|
|
@@ -1293,7 +1545,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1293
1545
|
});
|
|
1294
1546
|
}
|
|
1295
1547
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1296
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1297
1548
|
executionContext.state = stepRes.executionContext.state;
|
|
1298
1549
|
return stepRes.result;
|
|
1299
1550
|
}
|
|
@@ -1321,17 +1572,17 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1321
1572
|
resourceId,
|
|
1322
1573
|
snapshot: {
|
|
1323
1574
|
runId,
|
|
1575
|
+
status: workflowStatus,
|
|
1324
1576
|
value: executionContext.state,
|
|
1325
1577
|
context: stepResults,
|
|
1326
|
-
activePaths:
|
|
1578
|
+
activePaths: executionContext.executionPath,
|
|
1579
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1327
1580
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1328
1581
|
resumeLabels: executionContext.resumeLabels,
|
|
1329
1582
|
waitingPaths: {},
|
|
1330
1583
|
serializedStepGraph,
|
|
1331
|
-
status: workflowStatus,
|
|
1332
1584
|
result,
|
|
1333
1585
|
error,
|
|
1334
|
-
// @ts-ignore
|
|
1335
1586
|
timestamp: Date.now()
|
|
1336
1587
|
}
|
|
1337
1588
|
});
|
|
@@ -1344,6 +1595,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1344
1595
|
entry,
|
|
1345
1596
|
prevOutput,
|
|
1346
1597
|
stepResults,
|
|
1598
|
+
timeTravel,
|
|
1347
1599
|
resume,
|
|
1348
1600
|
executionContext,
|
|
1349
1601
|
emitter,
|
|
@@ -1462,10 +1714,12 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1462
1714
|
prevOutput,
|
|
1463
1715
|
stepResults,
|
|
1464
1716
|
resume,
|
|
1717
|
+
timeTravel,
|
|
1465
1718
|
executionContext: {
|
|
1466
1719
|
workflowId,
|
|
1467
1720
|
runId,
|
|
1468
1721
|
executionPath: [...executionContext.executionPath, index],
|
|
1722
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1469
1723
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1470
1724
|
resumeLabels: executionContext.resumeLabels,
|
|
1471
1725
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1489,13 +1743,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1489
1743
|
if (hasFailed) {
|
|
1490
1744
|
execResults = { status: "failed", error: hasFailed.error };
|
|
1491
1745
|
} else if (hasSuspended) {
|
|
1492
|
-
execResults = {
|
|
1746
|
+
execResults = {
|
|
1747
|
+
status: "suspended",
|
|
1748
|
+
suspendPayload: hasSuspended.suspendPayload,
|
|
1749
|
+
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1750
|
+
};
|
|
1493
1751
|
} else {
|
|
1494
1752
|
execResults = {
|
|
1495
1753
|
status: "success",
|
|
1496
1754
|
output: results.reduce((acc, result, index) => {
|
|
1497
1755
|
if (result.status === "success") {
|
|
1498
|
-
|
|
1756
|
+
if ("step" in stepsToRun[index]) {
|
|
1757
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1758
|
+
}
|
|
1499
1759
|
}
|
|
1500
1760
|
return acc;
|
|
1501
1761
|
}, {})
|