@mastra/inngest 0.0.0-course-20250527170450 → 0.0.0-custom-instrumentation-20250626084921
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 +251 -2
- package/dist/_tsup-dts-rollup.d.cts +103 -28
- package/dist/_tsup-dts-rollup.d.ts +103 -28
- package/dist/index.cjs +399 -42
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +399 -43
- package/package.json +18 -17
- package/src/index.test.ts +2607 -1177
- package/src/index.ts +618 -61
package/src/index.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
|
+
import type { ReadableStream } from 'node:stream/web';
|
|
2
3
|
import { subscribe } from '@inngest/realtime';
|
|
3
|
-
import type { Mastra, WorkflowRun, WorkflowRuns } from '@mastra/core';
|
|
4
|
+
import type { Agent, Mastra, ToolExecutionContext, WorkflowRun, WorkflowRuns } from '@mastra/core';
|
|
4
5
|
import { RuntimeContext } from '@mastra/core/di';
|
|
5
|
-
import {
|
|
6
|
+
import { Tool } from '@mastra/core/tools';
|
|
7
|
+
import { Workflow, Run, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
6
8
|
import type {
|
|
7
9
|
ExecuteFunction,
|
|
8
10
|
ExecutionContext,
|
|
@@ -13,12 +15,21 @@ import type {
|
|
|
13
15
|
StepFlowEntry,
|
|
14
16
|
StepResult,
|
|
15
17
|
WorkflowResult,
|
|
18
|
+
SerializedStepFlowEntry,
|
|
19
|
+
StepFailure,
|
|
20
|
+
Emitter,
|
|
21
|
+
WatchEvent,
|
|
22
|
+
StreamEvent,
|
|
16
23
|
} from '@mastra/core/workflows';
|
|
17
24
|
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
18
25
|
import type { Span } from '@opentelemetry/api';
|
|
19
26
|
import type { Inngest, BaseContext } from 'inngest';
|
|
20
27
|
import { serve as inngestServe } from 'inngest/hono';
|
|
21
|
-
import
|
|
28
|
+
import { z } from 'zod';
|
|
29
|
+
|
|
30
|
+
export type InngestEngineType = {
|
|
31
|
+
step: any;
|
|
32
|
+
};
|
|
22
33
|
|
|
23
34
|
export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest }): ReturnType<typeof inngestServe> {
|
|
24
35
|
const wfs = mastra.getWorkflows();
|
|
@@ -36,11 +47,13 @@ export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest })
|
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
export class InngestRun<
|
|
50
|
+
TEngineType = InngestEngineType,
|
|
39
51
|
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
40
52
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
41
53
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
42
|
-
> extends Run<TSteps, TInput, TOutput> {
|
|
54
|
+
> extends Run<TEngineType, TSteps, TInput, TOutput> {
|
|
43
55
|
private inngest: Inngest;
|
|
56
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
44
57
|
#mastra: Mastra;
|
|
45
58
|
|
|
46
59
|
constructor(
|
|
@@ -49,6 +62,7 @@ export class InngestRun<
|
|
|
49
62
|
runId: string;
|
|
50
63
|
executionEngine: ExecutionEngine;
|
|
51
64
|
executionGraph: ExecutionGraph;
|
|
65
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
52
66
|
mastra?: Mastra;
|
|
53
67
|
retryConfig?: {
|
|
54
68
|
attempts?: number;
|
|
@@ -60,11 +74,12 @@ export class InngestRun<
|
|
|
60
74
|
) {
|
|
61
75
|
super(params);
|
|
62
76
|
this.inngest = inngest;
|
|
77
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
63
78
|
this.#mastra = params.mastra!;
|
|
64
79
|
}
|
|
65
80
|
|
|
66
81
|
async getRuns(eventId: string) {
|
|
67
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
82
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? 'https://api.inngest.com'}/v1/events/${eventId}/runs`, {
|
|
68
83
|
headers: {
|
|
69
84
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`,
|
|
70
85
|
},
|
|
@@ -75,7 +90,8 @@ export class InngestRun<
|
|
|
75
90
|
|
|
76
91
|
async getRunOutput(eventId: string) {
|
|
77
92
|
let runs = await this.getRuns(eventId);
|
|
78
|
-
|
|
93
|
+
|
|
94
|
+
while (runs?.[0]?.status !== 'Completed' || runs?.[0]?.event_id !== eventId) {
|
|
79
95
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
80
96
|
runs = await this.getRuns(eventId);
|
|
81
97
|
if (runs?.[0]?.status === 'Failed' || runs?.[0]?.status === 'Cancelled') {
|
|
@@ -85,6 +101,13 @@ export class InngestRun<
|
|
|
85
101
|
return runs?.[0];
|
|
86
102
|
}
|
|
87
103
|
|
|
104
|
+
async sendEvent(event: string, data: any) {
|
|
105
|
+
await this.inngest.send({
|
|
106
|
+
name: `user-event-${event}`,
|
|
107
|
+
data,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
88
111
|
async start({
|
|
89
112
|
inputData,
|
|
90
113
|
}: {
|
|
@@ -96,11 +119,13 @@ export class InngestRun<
|
|
|
96
119
|
runId: this.runId,
|
|
97
120
|
snapshot: {
|
|
98
121
|
runId: this.runId,
|
|
122
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
99
123
|
value: {},
|
|
100
124
|
context: {} as any,
|
|
101
125
|
activePaths: [],
|
|
102
126
|
suspendedPaths: {},
|
|
103
127
|
timestamp: Date.now(),
|
|
128
|
+
status: 'running',
|
|
104
129
|
},
|
|
105
130
|
});
|
|
106
131
|
|
|
@@ -134,6 +159,27 @@ export class InngestRun<
|
|
|
134
159
|
| string
|
|
135
160
|
| string[];
|
|
136
161
|
runtimeContext?: RuntimeContext;
|
|
162
|
+
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
163
|
+
const p = this._resume(params).then(result => {
|
|
164
|
+
if (result.status !== 'suspended') {
|
|
165
|
+
this.closeStreamAction?.().catch(() => {});
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
this.executionResults = p;
|
|
172
|
+
return p;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async _resume<TResumeSchema extends z.ZodType<any>>(params: {
|
|
176
|
+
resumeData?: z.infer<TResumeSchema>;
|
|
177
|
+
step:
|
|
178
|
+
| Step<string, any, any, TResumeSchema, any>
|
|
179
|
+
| [...Step<string, any, any, any, any>[], Step<string, any, any, TResumeSchema, any>]
|
|
180
|
+
| string
|
|
181
|
+
| string[];
|
|
182
|
+
runtimeContext?: RuntimeContext;
|
|
137
183
|
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
138
184
|
const steps: string[] = (Array.isArray(params.step) ? params.step : [params.step]).map(step =>
|
|
139
185
|
typeof step === 'string' ? step : step?.id,
|
|
@@ -171,37 +217,82 @@ export class InngestRun<
|
|
|
171
217
|
return result;
|
|
172
218
|
}
|
|
173
219
|
|
|
174
|
-
watch(cb: (event:
|
|
220
|
+
watch(cb: (event: WatchEvent) => void, type: 'watch' | 'watch-v2' = 'watch'): () => void {
|
|
221
|
+
let active = true;
|
|
175
222
|
const streamPromise = subscribe(
|
|
176
223
|
{
|
|
177
224
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
178
|
-
topics: [
|
|
225
|
+
topics: [type],
|
|
179
226
|
app: this.inngest,
|
|
180
227
|
},
|
|
181
228
|
(message: any) => {
|
|
182
|
-
|
|
229
|
+
if (active) {
|
|
230
|
+
cb(message.data);
|
|
231
|
+
}
|
|
183
232
|
},
|
|
184
233
|
);
|
|
185
234
|
|
|
186
235
|
return () => {
|
|
236
|
+
active = false;
|
|
187
237
|
streamPromise
|
|
188
|
-
.then((stream:
|
|
189
|
-
stream.cancel();
|
|
238
|
+
.then(async (stream: Awaited<typeof streamPromise>) => {
|
|
239
|
+
return stream.cancel();
|
|
190
240
|
})
|
|
191
241
|
.catch(err => {
|
|
192
242
|
console.error(err);
|
|
193
243
|
});
|
|
194
244
|
};
|
|
195
245
|
}
|
|
246
|
+
|
|
247
|
+
stream({ inputData, runtimeContext }: { inputData?: z.infer<TInput>; runtimeContext?: RuntimeContext } = {}): {
|
|
248
|
+
stream: ReadableStream<StreamEvent>;
|
|
249
|
+
getWorkflowState: () => Promise<WorkflowResult<TOutput, TSteps>>;
|
|
250
|
+
} {
|
|
251
|
+
const { readable, writable } = new TransformStream<StreamEvent, StreamEvent>();
|
|
252
|
+
|
|
253
|
+
const writer = writable.getWriter();
|
|
254
|
+
const unwatch = this.watch(async event => {
|
|
255
|
+
try {
|
|
256
|
+
// watch-v2 events are data stream events, so we need to cast them to the correct type
|
|
257
|
+
await writer.write(event as any);
|
|
258
|
+
} catch {}
|
|
259
|
+
}, 'watch-v2');
|
|
260
|
+
|
|
261
|
+
this.closeStreamAction = async () => {
|
|
262
|
+
unwatch();
|
|
263
|
+
|
|
264
|
+
try {
|
|
265
|
+
await writer.close();
|
|
266
|
+
} catch (err) {
|
|
267
|
+
console.error('Error closing stream:', err);
|
|
268
|
+
} finally {
|
|
269
|
+
writer.releaseLock();
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then(result => {
|
|
274
|
+
if (result.status !== 'suspended') {
|
|
275
|
+
this.closeStreamAction?.().catch(() => {});
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return result;
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
return {
|
|
282
|
+
stream: readable as ReadableStream<StreamEvent>,
|
|
283
|
+
getWorkflowState: () => this.executionResults!,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
196
286
|
}
|
|
197
287
|
|
|
198
288
|
export class InngestWorkflow<
|
|
289
|
+
TEngineType = InngestEngineType,
|
|
199
290
|
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
200
291
|
TWorkflowId extends string = string,
|
|
201
292
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
202
293
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
203
294
|
TPrevSchema extends z.ZodType<any> = TInput,
|
|
204
|
-
> extends Workflow<TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
295
|
+
> extends Workflow<TEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
205
296
|
#mastra: Mastra;
|
|
206
297
|
public inngest: Inngest;
|
|
207
298
|
|
|
@@ -233,7 +324,10 @@ export class InngestWorkflow<
|
|
|
233
324
|
const storage = this.#mastra?.getStorage();
|
|
234
325
|
if (!storage) {
|
|
235
326
|
this.logger.debug('Cannot get workflow runs. Mastra engine is not initialized');
|
|
236
|
-
|
|
327
|
+
//returning in memory run if no storage is initialized
|
|
328
|
+
return this.runs.get(runId)
|
|
329
|
+
? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as WorkflowRun)
|
|
330
|
+
: null;
|
|
237
331
|
}
|
|
238
332
|
const run = (await storage.getWorkflowRunById({ runId, workflowName: this.id })) as unknown as WorkflowRun;
|
|
239
333
|
|
|
@@ -243,6 +337,32 @@ export class InngestWorkflow<
|
|
|
243
337
|
);
|
|
244
338
|
}
|
|
245
339
|
|
|
340
|
+
async getWorkflowRunExecutionResult(runId: string): Promise<WatchEvent['payload']['workflowState'] | null> {
|
|
341
|
+
const storage = this.#mastra?.getStorage();
|
|
342
|
+
if (!storage) {
|
|
343
|
+
this.logger.debug('Cannot get workflow run execution result. Mastra storage is not initialized');
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
348
|
+
|
|
349
|
+
if (!run?.snapshot) {
|
|
350
|
+
return null;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if (typeof run.snapshot === 'string') {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return {
|
|
358
|
+
status: run.snapshot.status,
|
|
359
|
+
result: run.snapshot.result,
|
|
360
|
+
error: run.snapshot.error,
|
|
361
|
+
payload: run.snapshot.context?.input,
|
|
362
|
+
steps: run.snapshot.context as any,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
246
366
|
__registerMastra(mastra: Mastra) {
|
|
247
367
|
this.#mastra = mastra;
|
|
248
368
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -266,11 +386,11 @@ export class InngestWorkflow<
|
|
|
266
386
|
}
|
|
267
387
|
}
|
|
268
388
|
|
|
269
|
-
createRun(options?: { runId?: string }): Run<TSteps, TInput, TOutput> {
|
|
389
|
+
createRun(options?: { runId?: string }): Run<TEngineType, TSteps, TInput, TOutput> {
|
|
270
390
|
const runIdToUse = options?.runId || randomUUID();
|
|
271
391
|
|
|
272
392
|
// Return a new Run instance with object parameters
|
|
273
|
-
const run: Run<TSteps, TInput, TOutput> =
|
|
393
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
274
394
|
this.runs.get(runIdToUse) ??
|
|
275
395
|
new InngestRun(
|
|
276
396
|
{
|
|
@@ -278,6 +398,7 @@ export class InngestWorkflow<
|
|
|
278
398
|
runId: runIdToUse,
|
|
279
399
|
executionEngine: this.executionEngine,
|
|
280
400
|
executionGraph: this.executionGraph,
|
|
401
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
281
402
|
mastra: this.#mastra,
|
|
282
403
|
retryConfig: this.retryConfig,
|
|
283
404
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
@@ -289,6 +410,49 @@ export class InngestWorkflow<
|
|
|
289
410
|
return run;
|
|
290
411
|
}
|
|
291
412
|
|
|
413
|
+
async createRunAsync(options?: { runId?: string }): Promise<Run<TEngineType, TSteps, TInput, TOutput>> {
|
|
414
|
+
const runIdToUse = options?.runId || randomUUID();
|
|
415
|
+
|
|
416
|
+
// Return a new Run instance with object parameters
|
|
417
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
418
|
+
this.runs.get(runIdToUse) ??
|
|
419
|
+
new InngestRun(
|
|
420
|
+
{
|
|
421
|
+
workflowId: this.id,
|
|
422
|
+
runId: runIdToUse,
|
|
423
|
+
executionEngine: this.executionEngine,
|
|
424
|
+
executionGraph: this.executionGraph,
|
|
425
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
426
|
+
mastra: this.#mastra,
|
|
427
|
+
retryConfig: this.retryConfig,
|
|
428
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
429
|
+
},
|
|
430
|
+
this.inngest,
|
|
431
|
+
);
|
|
432
|
+
|
|
433
|
+
this.runs.set(runIdToUse, run);
|
|
434
|
+
|
|
435
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
436
|
+
workflowName: this.id,
|
|
437
|
+
runId: runIdToUse,
|
|
438
|
+
snapshot: {
|
|
439
|
+
runId: runIdToUse,
|
|
440
|
+
status: 'pending',
|
|
441
|
+
value: {},
|
|
442
|
+
context: {},
|
|
443
|
+
activePaths: [],
|
|
444
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
445
|
+
suspendedPaths: {},
|
|
446
|
+
result: undefined,
|
|
447
|
+
error: undefined,
|
|
448
|
+
// @ts-ignore
|
|
449
|
+
timestamp: Date.now(),
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
return run;
|
|
454
|
+
}
|
|
455
|
+
|
|
292
456
|
getFunction() {
|
|
293
457
|
if (this.function) {
|
|
294
458
|
return this.function;
|
|
@@ -315,13 +479,22 @@ export class InngestWorkflow<
|
|
|
315
479
|
try {
|
|
316
480
|
await publish({
|
|
317
481
|
channel: `workflow:${this.id}:${runId}`,
|
|
318
|
-
topic:
|
|
482
|
+
topic: event,
|
|
319
483
|
data,
|
|
320
484
|
});
|
|
321
485
|
} catch (err: any) {
|
|
322
486
|
this.logger.error('Error emitting event: ' + (err?.stack ?? err?.message ?? err));
|
|
323
487
|
}
|
|
324
488
|
},
|
|
489
|
+
on: (_event: string, _callback: (data: any) => void) => {
|
|
490
|
+
// no-op
|
|
491
|
+
},
|
|
492
|
+
off: (_event: string, _callback: (data: any) => void) => {
|
|
493
|
+
// no-op
|
|
494
|
+
},
|
|
495
|
+
once: (_event: string, _callback: (data: any) => void) => {
|
|
496
|
+
// no-op
|
|
497
|
+
},
|
|
325
498
|
};
|
|
326
499
|
|
|
327
500
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -329,6 +502,7 @@ export class InngestWorkflow<
|
|
|
329
502
|
workflowId: this.id,
|
|
330
503
|
runId,
|
|
331
504
|
graph: this.executionGraph,
|
|
505
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
332
506
|
input: inputData,
|
|
333
507
|
emitter,
|
|
334
508
|
retryConfig: this.retryConfig,
|
|
@@ -362,29 +536,192 @@ export class InngestWorkflow<
|
|
|
362
536
|
}
|
|
363
537
|
}
|
|
364
538
|
|
|
365
|
-
function
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
539
|
+
function isAgent(params: any): params is Agent<any, any, any> {
|
|
540
|
+
return params?.component === 'AGENT';
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
function isTool(params: any): params is Tool<any, any, any> {
|
|
544
|
+
return params instanceof Tool;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
export function createStep<
|
|
548
|
+
TStepId extends string,
|
|
549
|
+
TStepInput extends z.ZodType<any>,
|
|
550
|
+
TStepOutput extends z.ZodType<any>,
|
|
551
|
+
TResumeSchema extends z.ZodType<any>,
|
|
552
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
553
|
+
>(params: {
|
|
554
|
+
id: TStepId;
|
|
555
|
+
description?: string;
|
|
556
|
+
inputSchema: TStepInput;
|
|
557
|
+
outputSchema: TStepOutput;
|
|
558
|
+
resumeSchema?: TResumeSchema;
|
|
559
|
+
suspendSchema?: TSuspendSchema;
|
|
560
|
+
execute: ExecuteFunction<
|
|
561
|
+
z.infer<TStepInput>,
|
|
562
|
+
z.infer<TStepOutput>,
|
|
563
|
+
z.infer<TResumeSchema>,
|
|
564
|
+
z.infer<TSuspendSchema>,
|
|
565
|
+
InngestEngineType
|
|
566
|
+
>;
|
|
567
|
+
}): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
568
|
+
|
|
569
|
+
export function createStep<
|
|
570
|
+
TStepId extends string,
|
|
571
|
+
TStepInput extends z.ZodObject<{ prompt: z.ZodString }>,
|
|
572
|
+
TStepOutput extends z.ZodObject<{ text: z.ZodString }>,
|
|
573
|
+
TResumeSchema extends z.ZodType<any>,
|
|
574
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
370
575
|
>(
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
576
|
+
agent: Agent<TStepId, any, any>,
|
|
577
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
578
|
+
|
|
579
|
+
export function createStep<
|
|
580
|
+
TSchemaIn extends z.ZodType<any>,
|
|
581
|
+
TSchemaOut extends z.ZodType<any>,
|
|
582
|
+
TContext extends ToolExecutionContext<TSchemaIn>,
|
|
583
|
+
>(
|
|
584
|
+
tool: Tool<TSchemaIn, TSchemaOut, TContext> & {
|
|
585
|
+
inputSchema: TSchemaIn;
|
|
586
|
+
outputSchema: TSchemaOut;
|
|
587
|
+
execute: (context: TContext) => Promise<any>;
|
|
588
|
+
},
|
|
589
|
+
): Step<string, TSchemaIn, TSchemaOut, z.ZodType<any>, z.ZodType<any>, InngestEngineType>;
|
|
590
|
+
export function createStep<
|
|
591
|
+
TStepId extends string,
|
|
592
|
+
TStepInput extends z.ZodType<any>,
|
|
593
|
+
TStepOutput extends z.ZodType<any>,
|
|
594
|
+
TResumeSchema extends z.ZodType<any>,
|
|
595
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
596
|
+
>(
|
|
597
|
+
params:
|
|
598
|
+
| {
|
|
599
|
+
id: TStepId;
|
|
600
|
+
description?: string;
|
|
601
|
+
inputSchema: TStepInput;
|
|
602
|
+
outputSchema: TStepOutput;
|
|
603
|
+
resumeSchema?: TResumeSchema;
|
|
604
|
+
suspendSchema?: TSuspendSchema;
|
|
605
|
+
execute: ExecuteFunction<
|
|
606
|
+
z.infer<TStepInput>,
|
|
607
|
+
z.infer<TStepOutput>,
|
|
608
|
+
z.infer<TResumeSchema>,
|
|
609
|
+
z.infer<TSuspendSchema>,
|
|
610
|
+
InngestEngineType
|
|
611
|
+
>;
|
|
612
|
+
}
|
|
613
|
+
| Agent<any, any, any>
|
|
614
|
+
| (Tool<TStepInput, TStepOutput, any> & {
|
|
615
|
+
inputSchema: TStepInput;
|
|
616
|
+
outputSchema: TStepOutput;
|
|
617
|
+
execute: (context: ToolExecutionContext<TStepInput>) => Promise<any>;
|
|
618
|
+
}),
|
|
619
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType> {
|
|
620
|
+
if (isAgent(params)) {
|
|
621
|
+
return {
|
|
622
|
+
id: params.name,
|
|
623
|
+
// @ts-ignore
|
|
624
|
+
inputSchema: z.object({
|
|
625
|
+
prompt: z.string(),
|
|
626
|
+
// resourceId: z.string().optional(),
|
|
627
|
+
// threadId: z.string().optional(),
|
|
628
|
+
}),
|
|
629
|
+
// @ts-ignore
|
|
630
|
+
outputSchema: z.object({
|
|
631
|
+
text: z.string(),
|
|
632
|
+
}),
|
|
633
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
|
|
634
|
+
let streamPromise = {} as {
|
|
635
|
+
promise: Promise<string>;
|
|
636
|
+
resolve: (value: string) => void;
|
|
637
|
+
reject: (reason?: any) => void;
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
641
|
+
streamPromise.resolve = resolve;
|
|
642
|
+
streamPromise.reject = reject;
|
|
643
|
+
});
|
|
644
|
+
const toolData = {
|
|
645
|
+
name: params.name,
|
|
646
|
+
args: inputData,
|
|
647
|
+
};
|
|
648
|
+
await emitter.emit('watch-v2', {
|
|
649
|
+
type: 'tool-call-streaming-start',
|
|
650
|
+
...toolData,
|
|
651
|
+
});
|
|
652
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
653
|
+
// resourceId: inputData.resourceId,
|
|
654
|
+
// threadId: inputData.threadId,
|
|
655
|
+
runtimeContext,
|
|
656
|
+
onFinish: result => {
|
|
657
|
+
streamPromise.resolve(result.text);
|
|
658
|
+
},
|
|
659
|
+
});
|
|
384
660
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
661
|
+
for await (const chunk of fullStream) {
|
|
662
|
+
switch (chunk.type) {
|
|
663
|
+
case 'text-delta':
|
|
664
|
+
await emitter.emit('watch-v2', {
|
|
665
|
+
type: 'tool-call-delta',
|
|
666
|
+
...toolData,
|
|
667
|
+
argsTextDelta: chunk.textDelta,
|
|
668
|
+
});
|
|
669
|
+
break;
|
|
670
|
+
|
|
671
|
+
case 'step-start':
|
|
672
|
+
case 'step-finish':
|
|
673
|
+
case 'finish':
|
|
674
|
+
break;
|
|
675
|
+
|
|
676
|
+
case 'tool-call':
|
|
677
|
+
case 'tool-result':
|
|
678
|
+
case 'tool-call-streaming-start':
|
|
679
|
+
case 'tool-call-delta':
|
|
680
|
+
case 'source':
|
|
681
|
+
case 'file':
|
|
682
|
+
default:
|
|
683
|
+
await emitter.emit('watch-v2', chunk);
|
|
684
|
+
break;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return {
|
|
689
|
+
text: await streamPromise.promise,
|
|
690
|
+
};
|
|
691
|
+
},
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (isTool(params)) {
|
|
696
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
697
|
+
throw new Error('Tool must have input and output schemas defined');
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
return {
|
|
701
|
+
// TODO: tool probably should have strong id type
|
|
702
|
+
// @ts-ignore
|
|
703
|
+
id: params.id,
|
|
704
|
+
inputSchema: params.inputSchema,
|
|
705
|
+
outputSchema: params.outputSchema,
|
|
706
|
+
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
707
|
+
return params.execute({
|
|
708
|
+
context: inputData,
|
|
709
|
+
mastra,
|
|
710
|
+
runtimeContext,
|
|
711
|
+
});
|
|
712
|
+
},
|
|
713
|
+
};
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
return {
|
|
717
|
+
id: params.id,
|
|
718
|
+
description: params.description,
|
|
719
|
+
inputSchema: params.inputSchema,
|
|
720
|
+
outputSchema: params.outputSchema,
|
|
721
|
+
resumeSchema: params.resumeSchema,
|
|
722
|
+
suspendSchema: params.suspendSchema,
|
|
723
|
+
execute: params.execute,
|
|
724
|
+
};
|
|
388
725
|
}
|
|
389
726
|
|
|
390
727
|
export function init(inngest: Inngest) {
|
|
@@ -393,13 +730,59 @@ export function init(inngest: Inngest) {
|
|
|
393
730
|
TWorkflowId extends string = string,
|
|
394
731
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
395
732
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
396
|
-
TSteps extends Step<string, any, any
|
|
733
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
734
|
+
string,
|
|
735
|
+
any,
|
|
736
|
+
any,
|
|
737
|
+
any,
|
|
738
|
+
any,
|
|
739
|
+
InngestEngineType
|
|
740
|
+
>[],
|
|
397
741
|
>(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
|
|
398
|
-
return new InngestWorkflow(params, inngest);
|
|
742
|
+
return new InngestWorkflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TInput>(params, inngest);
|
|
399
743
|
},
|
|
400
744
|
createStep,
|
|
401
|
-
cloneStep
|
|
402
|
-
|
|
745
|
+
cloneStep<TStepId extends string>(
|
|
746
|
+
step: Step<string, any, any, any, any, InngestEngineType>,
|
|
747
|
+
opts: { id: TStepId },
|
|
748
|
+
): Step<TStepId, any, any, any, any, InngestEngineType> {
|
|
749
|
+
return {
|
|
750
|
+
id: opts.id,
|
|
751
|
+
description: step.description,
|
|
752
|
+
inputSchema: step.inputSchema,
|
|
753
|
+
outputSchema: step.outputSchema,
|
|
754
|
+
execute: step.execute,
|
|
755
|
+
};
|
|
756
|
+
},
|
|
757
|
+
cloneWorkflow<
|
|
758
|
+
TWorkflowId extends string = string,
|
|
759
|
+
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
760
|
+
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
761
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
762
|
+
string,
|
|
763
|
+
any,
|
|
764
|
+
any,
|
|
765
|
+
any,
|
|
766
|
+
any,
|
|
767
|
+
InngestEngineType
|
|
768
|
+
>[],
|
|
769
|
+
TPrevSchema extends z.ZodType<any> = TInput,
|
|
770
|
+
>(
|
|
771
|
+
workflow: Workflow<InngestEngineType, TSteps, string, TInput, TOutput, TPrevSchema>,
|
|
772
|
+
opts: { id: TWorkflowId },
|
|
773
|
+
): Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
774
|
+
const wf: Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> = new Workflow({
|
|
775
|
+
id: opts.id,
|
|
776
|
+
inputSchema: workflow.inputSchema,
|
|
777
|
+
outputSchema: workflow.outputSchema,
|
|
778
|
+
steps: workflow.stepDefs,
|
|
779
|
+
mastra: workflow.mastra,
|
|
780
|
+
});
|
|
781
|
+
|
|
782
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
783
|
+
wf.commit();
|
|
784
|
+
return wf;
|
|
785
|
+
},
|
|
403
786
|
};
|
|
404
787
|
}
|
|
405
788
|
|
|
@@ -413,9 +796,44 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
413
796
|
this.inngestAttempts = inngestAttempts;
|
|
414
797
|
}
|
|
415
798
|
|
|
799
|
+
async execute<TInput, TOutput>(params: {
|
|
800
|
+
workflowId: string;
|
|
801
|
+
runId: string;
|
|
802
|
+
graph: ExecutionGraph;
|
|
803
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
804
|
+
input?: TInput;
|
|
805
|
+
resume?: {
|
|
806
|
+
// TODO: add execute path
|
|
807
|
+
steps: string[];
|
|
808
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
809
|
+
resumePayload: any;
|
|
810
|
+
resumePath: number[];
|
|
811
|
+
};
|
|
812
|
+
emitter: Emitter;
|
|
813
|
+
retryConfig?: {
|
|
814
|
+
attempts?: number;
|
|
815
|
+
delay?: number;
|
|
816
|
+
};
|
|
817
|
+
runtimeContext: RuntimeContext;
|
|
818
|
+
}): Promise<TOutput> {
|
|
819
|
+
await params.emitter.emit('watch-v2', {
|
|
820
|
+
type: 'start',
|
|
821
|
+
payload: { runId: params.runId },
|
|
822
|
+
});
|
|
823
|
+
|
|
824
|
+
const result = await super.execute<TInput, TOutput>(params);
|
|
825
|
+
|
|
826
|
+
await params.emitter.emit('watch-v2', {
|
|
827
|
+
type: 'finish',
|
|
828
|
+
payload: { runId: params.runId },
|
|
829
|
+
});
|
|
830
|
+
|
|
831
|
+
return result;
|
|
832
|
+
}
|
|
833
|
+
|
|
416
834
|
protected async fmtReturnValue<TOutput>(
|
|
417
835
|
executionSpan: Span | undefined,
|
|
418
|
-
emitter:
|
|
836
|
+
emitter: Emitter,
|
|
419
837
|
stepResults: Record<string, StepResult<any, any, any, any>>,
|
|
420
838
|
lastOutput: StepResult<any, any, any, any>,
|
|
421
839
|
error?: Error | string,
|
|
@@ -508,7 +926,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
508
926
|
resumePayload: any;
|
|
509
927
|
};
|
|
510
928
|
prevOutput: any;
|
|
511
|
-
emitter:
|
|
929
|
+
emitter: Emitter;
|
|
512
930
|
runtimeContext: RuntimeContext;
|
|
513
931
|
}): Promise<StepResult<any, any, any, any>> {
|
|
514
932
|
return super.executeStep({
|
|
@@ -524,6 +942,23 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
524
942
|
});
|
|
525
943
|
}
|
|
526
944
|
|
|
945
|
+
async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
946
|
+
await this.inngestStep.sleep(id, duration);
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
|
|
950
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
951
|
+
event: `user-event-${event}`,
|
|
952
|
+
timeout: timeout ?? 5e3,
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
if (eventData === null) {
|
|
956
|
+
throw 'Timeout waiting for event';
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
return eventData?.data;
|
|
960
|
+
}
|
|
961
|
+
|
|
527
962
|
async executeStep({
|
|
528
963
|
step,
|
|
529
964
|
stepResults,
|
|
@@ -548,12 +983,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
548
983
|
runId?: string;
|
|
549
984
|
};
|
|
550
985
|
prevOutput: any;
|
|
551
|
-
emitter:
|
|
986
|
+
emitter: Emitter;
|
|
552
987
|
runtimeContext: RuntimeContext;
|
|
553
988
|
}): Promise<StepResult<any, any, any, any>> {
|
|
554
|
-
await this.inngestStep.run(
|
|
989
|
+
const startedAt = await this.inngestStep.run(
|
|
555
990
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
556
991
|
async () => {
|
|
992
|
+
const startedAt = Date.now();
|
|
557
993
|
await emitter.emit('watch', {
|
|
558
994
|
type: 'watch',
|
|
559
995
|
payload: {
|
|
@@ -575,6 +1011,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
575
1011
|
},
|
|
576
1012
|
eventTimestamp: Date.now(),
|
|
577
1013
|
});
|
|
1014
|
+
|
|
1015
|
+
await emitter.emit('watch-v2', {
|
|
1016
|
+
type: 'step-start',
|
|
1017
|
+
payload: {
|
|
1018
|
+
id: step.id,
|
|
1019
|
+
},
|
|
1020
|
+
});
|
|
1021
|
+
|
|
1022
|
+
return startedAt;
|
|
578
1023
|
},
|
|
579
1024
|
);
|
|
580
1025
|
|
|
@@ -641,6 +1086,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
641
1086
|
eventTimestamp: Date.now(),
|
|
642
1087
|
});
|
|
643
1088
|
|
|
1089
|
+
await emitter.emit('watch-v2', {
|
|
1090
|
+
type: 'step-result',
|
|
1091
|
+
payload: {
|
|
1092
|
+
id: step.id,
|
|
1093
|
+
status: 'failed',
|
|
1094
|
+
},
|
|
1095
|
+
});
|
|
1096
|
+
|
|
644
1097
|
return { executionContext, result: { status: 'failed', error: result?.error } };
|
|
645
1098
|
} else if (result.status === 'suspended') {
|
|
646
1099
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -671,6 +1124,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
671
1124
|
eventTimestamp: Date.now(),
|
|
672
1125
|
});
|
|
673
1126
|
|
|
1127
|
+
await emitter.emit('watch-v2', {
|
|
1128
|
+
type: 'step-suspended',
|
|
1129
|
+
payload: {
|
|
1130
|
+
id: step.id,
|
|
1131
|
+
},
|
|
1132
|
+
});
|
|
1133
|
+
|
|
674
1134
|
return {
|
|
675
1135
|
executionContext,
|
|
676
1136
|
result: {
|
|
@@ -727,6 +1187,14 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
727
1187
|
eventTimestamp: Date.now(),
|
|
728
1188
|
});
|
|
729
1189
|
|
|
1190
|
+
await emitter.emit('watch-v2', {
|
|
1191
|
+
type: 'step-finish',
|
|
1192
|
+
payload: {
|
|
1193
|
+
id: step.id,
|
|
1194
|
+
metadata: {},
|
|
1195
|
+
},
|
|
1196
|
+
});
|
|
1197
|
+
|
|
730
1198
|
return { executionContext, result: { status: 'success', output: result?.result } };
|
|
731
1199
|
},
|
|
732
1200
|
);
|
|
@@ -738,8 +1206,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
738
1206
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
739
1207
|
let execResults: any;
|
|
740
1208
|
let suspended: { payload: any } | undefined;
|
|
1209
|
+
let bailed: { payload: any } | undefined;
|
|
1210
|
+
|
|
741
1211
|
try {
|
|
742
1212
|
const result = await step.execute({
|
|
1213
|
+
runId: executionContext.runId,
|
|
743
1214
|
mastra: this.mastra!,
|
|
744
1215
|
runtimeContext,
|
|
745
1216
|
inputData: prevOutput,
|
|
@@ -757,22 +1228,55 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
757
1228
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
758
1229
|
suspended = { payload: suspendPayload };
|
|
759
1230
|
},
|
|
1231
|
+
bail: (result: any) => {
|
|
1232
|
+
bailed = { payload: result };
|
|
1233
|
+
},
|
|
760
1234
|
resume: {
|
|
761
1235
|
steps: resume?.steps?.slice(1) || [],
|
|
762
1236
|
resumePayload: resume?.resumePayload,
|
|
763
1237
|
// @ts-ignore
|
|
764
1238
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId,
|
|
765
1239
|
},
|
|
766
|
-
emitter,
|
|
1240
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1241
|
+
engine: {
|
|
1242
|
+
step: this.inngestStep,
|
|
1243
|
+
},
|
|
767
1244
|
});
|
|
768
|
-
|
|
769
|
-
|
|
1245
|
+
const endedAt = Date.now();
|
|
1246
|
+
|
|
1247
|
+
execResults = {
|
|
1248
|
+
status: 'success',
|
|
1249
|
+
output: result,
|
|
1250
|
+
startedAt,
|
|
1251
|
+
endedAt,
|
|
1252
|
+
payload: prevOutput,
|
|
1253
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1254
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1255
|
+
};
|
|
770
1256
|
} catch (e) {
|
|
771
|
-
execResults = {
|
|
1257
|
+
execResults = {
|
|
1258
|
+
status: 'failed',
|
|
1259
|
+
payload: prevOutput,
|
|
1260
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1261
|
+
endedAt: Date.now(),
|
|
1262
|
+
startedAt,
|
|
1263
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1264
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1265
|
+
};
|
|
772
1266
|
}
|
|
773
1267
|
|
|
774
1268
|
if (suspended) {
|
|
775
|
-
execResults = {
|
|
1269
|
+
execResults = {
|
|
1270
|
+
status: 'suspended',
|
|
1271
|
+
suspendedPayload: suspended.payload,
|
|
1272
|
+
payload: prevOutput,
|
|
1273
|
+
suspendedAt: Date.now(),
|
|
1274
|
+
startedAt,
|
|
1275
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1276
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1277
|
+
};
|
|
1278
|
+
} else if (bailed) {
|
|
1279
|
+
execResults = { status: 'bailed', output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
776
1280
|
}
|
|
777
1281
|
|
|
778
1282
|
if (execResults.status === 'failed') {
|
|
@@ -786,12 +1290,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
786
1290
|
payload: {
|
|
787
1291
|
currentStep: {
|
|
788
1292
|
id: step.id,
|
|
789
|
-
|
|
790
|
-
output: execResults.output,
|
|
1293
|
+
...execResults,
|
|
791
1294
|
},
|
|
792
1295
|
workflowState: {
|
|
793
1296
|
status: 'running',
|
|
794
|
-
steps: stepResults,
|
|
1297
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
795
1298
|
result: null,
|
|
796
1299
|
error: null,
|
|
797
1300
|
},
|
|
@@ -799,6 +1302,34 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
799
1302
|
eventTimestamp: Date.now(),
|
|
800
1303
|
});
|
|
801
1304
|
|
|
1305
|
+
if (execResults.status === 'suspended') {
|
|
1306
|
+
await emitter.emit('watch-v2', {
|
|
1307
|
+
type: 'step-suspended',
|
|
1308
|
+
payload: {
|
|
1309
|
+
id: step.id,
|
|
1310
|
+
status: execResults.status,
|
|
1311
|
+
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1312
|
+
},
|
|
1313
|
+
});
|
|
1314
|
+
} else {
|
|
1315
|
+
await emitter.emit('watch-v2', {
|
|
1316
|
+
type: 'step-result',
|
|
1317
|
+
payload: {
|
|
1318
|
+
id: step.id,
|
|
1319
|
+
status: execResults.status,
|
|
1320
|
+
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1321
|
+
},
|
|
1322
|
+
});
|
|
1323
|
+
|
|
1324
|
+
await emitter.emit('watch-v2', {
|
|
1325
|
+
type: 'step-finish',
|
|
1326
|
+
payload: {
|
|
1327
|
+
id: step.id,
|
|
1328
|
+
metadata: {},
|
|
1329
|
+
},
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
|
|
802
1333
|
return { result: execResults, executionContext, stepResults };
|
|
803
1334
|
});
|
|
804
1335
|
|
|
@@ -816,11 +1347,19 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
816
1347
|
runId,
|
|
817
1348
|
stepResults,
|
|
818
1349
|
executionContext,
|
|
1350
|
+
serializedStepGraph,
|
|
1351
|
+
workflowStatus,
|
|
1352
|
+
result,
|
|
1353
|
+
error,
|
|
819
1354
|
}: {
|
|
820
1355
|
workflowId: string;
|
|
821
1356
|
runId: string;
|
|
822
1357
|
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1358
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
823
1359
|
executionContext: ExecutionContext;
|
|
1360
|
+
workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
|
|
1361
|
+
result?: Record<string, any>;
|
|
1362
|
+
error?: string | Error;
|
|
824
1363
|
}) {
|
|
825
1364
|
await this.inngestStep.run(
|
|
826
1365
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -834,6 +1373,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
834
1373
|
context: stepResults as any,
|
|
835
1374
|
activePaths: [],
|
|
836
1375
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1376
|
+
serializedStepGraph,
|
|
1377
|
+
status: workflowStatus,
|
|
1378
|
+
result,
|
|
1379
|
+
error,
|
|
837
1380
|
// @ts-ignore
|
|
838
1381
|
timestamp: Date.now(),
|
|
839
1382
|
},
|
|
@@ -849,6 +1392,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
849
1392
|
prevOutput,
|
|
850
1393
|
prevStep,
|
|
851
1394
|
stepResults,
|
|
1395
|
+
serializedStepGraph,
|
|
852
1396
|
resume,
|
|
853
1397
|
executionContext,
|
|
854
1398
|
emitter,
|
|
@@ -856,8 +1400,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
856
1400
|
}: {
|
|
857
1401
|
workflowId: string;
|
|
858
1402
|
runId: string;
|
|
859
|
-
entry: {
|
|
1403
|
+
entry: {
|
|
1404
|
+
type: 'conditional';
|
|
1405
|
+
steps: StepFlowEntry[];
|
|
1406
|
+
conditions: ExecuteFunction<any, any, any, any, InngestEngineType>[];
|
|
1407
|
+
};
|
|
860
1408
|
prevStep: StepFlowEntry;
|
|
1409
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
861
1410
|
prevOutput: any;
|
|
862
1411
|
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
863
1412
|
resume?: {
|
|
@@ -867,7 +1416,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
867
1416
|
resumePath: number[];
|
|
868
1417
|
};
|
|
869
1418
|
executionContext: ExecutionContext;
|
|
870
|
-
emitter:
|
|
1419
|
+
emitter: Emitter;
|
|
871
1420
|
runtimeContext: RuntimeContext;
|
|
872
1421
|
}): Promise<StepResult<any, any, any, any>> {
|
|
873
1422
|
let execResults: any;
|
|
@@ -877,6 +1426,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
877
1426
|
this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
878
1427
|
try {
|
|
879
1428
|
const result = await cond({
|
|
1429
|
+
runId,
|
|
880
1430
|
mastra: this.mastra!,
|
|
881
1431
|
runtimeContext,
|
|
882
1432
|
inputData: prevOutput,
|
|
@@ -896,7 +1446,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
896
1446
|
|
|
897
1447
|
// TODO: this function shouldn't have suspend probably?
|
|
898
1448
|
suspend: async (_suspendPayload: any) => {},
|
|
1449
|
+
bail: () => {},
|
|
899
1450
|
[EMITTER_SYMBOL]: emitter,
|
|
1451
|
+
engine: {
|
|
1452
|
+
step: this.inngestStep,
|
|
1453
|
+
},
|
|
900
1454
|
});
|
|
901
1455
|
return result ? index : null;
|
|
902
1456
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -909,7 +1463,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
909
1463
|
).filter((index: any): index is number => index !== null);
|
|
910
1464
|
|
|
911
1465
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
912
|
-
const results: StepResult<any, any, any, any>[] = await Promise.all(
|
|
1466
|
+
const results: { result: StepResult<any, any, any, any> }[] = await Promise.all(
|
|
913
1467
|
stepsToRun.map((step, index) =>
|
|
914
1468
|
this.executeEntry({
|
|
915
1469
|
workflowId,
|
|
@@ -918,6 +1472,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
918
1472
|
prevStep,
|
|
919
1473
|
stepResults,
|
|
920
1474
|
resume,
|
|
1475
|
+
serializedStepGraph,
|
|
921
1476
|
executionContext: {
|
|
922
1477
|
workflowId,
|
|
923
1478
|
runId,
|
|
@@ -931,17 +1486,19 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
931
1486
|
}),
|
|
932
1487
|
),
|
|
933
1488
|
);
|
|
934
|
-
const hasFailed = results.find(result => result.status === 'failed')
|
|
935
|
-
|
|
1489
|
+
const hasFailed = results.find(result => result.result.status === 'failed') as {
|
|
1490
|
+
result: StepFailure<any, any, any>;
|
|
1491
|
+
};
|
|
1492
|
+
const hasSuspended = results.find(result => result.result.status === 'suspended');
|
|
936
1493
|
if (hasFailed) {
|
|
937
|
-
execResults = { status: 'failed', error: hasFailed.error };
|
|
1494
|
+
execResults = { status: 'failed', error: hasFailed.result.error };
|
|
938
1495
|
} else if (hasSuspended) {
|
|
939
|
-
execResults = { status: 'suspended', payload: hasSuspended.
|
|
1496
|
+
execResults = { status: 'suspended', payload: hasSuspended.result.suspendPayload };
|
|
940
1497
|
} else {
|
|
941
1498
|
execResults = {
|
|
942
1499
|
status: 'success',
|
|
943
1500
|
output: results.reduce((acc: Record<string, any>, result, index) => {
|
|
944
|
-
if (result.status === 'success') {
|
|
1501
|
+
if (result.result.status === 'success') {
|
|
945
1502
|
// @ts-ignore
|
|
946
1503
|
acc[stepsToRun[index]!.step.id] = result.output;
|
|
947
1504
|
}
|