@mastra/inngest 1.0.0-beta.0 → 1.0.0-beta.2
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 +56 -0
- package/dist/index.cjs +282 -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 +284 -48
- package/dist/index.js.map +1 -1
- package/package.json +11 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# @mastra/inngest
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dependencies updates: ([#10120](https://github.com/mastra-ai/mastra/pull/10120))
|
|
8
|
+
- Updated dependency [`@inngest/realtime@^0.4.5` ↗︎](https://www.npmjs.com/package/@inngest/realtime/v/0.4.5) (from `^0.4.4`, in `dependencies`)
|
|
9
|
+
|
|
10
|
+
- fix resumeStream type to use resumeSchema ([#10202](https://github.com/mastra-ai/mastra/pull/10202))
|
|
11
|
+
|
|
12
|
+
- Add restart method to workflow run that allows restarting an active workflow run ([#9750](https://github.com/mastra-ai/mastra/pull/9750))
|
|
13
|
+
Add status filter to `listWorkflowRuns`
|
|
14
|
+
Add automatic restart to restart active workflow runs when server starts
|
|
15
|
+
|
|
16
|
+
- Validate schemas by default in workflow. Previously, if you want schemas in the workflow to be validated, you'd have to add `validateInputs` option, now, this will be done by default but can be disabled. ([#10186](https://github.com/mastra-ai/mastra/pull/10186))
|
|
17
|
+
|
|
18
|
+
For workflows whose schemas and step schemas you don't want validated, do this
|
|
19
|
+
|
|
20
|
+
```diff
|
|
21
|
+
createWorkflow({
|
|
22
|
+
+ options: {
|
|
23
|
+
+ validateInputs: false
|
|
24
|
+
+ }
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Fix inngest parallel workflow ([#10169](https://github.com/mastra-ai/mastra/pull/10169))
|
|
29
|
+
Fix tool as step in inngest
|
|
30
|
+
Fix inngest nested workflow
|
|
31
|
+
|
|
32
|
+
- Add timeTravel to workflows. This makes it possible to start a workflow run from a particular step in the workflow ([#9994](https://github.com/mastra-ai/mastra/pull/9994))
|
|
33
|
+
|
|
34
|
+
Example code:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const result = await run.timeTravel({
|
|
38
|
+
step: 'step2',
|
|
39
|
+
inputData: {
|
|
40
|
+
value: 'input',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- Updated dependencies [[`2319326`](https://github.com/mastra-ai/mastra/commit/2319326f8c64e503a09bbcf14be2dd65405445e0), [`d629361`](https://github.com/mastra-ai/mastra/commit/d629361a60f6565b5bfb11976fdaf7308af858e2), [`08c31c1`](https://github.com/mastra-ai/mastra/commit/08c31c188ebccd598acaf55e888b6397d01f7eae), [`fd3d338`](https://github.com/mastra-ai/mastra/commit/fd3d338a2c362174ed5b383f1f011ad9fb0302aa), [`c30400a`](https://github.com/mastra-ai/mastra/commit/c30400a49b994b1b97256fe785eb6c906fc2b232), [`69e0a87`](https://github.com/mastra-ai/mastra/commit/69e0a878896a2da9494945d86e056a5f8f05b851), [`01f8878`](https://github.com/mastra-ai/mastra/commit/01f88783de25e4de048c1c8aace43e26373c6ea5), [`4c77209`](https://github.com/mastra-ai/mastra/commit/4c77209e6c11678808b365d545845918c40045c8), [`d827d08`](https://github.com/mastra-ai/mastra/commit/d827d0808ffe1f3553a84e975806cc989b9735dd), [`23c10a1`](https://github.com/mastra-ai/mastra/commit/23c10a1efdd9a693c405511ab2dc8a1236603162), [`676ccc7`](https://github.com/mastra-ai/mastra/commit/676ccc7fe92468d2d45d39c31a87825c89fd1ea0), [`c10398d`](https://github.com/mastra-ai/mastra/commit/c10398d5b88f1d4af556f4267ff06f1d11e89179), [`00c2387`](https://github.com/mastra-ai/mastra/commit/00c2387f5f04a365316f851e58666ac43f8c4edf), [`ad6250d`](https://github.com/mastra-ai/mastra/commit/ad6250dbdaad927e29f74a27b83f6c468b50a705), [`3a73998`](https://github.com/mastra-ai/mastra/commit/3a73998fa4ebeb7f3dc9301afe78095fc63e7999), [`e16d553`](https://github.com/mastra-ai/mastra/commit/e16d55338403c7553531cc568125c63d53653dff), [`4d59f58`](https://github.com/mastra-ai/mastra/commit/4d59f58de2d90d6e2810a19d4518e38ddddb9038), [`e1bb9c9`](https://github.com/mastra-ai/mastra/commit/e1bb9c94b4eb68b019ae275981be3feb769b5365), [`351a11f`](https://github.com/mastra-ai/mastra/commit/351a11fcaf2ed1008977fa9b9a489fc422e51cd4)]:
|
|
46
|
+
- @mastra/core@1.0.0-beta.3
|
|
47
|
+
|
|
48
|
+
## 1.0.0-beta.1
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- Make suspendPayload optional when calling `suspend()` ([#9926](https://github.com/mastra-ai/mastra/pull/9926))
|
|
53
|
+
Save value returned as `suspendOutput` if user returns data still after calling `suspend()`
|
|
54
|
+
Automatically call `commit()` on uncommitted workflows when registering in Mastra instance
|
|
55
|
+
Show actual suspendPayload on Studio in suspend/resume flow
|
|
56
|
+
- Updated dependencies [[`465ac05`](https://github.com/mastra-ai/mastra/commit/465ac0526a91d175542091c675181f1a96c98c46)]:
|
|
57
|
+
- @mastra/core@1.0.0-beta.2
|
|
58
|
+
|
|
3
59
|
## 1.0.0-beta.0
|
|
4
60
|
|
|
5
61
|
### Major Changes
|
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(
|
|
@@ -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,36 @@ 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
|
-
execute: async ({
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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,
|
|
675
851
|
requestContext,
|
|
676
852
|
tracingContext,
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
853
|
+
resumeData,
|
|
854
|
+
workflow: {
|
|
855
|
+
runId,
|
|
856
|
+
suspend,
|
|
857
|
+
workflowId,
|
|
858
|
+
state,
|
|
859
|
+
setState
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
return params.execute(inputData, toolContext);
|
|
680
863
|
},
|
|
681
864
|
component: "TOOL"
|
|
682
865
|
};
|
|
@@ -710,6 +893,8 @@ function init(inngest) {
|
|
|
710
893
|
suspendSchema: step.suspendSchema,
|
|
711
894
|
stateSchema: step.stateSchema,
|
|
712
895
|
execute: step.execute,
|
|
896
|
+
retries: step.retries,
|
|
897
|
+
scorers: step.scorers,
|
|
713
898
|
component: step.component
|
|
714
899
|
};
|
|
715
900
|
},
|
|
@@ -949,6 +1134,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
949
1134
|
stepResults,
|
|
950
1135
|
executionContext,
|
|
951
1136
|
resume,
|
|
1137
|
+
timeTravel,
|
|
952
1138
|
prevOutput,
|
|
953
1139
|
emitter,
|
|
954
1140
|
abortController,
|
|
@@ -969,7 +1155,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
969
1155
|
const { inputData, validationError } = await workflows.validateStepInput({
|
|
970
1156
|
prevOutput,
|
|
971
1157
|
step,
|
|
972
|
-
validateInputs: this.options?.validateInputs ??
|
|
1158
|
+
validateInputs: this.options?.validateInputs ?? true
|
|
973
1159
|
});
|
|
974
1160
|
const startedAt = await this.inngestStep.run(
|
|
975
1161
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
@@ -991,9 +1177,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
991
1177
|
const isResume = !!resume?.steps?.length;
|
|
992
1178
|
let result;
|
|
993
1179
|
let runId;
|
|
1180
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
994
1181
|
try {
|
|
995
1182
|
if (isResume) {
|
|
996
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1183
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
997
1184
|
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
998
1185
|
workflowName: step.id,
|
|
999
1186
|
runId
|
|
@@ -1009,8 +1196,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1009
1196
|
steps: resume.steps.slice(1),
|
|
1010
1197
|
stepResults: snapshot?.context,
|
|
1011
1198
|
resumePayload: resume.resumePayload,
|
|
1012
|
-
|
|
1013
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1199
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1014
1200
|
},
|
|
1015
1201
|
outputOptions: { includeState: true }
|
|
1016
1202
|
}
|
|
@@ -1018,6 +1204,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1018
1204
|
result = invokeResp.result;
|
|
1019
1205
|
runId = invokeResp.runId;
|
|
1020
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;
|
|
1021
1233
|
} else {
|
|
1022
1234
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1023
1235
|
function: step.getFunction(),
|
|
@@ -1130,14 +1342,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1130
1342
|
let execResults;
|
|
1131
1343
|
let suspended;
|
|
1132
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
|
+
}
|
|
1133
1360
|
try {
|
|
1134
1361
|
if (validationError) {
|
|
1135
1362
|
throw validationError;
|
|
1136
1363
|
}
|
|
1364
|
+
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1137
1365
|
const result = await step.execute({
|
|
1138
1366
|
runId: executionContext.runId,
|
|
1367
|
+
workflowId: executionContext.workflowId,
|
|
1139
1368
|
mastra: this.mastra,
|
|
1140
1369
|
requestContext,
|
|
1370
|
+
retryCount,
|
|
1141
1371
|
writer: new tools.ToolStream(
|
|
1142
1372
|
{
|
|
1143
1373
|
prefix: "workflow-step",
|
|
@@ -1152,7 +1382,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1152
1382
|
executionContext.state = state;
|
|
1153
1383
|
},
|
|
1154
1384
|
inputData,
|
|
1155
|
-
resumeData:
|
|
1385
|
+
resumeData: resumeDataToUse,
|
|
1156
1386
|
tracingContext: {
|
|
1157
1387
|
currentSpan: stepSpan
|
|
1158
1388
|
},
|
|
@@ -1174,11 +1404,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1174
1404
|
bail: (result2) => {
|
|
1175
1405
|
bailed = { payload: result2 };
|
|
1176
1406
|
},
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
resumePayload: resume?.resumePayload,
|
|
1180
|
-
// @ts-ignore
|
|
1181
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1407
|
+
abort: () => {
|
|
1408
|
+
abortController?.abort();
|
|
1182
1409
|
},
|
|
1183
1410
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1184
1411
|
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
@@ -1194,8 +1421,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1194
1421
|
startedAt,
|
|
1195
1422
|
endedAt,
|
|
1196
1423
|
payload: inputData,
|
|
1197
|
-
resumedAt:
|
|
1198
|
-
resumePayload:
|
|
1424
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1425
|
+
resumePayload: resumeDataToUse
|
|
1199
1426
|
};
|
|
1200
1427
|
} catch (e) {
|
|
1201
1428
|
const stepFailure = {
|
|
@@ -1204,8 +1431,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1204
1431
|
error: e instanceof Error ? e.message : String(e),
|
|
1205
1432
|
endedAt: Date.now(),
|
|
1206
1433
|
startedAt,
|
|
1207
|
-
resumedAt:
|
|
1208
|
-
resumePayload:
|
|
1434
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1435
|
+
resumePayload: resumeDataToUse
|
|
1209
1436
|
};
|
|
1210
1437
|
execResults = stepFailure;
|
|
1211
1438
|
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
@@ -1218,11 +1445,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1218
1445
|
execResults = {
|
|
1219
1446
|
status: "suspended",
|
|
1220
1447
|
suspendPayload: suspended.payload,
|
|
1448
|
+
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1221
1449
|
payload: inputData,
|
|
1222
1450
|
suspendedAt: Date.now(),
|
|
1223
1451
|
startedAt,
|
|
1224
|
-
resumedAt:
|
|
1225
|
-
resumePayload:
|
|
1452
|
+
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1453
|
+
resumePayload: resumeDataToUse
|
|
1226
1454
|
};
|
|
1227
1455
|
} else if (bailed) {
|
|
1228
1456
|
execResults = {
|
|
@@ -1295,7 +1523,6 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1295
1523
|
});
|
|
1296
1524
|
}
|
|
1297
1525
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1298
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1299
1526
|
executionContext.state = stepRes.executionContext.state;
|
|
1300
1527
|
return stepRes.result;
|
|
1301
1528
|
}
|
|
@@ -1323,17 +1550,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1323
1550
|
resourceId,
|
|
1324
1551
|
snapshot: {
|
|
1325
1552
|
runId,
|
|
1553
|
+
status: workflowStatus,
|
|
1326
1554
|
value: executionContext.state,
|
|
1327
1555
|
context: stepResults,
|
|
1328
|
-
activePaths:
|
|
1556
|
+
activePaths: executionContext.executionPath,
|
|
1557
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1329
1558
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1330
1559
|
resumeLabels: executionContext.resumeLabels,
|
|
1331
1560
|
waitingPaths: {},
|
|
1332
1561
|
serializedStepGraph,
|
|
1333
|
-
status: workflowStatus,
|
|
1334
1562
|
result,
|
|
1335
1563
|
error,
|
|
1336
|
-
// @ts-ignore
|
|
1337
1564
|
timestamp: Date.now()
|
|
1338
1565
|
}
|
|
1339
1566
|
});
|
|
@@ -1346,6 +1573,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1346
1573
|
entry,
|
|
1347
1574
|
prevOutput,
|
|
1348
1575
|
stepResults,
|
|
1576
|
+
timeTravel,
|
|
1349
1577
|
resume,
|
|
1350
1578
|
executionContext,
|
|
1351
1579
|
emitter,
|
|
@@ -1464,10 +1692,12 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1464
1692
|
prevOutput,
|
|
1465
1693
|
stepResults,
|
|
1466
1694
|
resume,
|
|
1695
|
+
timeTravel,
|
|
1467
1696
|
executionContext: {
|
|
1468
1697
|
workflowId,
|
|
1469
1698
|
runId,
|
|
1470
1699
|
executionPath: [...executionContext.executionPath, index],
|
|
1700
|
+
activeStepsPath: executionContext.activeStepsPath,
|
|
1471
1701
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1472
1702
|
resumeLabels: executionContext.resumeLabels,
|
|
1473
1703
|
retryConfig: executionContext.retryConfig,
|
|
@@ -1491,13 +1721,19 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1491
1721
|
if (hasFailed) {
|
|
1492
1722
|
execResults = { status: "failed", error: hasFailed.error };
|
|
1493
1723
|
} else if (hasSuspended) {
|
|
1494
|
-
execResults = {
|
|
1724
|
+
execResults = {
|
|
1725
|
+
status: "suspended",
|
|
1726
|
+
suspendPayload: hasSuspended.suspendPayload,
|
|
1727
|
+
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1728
|
+
};
|
|
1495
1729
|
} else {
|
|
1496
1730
|
execResults = {
|
|
1497
1731
|
status: "success",
|
|
1498
1732
|
output: results.reduce((acc, result, index) => {
|
|
1499
1733
|
if (result.status === "success") {
|
|
1500
|
-
|
|
1734
|
+
if ("step" in stepsToRun[index]) {
|
|
1735
|
+
acc[stepsToRun[index].step.id] = result.output;
|
|
1736
|
+
}
|
|
1501
1737
|
}
|
|
1502
1738
|
return acc;
|
|
1503
1739
|
}, {})
|