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