@mastra/inngest 0.0.0-add-runtime-context-to-openai-realtime-20250516201052 → 0.0.0-ai-v5-20250625014956
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 +285 -2
- package/dist/_tsup-dts-rollup.d.cts +127 -56
- package/dist/_tsup-dts-rollup.d.ts +127 -56
- package/dist/index.cjs +362 -47
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +359 -45
- package/package.json +20 -16
- package/src/index.test.ts +4576 -3254
- package/src/index.ts +593 -89
package/src/index.ts
CHANGED
|
@@ -1,27 +1,37 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
2
|
import { subscribe } from '@inngest/realtime';
|
|
3
|
-
import type { Mastra,
|
|
3
|
+
import type { Agent, Mastra, ToolExecutionContext, WorkflowRun, WorkflowRuns } from '@mastra/core';
|
|
4
4
|
import { RuntimeContext } from '@mastra/core/di';
|
|
5
|
-
import {
|
|
5
|
+
import { Tool } from '@mastra/core/tools';
|
|
6
|
+
import { Workflow, Run, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
6
7
|
import type {
|
|
7
8
|
ExecuteFunction,
|
|
8
9
|
ExecutionContext,
|
|
9
10
|
ExecutionEngine,
|
|
10
11
|
ExecutionGraph,
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
NewWorkflowConfig,
|
|
12
|
+
Step,
|
|
13
|
+
WorkflowConfig,
|
|
14
14
|
StepFlowEntry,
|
|
15
15
|
StepResult,
|
|
16
16
|
WorkflowResult,
|
|
17
|
-
|
|
17
|
+
SerializedStepFlowEntry,
|
|
18
|
+
StepFailure,
|
|
19
|
+
Emitter,
|
|
20
|
+
WatchEvent,
|
|
21
|
+
StreamEvent,
|
|
22
|
+
} from '@mastra/core/workflows';
|
|
23
|
+
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
18
24
|
import type { Span } from '@opentelemetry/api';
|
|
19
25
|
import type { Inngest, BaseContext } from 'inngest';
|
|
20
26
|
import { serve as inngestServe } from 'inngest/hono';
|
|
21
|
-
import
|
|
27
|
+
import { z } from 'zod';
|
|
28
|
+
|
|
29
|
+
export type InngestEngineType = {
|
|
30
|
+
step: any;
|
|
31
|
+
};
|
|
22
32
|
|
|
23
33
|
export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest }): ReturnType<typeof inngestServe> {
|
|
24
|
-
const wfs = mastra.
|
|
34
|
+
const wfs = mastra.getWorkflows();
|
|
25
35
|
const functions = Object.values(wfs).flatMap(wf => {
|
|
26
36
|
if (wf instanceof InngestWorkflow) {
|
|
27
37
|
wf.__registerMastra(mastra);
|
|
@@ -36,11 +46,13 @@ export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest })
|
|
|
36
46
|
}
|
|
37
47
|
|
|
38
48
|
export class InngestRun<
|
|
39
|
-
|
|
49
|
+
TEngineType = InngestEngineType,
|
|
50
|
+
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
40
51
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
41
52
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
42
|
-
> extends Run<TSteps, TInput, TOutput> {
|
|
53
|
+
> extends Run<TEngineType, TSteps, TInput, TOutput> {
|
|
43
54
|
private inngest: Inngest;
|
|
55
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
44
56
|
#mastra: Mastra;
|
|
45
57
|
|
|
46
58
|
constructor(
|
|
@@ -49,6 +61,7 @@ export class InngestRun<
|
|
|
49
61
|
runId: string;
|
|
50
62
|
executionEngine: ExecutionEngine;
|
|
51
63
|
executionGraph: ExecutionGraph;
|
|
64
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
52
65
|
mastra?: Mastra;
|
|
53
66
|
retryConfig?: {
|
|
54
67
|
attempts?: number;
|
|
@@ -60,11 +73,12 @@ export class InngestRun<
|
|
|
60
73
|
) {
|
|
61
74
|
super(params);
|
|
62
75
|
this.inngest = inngest;
|
|
76
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
63
77
|
this.#mastra = params.mastra!;
|
|
64
78
|
}
|
|
65
79
|
|
|
66
80
|
async getRuns(eventId: string) {
|
|
67
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
81
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? 'https://api.inngest.com'}/v1/events/${eventId}/runs`, {
|
|
68
82
|
headers: {
|
|
69
83
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`,
|
|
70
84
|
},
|
|
@@ -75,7 +89,8 @@ export class InngestRun<
|
|
|
75
89
|
|
|
76
90
|
async getRunOutput(eventId: string) {
|
|
77
91
|
let runs = await this.getRuns(eventId);
|
|
78
|
-
|
|
92
|
+
|
|
93
|
+
while (runs?.[0]?.status !== 'Completed' || runs?.[0]?.event_id !== eventId) {
|
|
79
94
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
80
95
|
runs = await this.getRuns(eventId);
|
|
81
96
|
if (runs?.[0]?.status === 'Failed' || runs?.[0]?.status === 'Cancelled') {
|
|
@@ -85,6 +100,13 @@ export class InngestRun<
|
|
|
85
100
|
return runs?.[0];
|
|
86
101
|
}
|
|
87
102
|
|
|
103
|
+
async sendEvent(event: string, data: any) {
|
|
104
|
+
await this.inngest.send({
|
|
105
|
+
name: `user-event-${event}`,
|
|
106
|
+
data,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
88
110
|
async start({
|
|
89
111
|
inputData,
|
|
90
112
|
}: {
|
|
@@ -96,11 +118,13 @@ export class InngestRun<
|
|
|
96
118
|
runId: this.runId,
|
|
97
119
|
snapshot: {
|
|
98
120
|
runId: this.runId,
|
|
121
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
99
122
|
value: {},
|
|
100
123
|
context: {} as any,
|
|
101
124
|
activePaths: [],
|
|
102
125
|
suspendedPaths: {},
|
|
103
126
|
timestamp: Date.now(),
|
|
127
|
+
status: 'running',
|
|
104
128
|
},
|
|
105
129
|
});
|
|
106
130
|
|
|
@@ -134,6 +158,27 @@ export class InngestRun<
|
|
|
134
158
|
| string
|
|
135
159
|
| string[];
|
|
136
160
|
runtimeContext?: RuntimeContext;
|
|
161
|
+
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
162
|
+
const p = this._resume(params).then(result => {
|
|
163
|
+
if (result.status !== 'suspended') {
|
|
164
|
+
this.closeStreamAction?.().catch(() => {});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return result;
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
this.executionResults = p;
|
|
171
|
+
return p;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async _resume<TResumeSchema extends z.ZodType<any>>(params: {
|
|
175
|
+
resumeData?: z.infer<TResumeSchema>;
|
|
176
|
+
step:
|
|
177
|
+
| Step<string, any, any, TResumeSchema, any>
|
|
178
|
+
| [...Step<string, any, any, any, any>[], Step<string, any, any, TResumeSchema, any>]
|
|
179
|
+
| string
|
|
180
|
+
| string[];
|
|
181
|
+
runtimeContext?: RuntimeContext;
|
|
137
182
|
}): Promise<WorkflowResult<TOutput, TSteps>> {
|
|
138
183
|
const steps: string[] = (Array.isArray(params.step) ? params.step : [params.step]).map(step =>
|
|
139
184
|
typeof step === 'string' ? step : step?.id,
|
|
@@ -171,43 +216,88 @@ export class InngestRun<
|
|
|
171
216
|
return result;
|
|
172
217
|
}
|
|
173
218
|
|
|
174
|
-
watch(cb: (event:
|
|
219
|
+
watch(cb: (event: WatchEvent) => void, type: 'watch' | 'watch-v2' = 'watch'): () => void {
|
|
220
|
+
let active = true;
|
|
175
221
|
const streamPromise = subscribe(
|
|
176
222
|
{
|
|
177
223
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
178
|
-
topics: [
|
|
224
|
+
topics: [type],
|
|
179
225
|
app: this.inngest,
|
|
180
226
|
},
|
|
181
227
|
(message: any) => {
|
|
182
|
-
|
|
228
|
+
if (active) {
|
|
229
|
+
cb(message.data);
|
|
230
|
+
}
|
|
183
231
|
},
|
|
184
232
|
);
|
|
185
233
|
|
|
186
234
|
return () => {
|
|
235
|
+
active = false;
|
|
187
236
|
streamPromise
|
|
188
|
-
.then((stream:
|
|
189
|
-
stream.cancel();
|
|
237
|
+
.then(async (stream: Awaited<typeof streamPromise>) => {
|
|
238
|
+
return stream.cancel();
|
|
190
239
|
})
|
|
191
240
|
.catch(err => {
|
|
192
241
|
console.error(err);
|
|
193
242
|
});
|
|
194
243
|
};
|
|
195
244
|
}
|
|
245
|
+
|
|
246
|
+
stream({ inputData, runtimeContext }: { inputData?: z.infer<TInput>; runtimeContext?: RuntimeContext } = {}): {
|
|
247
|
+
stream: ReadableStream<StreamEvent>;
|
|
248
|
+
getWorkflowState: () => Promise<WorkflowResult<TOutput, TSteps>>;
|
|
249
|
+
} {
|
|
250
|
+
const { readable, writable } = new TransformStream<StreamEvent, StreamEvent>();
|
|
251
|
+
|
|
252
|
+
const writer = writable.getWriter();
|
|
253
|
+
const unwatch = this.watch(async event => {
|
|
254
|
+
try {
|
|
255
|
+
// watch-v2 events are data stream events, so we need to cast them to the correct type
|
|
256
|
+
await writer.write(event as any);
|
|
257
|
+
} catch {}
|
|
258
|
+
}, 'watch-v2');
|
|
259
|
+
|
|
260
|
+
this.closeStreamAction = async () => {
|
|
261
|
+
unwatch();
|
|
262
|
+
|
|
263
|
+
try {
|
|
264
|
+
await writer.close();
|
|
265
|
+
} catch (err) {
|
|
266
|
+
console.error('Error closing stream:', err);
|
|
267
|
+
} finally {
|
|
268
|
+
writer.releaseLock();
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then(result => {
|
|
273
|
+
if (result.status !== 'suspended') {
|
|
274
|
+
this.closeStreamAction?.().catch(() => {});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return result;
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
return {
|
|
281
|
+
stream: readable,
|
|
282
|
+
getWorkflowState: () => this.executionResults!,
|
|
283
|
+
};
|
|
284
|
+
}
|
|
196
285
|
}
|
|
197
286
|
|
|
198
287
|
export class InngestWorkflow<
|
|
199
|
-
|
|
288
|
+
TEngineType = InngestEngineType,
|
|
289
|
+
TSteps extends Step<string, any, any>[] = Step<string, any, any>[],
|
|
200
290
|
TWorkflowId extends string = string,
|
|
201
291
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
202
292
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
203
293
|
TPrevSchema extends z.ZodType<any> = TInput,
|
|
204
|
-
> extends
|
|
294
|
+
> extends Workflow<TEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
205
295
|
#mastra: Mastra;
|
|
206
296
|
public inngest: Inngest;
|
|
207
297
|
|
|
208
298
|
private function: ReturnType<Inngest['createFunction']> | undefined;
|
|
209
299
|
|
|
210
|
-
constructor(params:
|
|
300
|
+
constructor(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>, inngest: Inngest) {
|
|
211
301
|
super(params);
|
|
212
302
|
this.#mastra = params.mastra!;
|
|
213
303
|
this.inngest = inngest;
|
|
@@ -226,25 +316,52 @@ export class InngestWorkflow<
|
|
|
226
316
|
return { runs: [], total: 0 };
|
|
227
317
|
}
|
|
228
318
|
|
|
229
|
-
return storage.getWorkflowRuns({ workflowName: this.id, ...(args ?? {}) }) as unknown as
|
|
319
|
+
return storage.getWorkflowRuns({ workflowName: this.id, ...(args ?? {}) }) as unknown as WorkflowRuns;
|
|
230
320
|
}
|
|
231
321
|
|
|
232
|
-
async getWorkflowRunById(runId: string): Promise<
|
|
322
|
+
async getWorkflowRunById(runId: string): Promise<WorkflowRun | null> {
|
|
233
323
|
const storage = this.#mastra?.getStorage();
|
|
234
324
|
if (!storage) {
|
|
235
325
|
this.logger.debug('Cannot get workflow runs. Mastra engine is not initialized');
|
|
236
|
-
|
|
326
|
+
//returning in memory run if no storage is initialized
|
|
327
|
+
return this.runs.get(runId)
|
|
328
|
+
? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as WorkflowRun)
|
|
329
|
+
: null;
|
|
237
330
|
}
|
|
238
|
-
const run = (await storage.getWorkflowRunById({ runId, workflowName: this.id })) as unknown as
|
|
331
|
+
const run = (await storage.getWorkflowRunById({ runId, workflowName: this.id })) as unknown as WorkflowRun;
|
|
239
332
|
|
|
240
333
|
return (
|
|
241
334
|
run ??
|
|
242
|
-
(this.runs.get(runId)
|
|
243
|
-
? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as VNextWorkflowRun)
|
|
244
|
-
: null)
|
|
335
|
+
(this.runs.get(runId) ? ({ ...this.runs.get(runId), workflowName: this.id } as unknown as WorkflowRun) : null)
|
|
245
336
|
);
|
|
246
337
|
}
|
|
247
338
|
|
|
339
|
+
async getWorkflowRunExecutionResult(runId: string): Promise<WatchEvent['payload']['workflowState'] | null> {
|
|
340
|
+
const storage = this.#mastra?.getStorage();
|
|
341
|
+
if (!storage) {
|
|
342
|
+
this.logger.debug('Cannot get workflow run execution result. Mastra storage is not initialized');
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
347
|
+
|
|
348
|
+
if (!run?.snapshot) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (typeof run.snapshot === 'string') {
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return {
|
|
357
|
+
status: run.snapshot.status,
|
|
358
|
+
result: run.snapshot.result,
|
|
359
|
+
error: run.snapshot.error,
|
|
360
|
+
payload: run.snapshot.context?.input,
|
|
361
|
+
steps: run.snapshot.context as any,
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
248
365
|
__registerMastra(mastra: Mastra) {
|
|
249
366
|
this.#mastra = mastra;
|
|
250
367
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -268,11 +385,11 @@ export class InngestWorkflow<
|
|
|
268
385
|
}
|
|
269
386
|
}
|
|
270
387
|
|
|
271
|
-
createRun(options?: { runId?: string }): Run<TSteps, TInput, TOutput> {
|
|
388
|
+
createRun(options?: { runId?: string }): Run<TEngineType, TSteps, TInput, TOutput> {
|
|
272
389
|
const runIdToUse = options?.runId || randomUUID();
|
|
273
390
|
|
|
274
391
|
// Return a new Run instance with object parameters
|
|
275
|
-
const run: Run<TSteps, TInput, TOutput> =
|
|
392
|
+
const run: Run<TEngineType, TSteps, TInput, TOutput> =
|
|
276
393
|
this.runs.get(runIdToUse) ??
|
|
277
394
|
new InngestRun(
|
|
278
395
|
{
|
|
@@ -280,6 +397,7 @@ export class InngestWorkflow<
|
|
|
280
397
|
runId: runIdToUse,
|
|
281
398
|
executionEngine: this.executionEngine,
|
|
282
399
|
executionGraph: this.executionGraph,
|
|
400
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
283
401
|
mastra: this.#mastra,
|
|
284
402
|
retryConfig: this.retryConfig,
|
|
285
403
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
@@ -317,13 +435,22 @@ export class InngestWorkflow<
|
|
|
317
435
|
try {
|
|
318
436
|
await publish({
|
|
319
437
|
channel: `workflow:${this.id}:${runId}`,
|
|
320
|
-
topic:
|
|
438
|
+
topic: event,
|
|
321
439
|
data,
|
|
322
440
|
});
|
|
323
441
|
} catch (err: any) {
|
|
324
442
|
this.logger.error('Error emitting event: ' + (err?.stack ?? err?.message ?? err));
|
|
325
443
|
}
|
|
326
444
|
},
|
|
445
|
+
on: (_event: string, _callback: (data: any) => void) => {
|
|
446
|
+
// no-op
|
|
447
|
+
},
|
|
448
|
+
off: (_event: string, _callback: (data: any) => void) => {
|
|
449
|
+
// no-op
|
|
450
|
+
},
|
|
451
|
+
once: (_event: string, _callback: (data: any) => void) => {
|
|
452
|
+
// no-op
|
|
453
|
+
},
|
|
327
454
|
};
|
|
328
455
|
|
|
329
456
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -331,6 +458,7 @@ export class InngestWorkflow<
|
|
|
331
458
|
workflowId: this.id,
|
|
332
459
|
runId,
|
|
333
460
|
graph: this.executionGraph,
|
|
461
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
334
462
|
input: inputData,
|
|
335
463
|
emitter,
|
|
336
464
|
retryConfig: this.retryConfig,
|
|
@@ -364,29 +492,192 @@ export class InngestWorkflow<
|
|
|
364
492
|
}
|
|
365
493
|
}
|
|
366
494
|
|
|
367
|
-
function
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
495
|
+
function isAgent(params: any): params is Agent<any, any, any> {
|
|
496
|
+
return params?.component === 'AGENT';
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function isTool(params: any): params is Tool<any, any, any> {
|
|
500
|
+
return params instanceof Tool;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export function createStep<
|
|
504
|
+
TStepId extends string,
|
|
505
|
+
TStepInput extends z.ZodType<any>,
|
|
506
|
+
TStepOutput extends z.ZodType<any>,
|
|
507
|
+
TResumeSchema extends z.ZodType<any>,
|
|
508
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
509
|
+
>(params: {
|
|
510
|
+
id: TStepId;
|
|
511
|
+
description?: string;
|
|
512
|
+
inputSchema: TStepInput;
|
|
513
|
+
outputSchema: TStepOutput;
|
|
514
|
+
resumeSchema?: TResumeSchema;
|
|
515
|
+
suspendSchema?: TSuspendSchema;
|
|
516
|
+
execute: ExecuteFunction<
|
|
517
|
+
z.infer<TStepInput>,
|
|
518
|
+
z.infer<TStepOutput>,
|
|
519
|
+
z.infer<TResumeSchema>,
|
|
520
|
+
z.infer<TSuspendSchema>,
|
|
521
|
+
InngestEngineType
|
|
522
|
+
>;
|
|
523
|
+
}): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
524
|
+
|
|
525
|
+
export function createStep<
|
|
526
|
+
TStepId extends string,
|
|
527
|
+
TStepInput extends z.ZodObject<{ prompt: z.ZodString }>,
|
|
528
|
+
TStepOutput extends z.ZodObject<{ text: z.ZodString }>,
|
|
529
|
+
TResumeSchema extends z.ZodType<any>,
|
|
530
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
372
531
|
>(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
532
|
+
agent: Agent<TStepId, any, any>,
|
|
533
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType>;
|
|
534
|
+
|
|
535
|
+
export function createStep<
|
|
536
|
+
TSchemaIn extends z.ZodType<any>,
|
|
537
|
+
TSchemaOut extends z.ZodType<any>,
|
|
538
|
+
TContext extends ToolExecutionContext<TSchemaIn>,
|
|
539
|
+
>(
|
|
540
|
+
tool: Tool<TSchemaIn, TSchemaOut, TContext> & {
|
|
541
|
+
inputSchema: TSchemaIn;
|
|
542
|
+
outputSchema: TSchemaOut;
|
|
543
|
+
execute: (context: TContext) => Promise<any>;
|
|
544
|
+
},
|
|
545
|
+
): Step<string, TSchemaIn, TSchemaOut, z.ZodType<any>, z.ZodType<any>, InngestEngineType>;
|
|
546
|
+
export function createStep<
|
|
547
|
+
TStepId extends string,
|
|
548
|
+
TStepInput extends z.ZodType<any>,
|
|
549
|
+
TStepOutput extends z.ZodType<any>,
|
|
550
|
+
TResumeSchema extends z.ZodType<any>,
|
|
551
|
+
TSuspendSchema extends z.ZodType<any>,
|
|
552
|
+
>(
|
|
553
|
+
params:
|
|
554
|
+
| {
|
|
555
|
+
id: TStepId;
|
|
556
|
+
description?: string;
|
|
557
|
+
inputSchema: TStepInput;
|
|
558
|
+
outputSchema: TStepOutput;
|
|
559
|
+
resumeSchema?: TResumeSchema;
|
|
560
|
+
suspendSchema?: TSuspendSchema;
|
|
561
|
+
execute: ExecuteFunction<
|
|
562
|
+
z.infer<TStepInput>,
|
|
563
|
+
z.infer<TStepOutput>,
|
|
564
|
+
z.infer<TResumeSchema>,
|
|
565
|
+
z.infer<TSuspendSchema>,
|
|
566
|
+
InngestEngineType
|
|
567
|
+
>;
|
|
568
|
+
}
|
|
569
|
+
| Agent<any, any, any>
|
|
570
|
+
| (Tool<TStepInput, TStepOutput, any> & {
|
|
571
|
+
inputSchema: TStepInput;
|
|
572
|
+
outputSchema: TStepOutput;
|
|
573
|
+
execute: (context: ToolExecutionContext<TStepInput>) => Promise<any>;
|
|
574
|
+
}),
|
|
575
|
+
): Step<TStepId, TStepInput, TStepOutput, TResumeSchema, TSuspendSchema, InngestEngineType> {
|
|
576
|
+
if (isAgent(params)) {
|
|
577
|
+
return {
|
|
578
|
+
id: params.name,
|
|
579
|
+
// @ts-ignore
|
|
580
|
+
inputSchema: z.object({
|
|
581
|
+
prompt: z.string(),
|
|
582
|
+
// resourceId: z.string().optional(),
|
|
583
|
+
// threadId: z.string().optional(),
|
|
584
|
+
}),
|
|
585
|
+
// @ts-ignore
|
|
586
|
+
outputSchema: z.object({
|
|
587
|
+
text: z.string(),
|
|
588
|
+
}),
|
|
589
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
|
|
590
|
+
let streamPromise = {} as {
|
|
591
|
+
promise: Promise<string>;
|
|
592
|
+
resolve: (value: string) => void;
|
|
593
|
+
reject: (reason?: any) => void;
|
|
594
|
+
};
|
|
386
595
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
596
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
597
|
+
streamPromise.resolve = resolve;
|
|
598
|
+
streamPromise.reject = reject;
|
|
599
|
+
});
|
|
600
|
+
const toolData = {
|
|
601
|
+
name: params.name,
|
|
602
|
+
args: inputData,
|
|
603
|
+
};
|
|
604
|
+
await emitter.emit('watch-v2', {
|
|
605
|
+
type: 'tool-call-streaming-start',
|
|
606
|
+
...toolData,
|
|
607
|
+
});
|
|
608
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
609
|
+
// resourceId: inputData.resourceId,
|
|
610
|
+
// threadId: inputData.threadId,
|
|
611
|
+
runtimeContext,
|
|
612
|
+
onFinish: result => {
|
|
613
|
+
streamPromise.resolve(result.text);
|
|
614
|
+
},
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
for await (const chunk of fullStream) {
|
|
618
|
+
switch (chunk.type) {
|
|
619
|
+
case 'text':
|
|
620
|
+
await emitter.emit('watch-v2', {
|
|
621
|
+
type: 'tool-call-delta',
|
|
622
|
+
...toolData,
|
|
623
|
+
argsTextDelta: chunk.text,
|
|
624
|
+
});
|
|
625
|
+
break;
|
|
626
|
+
|
|
627
|
+
case 'start-step':
|
|
628
|
+
case 'finish-step':
|
|
629
|
+
case 'finish':
|
|
630
|
+
break;
|
|
631
|
+
|
|
632
|
+
case 'tool-call':
|
|
633
|
+
case 'tool-result':
|
|
634
|
+
case 'tool-input-start':
|
|
635
|
+
case 'tool-input-delta':
|
|
636
|
+
case 'source':
|
|
637
|
+
case 'file':
|
|
638
|
+
default:
|
|
639
|
+
await emitter.emit('watch-v2', chunk);
|
|
640
|
+
break;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return {
|
|
645
|
+
text: await streamPromise.promise,
|
|
646
|
+
};
|
|
647
|
+
},
|
|
648
|
+
};
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
if (isTool(params)) {
|
|
652
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
653
|
+
throw new Error('Tool must have input and output schemas defined');
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
return {
|
|
657
|
+
// TODO: tool probably should have strong id type
|
|
658
|
+
// @ts-ignore
|
|
659
|
+
id: params.id,
|
|
660
|
+
inputSchema: params.inputSchema,
|
|
661
|
+
outputSchema: params.outputSchema,
|
|
662
|
+
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
663
|
+
return params.execute({
|
|
664
|
+
context: inputData,
|
|
665
|
+
mastra,
|
|
666
|
+
runtimeContext,
|
|
667
|
+
});
|
|
668
|
+
},
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
return {
|
|
673
|
+
id: params.id,
|
|
674
|
+
description: params.description,
|
|
675
|
+
inputSchema: params.inputSchema,
|
|
676
|
+
outputSchema: params.outputSchema,
|
|
677
|
+
resumeSchema: params.resumeSchema,
|
|
678
|
+
suspendSchema: params.suspendSchema,
|
|
679
|
+
execute: params.execute,
|
|
680
|
+
};
|
|
390
681
|
}
|
|
391
682
|
|
|
392
683
|
export function init(inngest: Inngest) {
|
|
@@ -395,13 +686,59 @@ export function init(inngest: Inngest) {
|
|
|
395
686
|
TWorkflowId extends string = string,
|
|
396
687
|
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
397
688
|
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
398
|
-
TSteps extends Step<string, any, any
|
|
399
|
-
|
|
400
|
-
|
|
689
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
690
|
+
string,
|
|
691
|
+
any,
|
|
692
|
+
any,
|
|
693
|
+
any,
|
|
694
|
+
any,
|
|
695
|
+
InngestEngineType
|
|
696
|
+
>[],
|
|
697
|
+
>(params: WorkflowConfig<TWorkflowId, TInput, TOutput, TSteps>) {
|
|
698
|
+
return new InngestWorkflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TInput>(params, inngest);
|
|
401
699
|
},
|
|
402
700
|
createStep,
|
|
403
|
-
cloneStep
|
|
404
|
-
|
|
701
|
+
cloneStep<TStepId extends string>(
|
|
702
|
+
step: Step<string, any, any, any, any, InngestEngineType>,
|
|
703
|
+
opts: { id: TStepId },
|
|
704
|
+
): Step<TStepId, any, any, any, any, InngestEngineType> {
|
|
705
|
+
return {
|
|
706
|
+
id: opts.id,
|
|
707
|
+
description: step.description,
|
|
708
|
+
inputSchema: step.inputSchema,
|
|
709
|
+
outputSchema: step.outputSchema,
|
|
710
|
+
execute: step.execute,
|
|
711
|
+
};
|
|
712
|
+
},
|
|
713
|
+
cloneWorkflow<
|
|
714
|
+
TWorkflowId extends string = string,
|
|
715
|
+
TInput extends z.ZodType<any> = z.ZodType<any>,
|
|
716
|
+
TOutput extends z.ZodType<any> = z.ZodType<any>,
|
|
717
|
+
TSteps extends Step<string, any, any, any, any, InngestEngineType>[] = Step<
|
|
718
|
+
string,
|
|
719
|
+
any,
|
|
720
|
+
any,
|
|
721
|
+
any,
|
|
722
|
+
any,
|
|
723
|
+
InngestEngineType
|
|
724
|
+
>[],
|
|
725
|
+
TPrevSchema extends z.ZodType<any> = TInput,
|
|
726
|
+
>(
|
|
727
|
+
workflow: Workflow<InngestEngineType, TSteps, string, TInput, TOutput, TPrevSchema>,
|
|
728
|
+
opts: { id: TWorkflowId },
|
|
729
|
+
): Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> {
|
|
730
|
+
const wf: Workflow<InngestEngineType, TSteps, TWorkflowId, TInput, TOutput, TPrevSchema> = new Workflow({
|
|
731
|
+
id: opts.id,
|
|
732
|
+
inputSchema: workflow.inputSchema,
|
|
733
|
+
outputSchema: workflow.outputSchema,
|
|
734
|
+
steps: workflow.stepDefs,
|
|
735
|
+
mastra: workflow.mastra,
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
739
|
+
wf.commit();
|
|
740
|
+
return wf;
|
|
741
|
+
},
|
|
405
742
|
};
|
|
406
743
|
}
|
|
407
744
|
|
|
@@ -415,11 +752,46 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
415
752
|
this.inngestAttempts = inngestAttempts;
|
|
416
753
|
}
|
|
417
754
|
|
|
755
|
+
async execute<TInput, TOutput>(params: {
|
|
756
|
+
workflowId: string;
|
|
757
|
+
runId: string;
|
|
758
|
+
graph: ExecutionGraph;
|
|
759
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
760
|
+
input?: TInput;
|
|
761
|
+
resume?: {
|
|
762
|
+
// TODO: add execute path
|
|
763
|
+
steps: string[];
|
|
764
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
765
|
+
resumePayload: any;
|
|
766
|
+
resumePath: number[];
|
|
767
|
+
};
|
|
768
|
+
emitter: Emitter;
|
|
769
|
+
retryConfig?: {
|
|
770
|
+
attempts?: number;
|
|
771
|
+
delay?: number;
|
|
772
|
+
};
|
|
773
|
+
runtimeContext: RuntimeContext;
|
|
774
|
+
}): Promise<TOutput> {
|
|
775
|
+
await params.emitter.emit('watch-v2', {
|
|
776
|
+
type: 'start',
|
|
777
|
+
payload: { runId: params.runId },
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
const result = await super.execute<TInput, TOutput>(params);
|
|
781
|
+
|
|
782
|
+
await params.emitter.emit('watch-v2', {
|
|
783
|
+
type: 'finish',
|
|
784
|
+
payload: { runId: params.runId },
|
|
785
|
+
});
|
|
786
|
+
|
|
787
|
+
return result;
|
|
788
|
+
}
|
|
789
|
+
|
|
418
790
|
protected async fmtReturnValue<TOutput>(
|
|
419
791
|
executionSpan: Span | undefined,
|
|
420
|
-
emitter:
|
|
421
|
-
stepResults: Record<string, StepResult<any>>,
|
|
422
|
-
lastOutput: StepResult<any>,
|
|
792
|
+
emitter: Emitter,
|
|
793
|
+
stepResults: Record<string, StepResult<any, any, any, any>>,
|
|
794
|
+
lastOutput: StepResult<any, any, any, any>,
|
|
423
795
|
error?: Error | string,
|
|
424
796
|
): Promise<TOutput> {
|
|
425
797
|
const base: any = {
|
|
@@ -503,16 +875,16 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
503
875
|
workflowId: string;
|
|
504
876
|
runId: string;
|
|
505
877
|
step: Step<string, any, any>;
|
|
506
|
-
stepResults: Record<string, StepResult<any>>;
|
|
878
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
507
879
|
executionContext: ExecutionContext;
|
|
508
880
|
resume?: {
|
|
509
881
|
steps: string[];
|
|
510
882
|
resumePayload: any;
|
|
511
883
|
};
|
|
512
884
|
prevOutput: any;
|
|
513
|
-
emitter:
|
|
885
|
+
emitter: Emitter;
|
|
514
886
|
runtimeContext: RuntimeContext;
|
|
515
|
-
}): Promise<StepResult<any>> {
|
|
887
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
516
888
|
return super.executeStep({
|
|
517
889
|
workflowId,
|
|
518
890
|
runId,
|
|
@@ -526,6 +898,23 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
526
898
|
});
|
|
527
899
|
}
|
|
528
900
|
|
|
901
|
+
async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
902
|
+
await this.inngestStep.sleep(id, duration);
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
|
|
906
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
907
|
+
event: `user-event-${event}`,
|
|
908
|
+
timeout: timeout ?? 5e3,
|
|
909
|
+
});
|
|
910
|
+
|
|
911
|
+
if (eventData === null) {
|
|
912
|
+
throw 'Timeout waiting for event';
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
return eventData?.data;
|
|
916
|
+
}
|
|
917
|
+
|
|
529
918
|
async executeStep({
|
|
530
919
|
step,
|
|
531
920
|
stepResults,
|
|
@@ -536,7 +925,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
536
925
|
runtimeContext,
|
|
537
926
|
}: {
|
|
538
927
|
step: Step<string, any, any>;
|
|
539
|
-
stepResults: Record<string, StepResult<any>>;
|
|
928
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
540
929
|
executionContext: {
|
|
541
930
|
workflowId: string;
|
|
542
931
|
runId: string;
|
|
@@ -550,12 +939,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
550
939
|
runId?: string;
|
|
551
940
|
};
|
|
552
941
|
prevOutput: any;
|
|
553
|
-
emitter:
|
|
942
|
+
emitter: Emitter;
|
|
554
943
|
runtimeContext: RuntimeContext;
|
|
555
|
-
}): Promise<StepResult<any>> {
|
|
556
|
-
await this.inngestStep.run(
|
|
944
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
945
|
+
const startedAt = await this.inngestStep.run(
|
|
557
946
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
558
947
|
async () => {
|
|
948
|
+
const startedAt = Date.now();
|
|
559
949
|
await emitter.emit('watch', {
|
|
560
950
|
type: 'watch',
|
|
561
951
|
payload: {
|
|
@@ -577,6 +967,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
577
967
|
},
|
|
578
968
|
eventTimestamp: Date.now(),
|
|
579
969
|
});
|
|
970
|
+
|
|
971
|
+
await emitter.emit('watch-v2', {
|
|
972
|
+
type: 'step-start',
|
|
973
|
+
payload: {
|
|
974
|
+
id: step.id,
|
|
975
|
+
},
|
|
976
|
+
});
|
|
977
|
+
|
|
978
|
+
return startedAt;
|
|
580
979
|
},
|
|
581
980
|
);
|
|
582
981
|
|
|
@@ -643,10 +1042,18 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
643
1042
|
eventTimestamp: Date.now(),
|
|
644
1043
|
});
|
|
645
1044
|
|
|
1045
|
+
await emitter.emit('watch-v2', {
|
|
1046
|
+
type: 'step-result',
|
|
1047
|
+
payload: {
|
|
1048
|
+
id: step.id,
|
|
1049
|
+
status: 'failed',
|
|
1050
|
+
},
|
|
1051
|
+
});
|
|
1052
|
+
|
|
646
1053
|
return { executionContext, result: { status: 'failed', error: result?.error } };
|
|
647
1054
|
} else if (result.status === 'suspended') {
|
|
648
1055
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
649
|
-
const stepRes: StepResult<any> = stepResult as StepResult<any>;
|
|
1056
|
+
const stepRes: StepResult<any, any, any, any> = stepResult as StepResult<any, any, any, any>;
|
|
650
1057
|
return stepRes?.status === 'suspended';
|
|
651
1058
|
});
|
|
652
1059
|
|
|
@@ -673,6 +1080,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
673
1080
|
eventTimestamp: Date.now(),
|
|
674
1081
|
});
|
|
675
1082
|
|
|
1083
|
+
await emitter.emit('watch-v2', {
|
|
1084
|
+
type: 'step-suspended',
|
|
1085
|
+
payload: {
|
|
1086
|
+
id: step.id,
|
|
1087
|
+
},
|
|
1088
|
+
});
|
|
1089
|
+
|
|
676
1090
|
return {
|
|
677
1091
|
executionContext,
|
|
678
1092
|
result: {
|
|
@@ -729,19 +1143,29 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
729
1143
|
eventTimestamp: Date.now(),
|
|
730
1144
|
});
|
|
731
1145
|
|
|
1146
|
+
await emitter.emit('watch-v2', {
|
|
1147
|
+
type: 'step-finish',
|
|
1148
|
+
payload: {
|
|
1149
|
+
id: step.id,
|
|
1150
|
+
metadata: {},
|
|
1151
|
+
},
|
|
1152
|
+
});
|
|
1153
|
+
|
|
732
1154
|
return { executionContext, result: { status: 'success', output: result?.result } };
|
|
733
1155
|
},
|
|
734
1156
|
);
|
|
735
1157
|
|
|
736
1158
|
Object.assign(executionContext, res.executionContext);
|
|
737
|
-
return res.result as StepResult<any>;
|
|
1159
|
+
return res.result as StepResult<any, any, any, any>;
|
|
738
1160
|
}
|
|
739
1161
|
|
|
740
1162
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
741
1163
|
let execResults: any;
|
|
742
1164
|
let suspended: { payload: any } | undefined;
|
|
1165
|
+
|
|
743
1166
|
try {
|
|
744
1167
|
const result = await step.execute({
|
|
1168
|
+
runId: executionContext.runId,
|
|
745
1169
|
mastra: this.mastra!,
|
|
746
1170
|
runtimeContext,
|
|
747
1171
|
inputData: prevOutput,
|
|
@@ -765,16 +1189,44 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
765
1189
|
// @ts-ignore
|
|
766
1190
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId,
|
|
767
1191
|
},
|
|
768
|
-
emitter,
|
|
1192
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1193
|
+
engine: {
|
|
1194
|
+
step: this.inngestStep,
|
|
1195
|
+
},
|
|
769
1196
|
});
|
|
770
|
-
|
|
771
|
-
|
|
1197
|
+
const endedAt = Date.now();
|
|
1198
|
+
|
|
1199
|
+
execResults = {
|
|
1200
|
+
status: 'success',
|
|
1201
|
+
output: result,
|
|
1202
|
+
startedAt,
|
|
1203
|
+
endedAt,
|
|
1204
|
+
payload: prevOutput,
|
|
1205
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1206
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1207
|
+
};
|
|
772
1208
|
} catch (e) {
|
|
773
|
-
execResults = {
|
|
1209
|
+
execResults = {
|
|
1210
|
+
status: 'failed',
|
|
1211
|
+
payload: prevOutput,
|
|
1212
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1213
|
+
endedAt: Date.now(),
|
|
1214
|
+
startedAt,
|
|
1215
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1216
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1217
|
+
};
|
|
774
1218
|
}
|
|
775
1219
|
|
|
776
1220
|
if (suspended) {
|
|
777
|
-
execResults = {
|
|
1221
|
+
execResults = {
|
|
1222
|
+
status: 'suspended',
|
|
1223
|
+
suspendedPayload: suspended.payload,
|
|
1224
|
+
payload: prevOutput,
|
|
1225
|
+
suspendedAt: Date.now(),
|
|
1226
|
+
startedAt,
|
|
1227
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : undefined,
|
|
1228
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
|
|
1229
|
+
};
|
|
778
1230
|
}
|
|
779
1231
|
|
|
780
1232
|
if (execResults.status === 'failed') {
|
|
@@ -788,12 +1240,11 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
788
1240
|
payload: {
|
|
789
1241
|
currentStep: {
|
|
790
1242
|
id: step.id,
|
|
791
|
-
|
|
792
|
-
output: execResults.output,
|
|
1243
|
+
...execResults,
|
|
793
1244
|
},
|
|
794
1245
|
workflowState: {
|
|
795
1246
|
status: 'running',
|
|
796
|
-
steps: stepResults,
|
|
1247
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
797
1248
|
result: null,
|
|
798
1249
|
error: null,
|
|
799
1250
|
},
|
|
@@ -801,6 +1252,34 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
801
1252
|
eventTimestamp: Date.now(),
|
|
802
1253
|
});
|
|
803
1254
|
|
|
1255
|
+
if (execResults.status === 'suspended') {
|
|
1256
|
+
await emitter.emit('watch-v2', {
|
|
1257
|
+
type: 'step-suspended',
|
|
1258
|
+
payload: {
|
|
1259
|
+
id: step.id,
|
|
1260
|
+
status: execResults.status,
|
|
1261
|
+
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1262
|
+
},
|
|
1263
|
+
});
|
|
1264
|
+
} else {
|
|
1265
|
+
await emitter.emit('watch-v2', {
|
|
1266
|
+
type: 'step-result',
|
|
1267
|
+
payload: {
|
|
1268
|
+
id: step.id,
|
|
1269
|
+
status: execResults.status,
|
|
1270
|
+
output: execResults.status === 'success' ? execResults?.output : undefined,
|
|
1271
|
+
},
|
|
1272
|
+
});
|
|
1273
|
+
|
|
1274
|
+
await emitter.emit('watch-v2', {
|
|
1275
|
+
type: 'step-finish',
|
|
1276
|
+
payload: {
|
|
1277
|
+
id: step.id,
|
|
1278
|
+
metadata: {},
|
|
1279
|
+
},
|
|
1280
|
+
});
|
|
1281
|
+
}
|
|
1282
|
+
|
|
804
1283
|
return { result: execResults, executionContext, stepResults };
|
|
805
1284
|
});
|
|
806
1285
|
|
|
@@ -818,11 +1297,19 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
818
1297
|
runId,
|
|
819
1298
|
stepResults,
|
|
820
1299
|
executionContext,
|
|
1300
|
+
serializedStepGraph,
|
|
1301
|
+
workflowStatus,
|
|
1302
|
+
result,
|
|
1303
|
+
error,
|
|
821
1304
|
}: {
|
|
822
1305
|
workflowId: string;
|
|
823
1306
|
runId: string;
|
|
824
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1307
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
1308
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
825
1309
|
executionContext: ExecutionContext;
|
|
1310
|
+
workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
|
|
1311
|
+
result?: Record<string, any>;
|
|
1312
|
+
error?: string | Error;
|
|
826
1313
|
}) {
|
|
827
1314
|
await this.inngestStep.run(
|
|
828
1315
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -836,6 +1323,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
836
1323
|
context: stepResults as any,
|
|
837
1324
|
activePaths: [],
|
|
838
1325
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1326
|
+
serializedStepGraph,
|
|
1327
|
+
status: workflowStatus,
|
|
1328
|
+
result,
|
|
1329
|
+
error,
|
|
839
1330
|
// @ts-ignore
|
|
840
1331
|
timestamp: Date.now(),
|
|
841
1332
|
},
|
|
@@ -851,6 +1342,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
851
1342
|
prevOutput,
|
|
852
1343
|
prevStep,
|
|
853
1344
|
stepResults,
|
|
1345
|
+
serializedStepGraph,
|
|
854
1346
|
resume,
|
|
855
1347
|
executionContext,
|
|
856
1348
|
emitter,
|
|
@@ -858,20 +1350,25 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
858
1350
|
}: {
|
|
859
1351
|
workflowId: string;
|
|
860
1352
|
runId: string;
|
|
861
|
-
entry: {
|
|
1353
|
+
entry: {
|
|
1354
|
+
type: 'conditional';
|
|
1355
|
+
steps: StepFlowEntry[];
|
|
1356
|
+
conditions: ExecuteFunction<any, any, any, any, InngestEngineType>[];
|
|
1357
|
+
};
|
|
862
1358
|
prevStep: StepFlowEntry;
|
|
1359
|
+
serializedStepGraph: SerializedStepFlowEntry[];
|
|
863
1360
|
prevOutput: any;
|
|
864
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1361
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
865
1362
|
resume?: {
|
|
866
1363
|
steps: string[];
|
|
867
|
-
stepResults: Record<string, StepResult<any>>;
|
|
1364
|
+
stepResults: Record<string, StepResult<any, any, any, any>>;
|
|
868
1365
|
resumePayload: any;
|
|
869
1366
|
resumePath: number[];
|
|
870
1367
|
};
|
|
871
1368
|
executionContext: ExecutionContext;
|
|
872
|
-
emitter:
|
|
1369
|
+
emitter: Emitter;
|
|
873
1370
|
runtimeContext: RuntimeContext;
|
|
874
|
-
}): Promise<StepResult<any>> {
|
|
1371
|
+
}): Promise<StepResult<any, any, any, any>> {
|
|
875
1372
|
let execResults: any;
|
|
876
1373
|
const truthyIndexes = (
|
|
877
1374
|
await Promise.all(
|
|
@@ -879,6 +1376,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
879
1376
|
this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
880
1377
|
try {
|
|
881
1378
|
const result = await cond({
|
|
1379
|
+
runId,
|
|
882
1380
|
mastra: this.mastra!,
|
|
883
1381
|
runtimeContext,
|
|
884
1382
|
inputData: prevOutput,
|
|
@@ -898,7 +1396,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
898
1396
|
|
|
899
1397
|
// TODO: this function shouldn't have suspend probably?
|
|
900
1398
|
suspend: async (_suspendPayload: any) => {},
|
|
901
|
-
emitter,
|
|
1399
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1400
|
+
engine: {
|
|
1401
|
+
step: this.inngestStep,
|
|
1402
|
+
},
|
|
902
1403
|
});
|
|
903
1404
|
return result ? index : null;
|
|
904
1405
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -911,7 +1412,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
911
1412
|
).filter((index: any): index is number => index !== null);
|
|
912
1413
|
|
|
913
1414
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
914
|
-
const results: StepResult<any>[] = await Promise.all(
|
|
1415
|
+
const results: { result: StepResult<any, any, any, any> }[] = await Promise.all(
|
|
915
1416
|
stepsToRun.map((step, index) =>
|
|
916
1417
|
this.executeEntry({
|
|
917
1418
|
workflowId,
|
|
@@ -920,6 +1421,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
920
1421
|
prevStep,
|
|
921
1422
|
stepResults,
|
|
922
1423
|
resume,
|
|
1424
|
+
serializedStepGraph,
|
|
923
1425
|
executionContext: {
|
|
924
1426
|
workflowId,
|
|
925
1427
|
runId,
|
|
@@ -933,17 +1435,19 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
|
|
|
933
1435
|
}),
|
|
934
1436
|
),
|
|
935
1437
|
);
|
|
936
|
-
const hasFailed = results.find(result => result.status === 'failed')
|
|
937
|
-
|
|
1438
|
+
const hasFailed = results.find(result => result.result.status === 'failed') as {
|
|
1439
|
+
result: StepFailure<any, any, any>;
|
|
1440
|
+
};
|
|
1441
|
+
const hasSuspended = results.find(result => result.result.status === 'suspended');
|
|
938
1442
|
if (hasFailed) {
|
|
939
|
-
execResults = { status: 'failed', error: hasFailed.error };
|
|
1443
|
+
execResults = { status: 'failed', error: hasFailed.result.error };
|
|
940
1444
|
} else if (hasSuspended) {
|
|
941
|
-
execResults = { status: 'suspended', payload: hasSuspended.
|
|
1445
|
+
execResults = { status: 'suspended', payload: hasSuspended.result.suspendPayload };
|
|
942
1446
|
} else {
|
|
943
1447
|
execResults = {
|
|
944
1448
|
status: 'success',
|
|
945
1449
|
output: results.reduce((acc: Record<string, any>, result, index) => {
|
|
946
|
-
if (result.status === 'success') {
|
|
1450
|
+
if (result.result.status === 'success') {
|
|
947
1451
|
// @ts-ignore
|
|
948
1452
|
acc[stepsToRun[index]!.step.id] = result.output;
|
|
949
1453
|
}
|