@mastra/inngest 0.0.0-message-list-update-20250715150321 → 0.0.0-monorepo-binary-20251013210052
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 +708 -3
- package/dist/index.cjs +611 -329
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +309 -7
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +614 -332
- package/dist/index.js.map +1 -0
- package/package.json +31 -17
- package/dist/_tsup-dts-rollup.d.cts +0 -310
- package/dist/_tsup-dts-rollup.d.ts +0 -310
- package/dist/index.d.cts +0 -7
- package/docker-compose.yaml +0 -10
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -7697
- package/src/index.ts +0 -1737
- package/tsconfig.json +0 -5
- 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
|
-
import { Tool } from '@mastra/core/tools';
|
|
5
|
-
import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
6
|
-
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
5
|
+
import { ToolStream, Tool } from '@mastra/core/tools';
|
|
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,16 +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,
|
|
181
|
+
workflowId: this.workflowId,
|
|
156
182
|
stepResults: snapshot?.context,
|
|
157
183
|
resume: {
|
|
158
184
|
steps,
|
|
159
185
|
stepResults: snapshot?.context,
|
|
160
|
-
resumePayload:
|
|
186
|
+
resumePayload: resumeDataToUse,
|
|
161
187
|
// @ts-ignore
|
|
162
188
|
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
163
189
|
}
|
|
@@ -202,7 +228,11 @@ var InngestRun = class extends Run {
|
|
|
202
228
|
const writer = writable.getWriter();
|
|
203
229
|
const unwatch = this.watch(async (event) => {
|
|
204
230
|
try {
|
|
205
|
-
|
|
231
|
+
const e = {
|
|
232
|
+
...event,
|
|
233
|
+
type: event.type.replace("workflow-", "")
|
|
234
|
+
};
|
|
235
|
+
await writer.write(e);
|
|
206
236
|
} catch {
|
|
207
237
|
}
|
|
208
238
|
}, "watch-v2");
|
|
@@ -233,8 +263,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
233
263
|
#mastra;
|
|
234
264
|
inngest;
|
|
235
265
|
function;
|
|
266
|
+
flowControlConfig;
|
|
236
267
|
constructor(params, inngest) {
|
|
237
|
-
|
|
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;
|
|
238
274
|
this.#mastra = params.mastra;
|
|
239
275
|
this.inngest = inngest;
|
|
240
276
|
}
|
|
@@ -255,27 +291,6 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
255
291
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
256
292
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
257
293
|
}
|
|
258
|
-
async getWorkflowRunExecutionResult(runId) {
|
|
259
|
-
const storage = this.#mastra?.getStorage();
|
|
260
|
-
if (!storage) {
|
|
261
|
-
this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
|
|
262
|
-
return null;
|
|
263
|
-
}
|
|
264
|
-
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
265
|
-
if (!run?.snapshot) {
|
|
266
|
-
return null;
|
|
267
|
-
}
|
|
268
|
-
if (typeof run.snapshot === "string") {
|
|
269
|
-
return null;
|
|
270
|
-
}
|
|
271
|
-
return {
|
|
272
|
-
status: run.snapshot.status,
|
|
273
|
-
result: run.snapshot.result,
|
|
274
|
-
error: run.snapshot.error,
|
|
275
|
-
payload: run.snapshot.context?.input,
|
|
276
|
-
steps: run.snapshot.context
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
294
|
__registerMastra(mastra) {
|
|
280
295
|
this.#mastra = mastra;
|
|
281
296
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -294,23 +309,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
294
309
|
}
|
|
295
310
|
}
|
|
296
311
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
executionGraph: this.executionGraph,
|
|
305
|
-
serializedStepGraph: this.serializedStepGraph,
|
|
306
|
-
mastra: this.#mastra,
|
|
307
|
-
retryConfig: this.retryConfig,
|
|
308
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
309
|
-
},
|
|
310
|
-
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."
|
|
311
319
|
);
|
|
312
|
-
this.runs.set(runIdToUse, run);
|
|
313
|
-
return run;
|
|
314
320
|
}
|
|
315
321
|
async createRunAsync(options) {
|
|
316
322
|
const runIdToUse = options?.runId || randomUUID();
|
|
@@ -318,27 +324,35 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
318
324
|
{
|
|
319
325
|
workflowId: this.id,
|
|
320
326
|
runId: runIdToUse,
|
|
327
|
+
resourceId: options?.resourceId,
|
|
321
328
|
executionEngine: this.executionEngine,
|
|
322
329
|
executionGraph: this.executionGraph,
|
|
323
330
|
serializedStepGraph: this.serializedStepGraph,
|
|
324
331
|
mastra: this.#mastra,
|
|
325
332
|
retryConfig: this.retryConfig,
|
|
326
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
333
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
334
|
+
workflowSteps: this.steps
|
|
327
335
|
},
|
|
328
336
|
this.inngest
|
|
329
337
|
);
|
|
330
338
|
this.runs.set(runIdToUse, run);
|
|
331
|
-
const
|
|
332
|
-
|
|
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) {
|
|
333
345
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
334
346
|
workflowName: this.id,
|
|
335
347
|
runId: runIdToUse,
|
|
348
|
+
resourceId: options?.resourceId,
|
|
336
349
|
snapshot: {
|
|
337
350
|
runId: runIdToUse,
|
|
338
351
|
status: "pending",
|
|
339
352
|
value: {},
|
|
340
353
|
context: {},
|
|
341
354
|
activePaths: [],
|
|
355
|
+
waitingPaths: {},
|
|
342
356
|
serializedStepGraph: this.serializedStepGraph,
|
|
343
357
|
suspendedPaths: {},
|
|
344
358
|
result: void 0,
|
|
@@ -359,11 +373,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
359
373
|
id: `workflow.${this.id}`,
|
|
360
374
|
// @ts-ignore
|
|
361
375
|
retries: this.retryConfig?.attempts ?? 0,
|
|
362
|
-
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
376
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
377
|
+
// Spread flow control configuration
|
|
378
|
+
...this.flowControlConfig
|
|
363
379
|
},
|
|
364
380
|
{ event: `workflow.${this.id}` },
|
|
365
381
|
async ({ event, step, attempt, publish }) => {
|
|
366
|
-
let { inputData, runId, resume } = event.data;
|
|
382
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions } = event.data;
|
|
367
383
|
if (!runId) {
|
|
368
384
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
369
385
|
return randomUUID();
|
|
@@ -391,19 +407,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
391
407
|
once: (_event, _callback) => {
|
|
392
408
|
}
|
|
393
409
|
};
|
|
394
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
410
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
395
411
|
const result = await engine.execute({
|
|
396
412
|
workflowId: this.id,
|
|
397
413
|
runId,
|
|
414
|
+
resourceId,
|
|
398
415
|
graph: this.executionGraph,
|
|
399
416
|
serializedStepGraph: this.serializedStepGraph,
|
|
400
417
|
input: inputData,
|
|
418
|
+
initialState,
|
|
401
419
|
emitter,
|
|
402
420
|
retryConfig: this.retryConfig,
|
|
403
421
|
runtimeContext: new RuntimeContext(),
|
|
404
422
|
// TODO
|
|
405
423
|
resume,
|
|
406
|
-
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;
|
|
407
436
|
});
|
|
408
437
|
return { result, runId };
|
|
409
438
|
}
|
|
@@ -437,17 +466,16 @@ function createStep(params) {
|
|
|
437
466
|
if (isAgent(params)) {
|
|
438
467
|
return {
|
|
439
468
|
id: params.name,
|
|
469
|
+
description: params.getDescription(),
|
|
440
470
|
// @ts-ignore
|
|
441
471
|
inputSchema: z.object({
|
|
442
472
|
prompt: z.string()
|
|
443
|
-
// resourceId: z.string().optional(),
|
|
444
|
-
// threadId: z.string().optional(),
|
|
445
473
|
}),
|
|
446
474
|
// @ts-ignore
|
|
447
475
|
outputSchema: z.object({
|
|
448
476
|
text: z.string()
|
|
449
477
|
}),
|
|
450
|
-
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
478
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
|
|
451
479
|
let streamPromise = {};
|
|
452
480
|
streamPromise.promise = new Promise((resolve, reject) => {
|
|
453
481
|
streamPromise.resolve = resolve;
|
|
@@ -457,50 +485,66 @@ function createStep(params) {
|
|
|
457
485
|
name: params.name,
|
|
458
486
|
args: inputData
|
|
459
487
|
};
|
|
460
|
-
await
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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") {
|
|
479
531
|
await emitter.emit("watch-v2", {
|
|
480
532
|
type: "tool-call-delta",
|
|
481
|
-
...toolData,
|
|
533
|
+
...toolData ?? {},
|
|
482
534
|
argsTextDelta: chunk.textDelta
|
|
483
535
|
});
|
|
484
|
-
|
|
485
|
-
case "step-start":
|
|
486
|
-
case "step-finish":
|
|
487
|
-
case "finish":
|
|
488
|
-
break;
|
|
489
|
-
case "tool-call":
|
|
490
|
-
case "tool-result":
|
|
491
|
-
case "tool-call-streaming-start":
|
|
492
|
-
case "tool-call-delta":
|
|
493
|
-
case "source":
|
|
494
|
-
case "file":
|
|
495
|
-
default:
|
|
496
|
-
await emitter.emit("watch-v2", chunk);
|
|
497
|
-
break;
|
|
536
|
+
}
|
|
498
537
|
}
|
|
499
538
|
}
|
|
539
|
+
await emitter.emit("watch-v2", {
|
|
540
|
+
type: "tool-call-streaming-finish",
|
|
541
|
+
...toolData ?? {}
|
|
542
|
+
});
|
|
500
543
|
return {
|
|
501
544
|
text: await streamPromise.promise
|
|
502
545
|
};
|
|
503
|
-
}
|
|
546
|
+
},
|
|
547
|
+
component: params.component
|
|
504
548
|
};
|
|
505
549
|
}
|
|
506
550
|
if (isTool(params)) {
|
|
@@ -511,15 +555,20 @@ function createStep(params) {
|
|
|
511
555
|
// TODO: tool probably should have strong id type
|
|
512
556
|
// @ts-ignore
|
|
513
557
|
id: params.id,
|
|
558
|
+
description: params.description,
|
|
514
559
|
inputSchema: params.inputSchema,
|
|
515
560
|
outputSchema: params.outputSchema,
|
|
516
|
-
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
561
|
+
execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
|
|
517
562
|
return params.execute({
|
|
518
563
|
context: inputData,
|
|
519
|
-
mastra,
|
|
520
|
-
runtimeContext
|
|
564
|
+
mastra: wrapMastra(mastra, tracingContext),
|
|
565
|
+
runtimeContext,
|
|
566
|
+
tracingContext,
|
|
567
|
+
suspend,
|
|
568
|
+
resumeData
|
|
521
569
|
});
|
|
522
|
-
}
|
|
570
|
+
},
|
|
571
|
+
component: "TOOL"
|
|
523
572
|
};
|
|
524
573
|
}
|
|
525
574
|
return {
|
|
@@ -535,7 +584,10 @@ function createStep(params) {
|
|
|
535
584
|
function init(inngest) {
|
|
536
585
|
return {
|
|
537
586
|
createWorkflow(params) {
|
|
538
|
-
return new InngestWorkflow(
|
|
587
|
+
return new InngestWorkflow(
|
|
588
|
+
params,
|
|
589
|
+
inngest
|
|
590
|
+
);
|
|
539
591
|
},
|
|
540
592
|
createStep,
|
|
541
593
|
cloneStep(step, opts) {
|
|
@@ -544,7 +596,11 @@ function init(inngest) {
|
|
|
544
596
|
description: step.description,
|
|
545
597
|
inputSchema: step.inputSchema,
|
|
546
598
|
outputSchema: step.outputSchema,
|
|
547
|
-
|
|
599
|
+
resumeSchema: step.resumeSchema,
|
|
600
|
+
suspendSchema: step.suspendSchema,
|
|
601
|
+
stateSchema: step.stateSchema,
|
|
602
|
+
execute: step.execute,
|
|
603
|
+
component: step.component
|
|
548
604
|
};
|
|
549
605
|
},
|
|
550
606
|
cloneWorkflow(workflow, opts) {
|
|
@@ -564,19 +620,19 @@ function init(inngest) {
|
|
|
564
620
|
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
565
621
|
inngestStep;
|
|
566
622
|
inngestAttempts;
|
|
567
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
568
|
-
super({ mastra });
|
|
623
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
624
|
+
super({ mastra, options });
|
|
569
625
|
this.inngestStep = inngestStep;
|
|
570
626
|
this.inngestAttempts = inngestAttempts;
|
|
571
627
|
}
|
|
572
628
|
async execute(params) {
|
|
573
629
|
await params.emitter.emit("watch-v2", {
|
|
574
|
-
type: "start",
|
|
630
|
+
type: "workflow-start",
|
|
575
631
|
payload: { runId: params.runId }
|
|
576
632
|
});
|
|
577
633
|
const result = await super.execute(params);
|
|
578
634
|
await params.emitter.emit("watch-v2", {
|
|
579
|
-
type: "finish",
|
|
635
|
+
type: "workflow-finish",
|
|
580
636
|
payload: { runId: params.runId }
|
|
581
637
|
});
|
|
582
638
|
return result;
|
|
@@ -628,7 +684,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
628
684
|
});
|
|
629
685
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
630
686
|
if (stepResult?.status === "suspended") {
|
|
631
|
-
const nestedPath = stepResult?.
|
|
687
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
632
688
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
633
689
|
}
|
|
634
690
|
return [];
|
|
@@ -638,31 +694,6 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
638
694
|
executionSpan?.end();
|
|
639
695
|
return base;
|
|
640
696
|
}
|
|
641
|
-
async superExecuteStep({
|
|
642
|
-
workflowId,
|
|
643
|
-
runId,
|
|
644
|
-
step,
|
|
645
|
-
stepResults,
|
|
646
|
-
executionContext,
|
|
647
|
-
resume,
|
|
648
|
-
prevOutput,
|
|
649
|
-
emitter,
|
|
650
|
-
abortController,
|
|
651
|
-
runtimeContext
|
|
652
|
-
}) {
|
|
653
|
-
return super.executeStep({
|
|
654
|
-
workflowId,
|
|
655
|
-
runId,
|
|
656
|
-
step,
|
|
657
|
-
stepResults,
|
|
658
|
-
executionContext,
|
|
659
|
-
resume,
|
|
660
|
-
prevOutput,
|
|
661
|
-
emitter,
|
|
662
|
-
abortController,
|
|
663
|
-
runtimeContext
|
|
664
|
-
});
|
|
665
|
-
}
|
|
666
697
|
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
667
698
|
// await this.inngestStep.sleep(id, duration);
|
|
668
699
|
// }
|
|
@@ -674,28 +705,40 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
674
705
|
stepResults,
|
|
675
706
|
emitter,
|
|
676
707
|
abortController,
|
|
677
|
-
runtimeContext
|
|
708
|
+
runtimeContext,
|
|
709
|
+
executionContext,
|
|
710
|
+
writableStream,
|
|
711
|
+
tracingContext
|
|
678
712
|
}) {
|
|
679
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
|
+
});
|
|
680
723
|
if (fn) {
|
|
724
|
+
const stepCallId = randomUUID();
|
|
681
725
|
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
682
726
|
return await fn({
|
|
683
727
|
runId,
|
|
728
|
+
workflowId,
|
|
684
729
|
mastra: this.mastra,
|
|
685
730
|
runtimeContext,
|
|
686
731
|
inputData: prevOutput,
|
|
732
|
+
state: executionContext.state,
|
|
733
|
+
setState: (state) => {
|
|
734
|
+
executionContext.state = state;
|
|
735
|
+
},
|
|
687
736
|
runCount: -1,
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
if (!step?.id) {
|
|
691
|
-
return null;
|
|
692
|
-
}
|
|
693
|
-
const result = stepResults[step.id];
|
|
694
|
-
if (result?.status === "success") {
|
|
695
|
-
return result.output;
|
|
696
|
-
}
|
|
697
|
-
return null;
|
|
737
|
+
tracingContext: {
|
|
738
|
+
currentSpan: sleepSpan
|
|
698
739
|
},
|
|
740
|
+
getInitData: () => stepResults?.input,
|
|
741
|
+
getStepResult: getStepResult.bind(this, stepResults),
|
|
699
742
|
// TODO: this function shouldn't have suspend probably?
|
|
700
743
|
suspend: async (_suspendPayload) => {
|
|
701
744
|
},
|
|
@@ -705,12 +748,34 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
705
748
|
abortController?.abort();
|
|
706
749
|
},
|
|
707
750
|
[EMITTER_SYMBOL]: emitter,
|
|
751
|
+
// TODO: add streamVNext support
|
|
752
|
+
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
708
753
|
engine: { step: this.inngestStep },
|
|
709
|
-
abortSignal: abortController?.signal
|
|
754
|
+
abortSignal: abortController?.signal,
|
|
755
|
+
writer: new ToolStream(
|
|
756
|
+
{
|
|
757
|
+
prefix: "workflow-step",
|
|
758
|
+
callId: stepCallId,
|
|
759
|
+
name: "sleep",
|
|
760
|
+
runId
|
|
761
|
+
},
|
|
762
|
+
writableStream
|
|
763
|
+
)
|
|
710
764
|
});
|
|
711
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;
|
|
712
778
|
}
|
|
713
|
-
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
714
779
|
}
|
|
715
780
|
async executeSleepUntil({
|
|
716
781
|
workflowId,
|
|
@@ -720,28 +785,41 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
720
785
|
stepResults,
|
|
721
786
|
emitter,
|
|
722
787
|
abortController,
|
|
723
|
-
runtimeContext
|
|
788
|
+
runtimeContext,
|
|
789
|
+
executionContext,
|
|
790
|
+
writableStream,
|
|
791
|
+
tracingContext
|
|
724
792
|
}) {
|
|
725
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
|
+
});
|
|
726
804
|
if (fn) {
|
|
727
805
|
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
806
|
+
const stepCallId = randomUUID();
|
|
728
807
|
return await fn({
|
|
729
808
|
runId,
|
|
809
|
+
workflowId,
|
|
730
810
|
mastra: this.mastra,
|
|
731
811
|
runtimeContext,
|
|
732
812
|
inputData: prevOutput,
|
|
813
|
+
state: executionContext.state,
|
|
814
|
+
setState: (state) => {
|
|
815
|
+
executionContext.state = state;
|
|
816
|
+
},
|
|
733
817
|
runCount: -1,
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
if (!step?.id) {
|
|
737
|
-
return null;
|
|
738
|
-
}
|
|
739
|
-
const result = stepResults[step.id];
|
|
740
|
-
if (result?.status === "success") {
|
|
741
|
-
return result.output;
|
|
742
|
-
}
|
|
743
|
-
return null;
|
|
818
|
+
tracingContext: {
|
|
819
|
+
currentSpan: sleepUntilSpan
|
|
744
820
|
},
|
|
821
|
+
getInitData: () => stepResults?.input,
|
|
822
|
+
getStepResult: getStepResult.bind(this, stepResults),
|
|
745
823
|
// TODO: this function shouldn't have suspend probably?
|
|
746
824
|
suspend: async (_suspendPayload) => {
|
|
747
825
|
},
|
|
@@ -751,15 +829,42 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
751
829
|
abortController?.abort();
|
|
752
830
|
},
|
|
753
831
|
[EMITTER_SYMBOL]: emitter,
|
|
832
|
+
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
833
|
+
// TODO: add streamVNext support
|
|
754
834
|
engine: { step: this.inngestStep },
|
|
755
|
-
abortSignal: abortController?.signal
|
|
835
|
+
abortSignal: abortController?.signal,
|
|
836
|
+
writer: new ToolStream(
|
|
837
|
+
{
|
|
838
|
+
prefix: "workflow-step",
|
|
839
|
+
callId: stepCallId,
|
|
840
|
+
name: "sleep",
|
|
841
|
+
runId
|
|
842
|
+
},
|
|
843
|
+
writableStream
|
|
844
|
+
)
|
|
756
845
|
});
|
|
757
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
|
+
});
|
|
758
856
|
}
|
|
759
857
|
if (!(date instanceof Date)) {
|
|
858
|
+
sleepUntilSpan?.end();
|
|
760
859
|
return;
|
|
761
860
|
}
|
|
762
|
-
|
|
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
|
+
}
|
|
763
868
|
}
|
|
764
869
|
async executeWaitForEvent({ event, timeout }) {
|
|
765
870
|
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
@@ -779,8 +884,25 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
779
884
|
prevOutput,
|
|
780
885
|
emitter,
|
|
781
886
|
abortController,
|
|
782
|
-
runtimeContext
|
|
887
|
+
runtimeContext,
|
|
888
|
+
tracingContext,
|
|
889
|
+
writableStream,
|
|
890
|
+
disableScorers
|
|
783
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
|
+
});
|
|
784
906
|
const startedAt = await this.inngestStep.run(
|
|
785
907
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
786
908
|
async () => {
|
|
@@ -807,11 +929,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
807
929
|
eventTimestamp: Date.now()
|
|
808
930
|
});
|
|
809
931
|
await emitter.emit("watch-v2", {
|
|
810
|
-
type: "step-start",
|
|
932
|
+
type: "workflow-step-start",
|
|
811
933
|
payload: {
|
|
812
934
|
id: step.id,
|
|
813
935
|
status: "running",
|
|
814
|
-
payload:
|
|
936
|
+
payload: inputData,
|
|
815
937
|
startedAt: startedAt2
|
|
816
938
|
}
|
|
817
939
|
});
|
|
@@ -822,38 +944,60 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
822
944
|
const isResume = !!resume?.steps?.length;
|
|
823
945
|
let result;
|
|
824
946
|
let runId;
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
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 ?? {},
|
|
837
959
|
runId,
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
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 }
|
|
843
969
|
}
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
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
|
+
}
|
|
857
1001
|
}
|
|
858
1002
|
const res = await this.inngestStep.run(
|
|
859
1003
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
@@ -877,7 +1021,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
877
1021
|
eventTimestamp: Date.now()
|
|
878
1022
|
});
|
|
879
1023
|
await emitter.emit("watch-v2", {
|
|
880
|
-
type: "step-result",
|
|
1024
|
+
type: "workflow-step-result",
|
|
881
1025
|
payload: {
|
|
882
1026
|
id: step.id,
|
|
883
1027
|
status: "failed",
|
|
@@ -892,7 +1036,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
892
1036
|
return stepRes2?.status === "suspended";
|
|
893
1037
|
});
|
|
894
1038
|
for (const [stepName, stepResult] of suspendedSteps) {
|
|
895
|
-
const suspendPath = [stepName, ...stepResult?.
|
|
1039
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
896
1040
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
897
1041
|
await emitter.emit("watch", {
|
|
898
1042
|
type: "watch",
|
|
@@ -900,7 +1044,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
900
1044
|
currentStep: {
|
|
901
1045
|
id: step.id,
|
|
902
1046
|
status: "suspended",
|
|
903
|
-
payload:
|
|
1047
|
+
payload: stepResult.payload,
|
|
1048
|
+
suspendPayload: {
|
|
1049
|
+
...stepResult?.suspendPayload,
|
|
1050
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1051
|
+
}
|
|
904
1052
|
},
|
|
905
1053
|
workflowState: {
|
|
906
1054
|
status: "running",
|
|
@@ -912,7 +1060,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
912
1060
|
eventTimestamp: Date.now()
|
|
913
1061
|
});
|
|
914
1062
|
await emitter.emit("watch-v2", {
|
|
915
|
-
type: "step-suspended",
|
|
1063
|
+
type: "workflow-step-suspended",
|
|
916
1064
|
payload: {
|
|
917
1065
|
id: step.id,
|
|
918
1066
|
status: "suspended"
|
|
@@ -922,7 +1070,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
922
1070
|
executionContext,
|
|
923
1071
|
result: {
|
|
924
1072
|
status: "suspended",
|
|
925
|
-
payload:
|
|
1073
|
+
payload: stepResult.payload,
|
|
1074
|
+
suspendPayload: {
|
|
1075
|
+
...stepResult?.suspendPayload,
|
|
1076
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1077
|
+
}
|
|
926
1078
|
}
|
|
927
1079
|
};
|
|
928
1080
|
}
|
|
@@ -969,7 +1121,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
969
1121
|
eventTimestamp: Date.now()
|
|
970
1122
|
});
|
|
971
1123
|
await emitter.emit("watch-v2", {
|
|
972
|
-
type: "step-result",
|
|
1124
|
+
type: "workflow-step-result",
|
|
973
1125
|
payload: {
|
|
974
1126
|
id: step.id,
|
|
975
1127
|
status: "success",
|
|
@@ -977,7 +1129,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
977
1129
|
}
|
|
978
1130
|
});
|
|
979
1131
|
await emitter.emit("watch-v2", {
|
|
980
|
-
type: "step-finish",
|
|
1132
|
+
type: "workflow-step-finish",
|
|
981
1133
|
payload: {
|
|
982
1134
|
id: step.id,
|
|
983
1135
|
metadata: {}
|
|
@@ -987,135 +1139,193 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
987
1139
|
}
|
|
988
1140
|
);
|
|
989
1141
|
Object.assign(executionContext, res.executionContext);
|
|
990
|
-
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
|
+
};
|
|
991
1150
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
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
|
|
1008
1254
|
}
|
|
1009
|
-
return null;
|
|
1010
|
-
},
|
|
1011
|
-
suspend: async (suspendPayload) => {
|
|
1012
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1013
|
-
suspended = { payload: suspendPayload };
|
|
1014
|
-
},
|
|
1015
|
-
bail: (result2) => {
|
|
1016
|
-
bailed = { payload: result2 };
|
|
1017
|
-
},
|
|
1018
|
-
resume: {
|
|
1019
|
-
steps: resume?.steps?.slice(1) || [],
|
|
1020
|
-
resumePayload: resume?.resumePayload,
|
|
1021
|
-
// @ts-ignore
|
|
1022
|
-
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
1023
|
-
},
|
|
1024
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1025
|
-
engine: {
|
|
1026
|
-
step: this.inngestStep
|
|
1027
1255
|
},
|
|
1028
|
-
|
|
1256
|
+
eventTimestamp: Date.now()
|
|
1029
1257
|
});
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
status: "suspended",
|
|
1054
|
-
suspendedPayload: suspended.payload,
|
|
1055
|
-
payload: prevOutput,
|
|
1056
|
-
suspendedAt: Date.now(),
|
|
1057
|
-
startedAt,
|
|
1058
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1059
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1060
|
-
};
|
|
1061
|
-
} else if (bailed) {
|
|
1062
|
-
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
1063
|
-
}
|
|
1064
|
-
if (execResults.status === "failed") {
|
|
1065
|
-
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
1066
|
-
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
|
+
});
|
|
1067
1281
|
}
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
type: "watch",
|
|
1071
|
-
payload: {
|
|
1072
|
-
currentStep: {
|
|
1073
|
-
id: step.id,
|
|
1074
|
-
...execResults
|
|
1075
|
-
},
|
|
1076
|
-
workflowState: {
|
|
1077
|
-
status: "running",
|
|
1078
|
-
steps: { ...stepResults, [step.id]: execResults },
|
|
1079
|
-
result: null,
|
|
1080
|
-
error: null
|
|
1081
|
-
}
|
|
1082
|
-
},
|
|
1083
|
-
eventTimestamp: Date.now()
|
|
1282
|
+
stepAISpan?.end({ output: execResults });
|
|
1283
|
+
return { result: execResults, executionContext, stepResults };
|
|
1084
1284
|
});
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
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
|
+
}
|
|
1111
1319
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1112
1320
|
Object.assign(stepResults, stepRes.stepResults);
|
|
1321
|
+
executionContext.state = stepRes.executionContext.state;
|
|
1113
1322
|
return stepRes.result;
|
|
1114
1323
|
}
|
|
1115
1324
|
async persistStepUpdate({
|
|
1116
1325
|
workflowId,
|
|
1117
1326
|
runId,
|
|
1118
1327
|
stepResults,
|
|
1328
|
+
resourceId,
|
|
1119
1329
|
executionContext,
|
|
1120
1330
|
serializedStepGraph,
|
|
1121
1331
|
workflowStatus,
|
|
@@ -1125,15 +1335,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1125
1335
|
await this.inngestStep.run(
|
|
1126
1336
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1127
1337
|
async () => {
|
|
1338
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1339
|
+
if (!shouldPersistSnapshot) {
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1128
1342
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1129
1343
|
workflowName: workflowId,
|
|
1130
1344
|
runId,
|
|
1345
|
+
resourceId,
|
|
1131
1346
|
snapshot: {
|
|
1132
1347
|
runId,
|
|
1133
|
-
value:
|
|
1348
|
+
value: executionContext.state,
|
|
1134
1349
|
context: stepResults,
|
|
1135
1350
|
activePaths: [],
|
|
1136
1351
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1352
|
+
waitingPaths: {},
|
|
1137
1353
|
serializedStepGraph,
|
|
1138
1354
|
status: workflowStatus,
|
|
1139
1355
|
result,
|
|
@@ -1157,30 +1373,50 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1157
1373
|
executionContext,
|
|
1158
1374
|
emitter,
|
|
1159
1375
|
abortController,
|
|
1160
|
-
runtimeContext
|
|
1376
|
+
runtimeContext,
|
|
1377
|
+
writableStream,
|
|
1378
|
+
disableScorers,
|
|
1379
|
+
tracingContext
|
|
1161
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
|
+
});
|
|
1162
1390
|
let execResults;
|
|
1163
1391
|
const truthyIndexes = (await Promise.all(
|
|
1164
1392
|
entry.conditions.map(
|
|
1165
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
|
+
});
|
|
1166
1403
|
try {
|
|
1167
1404
|
const result = await cond({
|
|
1168
1405
|
runId,
|
|
1406
|
+
workflowId,
|
|
1169
1407
|
mastra: this.mastra,
|
|
1170
1408
|
runtimeContext,
|
|
1171
1409
|
runCount: -1,
|
|
1172
1410
|
inputData: prevOutput,
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
if (result2?.status === "success") {
|
|
1180
|
-
return result2.output;
|
|
1181
|
-
}
|
|
1182
|
-
return null;
|
|
1411
|
+
state: executionContext.state,
|
|
1412
|
+
setState: (state) => {
|
|
1413
|
+
executionContext.state = state;
|
|
1414
|
+
},
|
|
1415
|
+
tracingContext: {
|
|
1416
|
+
currentSpan: evalSpan
|
|
1183
1417
|
},
|
|
1418
|
+
getInitData: () => stepResults?.input,
|
|
1419
|
+
getStepResult: getStepResult.bind(this, stepResults),
|
|
1184
1420
|
// TODO: this function shouldn't have suspend probably?
|
|
1185
1421
|
suspend: async (_suspendPayload) => {
|
|
1186
1422
|
},
|
|
@@ -1190,40 +1426,75 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1190
1426
|
abortController.abort();
|
|
1191
1427
|
},
|
|
1192
1428
|
[EMITTER_SYMBOL]: emitter,
|
|
1429
|
+
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1430
|
+
// TODO: add streamVNext support
|
|
1193
1431
|
engine: {
|
|
1194
1432
|
step: this.inngestStep
|
|
1195
1433
|
},
|
|
1196
|
-
abortSignal: abortController.signal
|
|
1434
|
+
abortSignal: abortController.signal,
|
|
1435
|
+
writer: new ToolStream(
|
|
1436
|
+
{
|
|
1437
|
+
prefix: "workflow-step",
|
|
1438
|
+
callId: randomUUID(),
|
|
1439
|
+
name: "conditional",
|
|
1440
|
+
runId
|
|
1441
|
+
},
|
|
1442
|
+
writableStream
|
|
1443
|
+
)
|
|
1444
|
+
});
|
|
1445
|
+
evalSpan?.end({
|
|
1446
|
+
output: result,
|
|
1447
|
+
attributes: {
|
|
1448
|
+
result: !!result
|
|
1449
|
+
}
|
|
1197
1450
|
});
|
|
1198
1451
|
return result ? index : null;
|
|
1199
1452
|
} catch (e) {
|
|
1453
|
+
evalSpan?.error({
|
|
1454
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1455
|
+
attributes: {
|
|
1456
|
+
result: false
|
|
1457
|
+
}
|
|
1458
|
+
});
|
|
1200
1459
|
return null;
|
|
1201
1460
|
}
|
|
1202
1461
|
})
|
|
1203
1462
|
)
|
|
1204
1463
|
)).filter((index) => index !== null);
|
|
1205
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
|
+
});
|
|
1206
1471
|
const results = await Promise.all(
|
|
1207
1472
|
stepsToRun.map(
|
|
1208
1473
|
(step, index) => this.executeEntry({
|
|
1209
1474
|
workflowId,
|
|
1210
1475
|
runId,
|
|
1211
1476
|
entry: step,
|
|
1477
|
+
serializedStepGraph,
|
|
1212
1478
|
prevStep,
|
|
1213
1479
|
stepResults,
|
|
1214
1480
|
resume,
|
|
1215
|
-
serializedStepGraph,
|
|
1216
1481
|
executionContext: {
|
|
1217
1482
|
workflowId,
|
|
1218
1483
|
runId,
|
|
1219
1484
|
executionPath: [...executionContext.executionPath, index],
|
|
1220
1485
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1221
1486
|
retryConfig: executionContext.retryConfig,
|
|
1222
|
-
executionSpan: executionContext.executionSpan
|
|
1487
|
+
executionSpan: executionContext.executionSpan,
|
|
1488
|
+
state: executionContext.state
|
|
1223
1489
|
},
|
|
1224
1490
|
emitter,
|
|
1225
1491
|
abortController,
|
|
1226
|
-
runtimeContext
|
|
1492
|
+
runtimeContext,
|
|
1493
|
+
writableStream,
|
|
1494
|
+
disableScorers,
|
|
1495
|
+
tracingContext: {
|
|
1496
|
+
currentSpan: conditionalSpan
|
|
1497
|
+
}
|
|
1227
1498
|
})
|
|
1228
1499
|
)
|
|
1229
1500
|
);
|
|
@@ -1232,7 +1503,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1232
1503
|
if (hasFailed) {
|
|
1233
1504
|
execResults = { status: "failed", error: hasFailed.result.error };
|
|
1234
1505
|
} else if (hasSuspended) {
|
|
1235
|
-
execResults = { status: "suspended",
|
|
1506
|
+
execResults = { status: "suspended", suspendPayload: hasSuspended.result.suspendPayload };
|
|
1236
1507
|
} else {
|
|
1237
1508
|
execResults = {
|
|
1238
1509
|
status: "success",
|
|
@@ -1244,8 +1515,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
1244
1515
|
}, {})
|
|
1245
1516
|
};
|
|
1246
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
|
+
}
|
|
1247
1527
|
return execResults;
|
|
1248
1528
|
}
|
|
1249
1529
|
};
|
|
1250
1530
|
|
|
1251
1531
|
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|
|
1532
|
+
//# sourceMappingURL=index.js.map
|
|
1533
|
+
//# sourceMappingURL=index.js.map
|