@mastra/inngest 0.0.0-transpile-packages-20250731152758 → 0.0.0-unified-sidebar-20251010130811
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 +552 -3
- package/dist/index.cjs +571 -332
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +84 -57
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +573 -334
- package/dist/index.js.map +1 -1
- package/package.json +30 -16
- package/docker-compose.yaml +0 -10
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -7815
- package/src/index.ts +0 -1784
- package/tsconfig.build.json +0 -9
- package/tsconfig.json +0 -5
- package/tsup.config.ts +0 -22
- package/vitest.config.ts +0 -14
package/dist/index.cjs
CHANGED
|
@@ -2,17 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
4
|
var realtime = require('@inngest/realtime');
|
|
5
|
+
var aiTracing = require('@mastra/core/ai-tracing');
|
|
5
6
|
var di = require('@mastra/core/di');
|
|
6
7
|
var tools = require('@mastra/core/tools');
|
|
7
8
|
var workflows = require('@mastra/core/workflows');
|
|
8
9
|
var _constants = require('@mastra/core/workflows/_constants');
|
|
10
|
+
var inngest = require('inngest');
|
|
9
11
|
var hono = require('inngest/hono');
|
|
10
12
|
var zod = require('zod');
|
|
11
13
|
|
|
12
14
|
// src/index.ts
|
|
13
|
-
function serve({
|
|
15
|
+
function serve({
|
|
16
|
+
mastra,
|
|
17
|
+
inngest,
|
|
18
|
+
functions: userFunctions = [],
|
|
19
|
+
registerOptions
|
|
20
|
+
}) {
|
|
14
21
|
const wfs = mastra.getWorkflows();
|
|
15
|
-
const
|
|
22
|
+
const workflowFunctions = Array.from(
|
|
16
23
|
new Set(
|
|
17
24
|
Object.values(wfs).flatMap((wf) => {
|
|
18
25
|
if (wf instanceof InngestWorkflow) {
|
|
@@ -24,8 +31,9 @@ function serve({ mastra, inngest }) {
|
|
|
24
31
|
)
|
|
25
32
|
);
|
|
26
33
|
return hono.serve({
|
|
34
|
+
...registerOptions,
|
|
27
35
|
client: inngest,
|
|
28
|
-
functions
|
|
36
|
+
functions: [...workflowFunctions, ...userFunctions]
|
|
29
37
|
});
|
|
30
38
|
}
|
|
31
39
|
var InngestRun = class extends workflows.Run {
|
|
@@ -53,9 +61,15 @@ var InngestRun = class extends workflows.Run {
|
|
|
53
61
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
54
62
|
runs = await this.getRuns(eventId);
|
|
55
63
|
if (runs?.[0]?.status === "Failed") {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
64
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
65
|
+
workflowName: this.workflowId,
|
|
66
|
+
runId: this.runId
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (runs?.[0]?.status === "Cancelled") {
|
|
59
73
|
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
60
74
|
workflowName: this.workflowId,
|
|
61
75
|
runId: this.runId
|
|
@@ -86,6 +100,7 @@ var InngestRun = class extends workflows.Run {
|
|
|
86
100
|
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
87
101
|
workflowName: this.workflowId,
|
|
88
102
|
runId: this.runId,
|
|
103
|
+
resourceId: this.resourceId,
|
|
89
104
|
snapshot: {
|
|
90
105
|
...snapshot,
|
|
91
106
|
status: "canceled"
|
|
@@ -94,11 +109,13 @@ var InngestRun = class extends workflows.Run {
|
|
|
94
109
|
}
|
|
95
110
|
}
|
|
96
111
|
async start({
|
|
97
|
-
inputData
|
|
112
|
+
inputData,
|
|
113
|
+
initialState
|
|
98
114
|
}) {
|
|
99
115
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
100
116
|
workflowName: this.workflowId,
|
|
101
117
|
runId: this.runId,
|
|
118
|
+
resourceId: this.resourceId,
|
|
102
119
|
snapshot: {
|
|
103
120
|
runId: this.runId,
|
|
104
121
|
serializedStepGraph: this.serializedStepGraph,
|
|
@@ -106,15 +123,20 @@ var InngestRun = class extends workflows.Run {
|
|
|
106
123
|
context: {},
|
|
107
124
|
activePaths: [],
|
|
108
125
|
suspendedPaths: {},
|
|
126
|
+
waitingPaths: {},
|
|
109
127
|
timestamp: Date.now(),
|
|
110
128
|
status: "running"
|
|
111
129
|
}
|
|
112
130
|
});
|
|
131
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
132
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
113
133
|
const eventOutput = await this.inngest.send({
|
|
114
134
|
name: `workflow.${this.workflowId}`,
|
|
115
135
|
data: {
|
|
116
|
-
inputData,
|
|
117
|
-
|
|
136
|
+
inputData: inputDataToUse,
|
|
137
|
+
initialState: initialStateToUse,
|
|
138
|
+
runId: this.runId,
|
|
139
|
+
resourceId: this.resourceId
|
|
118
140
|
}
|
|
119
141
|
});
|
|
120
142
|
const eventId = eventOutput.ids[0];
|
|
@@ -150,17 +172,20 @@ var InngestRun = class extends workflows.Run {
|
|
|
150
172
|
workflowName: this.workflowId,
|
|
151
173
|
runId: this.runId
|
|
152
174
|
});
|
|
175
|
+
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
176
|
+
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
153
177
|
const eventOutput = await this.inngest.send({
|
|
154
178
|
name: `workflow.${this.workflowId}`,
|
|
155
179
|
data: {
|
|
156
|
-
inputData:
|
|
180
|
+
inputData: resumeDataToUse,
|
|
181
|
+
initialState: snapshot?.value ?? {},
|
|
157
182
|
runId: this.runId,
|
|
158
183
|
workflowId: this.workflowId,
|
|
159
184
|
stepResults: snapshot?.context,
|
|
160
185
|
resume: {
|
|
161
186
|
steps,
|
|
162
187
|
stepResults: snapshot?.context,
|
|
163
|
-
resumePayload:
|
|
188
|
+
resumePayload: resumeDataToUse,
|
|
164
189
|
// @ts-ignore
|
|
165
190
|
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
166
191
|
}
|
|
@@ -205,7 +230,11 @@ var InngestRun = class extends workflows.Run {
|
|
|
205
230
|
const writer = writable.getWriter();
|
|
206
231
|
const unwatch = this.watch(async (event) => {
|
|
207
232
|
try {
|
|
208
|
-
|
|
233
|
+
const e = {
|
|
234
|
+
...event,
|
|
235
|
+
type: event.type.replace("workflow-", "")
|
|
236
|
+
};
|
|
237
|
+
await writer.write(e);
|
|
209
238
|
} catch {
|
|
210
239
|
}
|
|
211
240
|
}, "watch-v2");
|
|
@@ -236,8 +265,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
236
265
|
#mastra;
|
|
237
266
|
inngest;
|
|
238
267
|
function;
|
|
268
|
+
flowControlConfig;
|
|
239
269
|
constructor(params, inngest) {
|
|
240
|
-
|
|
270
|
+
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
271
|
+
super(workflowParams);
|
|
272
|
+
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
273
|
+
([_, value]) => value !== void 0
|
|
274
|
+
);
|
|
275
|
+
this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
|
|
241
276
|
this.#mastra = params.mastra;
|
|
242
277
|
this.inngest = inngest;
|
|
243
278
|
}
|
|
@@ -258,27 +293,6 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
258
293
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
259
294
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
260
295
|
}
|
|
261
|
-
async getWorkflowRunExecutionResult(runId) {
|
|
262
|
-
const storage = this.#mastra?.getStorage();
|
|
263
|
-
if (!storage) {
|
|
264
|
-
this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
|
|
265
|
-
return null;
|
|
266
|
-
}
|
|
267
|
-
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
268
|
-
if (!run?.snapshot) {
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
if (typeof run.snapshot === "string") {
|
|
272
|
-
return null;
|
|
273
|
-
}
|
|
274
|
-
return {
|
|
275
|
-
status: run.snapshot.status,
|
|
276
|
-
result: run.snapshot.result,
|
|
277
|
-
error: run.snapshot.error,
|
|
278
|
-
payload: run.snapshot.context?.input,
|
|
279
|
-
steps: run.snapshot.context
|
|
280
|
-
};
|
|
281
|
-
}
|
|
282
296
|
__registerMastra(mastra) {
|
|
283
297
|
this.#mastra = mastra;
|
|
284
298
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -297,23 +311,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
297
311
|
}
|
|
298
312
|
}
|
|
299
313
|
}
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
executionGraph: this.executionGraph,
|
|
308
|
-
serializedStepGraph: this.serializedStepGraph,
|
|
309
|
-
mastra: this.#mastra,
|
|
310
|
-
retryConfig: this.retryConfig,
|
|
311
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
312
|
-
},
|
|
313
|
-
this.inngest
|
|
314
|
+
/**
|
|
315
|
+
* @deprecated Use createRunAsync() instead.
|
|
316
|
+
* @throws {Error} Always throws an error directing users to use createRunAsync()
|
|
317
|
+
*/
|
|
318
|
+
createRun(_options) {
|
|
319
|
+
throw new Error(
|
|
320
|
+
"createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async."
|
|
314
321
|
);
|
|
315
|
-
this.runs.set(runIdToUse, run);
|
|
316
|
-
return run;
|
|
317
322
|
}
|
|
318
323
|
async createRunAsync(options) {
|
|
319
324
|
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
@@ -321,27 +326,35 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
321
326
|
{
|
|
322
327
|
workflowId: this.id,
|
|
323
328
|
runId: runIdToUse,
|
|
329
|
+
resourceId: options?.resourceId,
|
|
324
330
|
executionEngine: this.executionEngine,
|
|
325
331
|
executionGraph: this.executionGraph,
|
|
326
332
|
serializedStepGraph: this.serializedStepGraph,
|
|
327
333
|
mastra: this.#mastra,
|
|
328
334
|
retryConfig: this.retryConfig,
|
|
329
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
335
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
336
|
+
workflowSteps: this.steps
|
|
330
337
|
},
|
|
331
338
|
this.inngest
|
|
332
339
|
);
|
|
333
340
|
this.runs.set(runIdToUse, run);
|
|
334
|
-
const
|
|
335
|
-
|
|
341
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
|
|
342
|
+
workflowStatus: run.workflowRunStatus,
|
|
343
|
+
stepResults: {}
|
|
344
|
+
});
|
|
345
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
346
|
+
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
336
347
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
337
348
|
workflowName: this.id,
|
|
338
349
|
runId: runIdToUse,
|
|
350
|
+
resourceId: options?.resourceId,
|
|
339
351
|
snapshot: {
|
|
340
352
|
runId: runIdToUse,
|
|
341
353
|
status: "pending",
|
|
342
354
|
value: {},
|
|
343
355
|
context: {},
|
|
344
356
|
activePaths: [],
|
|
357
|
+
waitingPaths: {},
|
|
345
358
|
serializedStepGraph: this.serializedStepGraph,
|
|
346
359
|
suspendedPaths: {},
|
|
347
360
|
result: void 0,
|
|
@@ -362,11 +375,13 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
362
375
|
id: `workflow.${this.id}`,
|
|
363
376
|
// @ts-ignore
|
|
364
377
|
retries: this.retryConfig?.attempts ?? 0,
|
|
365
|
-
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
378
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
379
|
+
// Spread flow control configuration
|
|
380
|
+
...this.flowControlConfig
|
|
366
381
|
},
|
|
367
382
|
{ event: `workflow.${this.id}` },
|
|
368
383
|
async ({ event, step, attempt, publish }) => {
|
|
369
|
-
let { inputData, runId, resume } = event.data;
|
|
384
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
|
|
370
385
|
if (!runId) {
|
|
371
386
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
372
387
|
return crypto.randomUUID();
|
|
@@ -394,19 +409,32 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
394
409
|
once: (_event, _callback) => {
|
|
395
410
|
}
|
|
396
411
|
};
|
|
397
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
412
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
398
413
|
const result = await engine.execute({
|
|
399
414
|
workflowId: this.id,
|
|
400
415
|
runId,
|
|
416
|
+
resourceId,
|
|
401
417
|
graph: this.executionGraph,
|
|
402
418
|
serializedStepGraph: this.serializedStepGraph,
|
|
403
419
|
input: inputData,
|
|
420
|
+
initialState,
|
|
404
421
|
emitter,
|
|
405
422
|
retryConfig: this.retryConfig,
|
|
406
423
|
runtimeContext: new di.RuntimeContext(),
|
|
407
424
|
// TODO
|
|
408
425
|
resume,
|
|
409
|
-
abortController: new AbortController()
|
|
426
|
+
abortController: new AbortController(),
|
|
427
|
+
currentSpan: void 0,
|
|
428
|
+
// TODO: Pass actual parent AI span from workflow execution context
|
|
429
|
+
outputOptions
|
|
430
|
+
});
|
|
431
|
+
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
432
|
+
if (result.status === "failed") {
|
|
433
|
+
throw new inngest.NonRetriableError(`Workflow failed`, {
|
|
434
|
+
cause: result
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
return result;
|
|
410
438
|
});
|
|
411
439
|
return { result, runId };
|
|
412
440
|
}
|
|
@@ -440,17 +468,16 @@ function createStep(params) {
|
|
|
440
468
|
if (isAgent(params)) {
|
|
441
469
|
return {
|
|
442
470
|
id: params.name,
|
|
471
|
+
description: params.getDescription(),
|
|
443
472
|
// @ts-ignore
|
|
444
473
|
inputSchema: zod.z.object({
|
|
445
474
|
prompt: zod.z.string()
|
|
446
|
-
// resourceId: z.string().optional(),
|
|
447
|
-
// threadId: z.string().optional(),
|
|
448
475
|
}),
|
|
449
476
|
// @ts-ignore
|
|
450
477
|
outputSchema: zod.z.object({
|
|
451
478
|
text: zod.z.string()
|
|
452
479
|
}),
|
|
453
|
-
execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
480
|
+
execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
|
|
454
481
|
let streamPromise = {};
|
|
455
482
|
streamPromise.promise = new Promise((resolve, reject) => {
|
|
456
483
|
streamPromise.resolve = resolve;
|
|
@@ -460,50 +487,66 @@ function createStep(params) {
|
|
|
460
487
|
name: params.name,
|
|
461
488
|
args: inputData
|
|
462
489
|
};
|
|
463
|
-
await
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
490
|
+
if ((await params.getLLM()).getModel().specificationVersion === `v2`) {
|
|
491
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
492
|
+
runtimeContext,
|
|
493
|
+
tracingContext,
|
|
494
|
+
onFinish: (result) => {
|
|
495
|
+
streamPromise.resolve(result.text);
|
|
496
|
+
},
|
|
497
|
+
abortSignal
|
|
498
|
+
});
|
|
499
|
+
if (abortSignal.aborted) {
|
|
500
|
+
return abort();
|
|
501
|
+
}
|
|
502
|
+
await emitter.emit("watch-v2", {
|
|
503
|
+
type: "tool-call-streaming-start",
|
|
504
|
+
...toolData ?? {}
|
|
505
|
+
});
|
|
506
|
+
for await (const chunk of fullStream) {
|
|
507
|
+
if (chunk.type === "text-delta") {
|
|
508
|
+
await emitter.emit("watch-v2", {
|
|
509
|
+
type: "tool-call-delta",
|
|
510
|
+
...toolData ?? {},
|
|
511
|
+
argsTextDelta: chunk.payload.text
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
} else {
|
|
516
|
+
const { fullStream } = await params.streamLegacy(inputData.prompt, {
|
|
517
|
+
runtimeContext,
|
|
518
|
+
tracingContext,
|
|
519
|
+
onFinish: (result) => {
|
|
520
|
+
streamPromise.resolve(result.text);
|
|
521
|
+
},
|
|
522
|
+
abortSignal
|
|
523
|
+
});
|
|
524
|
+
if (abortSignal.aborted) {
|
|
525
|
+
return abort();
|
|
526
|
+
}
|
|
527
|
+
await emitter.emit("watch-v2", {
|
|
528
|
+
type: "tool-call-streaming-start",
|
|
529
|
+
...toolData ?? {}
|
|
530
|
+
});
|
|
531
|
+
for await (const chunk of fullStream) {
|
|
532
|
+
if (chunk.type === "text-delta") {
|
|
482
533
|
await emitter.emit("watch-v2", {
|
|
483
534
|
type: "tool-call-delta",
|
|
484
|
-
...toolData,
|
|
535
|
+
...toolData ?? {},
|
|
485
536
|
argsTextDelta: chunk.textDelta
|
|
486
537
|
});
|
|
487
|
-
|
|
488
|
-
case "step-start":
|
|
489
|
-
case "step-finish":
|
|
490
|
-
case "finish":
|
|
491
|
-
break;
|
|
492
|
-
case "tool-call":
|
|
493
|
-
case "tool-result":
|
|
494
|
-
case "tool-call-streaming-start":
|
|
495
|
-
case "tool-call-delta":
|
|
496
|
-
case "source":
|
|
497
|
-
case "file":
|
|
498
|
-
default:
|
|
499
|
-
await emitter.emit("watch-v2", chunk);
|
|
500
|
-
break;
|
|
538
|
+
}
|
|
501
539
|
}
|
|
502
540
|
}
|
|
541
|
+
await emitter.emit("watch-v2", {
|
|
542
|
+
type: "tool-call-streaming-finish",
|
|
543
|
+
...toolData ?? {}
|
|
544
|
+
});
|
|
503
545
|
return {
|
|
504
546
|
text: await streamPromise.promise
|
|
505
547
|
};
|
|
506
|
-
}
|
|
548
|
+
},
|
|
549
|
+
component: params.component
|
|
507
550
|
};
|
|
508
551
|
}
|
|
509
552
|
if (isTool(params)) {
|
|
@@ -514,15 +557,20 @@ function createStep(params) {
|
|
|
514
557
|
// TODO: tool probably should have strong id type
|
|
515
558
|
// @ts-ignore
|
|
516
559
|
id: params.id,
|
|
560
|
+
description: params.description,
|
|
517
561
|
inputSchema: params.inputSchema,
|
|
518
562
|
outputSchema: params.outputSchema,
|
|
519
|
-
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
563
|
+
execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
|
|
520
564
|
return params.execute({
|
|
521
565
|
context: inputData,
|
|
522
|
-
mastra,
|
|
523
|
-
runtimeContext
|
|
566
|
+
mastra: aiTracing.wrapMastra(mastra, tracingContext),
|
|
567
|
+
runtimeContext,
|
|
568
|
+
tracingContext,
|
|
569
|
+
suspend,
|
|
570
|
+
resumeData
|
|
524
571
|
});
|
|
525
|
-
}
|
|
572
|
+
},
|
|
573
|
+
component: "TOOL"
|
|
526
574
|
};
|
|
527
575
|
}
|
|
528
576
|
return {
|
|
@@ -538,7 +586,10 @@ function createStep(params) {
|
|
|
538
586
|
function init(inngest) {
|
|
539
587
|
return {
|
|
540
588
|
createWorkflow(params) {
|
|
541
|
-
return new InngestWorkflow(
|
|
589
|
+
return new InngestWorkflow(
|
|
590
|
+
params,
|
|
591
|
+
inngest
|
|
592
|
+
);
|
|
542
593
|
},
|
|
543
594
|
createStep,
|
|
544
595
|
cloneStep(step, opts) {
|
|
@@ -547,7 +598,11 @@ function init(inngest) {
|
|
|
547
598
|
description: step.description,
|
|
548
599
|
inputSchema: step.inputSchema,
|
|
549
600
|
outputSchema: step.outputSchema,
|
|
550
|
-
|
|
601
|
+
resumeSchema: step.resumeSchema,
|
|
602
|
+
suspendSchema: step.suspendSchema,
|
|
603
|
+
stateSchema: step.stateSchema,
|
|
604
|
+
execute: step.execute,
|
|
605
|
+
component: step.component
|
|
551
606
|
};
|
|
552
607
|
},
|
|
553
608
|
cloneWorkflow(workflow, opts) {
|
|
@@ -567,19 +622,19 @@ function init(inngest) {
|
|
|
567
622
|
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
568
623
|
inngestStep;
|
|
569
624
|
inngestAttempts;
|
|
570
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
571
|
-
super({ mastra });
|
|
625
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
626
|
+
super({ mastra, options });
|
|
572
627
|
this.inngestStep = inngestStep;
|
|
573
628
|
this.inngestAttempts = inngestAttempts;
|
|
574
629
|
}
|
|
575
630
|
async execute(params) {
|
|
576
631
|
await params.emitter.emit("watch-v2", {
|
|
577
|
-
type: "start",
|
|
632
|
+
type: "workflow-start",
|
|
578
633
|
payload: { runId: params.runId }
|
|
579
634
|
});
|
|
580
635
|
const result = await super.execute(params);
|
|
581
636
|
await params.emitter.emit("watch-v2", {
|
|
582
|
-
type: "finish",
|
|
637
|
+
type: "workflow-finish",
|
|
583
638
|
payload: { runId: params.runId }
|
|
584
639
|
});
|
|
585
640
|
return result;
|
|
@@ -631,7 +686,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
631
686
|
});
|
|
632
687
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
633
688
|
if (stepResult?.status === "suspended") {
|
|
634
|
-
const nestedPath = stepResult?.
|
|
689
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
635
690
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
636
691
|
}
|
|
637
692
|
return [];
|
|
@@ -641,33 +696,6 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
641
696
|
executionSpan?.end();
|
|
642
697
|
return base;
|
|
643
698
|
}
|
|
644
|
-
async superExecuteStep({
|
|
645
|
-
workflowId,
|
|
646
|
-
runId,
|
|
647
|
-
step,
|
|
648
|
-
stepResults,
|
|
649
|
-
executionContext,
|
|
650
|
-
resume,
|
|
651
|
-
prevOutput,
|
|
652
|
-
emitter,
|
|
653
|
-
abortController,
|
|
654
|
-
runtimeContext,
|
|
655
|
-
writableStream
|
|
656
|
-
}) {
|
|
657
|
-
return super.executeStep({
|
|
658
|
-
workflowId,
|
|
659
|
-
runId,
|
|
660
|
-
step,
|
|
661
|
-
stepResults,
|
|
662
|
-
executionContext,
|
|
663
|
-
resume,
|
|
664
|
-
prevOutput,
|
|
665
|
-
emitter,
|
|
666
|
-
abortController,
|
|
667
|
-
runtimeContext,
|
|
668
|
-
writableStream
|
|
669
|
-
});
|
|
670
|
-
}
|
|
671
699
|
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
672
700
|
// await this.inngestStep.sleep(id, duration);
|
|
673
701
|
// }
|
|
@@ -680,9 +708,20 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
680
708
|
emitter,
|
|
681
709
|
abortController,
|
|
682
710
|
runtimeContext,
|
|
683
|
-
|
|
711
|
+
executionContext,
|
|
712
|
+
writableStream,
|
|
713
|
+
tracingContext
|
|
684
714
|
}) {
|
|
685
715
|
let { duration, fn } = entry;
|
|
716
|
+
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
717
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
718
|
+
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
719
|
+
attributes: {
|
|
720
|
+
durationMs: duration,
|
|
721
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
722
|
+
},
|
|
723
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
724
|
+
});
|
|
686
725
|
if (fn) {
|
|
687
726
|
const stepCallId = crypto.randomUUID();
|
|
688
727
|
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
@@ -692,18 +731,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
692
731
|
mastra: this.mastra,
|
|
693
732
|
runtimeContext,
|
|
694
733
|
inputData: prevOutput,
|
|
734
|
+
state: executionContext.state,
|
|
735
|
+
setState: (state) => {
|
|
736
|
+
executionContext.state = state;
|
|
737
|
+
},
|
|
695
738
|
runCount: -1,
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
if (!step?.id) {
|
|
699
|
-
return null;
|
|
700
|
-
}
|
|
701
|
-
const result = stepResults[step.id];
|
|
702
|
-
if (result?.status === "success") {
|
|
703
|
-
return result.output;
|
|
704
|
-
}
|
|
705
|
-
return null;
|
|
739
|
+
tracingContext: {
|
|
740
|
+
currentSpan: sleepSpan
|
|
706
741
|
},
|
|
742
|
+
getInitData: () => stepResults?.input,
|
|
743
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
707
744
|
// TODO: this function shouldn't have suspend probably?
|
|
708
745
|
suspend: async (_suspendPayload) => {
|
|
709
746
|
},
|
|
@@ -713,11 +750,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
713
750
|
abortController?.abort();
|
|
714
751
|
},
|
|
715
752
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
753
|
+
// TODO: add streamVNext support
|
|
754
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
716
755
|
engine: { step: this.inngestStep },
|
|
717
756
|
abortSignal: abortController?.signal,
|
|
718
757
|
writer: new tools.ToolStream(
|
|
719
758
|
{
|
|
720
|
-
prefix: "step",
|
|
759
|
+
prefix: "workflow-step",
|
|
721
760
|
callId: stepCallId,
|
|
722
761
|
name: "sleep",
|
|
723
762
|
runId
|
|
@@ -726,8 +765,19 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
726
765
|
)
|
|
727
766
|
});
|
|
728
767
|
});
|
|
768
|
+
sleepSpan?.update({
|
|
769
|
+
attributes: {
|
|
770
|
+
durationMs: duration
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
try {
|
|
775
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
776
|
+
sleepSpan?.end();
|
|
777
|
+
} catch (e) {
|
|
778
|
+
sleepSpan?.error({ error: e });
|
|
779
|
+
throw e;
|
|
729
780
|
}
|
|
730
|
-
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
731
781
|
}
|
|
732
782
|
async executeSleepUntil({
|
|
733
783
|
workflowId,
|
|
@@ -738,9 +788,21 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
738
788
|
emitter,
|
|
739
789
|
abortController,
|
|
740
790
|
runtimeContext,
|
|
741
|
-
|
|
791
|
+
executionContext,
|
|
792
|
+
writableStream,
|
|
793
|
+
tracingContext
|
|
742
794
|
}) {
|
|
743
795
|
let { date, fn } = entry;
|
|
796
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
797
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
798
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
799
|
+
attributes: {
|
|
800
|
+
untilDate: date,
|
|
801
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
802
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
803
|
+
},
|
|
804
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
805
|
+
});
|
|
744
806
|
if (fn) {
|
|
745
807
|
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
746
808
|
const stepCallId = crypto.randomUUID();
|
|
@@ -750,18 +812,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
750
812
|
mastra: this.mastra,
|
|
751
813
|
runtimeContext,
|
|
752
814
|
inputData: prevOutput,
|
|
815
|
+
state: executionContext.state,
|
|
816
|
+
setState: (state) => {
|
|
817
|
+
executionContext.state = state;
|
|
818
|
+
},
|
|
753
819
|
runCount: -1,
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
if (!step?.id) {
|
|
757
|
-
return null;
|
|
758
|
-
}
|
|
759
|
-
const result = stepResults[step.id];
|
|
760
|
-
if (result?.status === "success") {
|
|
761
|
-
return result.output;
|
|
762
|
-
}
|
|
763
|
-
return null;
|
|
820
|
+
tracingContext: {
|
|
821
|
+
currentSpan: sleepUntilSpan
|
|
764
822
|
},
|
|
823
|
+
getInitData: () => stepResults?.input,
|
|
824
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
765
825
|
// TODO: this function shouldn't have suspend probably?
|
|
766
826
|
suspend: async (_suspendPayload) => {
|
|
767
827
|
},
|
|
@@ -771,11 +831,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
771
831
|
abortController?.abort();
|
|
772
832
|
},
|
|
773
833
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
834
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
835
|
+
// TODO: add streamVNext support
|
|
774
836
|
engine: { step: this.inngestStep },
|
|
775
837
|
abortSignal: abortController?.signal,
|
|
776
838
|
writer: new tools.ToolStream(
|
|
777
839
|
{
|
|
778
|
-
prefix: "step",
|
|
840
|
+
prefix: "workflow-step",
|
|
779
841
|
callId: stepCallId,
|
|
780
842
|
name: "sleep",
|
|
781
843
|
runId
|
|
@@ -784,11 +846,27 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
784
846
|
)
|
|
785
847
|
});
|
|
786
848
|
});
|
|
849
|
+
if (date && !(date instanceof Date)) {
|
|
850
|
+
date = new Date(date);
|
|
851
|
+
}
|
|
852
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
853
|
+
sleepUntilSpan?.update({
|
|
854
|
+
attributes: {
|
|
855
|
+
durationMs: Math.max(0, time)
|
|
856
|
+
}
|
|
857
|
+
});
|
|
787
858
|
}
|
|
788
859
|
if (!(date instanceof Date)) {
|
|
860
|
+
sleepUntilSpan?.end();
|
|
789
861
|
return;
|
|
790
862
|
}
|
|
791
|
-
|
|
863
|
+
try {
|
|
864
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
865
|
+
sleepUntilSpan?.end();
|
|
866
|
+
} catch (e) {
|
|
867
|
+
sleepUntilSpan?.error({ error: e });
|
|
868
|
+
throw e;
|
|
869
|
+
}
|
|
792
870
|
}
|
|
793
871
|
async executeWaitForEvent({ event, timeout }) {
|
|
794
872
|
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
@@ -809,8 +887,24 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
809
887
|
emitter,
|
|
810
888
|
abortController,
|
|
811
889
|
runtimeContext,
|
|
812
|
-
|
|
890
|
+
tracingContext,
|
|
891
|
+
writableStream,
|
|
892
|
+
disableScorers
|
|
813
893
|
}) {
|
|
894
|
+
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
895
|
+
name: `workflow step: '${step.id}'`,
|
|
896
|
+
type: aiTracing.AISpanType.WORKFLOW_STEP,
|
|
897
|
+
input: prevOutput,
|
|
898
|
+
attributes: {
|
|
899
|
+
stepId: step.id
|
|
900
|
+
},
|
|
901
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
902
|
+
});
|
|
903
|
+
const { inputData, validationError } = await workflows.validateStepInput({
|
|
904
|
+
prevOutput,
|
|
905
|
+
step,
|
|
906
|
+
validateInputs: this.options?.validateInputs ?? false
|
|
907
|
+
});
|
|
814
908
|
const startedAt = await this.inngestStep.run(
|
|
815
909
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
816
910
|
async () => {
|
|
@@ -837,11 +931,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
837
931
|
eventTimestamp: Date.now()
|
|
838
932
|
});
|
|
839
933
|
await emitter.emit("watch-v2", {
|
|
840
|
-
type: "step-start",
|
|
934
|
+
type: "workflow-step-start",
|
|
841
935
|
payload: {
|
|
842
936
|
id: step.id,
|
|
843
937
|
status: "running",
|
|
844
|
-
payload:
|
|
938
|
+
payload: inputData,
|
|
845
939
|
startedAt: startedAt2
|
|
846
940
|
}
|
|
847
941
|
});
|
|
@@ -852,38 +946,60 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
852
946
|
const isResume = !!resume?.steps?.length;
|
|
853
947
|
let result;
|
|
854
948
|
let runId;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
949
|
+
try {
|
|
950
|
+
if (isResume) {
|
|
951
|
+
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
952
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
953
|
+
workflowName: step.id,
|
|
954
|
+
runId
|
|
955
|
+
});
|
|
956
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
957
|
+
function: step.getFunction(),
|
|
958
|
+
data: {
|
|
959
|
+
inputData,
|
|
960
|
+
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
867
961
|
runId,
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
962
|
+
resume: {
|
|
963
|
+
runId,
|
|
964
|
+
steps: resume.steps.slice(1),
|
|
965
|
+
stepResults: snapshot?.context,
|
|
966
|
+
resumePayload: resume.resumePayload,
|
|
967
|
+
// @ts-ignore
|
|
968
|
+
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
969
|
+
},
|
|
970
|
+
outputOptions: { includeState: true }
|
|
873
971
|
}
|
|
874
|
-
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
972
|
+
});
|
|
973
|
+
result = invokeResp.result;
|
|
974
|
+
runId = invokeResp.runId;
|
|
975
|
+
executionContext.state = invokeResp.result.state;
|
|
976
|
+
} else {
|
|
977
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
978
|
+
function: step.getFunction(),
|
|
979
|
+
data: {
|
|
980
|
+
inputData,
|
|
981
|
+
initialState: executionContext.state ?? {},
|
|
982
|
+
outputOptions: { includeState: true }
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
result = invokeResp.result;
|
|
986
|
+
runId = invokeResp.runId;
|
|
987
|
+
executionContext.state = invokeResp.result.state;
|
|
988
|
+
}
|
|
989
|
+
} catch (e) {
|
|
990
|
+
const errorCause = e?.cause;
|
|
991
|
+
if (errorCause && typeof errorCause === "object") {
|
|
992
|
+
result = errorCause;
|
|
993
|
+
runId = errorCause.runId || crypto.randomUUID();
|
|
994
|
+
} else {
|
|
995
|
+
runId = crypto.randomUUID();
|
|
996
|
+
result = {
|
|
997
|
+
status: "failed",
|
|
998
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
999
|
+
steps: {},
|
|
1000
|
+
input: inputData
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
887
1003
|
}
|
|
888
1004
|
const res = await this.inngestStep.run(
|
|
889
1005
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
@@ -907,7 +1023,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
907
1023
|
eventTimestamp: Date.now()
|
|
908
1024
|
});
|
|
909
1025
|
await emitter.emit("watch-v2", {
|
|
910
|
-
type: "step-result",
|
|
1026
|
+
type: "workflow-step-result",
|
|
911
1027
|
payload: {
|
|
912
1028
|
id: step.id,
|
|
913
1029
|
status: "failed",
|
|
@@ -922,7 +1038,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
922
1038
|
return stepRes2?.status === "suspended";
|
|
923
1039
|
});
|
|
924
1040
|
for (const [stepName, stepResult] of suspendedSteps) {
|
|
925
|
-
const suspendPath = [stepName, ...stepResult?.
|
|
1041
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
926
1042
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
927
1043
|
await emitter.emit("watch", {
|
|
928
1044
|
type: "watch",
|
|
@@ -930,7 +1046,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
930
1046
|
currentStep: {
|
|
931
1047
|
id: step.id,
|
|
932
1048
|
status: "suspended",
|
|
933
|
-
payload:
|
|
1049
|
+
payload: stepResult.payload,
|
|
1050
|
+
suspendPayload: {
|
|
1051
|
+
...stepResult?.suspendPayload,
|
|
1052
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1053
|
+
}
|
|
934
1054
|
},
|
|
935
1055
|
workflowState: {
|
|
936
1056
|
status: "running",
|
|
@@ -942,7 +1062,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
942
1062
|
eventTimestamp: Date.now()
|
|
943
1063
|
});
|
|
944
1064
|
await emitter.emit("watch-v2", {
|
|
945
|
-
type: "step-suspended",
|
|
1065
|
+
type: "workflow-step-suspended",
|
|
946
1066
|
payload: {
|
|
947
1067
|
id: step.id,
|
|
948
1068
|
status: "suspended"
|
|
@@ -952,7 +1072,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
952
1072
|
executionContext,
|
|
953
1073
|
result: {
|
|
954
1074
|
status: "suspended",
|
|
955
|
-
payload:
|
|
1075
|
+
payload: stepResult.payload,
|
|
1076
|
+
suspendPayload: {
|
|
1077
|
+
...stepResult?.suspendPayload,
|
|
1078
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1079
|
+
}
|
|
956
1080
|
}
|
|
957
1081
|
};
|
|
958
1082
|
}
|
|
@@ -999,7 +1123,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
999
1123
|
eventTimestamp: Date.now()
|
|
1000
1124
|
});
|
|
1001
1125
|
await emitter.emit("watch-v2", {
|
|
1002
|
-
type: "step-result",
|
|
1126
|
+
type: "workflow-step-result",
|
|
1003
1127
|
payload: {
|
|
1004
1128
|
id: step.id,
|
|
1005
1129
|
status: "success",
|
|
@@ -1007,7 +1131,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1007
1131
|
}
|
|
1008
1132
|
});
|
|
1009
1133
|
await emitter.emit("watch-v2", {
|
|
1010
|
-
type: "step-finish",
|
|
1134
|
+
type: "workflow-step-finish",
|
|
1011
1135
|
payload: {
|
|
1012
1136
|
id: step.id,
|
|
1013
1137
|
metadata: {}
|
|
@@ -1017,136 +1141,193 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1017
1141
|
}
|
|
1018
1142
|
);
|
|
1019
1143
|
Object.assign(executionContext, res.executionContext);
|
|
1020
|
-
return
|
|
1144
|
+
return {
|
|
1145
|
+
...res.result,
|
|
1146
|
+
startedAt,
|
|
1147
|
+
endedAt: Date.now(),
|
|
1148
|
+
payload: inputData,
|
|
1149
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1150
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1151
|
+
};
|
|
1021
1152
|
}
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1153
|
+
let stepRes;
|
|
1154
|
+
try {
|
|
1155
|
+
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1156
|
+
let execResults;
|
|
1157
|
+
let suspended;
|
|
1158
|
+
let bailed;
|
|
1159
|
+
try {
|
|
1160
|
+
if (validationError) {
|
|
1161
|
+
throw validationError;
|
|
1162
|
+
}
|
|
1163
|
+
const result = await step.execute({
|
|
1164
|
+
runId: executionContext.runId,
|
|
1165
|
+
mastra: this.mastra,
|
|
1166
|
+
runtimeContext,
|
|
1167
|
+
writableStream,
|
|
1168
|
+
state: executionContext?.state ?? {},
|
|
1169
|
+
setState: (state) => {
|
|
1170
|
+
executionContext.state = state;
|
|
1171
|
+
},
|
|
1172
|
+
inputData,
|
|
1173
|
+
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1174
|
+
tracingContext: {
|
|
1175
|
+
currentSpan: stepAISpan
|
|
1176
|
+
},
|
|
1177
|
+
getInitData: () => stepResults?.input,
|
|
1178
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1179
|
+
suspend: async (suspendPayload) => {
|
|
1180
|
+
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1181
|
+
suspended = { payload: suspendPayload };
|
|
1182
|
+
},
|
|
1183
|
+
bail: (result2) => {
|
|
1184
|
+
bailed = { payload: result2 };
|
|
1185
|
+
},
|
|
1186
|
+
resume: {
|
|
1187
|
+
steps: resume?.steps?.slice(1) || [],
|
|
1188
|
+
resumePayload: resume?.resumePayload,
|
|
1189
|
+
// @ts-ignore
|
|
1190
|
+
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1191
|
+
},
|
|
1192
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1193
|
+
engine: {
|
|
1194
|
+
step: this.inngestStep
|
|
1195
|
+
},
|
|
1196
|
+
abortSignal: abortController.signal
|
|
1197
|
+
});
|
|
1198
|
+
const endedAt = Date.now();
|
|
1199
|
+
execResults = {
|
|
1200
|
+
status: "success",
|
|
1201
|
+
output: result,
|
|
1202
|
+
startedAt,
|
|
1203
|
+
endedAt,
|
|
1204
|
+
payload: inputData,
|
|
1205
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1206
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1207
|
+
};
|
|
1208
|
+
} catch (e) {
|
|
1209
|
+
const stepFailure = {
|
|
1210
|
+
status: "failed",
|
|
1211
|
+
payload: inputData,
|
|
1212
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1213
|
+
endedAt: Date.now(),
|
|
1214
|
+
startedAt,
|
|
1215
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1216
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1217
|
+
};
|
|
1218
|
+
execResults = stepFailure;
|
|
1219
|
+
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1220
|
+
stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1221
|
+
throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1222
|
+
cause: execResults
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
if (suspended) {
|
|
1226
|
+
execResults = {
|
|
1227
|
+
status: "suspended",
|
|
1228
|
+
suspendPayload: suspended.payload,
|
|
1229
|
+
payload: inputData,
|
|
1230
|
+
suspendedAt: Date.now(),
|
|
1231
|
+
startedAt,
|
|
1232
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1233
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1234
|
+
};
|
|
1235
|
+
} else if (bailed) {
|
|
1236
|
+
execResults = {
|
|
1237
|
+
status: "bailed",
|
|
1238
|
+
output: bailed.payload,
|
|
1239
|
+
payload: inputData,
|
|
1240
|
+
endedAt: Date.now(),
|
|
1241
|
+
startedAt
|
|
1242
|
+
};
|
|
1243
|
+
}
|
|
1244
|
+
await emitter.emit("watch", {
|
|
1245
|
+
type: "watch",
|
|
1246
|
+
payload: {
|
|
1247
|
+
currentStep: {
|
|
1248
|
+
id: step.id,
|
|
1249
|
+
...execResults
|
|
1250
|
+
},
|
|
1251
|
+
workflowState: {
|
|
1252
|
+
status: "running",
|
|
1253
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
1254
|
+
result: null,
|
|
1255
|
+
error: null
|
|
1039
1256
|
}
|
|
1040
|
-
return null;
|
|
1041
|
-
},
|
|
1042
|
-
suspend: async (suspendPayload) => {
|
|
1043
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1044
|
-
suspended = { payload: suspendPayload };
|
|
1045
|
-
},
|
|
1046
|
-
bail: (result2) => {
|
|
1047
|
-
bailed = { payload: result2 };
|
|
1048
|
-
},
|
|
1049
|
-
resume: {
|
|
1050
|
-
steps: resume?.steps?.slice(1) || [],
|
|
1051
|
-
resumePayload: resume?.resumePayload,
|
|
1052
|
-
// @ts-ignore
|
|
1053
|
-
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
1054
|
-
},
|
|
1055
|
-
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1056
|
-
engine: {
|
|
1057
|
-
step: this.inngestStep
|
|
1058
1257
|
},
|
|
1059
|
-
|
|
1258
|
+
eventTimestamp: Date.now()
|
|
1060
1259
|
});
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
status: "suspended",
|
|
1085
|
-
suspendedPayload: suspended.payload,
|
|
1086
|
-
payload: prevOutput,
|
|
1087
|
-
suspendedAt: Date.now(),
|
|
1088
|
-
startedAt,
|
|
1089
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1090
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1091
|
-
};
|
|
1092
|
-
} else if (bailed) {
|
|
1093
|
-
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
1094
|
-
}
|
|
1095
|
-
if (execResults.status === "failed") {
|
|
1096
|
-
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
1097
|
-
throw execResults.error;
|
|
1260
|
+
if (execResults.status === "suspended") {
|
|
1261
|
+
await emitter.emit("watch-v2", {
|
|
1262
|
+
type: "workflow-step-suspended",
|
|
1263
|
+
payload: {
|
|
1264
|
+
id: step.id,
|
|
1265
|
+
...execResults
|
|
1266
|
+
}
|
|
1267
|
+
});
|
|
1268
|
+
} else {
|
|
1269
|
+
await emitter.emit("watch-v2", {
|
|
1270
|
+
type: "workflow-step-result",
|
|
1271
|
+
payload: {
|
|
1272
|
+
id: step.id,
|
|
1273
|
+
...execResults
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1276
|
+
await emitter.emit("watch-v2", {
|
|
1277
|
+
type: "workflow-step-finish",
|
|
1278
|
+
payload: {
|
|
1279
|
+
id: step.id,
|
|
1280
|
+
metadata: {}
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
1098
1283
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
type: "watch",
|
|
1102
|
-
payload: {
|
|
1103
|
-
currentStep: {
|
|
1104
|
-
id: step.id,
|
|
1105
|
-
...execResults
|
|
1106
|
-
},
|
|
1107
|
-
workflowState: {
|
|
1108
|
-
status: "running",
|
|
1109
|
-
steps: { ...stepResults, [step.id]: execResults },
|
|
1110
|
-
result: null,
|
|
1111
|
-
error: null
|
|
1112
|
-
}
|
|
1113
|
-
},
|
|
1114
|
-
eventTimestamp: Date.now()
|
|
1284
|
+
stepAISpan?.end({ output: execResults });
|
|
1285
|
+
return { result: execResults, executionContext, stepResults };
|
|
1115
1286
|
});
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1287
|
+
} catch (e) {
|
|
1288
|
+
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1289
|
+
status: "failed",
|
|
1290
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1291
|
+
payload: inputData,
|
|
1292
|
+
startedAt,
|
|
1293
|
+
endedAt: Date.now()
|
|
1294
|
+
};
|
|
1295
|
+
stepRes = {
|
|
1296
|
+
result: stepFailure,
|
|
1297
|
+
executionContext,
|
|
1298
|
+
stepResults: {
|
|
1299
|
+
...stepResults,
|
|
1300
|
+
[step.id]: stepFailure
|
|
1301
|
+
}
|
|
1302
|
+
};
|
|
1303
|
+
}
|
|
1304
|
+
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1305
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1306
|
+
if (step.scorers) {
|
|
1307
|
+
await this.runScorers({
|
|
1308
|
+
scorers: step.scorers,
|
|
1309
|
+
runId: executionContext.runId,
|
|
1310
|
+
input: inputData,
|
|
1311
|
+
output: stepRes.result,
|
|
1312
|
+
workflowId: executionContext.workflowId,
|
|
1313
|
+
stepId: step.id,
|
|
1314
|
+
runtimeContext,
|
|
1315
|
+
disableScorers,
|
|
1316
|
+
tracingContext: { currentSpan: stepAISpan }
|
|
1317
|
+
});
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1142
1321
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1143
1322
|
Object.assign(stepResults, stepRes.stepResults);
|
|
1323
|
+
executionContext.state = stepRes.executionContext.state;
|
|
1144
1324
|
return stepRes.result;
|
|
1145
1325
|
}
|
|
1146
1326
|
async persistStepUpdate({
|
|
1147
1327
|
workflowId,
|
|
1148
1328
|
runId,
|
|
1149
1329
|
stepResults,
|
|
1330
|
+
resourceId,
|
|
1150
1331
|
executionContext,
|
|
1151
1332
|
serializedStepGraph,
|
|
1152
1333
|
workflowStatus,
|
|
@@ -1156,15 +1337,21 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1156
1337
|
await this.inngestStep.run(
|
|
1157
1338
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1158
1339
|
async () => {
|
|
1340
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1341
|
+
if (!shouldPersistSnapshot) {
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1159
1344
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1160
1345
|
workflowName: workflowId,
|
|
1161
1346
|
runId,
|
|
1347
|
+
resourceId,
|
|
1162
1348
|
snapshot: {
|
|
1163
1349
|
runId,
|
|
1164
|
-
value:
|
|
1350
|
+
value: executionContext.state,
|
|
1165
1351
|
context: stepResults,
|
|
1166
1352
|
activePaths: [],
|
|
1167
1353
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1354
|
+
waitingPaths: {},
|
|
1168
1355
|
serializedStepGraph,
|
|
1169
1356
|
status: workflowStatus,
|
|
1170
1357
|
result,
|
|
@@ -1189,12 +1376,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1189
1376
|
emitter,
|
|
1190
1377
|
abortController,
|
|
1191
1378
|
runtimeContext,
|
|
1192
|
-
writableStream
|
|
1379
|
+
writableStream,
|
|
1380
|
+
disableScorers,
|
|
1381
|
+
tracingContext
|
|
1193
1382
|
}) {
|
|
1383
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1384
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
|
|
1385
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1386
|
+
input: prevOutput,
|
|
1387
|
+
attributes: {
|
|
1388
|
+
conditionCount: entry.conditions.length
|
|
1389
|
+
},
|
|
1390
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1391
|
+
});
|
|
1194
1392
|
let execResults;
|
|
1195
1393
|
const truthyIndexes = (await Promise.all(
|
|
1196
1394
|
entry.conditions.map(
|
|
1197
1395
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1396
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1397
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1398
|
+
name: `condition: '${index}'`,
|
|
1399
|
+
input: prevOutput,
|
|
1400
|
+
attributes: {
|
|
1401
|
+
conditionIndex: index
|
|
1402
|
+
},
|
|
1403
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1404
|
+
});
|
|
1198
1405
|
try {
|
|
1199
1406
|
const result = await cond({
|
|
1200
1407
|
runId,
|
|
@@ -1203,17 +1410,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1203
1410
|
runtimeContext,
|
|
1204
1411
|
runCount: -1,
|
|
1205
1412
|
inputData: prevOutput,
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
return null;
|
|
1210
|
-
}
|
|
1211
|
-
const result2 = stepResults[step.id];
|
|
1212
|
-
if (result2?.status === "success") {
|
|
1213
|
-
return result2.output;
|
|
1214
|
-
}
|
|
1215
|
-
return null;
|
|
1413
|
+
state: executionContext.state,
|
|
1414
|
+
setState: (state) => {
|
|
1415
|
+
executionContext.state = state;
|
|
1216
1416
|
},
|
|
1417
|
+
tracingContext: {
|
|
1418
|
+
currentSpan: evalSpan
|
|
1419
|
+
},
|
|
1420
|
+
getInitData: () => stepResults?.input,
|
|
1421
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1217
1422
|
// TODO: this function shouldn't have suspend probably?
|
|
1218
1423
|
suspend: async (_suspendPayload) => {
|
|
1219
1424
|
},
|
|
@@ -1223,13 +1428,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1223
1428
|
abortController.abort();
|
|
1224
1429
|
},
|
|
1225
1430
|
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1431
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1432
|
+
// TODO: add streamVNext support
|
|
1226
1433
|
engine: {
|
|
1227
1434
|
step: this.inngestStep
|
|
1228
1435
|
},
|
|
1229
1436
|
abortSignal: abortController.signal,
|
|
1230
1437
|
writer: new tools.ToolStream(
|
|
1231
1438
|
{
|
|
1232
|
-
prefix: "step",
|
|
1439
|
+
prefix: "workflow-step",
|
|
1233
1440
|
callId: crypto.randomUUID(),
|
|
1234
1441
|
name: "conditional",
|
|
1235
1442
|
runId
|
|
@@ -1237,36 +1444,59 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1237
1444
|
writableStream
|
|
1238
1445
|
)
|
|
1239
1446
|
});
|
|
1447
|
+
evalSpan?.end({
|
|
1448
|
+
output: result,
|
|
1449
|
+
attributes: {
|
|
1450
|
+
result: !!result
|
|
1451
|
+
}
|
|
1452
|
+
});
|
|
1240
1453
|
return result ? index : null;
|
|
1241
1454
|
} catch (e) {
|
|
1455
|
+
evalSpan?.error({
|
|
1456
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1457
|
+
attributes: {
|
|
1458
|
+
result: false
|
|
1459
|
+
}
|
|
1460
|
+
});
|
|
1242
1461
|
return null;
|
|
1243
1462
|
}
|
|
1244
1463
|
})
|
|
1245
1464
|
)
|
|
1246
1465
|
)).filter((index) => index !== null);
|
|
1247
1466
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1467
|
+
conditionalSpan?.update({
|
|
1468
|
+
attributes: {
|
|
1469
|
+
truthyIndexes,
|
|
1470
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1471
|
+
}
|
|
1472
|
+
});
|
|
1248
1473
|
const results = await Promise.all(
|
|
1249
1474
|
stepsToRun.map(
|
|
1250
1475
|
(step, index) => this.executeEntry({
|
|
1251
1476
|
workflowId,
|
|
1252
1477
|
runId,
|
|
1253
1478
|
entry: step,
|
|
1479
|
+
serializedStepGraph,
|
|
1254
1480
|
prevStep,
|
|
1255
1481
|
stepResults,
|
|
1256
1482
|
resume,
|
|
1257
|
-
serializedStepGraph,
|
|
1258
1483
|
executionContext: {
|
|
1259
1484
|
workflowId,
|
|
1260
1485
|
runId,
|
|
1261
1486
|
executionPath: [...executionContext.executionPath, index],
|
|
1262
1487
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1263
1488
|
retryConfig: executionContext.retryConfig,
|
|
1264
|
-
executionSpan: executionContext.executionSpan
|
|
1489
|
+
executionSpan: executionContext.executionSpan,
|
|
1490
|
+
state: executionContext.state
|
|
1265
1491
|
},
|
|
1266
1492
|
emitter,
|
|
1267
1493
|
abortController,
|
|
1268
1494
|
runtimeContext,
|
|
1269
|
-
writableStream
|
|
1495
|
+
writableStream,
|
|
1496
|
+
disableScorers,
|
|
1497
|
+
tracingContext: {
|
|
1498
|
+
currentSpan: conditionalSpan
|
|
1499
|
+
}
|
|
1270
1500
|
})
|
|
1271
1501
|
)
|
|
1272
1502
|
);
|
|
@@ -1275,7 +1505,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1275
1505
|
if (hasFailed) {
|
|
1276
1506
|
execResults = { status: "failed", error: hasFailed.result.error };
|
|
1277
1507
|
} else if (hasSuspended) {
|
|
1278
|
-
execResults = { status: "suspended",
|
|
1508
|
+
execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
|
|
1279
1509
|
} else {
|
|
1280
1510
|
execResults = {
|
|
1281
1511
|
status: "success",
|
|
@@ -1287,6 +1517,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
1287
1517
|
}, {})
|
|
1288
1518
|
};
|
|
1289
1519
|
}
|
|
1520
|
+
if (execResults.status === "failed") {
|
|
1521
|
+
conditionalSpan?.error({
|
|
1522
|
+
error: new Error(execResults.error)
|
|
1523
|
+
});
|
|
1524
|
+
} else {
|
|
1525
|
+
conditionalSpan?.end({
|
|
1526
|
+
output: execResults.output || execResults
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1290
1529
|
return execResults;
|
|
1291
1530
|
}
|
|
1292
1531
|
};
|