@mastra/inngest 0.0.0-course-20250527170450 → 0.0.0-custom-instrumentation-20250708222033
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 +385 -2
- package/LICENSE.md +11 -42
- package/dist/_tsup-dts-rollup.d.cts +155 -40
- package/dist/_tsup-dts-rollup.d.ts +155 -40
- package/dist/index.cjs +576 -54
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +576 -55
- package/docker-compose.yaml +3 -3
- package/package.json +21 -19
- package/src/index.test.ts +5599 -3509
- package/src/index.ts +859 -79
- package/vitest.config.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
2
|
import { subscribe } from '@inngest/realtime';
|
|
3
3
|
import { RuntimeContext } from '@mastra/core/di';
|
|
4
|
-
import {
|
|
4
|
+
import { Tool } from '@mastra/core/tools';
|
|
5
|
+
import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
5
6
|
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
6
7
|
import { serve as serve$1 } from 'inngest/hono';
|
|
8
|
+
import { z } from 'zod';
|
|
7
9
|
|
|
8
10
|
// src/index.ts
|
|
9
11
|
function serve({ mastra, inngest }) {
|
|
10
12
|
const wfs = mastra.getWorkflows();
|
|
11
|
-
const functions =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
const functions = Array.from(
|
|
14
|
+
new Set(
|
|
15
|
+
Object.values(wfs).flatMap((wf) => {
|
|
16
|
+
if (wf instanceof InngestWorkflow) {
|
|
17
|
+
wf.__registerMastra(mastra);
|
|
18
|
+
return wf.getFunctions();
|
|
19
|
+
}
|
|
20
|
+
return [];
|
|
21
|
+
})
|
|
22
|
+
)
|
|
23
|
+
);
|
|
18
24
|
return serve$1({
|
|
19
25
|
client: inngest,
|
|
20
26
|
functions
|
|
@@ -22,14 +28,16 @@ function serve({ mastra, inngest }) {
|
|
|
22
28
|
}
|
|
23
29
|
var InngestRun = class extends Run {
|
|
24
30
|
inngest;
|
|
31
|
+
serializedStepGraph;
|
|
25
32
|
#mastra;
|
|
26
33
|
constructor(params, inngest) {
|
|
27
34
|
super(params);
|
|
28
35
|
this.inngest = inngest;
|
|
36
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
29
37
|
this.#mastra = params.mastra;
|
|
30
38
|
}
|
|
31
39
|
async getRuns(eventId) {
|
|
32
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
40
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
|
|
33
41
|
headers: {
|
|
34
42
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
35
43
|
}
|
|
@@ -39,15 +47,50 @@ var InngestRun = class extends Run {
|
|
|
39
47
|
}
|
|
40
48
|
async getRunOutput(eventId) {
|
|
41
49
|
let runs = await this.getRuns(eventId);
|
|
42
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
50
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
43
51
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
44
52
|
runs = await this.getRuns(eventId);
|
|
45
|
-
if (runs?.[0]?.status === "Failed"
|
|
53
|
+
if (runs?.[0]?.status === "Failed") {
|
|
54
|
+
console.log("run", runs?.[0]);
|
|
46
55
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
56
|
+
} else if (runs?.[0]?.status === "Cancelled") {
|
|
57
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
58
|
+
workflowName: this.workflowId,
|
|
59
|
+
runId: this.runId
|
|
60
|
+
});
|
|
61
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
47
62
|
}
|
|
48
63
|
}
|
|
49
64
|
return runs?.[0];
|
|
50
65
|
}
|
|
66
|
+
async sendEvent(event, data) {
|
|
67
|
+
await this.inngest.send({
|
|
68
|
+
name: `user-event-${event}`,
|
|
69
|
+
data
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
async cancel() {
|
|
73
|
+
await this.inngest.send({
|
|
74
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
75
|
+
data: {
|
|
76
|
+
runId: this.runId
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
80
|
+
workflowName: this.workflowId,
|
|
81
|
+
runId: this.runId
|
|
82
|
+
});
|
|
83
|
+
if (snapshot) {
|
|
84
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
85
|
+
workflowName: this.workflowId,
|
|
86
|
+
runId: this.runId,
|
|
87
|
+
snapshot: {
|
|
88
|
+
...snapshot,
|
|
89
|
+
status: "canceled"
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
51
94
|
async start({
|
|
52
95
|
inputData
|
|
53
96
|
}) {
|
|
@@ -56,11 +99,13 @@ var InngestRun = class extends Run {
|
|
|
56
99
|
runId: this.runId,
|
|
57
100
|
snapshot: {
|
|
58
101
|
runId: this.runId,
|
|
102
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
59
103
|
value: {},
|
|
60
104
|
context: {},
|
|
61
105
|
activePaths: [],
|
|
62
106
|
suspendedPaths: {},
|
|
63
|
-
timestamp: Date.now()
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
status: "running"
|
|
64
109
|
}
|
|
65
110
|
});
|
|
66
111
|
const eventOutput = await this.inngest.send({
|
|
@@ -79,10 +124,23 @@ var InngestRun = class extends Run {
|
|
|
79
124
|
if (result.status === "failed") {
|
|
80
125
|
result.error = new Error(result.error);
|
|
81
126
|
}
|
|
82
|
-
|
|
127
|
+
if (result.status !== "suspended") {
|
|
128
|
+
this.cleanup?.();
|
|
129
|
+
}
|
|
83
130
|
return result;
|
|
84
131
|
}
|
|
85
132
|
async resume(params) {
|
|
133
|
+
const p = this._resume(params).then((result) => {
|
|
134
|
+
if (result.status !== "suspended") {
|
|
135
|
+
this.closeStreamAction?.().catch(() => {
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
});
|
|
140
|
+
this.executionResults = p;
|
|
141
|
+
return p;
|
|
142
|
+
}
|
|
143
|
+
async _resume(params) {
|
|
86
144
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
87
145
|
(step) => typeof step === "string" ? step : step?.id
|
|
88
146
|
);
|
|
@@ -116,25 +174,60 @@ var InngestRun = class extends Run {
|
|
|
116
174
|
}
|
|
117
175
|
return result;
|
|
118
176
|
}
|
|
119
|
-
watch(cb) {
|
|
177
|
+
watch(cb, type = "watch") {
|
|
178
|
+
let active = true;
|
|
120
179
|
const streamPromise = subscribe(
|
|
121
180
|
{
|
|
122
181
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
123
|
-
topics: [
|
|
182
|
+
topics: [type],
|
|
124
183
|
app: this.inngest
|
|
125
184
|
},
|
|
126
185
|
(message) => {
|
|
127
|
-
|
|
186
|
+
if (active) {
|
|
187
|
+
cb(message.data);
|
|
188
|
+
}
|
|
128
189
|
}
|
|
129
190
|
);
|
|
130
191
|
return () => {
|
|
131
|
-
|
|
132
|
-
|
|
192
|
+
active = false;
|
|
193
|
+
streamPromise.then(async (stream) => {
|
|
194
|
+
return stream.cancel();
|
|
133
195
|
}).catch((err) => {
|
|
134
196
|
console.error(err);
|
|
135
197
|
});
|
|
136
198
|
};
|
|
137
199
|
}
|
|
200
|
+
stream({ inputData, runtimeContext } = {}) {
|
|
201
|
+
const { readable, writable } = new TransformStream();
|
|
202
|
+
const writer = writable.getWriter();
|
|
203
|
+
const unwatch = this.watch(async (event) => {
|
|
204
|
+
try {
|
|
205
|
+
await writer.write(event);
|
|
206
|
+
} catch {
|
|
207
|
+
}
|
|
208
|
+
}, "watch-v2");
|
|
209
|
+
this.closeStreamAction = async () => {
|
|
210
|
+
unwatch();
|
|
211
|
+
try {
|
|
212
|
+
await writer.close();
|
|
213
|
+
} catch (err) {
|
|
214
|
+
console.error("Error closing stream:", err);
|
|
215
|
+
} finally {
|
|
216
|
+
writer.releaseLock();
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
|
|
220
|
+
if (result.status !== "suspended") {
|
|
221
|
+
this.closeStreamAction?.().catch(() => {
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
return result;
|
|
225
|
+
});
|
|
226
|
+
return {
|
|
227
|
+
stream: readable,
|
|
228
|
+
getWorkflowState: () => this.executionResults
|
|
229
|
+
};
|
|
230
|
+
}
|
|
138
231
|
};
|
|
139
232
|
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
140
233
|
#mastra;
|
|
@@ -157,11 +250,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
157
250
|
const storage = this.#mastra?.getStorage();
|
|
158
251
|
if (!storage) {
|
|
159
252
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
160
|
-
return null;
|
|
253
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
161
254
|
}
|
|
162
255
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
163
256
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
164
257
|
}
|
|
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
|
+
}
|
|
165
279
|
__registerMastra(mastra) {
|
|
166
280
|
this.#mastra = mastra;
|
|
167
281
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -188,6 +302,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
188
302
|
runId: runIdToUse,
|
|
189
303
|
executionEngine: this.executionEngine,
|
|
190
304
|
executionGraph: this.executionGraph,
|
|
305
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
191
306
|
mastra: this.#mastra,
|
|
192
307
|
retryConfig: this.retryConfig,
|
|
193
308
|
cleanup: () => this.runs.delete(runIdToUse)
|
|
@@ -197,13 +312,55 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
197
312
|
this.runs.set(runIdToUse, run);
|
|
198
313
|
return run;
|
|
199
314
|
}
|
|
315
|
+
async createRunAsync(options) {
|
|
316
|
+
const runIdToUse = options?.runId || randomUUID();
|
|
317
|
+
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
318
|
+
{
|
|
319
|
+
workflowId: this.id,
|
|
320
|
+
runId: runIdToUse,
|
|
321
|
+
executionEngine: this.executionEngine,
|
|
322
|
+
executionGraph: this.executionGraph,
|
|
323
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
324
|
+
mastra: this.#mastra,
|
|
325
|
+
retryConfig: this.retryConfig,
|
|
326
|
+
cleanup: () => this.runs.delete(runIdToUse)
|
|
327
|
+
},
|
|
328
|
+
this.inngest
|
|
329
|
+
);
|
|
330
|
+
this.runs.set(runIdToUse, run);
|
|
331
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
|
|
332
|
+
if (!workflowSnapshotInStorage) {
|
|
333
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
334
|
+
workflowName: this.id,
|
|
335
|
+
runId: runIdToUse,
|
|
336
|
+
snapshot: {
|
|
337
|
+
runId: runIdToUse,
|
|
338
|
+
status: "pending",
|
|
339
|
+
value: {},
|
|
340
|
+
context: {},
|
|
341
|
+
activePaths: [],
|
|
342
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
343
|
+
suspendedPaths: {},
|
|
344
|
+
result: void 0,
|
|
345
|
+
error: void 0,
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
timestamp: Date.now()
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
return run;
|
|
352
|
+
}
|
|
200
353
|
getFunction() {
|
|
201
354
|
if (this.function) {
|
|
202
355
|
return this.function;
|
|
203
356
|
}
|
|
204
357
|
this.function = this.inngest.createFunction(
|
|
205
|
-
|
|
206
|
-
|
|
358
|
+
{
|
|
359
|
+
id: `workflow.${this.id}`,
|
|
360
|
+
// @ts-ignore
|
|
361
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
362
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
363
|
+
},
|
|
207
364
|
{ event: `workflow.${this.id}` },
|
|
208
365
|
async ({ event, step, attempt, publish }) => {
|
|
209
366
|
let { inputData, runId, resume } = event.data;
|
|
@@ -220,12 +377,18 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
220
377
|
try {
|
|
221
378
|
await publish({
|
|
222
379
|
channel: `workflow:${this.id}:${runId}`,
|
|
223
|
-
topic:
|
|
380
|
+
topic: event2,
|
|
224
381
|
data
|
|
225
382
|
});
|
|
226
383
|
} catch (err) {
|
|
227
384
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
228
385
|
}
|
|
386
|
+
},
|
|
387
|
+
on: (_event, _callback) => {
|
|
388
|
+
},
|
|
389
|
+
off: (_event, _callback) => {
|
|
390
|
+
},
|
|
391
|
+
once: (_event, _callback) => {
|
|
229
392
|
}
|
|
230
393
|
};
|
|
231
394
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -233,12 +396,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
233
396
|
workflowId: this.id,
|
|
234
397
|
runId,
|
|
235
398
|
graph: this.executionGraph,
|
|
399
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
236
400
|
input: inputData,
|
|
237
401
|
emitter,
|
|
238
402
|
retryConfig: this.retryConfig,
|
|
239
403
|
runtimeContext: new RuntimeContext(),
|
|
240
404
|
// TODO
|
|
241
|
-
resume
|
|
405
|
+
resume,
|
|
406
|
+
abortController: new AbortController()
|
|
242
407
|
});
|
|
243
408
|
return { result, runId };
|
|
244
409
|
}
|
|
@@ -262,20 +427,110 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
262
427
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
263
428
|
}
|
|
264
429
|
};
|
|
265
|
-
function
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
430
|
+
function isAgent(params) {
|
|
431
|
+
return params?.component === "AGENT";
|
|
432
|
+
}
|
|
433
|
+
function isTool(params) {
|
|
434
|
+
return params instanceof Tool;
|
|
435
|
+
}
|
|
436
|
+
function createStep(params) {
|
|
437
|
+
if (isAgent(params)) {
|
|
438
|
+
return {
|
|
439
|
+
id: params.name,
|
|
440
|
+
// @ts-ignore
|
|
441
|
+
inputSchema: z.object({
|
|
442
|
+
prompt: z.string()
|
|
443
|
+
// resourceId: z.string().optional(),
|
|
444
|
+
// threadId: z.string().optional(),
|
|
445
|
+
}),
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
outputSchema: z.object({
|
|
448
|
+
text: z.string()
|
|
449
|
+
}),
|
|
450
|
+
execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
451
|
+
let streamPromise = {};
|
|
452
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
453
|
+
streamPromise.resolve = resolve;
|
|
454
|
+
streamPromise.reject = reject;
|
|
455
|
+
});
|
|
456
|
+
const toolData = {
|
|
457
|
+
name: params.name,
|
|
458
|
+
args: inputData
|
|
459
|
+
};
|
|
460
|
+
await emitter.emit("watch-v2", {
|
|
461
|
+
type: "tool-call-streaming-start",
|
|
462
|
+
...toolData
|
|
463
|
+
});
|
|
464
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
465
|
+
// resourceId: inputData.resourceId,
|
|
466
|
+
// threadId: inputData.threadId,
|
|
467
|
+
runtimeContext,
|
|
468
|
+
onFinish: (result) => {
|
|
469
|
+
streamPromise.resolve(result.text);
|
|
470
|
+
},
|
|
471
|
+
abortSignal
|
|
472
|
+
});
|
|
473
|
+
if (abortSignal.aborted) {
|
|
474
|
+
return abort();
|
|
475
|
+
}
|
|
476
|
+
for await (const chunk of fullStream) {
|
|
477
|
+
switch (chunk.type) {
|
|
478
|
+
case "text-delta":
|
|
479
|
+
await emitter.emit("watch-v2", {
|
|
480
|
+
type: "tool-call-delta",
|
|
481
|
+
...toolData,
|
|
482
|
+
argsTextDelta: chunk.textDelta
|
|
483
|
+
});
|
|
484
|
+
break;
|
|
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;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
text: await streamPromise.promise
|
|
502
|
+
};
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
if (isTool(params)) {
|
|
507
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
508
|
+
throw new Error("Tool must have input and output schemas defined");
|
|
509
|
+
}
|
|
510
|
+
return {
|
|
511
|
+
// TODO: tool probably should have strong id type
|
|
512
|
+
// @ts-ignore
|
|
513
|
+
id: params.id,
|
|
514
|
+
inputSchema: params.inputSchema,
|
|
515
|
+
outputSchema: params.outputSchema,
|
|
516
|
+
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
517
|
+
return params.execute({
|
|
518
|
+
context: inputData,
|
|
519
|
+
mastra,
|
|
520
|
+
runtimeContext
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
return {
|
|
526
|
+
id: params.id,
|
|
527
|
+
description: params.description,
|
|
528
|
+
inputSchema: params.inputSchema,
|
|
529
|
+
outputSchema: params.outputSchema,
|
|
530
|
+
resumeSchema: params.resumeSchema,
|
|
531
|
+
suspendSchema: params.suspendSchema,
|
|
532
|
+
execute: params.execute
|
|
533
|
+
};
|
|
279
534
|
}
|
|
280
535
|
function init(inngest) {
|
|
281
536
|
return {
|
|
@@ -283,8 +538,27 @@ function init(inngest) {
|
|
|
283
538
|
return new InngestWorkflow(params, inngest);
|
|
284
539
|
},
|
|
285
540
|
createStep,
|
|
286
|
-
cloneStep,
|
|
287
|
-
|
|
541
|
+
cloneStep(step, opts) {
|
|
542
|
+
return {
|
|
543
|
+
id: opts.id,
|
|
544
|
+
description: step.description,
|
|
545
|
+
inputSchema: step.inputSchema,
|
|
546
|
+
outputSchema: step.outputSchema,
|
|
547
|
+
execute: step.execute
|
|
548
|
+
};
|
|
549
|
+
},
|
|
550
|
+
cloneWorkflow(workflow, opts) {
|
|
551
|
+
const wf = new Workflow({
|
|
552
|
+
id: opts.id,
|
|
553
|
+
inputSchema: workflow.inputSchema,
|
|
554
|
+
outputSchema: workflow.outputSchema,
|
|
555
|
+
steps: workflow.stepDefs,
|
|
556
|
+
mastra: workflow.mastra
|
|
557
|
+
});
|
|
558
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
559
|
+
wf.commit();
|
|
560
|
+
return wf;
|
|
561
|
+
}
|
|
288
562
|
};
|
|
289
563
|
}
|
|
290
564
|
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
@@ -295,6 +569,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
295
569
|
this.inngestStep = inngestStep;
|
|
296
570
|
this.inngestAttempts = inngestAttempts;
|
|
297
571
|
}
|
|
572
|
+
async execute(params) {
|
|
573
|
+
await params.emitter.emit("watch-v2", {
|
|
574
|
+
type: "start",
|
|
575
|
+
payload: { runId: params.runId }
|
|
576
|
+
});
|
|
577
|
+
const result = await super.execute(params);
|
|
578
|
+
await params.emitter.emit("watch-v2", {
|
|
579
|
+
type: "finish",
|
|
580
|
+
payload: { runId: params.runId }
|
|
581
|
+
});
|
|
582
|
+
return result;
|
|
583
|
+
}
|
|
298
584
|
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
299
585
|
const base = {
|
|
300
586
|
status: lastOutput.status,
|
|
@@ -361,6 +647,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
361
647
|
resume,
|
|
362
648
|
prevOutput,
|
|
363
649
|
emitter,
|
|
650
|
+
abortController,
|
|
364
651
|
runtimeContext
|
|
365
652
|
}) {
|
|
366
653
|
return super.executeStep({
|
|
@@ -372,9 +659,118 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
372
659
|
resume,
|
|
373
660
|
prevOutput,
|
|
374
661
|
emitter,
|
|
662
|
+
abortController,
|
|
375
663
|
runtimeContext
|
|
376
664
|
});
|
|
377
665
|
}
|
|
666
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
667
|
+
// await this.inngestStep.sleep(id, duration);
|
|
668
|
+
// }
|
|
669
|
+
async executeSleep({
|
|
670
|
+
workflowId,
|
|
671
|
+
runId,
|
|
672
|
+
entry,
|
|
673
|
+
prevOutput,
|
|
674
|
+
stepResults,
|
|
675
|
+
emitter,
|
|
676
|
+
abortController,
|
|
677
|
+
runtimeContext
|
|
678
|
+
}) {
|
|
679
|
+
let { duration, fn } = entry;
|
|
680
|
+
if (fn) {
|
|
681
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
682
|
+
return await fn({
|
|
683
|
+
runId,
|
|
684
|
+
mastra: this.mastra,
|
|
685
|
+
runtimeContext,
|
|
686
|
+
inputData: prevOutput,
|
|
687
|
+
runCount: -1,
|
|
688
|
+
getInitData: () => stepResults?.input,
|
|
689
|
+
getStepResult: (step) => {
|
|
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;
|
|
698
|
+
},
|
|
699
|
+
// TODO: this function shouldn't have suspend probably?
|
|
700
|
+
suspend: async (_suspendPayload) => {
|
|
701
|
+
},
|
|
702
|
+
bail: () => {
|
|
703
|
+
},
|
|
704
|
+
abort: () => {
|
|
705
|
+
abortController?.abort();
|
|
706
|
+
},
|
|
707
|
+
[EMITTER_SYMBOL]: emitter,
|
|
708
|
+
engine: { step: this.inngestStep },
|
|
709
|
+
abortSignal: abortController?.signal
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
714
|
+
}
|
|
715
|
+
async executeSleepUntil({
|
|
716
|
+
workflowId,
|
|
717
|
+
runId,
|
|
718
|
+
entry,
|
|
719
|
+
prevOutput,
|
|
720
|
+
stepResults,
|
|
721
|
+
emitter,
|
|
722
|
+
abortController,
|
|
723
|
+
runtimeContext
|
|
724
|
+
}) {
|
|
725
|
+
let { date, fn } = entry;
|
|
726
|
+
if (fn) {
|
|
727
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
728
|
+
return await fn({
|
|
729
|
+
runId,
|
|
730
|
+
mastra: this.mastra,
|
|
731
|
+
runtimeContext,
|
|
732
|
+
inputData: prevOutput,
|
|
733
|
+
runCount: -1,
|
|
734
|
+
getInitData: () => stepResults?.input,
|
|
735
|
+
getStepResult: (step) => {
|
|
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;
|
|
744
|
+
},
|
|
745
|
+
// TODO: this function shouldn't have suspend probably?
|
|
746
|
+
suspend: async (_suspendPayload) => {
|
|
747
|
+
},
|
|
748
|
+
bail: () => {
|
|
749
|
+
},
|
|
750
|
+
abort: () => {
|
|
751
|
+
abortController?.abort();
|
|
752
|
+
},
|
|
753
|
+
[EMITTER_SYMBOL]: emitter,
|
|
754
|
+
engine: { step: this.inngestStep },
|
|
755
|
+
abortSignal: abortController?.signal
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
if (!(date instanceof Date)) {
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
763
|
+
}
|
|
764
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
765
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
766
|
+
event: `user-event-${event}`,
|
|
767
|
+
timeout: timeout ?? 5e3
|
|
768
|
+
});
|
|
769
|
+
if (eventData === null) {
|
|
770
|
+
throw "Timeout waiting for event";
|
|
771
|
+
}
|
|
772
|
+
return eventData?.data;
|
|
773
|
+
}
|
|
378
774
|
async executeStep({
|
|
379
775
|
step,
|
|
380
776
|
stepResults,
|
|
@@ -382,11 +778,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
382
778
|
resume,
|
|
383
779
|
prevOutput,
|
|
384
780
|
emitter,
|
|
781
|
+
abortController,
|
|
385
782
|
runtimeContext
|
|
386
783
|
}) {
|
|
387
|
-
await this.inngestStep.run(
|
|
784
|
+
const startedAt = await this.inngestStep.run(
|
|
388
785
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
389
786
|
async () => {
|
|
787
|
+
const startedAt2 = Date.now();
|
|
390
788
|
await emitter.emit("watch", {
|
|
391
789
|
type: "watch",
|
|
392
790
|
payload: {
|
|
@@ -408,6 +806,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
408
806
|
},
|
|
409
807
|
eventTimestamp: Date.now()
|
|
410
808
|
});
|
|
809
|
+
await emitter.emit("watch-v2", {
|
|
810
|
+
type: "step-start",
|
|
811
|
+
payload: {
|
|
812
|
+
id: step.id,
|
|
813
|
+
status: "running",
|
|
814
|
+
payload: prevOutput,
|
|
815
|
+
startedAt: startedAt2
|
|
816
|
+
}
|
|
817
|
+
});
|
|
818
|
+
return startedAt2;
|
|
411
819
|
}
|
|
412
820
|
);
|
|
413
821
|
if (step instanceof InngestWorkflow) {
|
|
@@ -468,6 +876,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
468
876
|
},
|
|
469
877
|
eventTimestamp: Date.now()
|
|
470
878
|
});
|
|
879
|
+
await emitter.emit("watch-v2", {
|
|
880
|
+
type: "step-result",
|
|
881
|
+
payload: {
|
|
882
|
+
id: step.id,
|
|
883
|
+
status: "failed",
|
|
884
|
+
error: result?.error,
|
|
885
|
+
payload: prevOutput
|
|
886
|
+
}
|
|
887
|
+
});
|
|
471
888
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
472
889
|
} else if (result.status === "suspended") {
|
|
473
890
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -494,6 +911,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
494
911
|
},
|
|
495
912
|
eventTimestamp: Date.now()
|
|
496
913
|
});
|
|
914
|
+
await emitter.emit("watch-v2", {
|
|
915
|
+
type: "step-suspended",
|
|
916
|
+
payload: {
|
|
917
|
+
id: step.id,
|
|
918
|
+
status: "suspended"
|
|
919
|
+
}
|
|
920
|
+
});
|
|
497
921
|
return {
|
|
498
922
|
executionContext,
|
|
499
923
|
result: {
|
|
@@ -544,6 +968,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
544
968
|
},
|
|
545
969
|
eventTimestamp: Date.now()
|
|
546
970
|
});
|
|
971
|
+
await emitter.emit("watch-v2", {
|
|
972
|
+
type: "step-result",
|
|
973
|
+
payload: {
|
|
974
|
+
id: step.id,
|
|
975
|
+
status: "success",
|
|
976
|
+
output: result?.result
|
|
977
|
+
}
|
|
978
|
+
});
|
|
979
|
+
await emitter.emit("watch-v2", {
|
|
980
|
+
type: "step-finish",
|
|
981
|
+
payload: {
|
|
982
|
+
id: step.id,
|
|
983
|
+
metadata: {}
|
|
984
|
+
}
|
|
985
|
+
});
|
|
547
986
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
548
987
|
}
|
|
549
988
|
);
|
|
@@ -553,8 +992,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
553
992
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
554
993
|
let execResults;
|
|
555
994
|
let suspended;
|
|
995
|
+
let bailed;
|
|
556
996
|
try {
|
|
557
997
|
const result = await step.execute({
|
|
998
|
+
runId: executionContext.runId,
|
|
558
999
|
mastra: this.mastra,
|
|
559
1000
|
runtimeContext,
|
|
560
1001
|
inputData: prevOutput,
|
|
@@ -571,20 +1012,54 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
571
1012
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
572
1013
|
suspended = { payload: suspendPayload };
|
|
573
1014
|
},
|
|
1015
|
+
bail: (result2) => {
|
|
1016
|
+
bailed = { payload: result2 };
|
|
1017
|
+
},
|
|
574
1018
|
resume: {
|
|
575
1019
|
steps: resume?.steps?.slice(1) || [],
|
|
576
1020
|
resumePayload: resume?.resumePayload,
|
|
577
1021
|
// @ts-ignore
|
|
578
1022
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
579
1023
|
},
|
|
580
|
-
emitter
|
|
1024
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1025
|
+
engine: {
|
|
1026
|
+
step: this.inngestStep
|
|
1027
|
+
},
|
|
1028
|
+
abortSignal: abortController.signal
|
|
581
1029
|
});
|
|
582
|
-
|
|
1030
|
+
const endedAt = Date.now();
|
|
1031
|
+
execResults = {
|
|
1032
|
+
status: "success",
|
|
1033
|
+
output: result,
|
|
1034
|
+
startedAt,
|
|
1035
|
+
endedAt,
|
|
1036
|
+
payload: prevOutput,
|
|
1037
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1038
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1039
|
+
};
|
|
583
1040
|
} catch (e) {
|
|
584
|
-
execResults = {
|
|
1041
|
+
execResults = {
|
|
1042
|
+
status: "failed",
|
|
1043
|
+
payload: prevOutput,
|
|
1044
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1045
|
+
endedAt: Date.now(),
|
|
1046
|
+
startedAt,
|
|
1047
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1048
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1049
|
+
};
|
|
585
1050
|
}
|
|
586
1051
|
if (suspended) {
|
|
587
|
-
execResults = {
|
|
1052
|
+
execResults = {
|
|
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 };
|
|
588
1063
|
}
|
|
589
1064
|
if (execResults.status === "failed") {
|
|
590
1065
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
@@ -596,18 +1071,41 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
596
1071
|
payload: {
|
|
597
1072
|
currentStep: {
|
|
598
1073
|
id: step.id,
|
|
599
|
-
|
|
600
|
-
output: execResults.output
|
|
1074
|
+
...execResults
|
|
601
1075
|
},
|
|
602
1076
|
workflowState: {
|
|
603
1077
|
status: "running",
|
|
604
|
-
steps: stepResults,
|
|
1078
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
605
1079
|
result: null,
|
|
606
1080
|
error: null
|
|
607
1081
|
}
|
|
608
1082
|
},
|
|
609
1083
|
eventTimestamp: Date.now()
|
|
610
1084
|
});
|
|
1085
|
+
if (execResults.status === "suspended") {
|
|
1086
|
+
await emitter.emit("watch-v2", {
|
|
1087
|
+
type: "step-suspended",
|
|
1088
|
+
payload: {
|
|
1089
|
+
id: step.id,
|
|
1090
|
+
...execResults
|
|
1091
|
+
}
|
|
1092
|
+
});
|
|
1093
|
+
} else {
|
|
1094
|
+
await emitter.emit("watch-v2", {
|
|
1095
|
+
type: "step-result",
|
|
1096
|
+
payload: {
|
|
1097
|
+
id: step.id,
|
|
1098
|
+
...execResults
|
|
1099
|
+
}
|
|
1100
|
+
});
|
|
1101
|
+
await emitter.emit("watch-v2", {
|
|
1102
|
+
type: "step-finish",
|
|
1103
|
+
payload: {
|
|
1104
|
+
id: step.id,
|
|
1105
|
+
metadata: {}
|
|
1106
|
+
}
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
611
1109
|
return { result: execResults, executionContext, stepResults };
|
|
612
1110
|
});
|
|
613
1111
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
@@ -618,7 +1116,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
618
1116
|
workflowId,
|
|
619
1117
|
runId,
|
|
620
1118
|
stepResults,
|
|
621
|
-
executionContext
|
|
1119
|
+
executionContext,
|
|
1120
|
+
serializedStepGraph,
|
|
1121
|
+
workflowStatus,
|
|
1122
|
+
result,
|
|
1123
|
+
error
|
|
622
1124
|
}) {
|
|
623
1125
|
await this.inngestStep.run(
|
|
624
1126
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -632,6 +1134,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
632
1134
|
context: stepResults,
|
|
633
1135
|
activePaths: [],
|
|
634
1136
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1137
|
+
serializedStepGraph,
|
|
1138
|
+
status: workflowStatus,
|
|
1139
|
+
result,
|
|
1140
|
+
error,
|
|
635
1141
|
// @ts-ignore
|
|
636
1142
|
timestamp: Date.now()
|
|
637
1143
|
}
|
|
@@ -646,9 +1152,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
646
1152
|
prevOutput,
|
|
647
1153
|
prevStep,
|
|
648
1154
|
stepResults,
|
|
1155
|
+
serializedStepGraph,
|
|
649
1156
|
resume,
|
|
650
1157
|
executionContext,
|
|
651
1158
|
emitter,
|
|
1159
|
+
abortController,
|
|
652
1160
|
runtimeContext
|
|
653
1161
|
}) {
|
|
654
1162
|
let execResults;
|
|
@@ -657,8 +1165,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
657
1165
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
658
1166
|
try {
|
|
659
1167
|
const result = await cond({
|
|
1168
|
+
runId,
|
|
660
1169
|
mastra: this.mastra,
|
|
661
1170
|
runtimeContext,
|
|
1171
|
+
runCount: -1,
|
|
662
1172
|
inputData: prevOutput,
|
|
663
1173
|
getInitData: () => stepResults?.input,
|
|
664
1174
|
getStepResult: (step) => {
|
|
@@ -674,7 +1184,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
674
1184
|
// TODO: this function shouldn't have suspend probably?
|
|
675
1185
|
suspend: async (_suspendPayload) => {
|
|
676
1186
|
},
|
|
677
|
-
|
|
1187
|
+
bail: () => {
|
|
1188
|
+
},
|
|
1189
|
+
abort: () => {
|
|
1190
|
+
abortController.abort();
|
|
1191
|
+
},
|
|
1192
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1193
|
+
engine: {
|
|
1194
|
+
step: this.inngestStep
|
|
1195
|
+
},
|
|
1196
|
+
abortSignal: abortController.signal
|
|
678
1197
|
});
|
|
679
1198
|
return result ? index : null;
|
|
680
1199
|
} catch (e) {
|
|
@@ -693,6 +1212,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
693
1212
|
prevStep,
|
|
694
1213
|
stepResults,
|
|
695
1214
|
resume,
|
|
1215
|
+
serializedStepGraph,
|
|
696
1216
|
executionContext: {
|
|
697
1217
|
workflowId,
|
|
698
1218
|
runId,
|
|
@@ -702,21 +1222,22 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
702
1222
|
executionSpan: executionContext.executionSpan
|
|
703
1223
|
},
|
|
704
1224
|
emitter,
|
|
1225
|
+
abortController,
|
|
705
1226
|
runtimeContext
|
|
706
1227
|
})
|
|
707
1228
|
)
|
|
708
1229
|
);
|
|
709
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
710
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1230
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1231
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
711
1232
|
if (hasFailed) {
|
|
712
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1233
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
713
1234
|
} else if (hasSuspended) {
|
|
714
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1235
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
715
1236
|
} else {
|
|
716
1237
|
execResults = {
|
|
717
1238
|
status: "success",
|
|
718
1239
|
output: results.reduce((acc, result, index) => {
|
|
719
|
-
if (result.status === "success") {
|
|
1240
|
+
if (result.result.status === "success") {
|
|
720
1241
|
acc[stepsToRun[index].step.id] = result.output;
|
|
721
1242
|
}
|
|
722
1243
|
return acc;
|
|
@@ -727,4 +1248,4 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
727
1248
|
}
|
|
728
1249
|
};
|
|
729
1250
|
|
|
730
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
|
|
1251
|
+
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|