@mastra/inngest 0.0.0-generate-message-id-20250512171942 → 0.0.0-http-transporter-20250702160118
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 +431 -3
- package/dist/_tsup-dts-rollup.d.cts +136 -65
- package/dist/_tsup-dts-rollup.d.ts +136 -65
- package/dist/index.cjs +487 -59
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +484 -57
- package/docker-compose.yaml +3 -3
- package/package.json +22 -17
- package/src/index.test.ts +5026 -3333
- package/src/index.ts +733 -103
- package/vitest.config.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -1,19 +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';
|
|
6
|
+
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
5
7
|
import { serve as serve$1 } from 'inngest/hono';
|
|
8
|
+
import { z } from 'zod';
|
|
6
9
|
|
|
7
10
|
// src/index.ts
|
|
8
11
|
function serve({ mastra, inngest }) {
|
|
9
|
-
const wfs = mastra.
|
|
10
|
-
const functions =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const wfs = mastra.getWorkflows();
|
|
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
|
+
);
|
|
17
24
|
return serve$1({
|
|
18
25
|
client: inngest,
|
|
19
26
|
functions
|
|
@@ -21,14 +28,16 @@ function serve({ mastra, inngest }) {
|
|
|
21
28
|
}
|
|
22
29
|
var InngestRun = class extends Run {
|
|
23
30
|
inngest;
|
|
31
|
+
serializedStepGraph;
|
|
24
32
|
#mastra;
|
|
25
33
|
constructor(params, inngest) {
|
|
26
34
|
super(params);
|
|
27
35
|
this.inngest = inngest;
|
|
36
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
28
37
|
this.#mastra = params.mastra;
|
|
29
38
|
}
|
|
30
39
|
async getRuns(eventId) {
|
|
31
|
-
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`, {
|
|
32
41
|
headers: {
|
|
33
42
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
34
43
|
}
|
|
@@ -38,15 +47,50 @@ var InngestRun = class extends Run {
|
|
|
38
47
|
}
|
|
39
48
|
async getRunOutput(eventId) {
|
|
40
49
|
let runs = await this.getRuns(eventId);
|
|
41
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
50
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
42
51
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
43
52
|
runs = await this.getRuns(eventId);
|
|
44
|
-
if (runs?.[0]?.status === "Failed"
|
|
53
|
+
if (runs?.[0]?.status === "Failed") {
|
|
54
|
+
console.log("run", runs?.[0]);
|
|
45
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" } } };
|
|
46
62
|
}
|
|
47
63
|
}
|
|
48
64
|
return runs?.[0];
|
|
49
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
|
+
}
|
|
50
94
|
async start({
|
|
51
95
|
inputData
|
|
52
96
|
}) {
|
|
@@ -55,11 +99,13 @@ var InngestRun = class extends Run {
|
|
|
55
99
|
runId: this.runId,
|
|
56
100
|
snapshot: {
|
|
57
101
|
runId: this.runId,
|
|
102
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
58
103
|
value: {},
|
|
59
104
|
context: {},
|
|
60
105
|
activePaths: [],
|
|
61
106
|
suspendedPaths: {},
|
|
62
|
-
timestamp: Date.now()
|
|
107
|
+
timestamp: Date.now(),
|
|
108
|
+
status: "running"
|
|
63
109
|
}
|
|
64
110
|
});
|
|
65
111
|
const eventOutput = await this.inngest.send({
|
|
@@ -78,10 +124,23 @@ var InngestRun = class extends Run {
|
|
|
78
124
|
if (result.status === "failed") {
|
|
79
125
|
result.error = new Error(result.error);
|
|
80
126
|
}
|
|
81
|
-
|
|
127
|
+
if (result.status !== "suspended") {
|
|
128
|
+
this.cleanup?.();
|
|
129
|
+
}
|
|
82
130
|
return result;
|
|
83
131
|
}
|
|
84
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) {
|
|
85
144
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
86
145
|
(step) => typeof step === "string" ? step : step?.id
|
|
87
146
|
);
|
|
@@ -115,27 +174,62 @@ var InngestRun = class extends Run {
|
|
|
115
174
|
}
|
|
116
175
|
return result;
|
|
117
176
|
}
|
|
118
|
-
watch(cb) {
|
|
177
|
+
watch(cb, type = "watch") {
|
|
178
|
+
let active = true;
|
|
119
179
|
const streamPromise = subscribe(
|
|
120
180
|
{
|
|
121
181
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
122
|
-
topics: [
|
|
182
|
+
topics: [type],
|
|
123
183
|
app: this.inngest
|
|
124
184
|
},
|
|
125
185
|
(message) => {
|
|
126
|
-
|
|
186
|
+
if (active) {
|
|
187
|
+
cb(message.data);
|
|
188
|
+
}
|
|
127
189
|
}
|
|
128
190
|
);
|
|
129
191
|
return () => {
|
|
130
|
-
|
|
131
|
-
|
|
192
|
+
active = false;
|
|
193
|
+
streamPromise.then(async (stream) => {
|
|
194
|
+
return stream.cancel();
|
|
132
195
|
}).catch((err) => {
|
|
133
196
|
console.error(err);
|
|
134
197
|
});
|
|
135
198
|
};
|
|
136
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
|
+
}
|
|
137
231
|
};
|
|
138
|
-
var InngestWorkflow = class _InngestWorkflow extends
|
|
232
|
+
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
139
233
|
#mastra;
|
|
140
234
|
inngest;
|
|
141
235
|
function;
|
|
@@ -156,11 +250,32 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
156
250
|
const storage = this.#mastra?.getStorage();
|
|
157
251
|
if (!storage) {
|
|
158
252
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
159
|
-
return null;
|
|
253
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
160
254
|
}
|
|
161
255
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
162
256
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
163
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
|
+
}
|
|
164
279
|
__registerMastra(mastra) {
|
|
165
280
|
this.#mastra = mastra;
|
|
166
281
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -187,6 +302,7 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
187
302
|
runId: runIdToUse,
|
|
188
303
|
executionEngine: this.executionEngine,
|
|
189
304
|
executionGraph: this.executionGraph,
|
|
305
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
190
306
|
mastra: this.#mastra,
|
|
191
307
|
retryConfig: this.retryConfig,
|
|
192
308
|
cleanup: () => this.runs.delete(runIdToUse)
|
|
@@ -196,13 +312,55 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
196
312
|
this.runs.set(runIdToUse, run);
|
|
197
313
|
return run;
|
|
198
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
|
+
}
|
|
199
353
|
getFunction() {
|
|
200
354
|
if (this.function) {
|
|
201
355
|
return this.function;
|
|
202
356
|
}
|
|
203
357
|
this.function = this.inngest.createFunction(
|
|
204
|
-
|
|
205
|
-
|
|
358
|
+
{
|
|
359
|
+
id: `workflow.${this.id}`,
|
|
360
|
+
// @ts-ignore
|
|
361
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
362
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
363
|
+
},
|
|
206
364
|
{ event: `workflow.${this.id}` },
|
|
207
365
|
async ({ event, step, attempt, publish }) => {
|
|
208
366
|
let { inputData, runId, resume } = event.data;
|
|
@@ -219,12 +377,18 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
219
377
|
try {
|
|
220
378
|
await publish({
|
|
221
379
|
channel: `workflow:${this.id}:${runId}`,
|
|
222
|
-
topic:
|
|
380
|
+
topic: event2,
|
|
223
381
|
data
|
|
224
382
|
});
|
|
225
383
|
} catch (err) {
|
|
226
384
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
227
385
|
}
|
|
386
|
+
},
|
|
387
|
+
on: (_event, _callback) => {
|
|
388
|
+
},
|
|
389
|
+
off: (_event, _callback) => {
|
|
390
|
+
},
|
|
391
|
+
once: (_event, _callback) => {
|
|
228
392
|
}
|
|
229
393
|
};
|
|
230
394
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -232,12 +396,14 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
232
396
|
workflowId: this.id,
|
|
233
397
|
runId,
|
|
234
398
|
graph: this.executionGraph,
|
|
399
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
235
400
|
input: inputData,
|
|
236
401
|
emitter,
|
|
237
402
|
retryConfig: this.retryConfig,
|
|
238
403
|
runtimeContext: new RuntimeContext(),
|
|
239
404
|
// TODO
|
|
240
|
-
resume
|
|
405
|
+
resume,
|
|
406
|
+
abortController: new AbortController()
|
|
241
407
|
});
|
|
242
408
|
return { result, runId };
|
|
243
409
|
}
|
|
@@ -261,20 +427,110 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
261
427
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
262
428
|
}
|
|
263
429
|
};
|
|
264
|
-
function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
};
|
|
278
534
|
}
|
|
279
535
|
function init(inngest) {
|
|
280
536
|
return {
|
|
@@ -282,8 +538,27 @@ function init(inngest) {
|
|
|
282
538
|
return new InngestWorkflow(params, inngest);
|
|
283
539
|
},
|
|
284
540
|
createStep,
|
|
285
|
-
cloneStep,
|
|
286
|
-
|
|
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
|
+
}
|
|
287
562
|
};
|
|
288
563
|
}
|
|
289
564
|
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
@@ -294,6 +569,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
294
569
|
this.inngestStep = inngestStep;
|
|
295
570
|
this.inngestAttempts = inngestAttempts;
|
|
296
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
|
+
}
|
|
297
584
|
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
298
585
|
const base = {
|
|
299
586
|
status: lastOutput.status,
|
|
@@ -360,6 +647,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
360
647
|
resume,
|
|
361
648
|
prevOutput,
|
|
362
649
|
emitter,
|
|
650
|
+
abortController,
|
|
363
651
|
runtimeContext
|
|
364
652
|
}) {
|
|
365
653
|
return super.executeStep({
|
|
@@ -371,9 +659,23 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
371
659
|
resume,
|
|
372
660
|
prevOutput,
|
|
373
661
|
emitter,
|
|
662
|
+
abortController,
|
|
374
663
|
runtimeContext
|
|
375
664
|
});
|
|
376
665
|
}
|
|
666
|
+
async executeSleep({ id, duration }) {
|
|
667
|
+
await this.inngestStep.sleep(id, duration);
|
|
668
|
+
}
|
|
669
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
670
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
671
|
+
event: `user-event-${event}`,
|
|
672
|
+
timeout: timeout ?? 5e3
|
|
673
|
+
});
|
|
674
|
+
if (eventData === null) {
|
|
675
|
+
throw "Timeout waiting for event";
|
|
676
|
+
}
|
|
677
|
+
return eventData?.data;
|
|
678
|
+
}
|
|
377
679
|
async executeStep({
|
|
378
680
|
step,
|
|
379
681
|
stepResults,
|
|
@@ -381,11 +683,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
381
683
|
resume,
|
|
382
684
|
prevOutput,
|
|
383
685
|
emitter,
|
|
686
|
+
abortController,
|
|
384
687
|
runtimeContext
|
|
385
688
|
}) {
|
|
386
|
-
await this.inngestStep.run(
|
|
689
|
+
const startedAt = await this.inngestStep.run(
|
|
387
690
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
388
691
|
async () => {
|
|
692
|
+
const startedAt2 = Date.now();
|
|
389
693
|
await emitter.emit("watch", {
|
|
390
694
|
type: "watch",
|
|
391
695
|
payload: {
|
|
@@ -407,6 +711,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
407
711
|
},
|
|
408
712
|
eventTimestamp: Date.now()
|
|
409
713
|
});
|
|
714
|
+
await emitter.emit("watch-v2", {
|
|
715
|
+
type: "step-start",
|
|
716
|
+
payload: {
|
|
717
|
+
id: step.id,
|
|
718
|
+
status: "running",
|
|
719
|
+
payload: prevOutput,
|
|
720
|
+
startedAt: startedAt2
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
return startedAt2;
|
|
410
724
|
}
|
|
411
725
|
);
|
|
412
726
|
if (step instanceof InngestWorkflow) {
|
|
@@ -467,6 +781,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
467
781
|
},
|
|
468
782
|
eventTimestamp: Date.now()
|
|
469
783
|
});
|
|
784
|
+
await emitter.emit("watch-v2", {
|
|
785
|
+
type: "step-result",
|
|
786
|
+
payload: {
|
|
787
|
+
id: step.id,
|
|
788
|
+
status: "failed",
|
|
789
|
+
error: result?.error,
|
|
790
|
+
payload: prevOutput
|
|
791
|
+
}
|
|
792
|
+
});
|
|
470
793
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
471
794
|
} else if (result.status === "suspended") {
|
|
472
795
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -493,6 +816,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
493
816
|
},
|
|
494
817
|
eventTimestamp: Date.now()
|
|
495
818
|
});
|
|
819
|
+
await emitter.emit("watch-v2", {
|
|
820
|
+
type: "step-suspended",
|
|
821
|
+
payload: {
|
|
822
|
+
id: step.id,
|
|
823
|
+
status: "suspended"
|
|
824
|
+
}
|
|
825
|
+
});
|
|
496
826
|
return {
|
|
497
827
|
executionContext,
|
|
498
828
|
result: {
|
|
@@ -543,6 +873,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
543
873
|
},
|
|
544
874
|
eventTimestamp: Date.now()
|
|
545
875
|
});
|
|
876
|
+
await emitter.emit("watch-v2", {
|
|
877
|
+
type: "step-result",
|
|
878
|
+
payload: {
|
|
879
|
+
id: step.id,
|
|
880
|
+
status: "success",
|
|
881
|
+
output: result?.result
|
|
882
|
+
}
|
|
883
|
+
});
|
|
884
|
+
await emitter.emit("watch-v2", {
|
|
885
|
+
type: "step-finish",
|
|
886
|
+
payload: {
|
|
887
|
+
id: step.id,
|
|
888
|
+
metadata: {}
|
|
889
|
+
}
|
|
890
|
+
});
|
|
546
891
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
547
892
|
}
|
|
548
893
|
);
|
|
@@ -552,8 +897,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
552
897
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
553
898
|
let execResults;
|
|
554
899
|
let suspended;
|
|
900
|
+
let bailed;
|
|
555
901
|
try {
|
|
556
902
|
const result = await step.execute({
|
|
903
|
+
runId: executionContext.runId,
|
|
557
904
|
mastra: this.mastra,
|
|
558
905
|
runtimeContext,
|
|
559
906
|
inputData: prevOutput,
|
|
@@ -570,20 +917,54 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
570
917
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
571
918
|
suspended = { payload: suspendPayload };
|
|
572
919
|
},
|
|
920
|
+
bail: (result2) => {
|
|
921
|
+
bailed = { payload: result2 };
|
|
922
|
+
},
|
|
573
923
|
resume: {
|
|
574
924
|
steps: resume?.steps?.slice(1) || [],
|
|
575
925
|
resumePayload: resume?.resumePayload,
|
|
576
926
|
// @ts-ignore
|
|
577
927
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
578
928
|
},
|
|
579
|
-
emitter
|
|
929
|
+
[EMITTER_SYMBOL]: emitter,
|
|
930
|
+
engine: {
|
|
931
|
+
step: this.inngestStep
|
|
932
|
+
},
|
|
933
|
+
abortSignal: abortController.signal
|
|
580
934
|
});
|
|
581
|
-
|
|
935
|
+
const endedAt = Date.now();
|
|
936
|
+
execResults = {
|
|
937
|
+
status: "success",
|
|
938
|
+
output: result,
|
|
939
|
+
startedAt,
|
|
940
|
+
endedAt,
|
|
941
|
+
payload: prevOutput,
|
|
942
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
943
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
944
|
+
};
|
|
582
945
|
} catch (e) {
|
|
583
|
-
execResults = {
|
|
946
|
+
execResults = {
|
|
947
|
+
status: "failed",
|
|
948
|
+
payload: prevOutput,
|
|
949
|
+
error: e instanceof Error ? e.message : String(e),
|
|
950
|
+
endedAt: Date.now(),
|
|
951
|
+
startedAt,
|
|
952
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
953
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
954
|
+
};
|
|
584
955
|
}
|
|
585
956
|
if (suspended) {
|
|
586
|
-
execResults = {
|
|
957
|
+
execResults = {
|
|
958
|
+
status: "suspended",
|
|
959
|
+
suspendedPayload: suspended.payload,
|
|
960
|
+
payload: prevOutput,
|
|
961
|
+
suspendedAt: Date.now(),
|
|
962
|
+
startedAt,
|
|
963
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
964
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
965
|
+
};
|
|
966
|
+
} else if (bailed) {
|
|
967
|
+
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
587
968
|
}
|
|
588
969
|
if (execResults.status === "failed") {
|
|
589
970
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
@@ -595,18 +976,41 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
595
976
|
payload: {
|
|
596
977
|
currentStep: {
|
|
597
978
|
id: step.id,
|
|
598
|
-
|
|
599
|
-
output: execResults.output
|
|
979
|
+
...execResults
|
|
600
980
|
},
|
|
601
981
|
workflowState: {
|
|
602
982
|
status: "running",
|
|
603
|
-
steps: stepResults,
|
|
983
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
604
984
|
result: null,
|
|
605
985
|
error: null
|
|
606
986
|
}
|
|
607
987
|
},
|
|
608
988
|
eventTimestamp: Date.now()
|
|
609
989
|
});
|
|
990
|
+
if (execResults.status === "suspended") {
|
|
991
|
+
await emitter.emit("watch-v2", {
|
|
992
|
+
type: "step-suspended",
|
|
993
|
+
payload: {
|
|
994
|
+
id: step.id,
|
|
995
|
+
...execResults
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
} else {
|
|
999
|
+
await emitter.emit("watch-v2", {
|
|
1000
|
+
type: "step-result",
|
|
1001
|
+
payload: {
|
|
1002
|
+
id: step.id,
|
|
1003
|
+
...execResults
|
|
1004
|
+
}
|
|
1005
|
+
});
|
|
1006
|
+
await emitter.emit("watch-v2", {
|
|
1007
|
+
type: "step-finish",
|
|
1008
|
+
payload: {
|
|
1009
|
+
id: step.id,
|
|
1010
|
+
metadata: {}
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
610
1014
|
return { result: execResults, executionContext, stepResults };
|
|
611
1015
|
});
|
|
612
1016
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
@@ -617,7 +1021,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
617
1021
|
workflowId,
|
|
618
1022
|
runId,
|
|
619
1023
|
stepResults,
|
|
620
|
-
executionContext
|
|
1024
|
+
executionContext,
|
|
1025
|
+
serializedStepGraph,
|
|
1026
|
+
workflowStatus,
|
|
1027
|
+
result,
|
|
1028
|
+
error
|
|
621
1029
|
}) {
|
|
622
1030
|
await this.inngestStep.run(
|
|
623
1031
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -631,6 +1039,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
631
1039
|
context: stepResults,
|
|
632
1040
|
activePaths: [],
|
|
633
1041
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1042
|
+
serializedStepGraph,
|
|
1043
|
+
status: workflowStatus,
|
|
1044
|
+
result,
|
|
1045
|
+
error,
|
|
634
1046
|
// @ts-ignore
|
|
635
1047
|
timestamp: Date.now()
|
|
636
1048
|
}
|
|
@@ -645,9 +1057,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
645
1057
|
prevOutput,
|
|
646
1058
|
prevStep,
|
|
647
1059
|
stepResults,
|
|
1060
|
+
serializedStepGraph,
|
|
648
1061
|
resume,
|
|
649
1062
|
executionContext,
|
|
650
1063
|
emitter,
|
|
1064
|
+
abortController,
|
|
651
1065
|
runtimeContext
|
|
652
1066
|
}) {
|
|
653
1067
|
let execResults;
|
|
@@ -656,8 +1070,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
656
1070
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
657
1071
|
try {
|
|
658
1072
|
const result = await cond({
|
|
1073
|
+
runId,
|
|
659
1074
|
mastra: this.mastra,
|
|
660
1075
|
runtimeContext,
|
|
1076
|
+
runCount: -1,
|
|
661
1077
|
inputData: prevOutput,
|
|
662
1078
|
getInitData: () => stepResults?.input,
|
|
663
1079
|
getStepResult: (step) => {
|
|
@@ -673,7 +1089,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
673
1089
|
// TODO: this function shouldn't have suspend probably?
|
|
674
1090
|
suspend: async (_suspendPayload) => {
|
|
675
1091
|
},
|
|
676
|
-
|
|
1092
|
+
bail: () => {
|
|
1093
|
+
},
|
|
1094
|
+
abort: () => {
|
|
1095
|
+
abortController.abort();
|
|
1096
|
+
},
|
|
1097
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1098
|
+
engine: {
|
|
1099
|
+
step: this.inngestStep
|
|
1100
|
+
},
|
|
1101
|
+
abortSignal: abortController.signal
|
|
677
1102
|
});
|
|
678
1103
|
return result ? index : null;
|
|
679
1104
|
} catch (e) {
|
|
@@ -692,6 +1117,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
692
1117
|
prevStep,
|
|
693
1118
|
stepResults,
|
|
694
1119
|
resume,
|
|
1120
|
+
serializedStepGraph,
|
|
695
1121
|
executionContext: {
|
|
696
1122
|
workflowId,
|
|
697
1123
|
runId,
|
|
@@ -701,21 +1127,22 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
701
1127
|
executionSpan: executionContext.executionSpan
|
|
702
1128
|
},
|
|
703
1129
|
emitter,
|
|
1130
|
+
abortController,
|
|
704
1131
|
runtimeContext
|
|
705
1132
|
})
|
|
706
1133
|
)
|
|
707
1134
|
);
|
|
708
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
709
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1135
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1136
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
710
1137
|
if (hasFailed) {
|
|
711
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1138
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
712
1139
|
} else if (hasSuspended) {
|
|
713
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1140
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
714
1141
|
} else {
|
|
715
1142
|
execResults = {
|
|
716
1143
|
status: "success",
|
|
717
1144
|
output: results.reduce((acc, result, index) => {
|
|
718
|
-
if (result.status === "success") {
|
|
1145
|
+
if (result.result.status === "success") {
|
|
719
1146
|
acc[stepsToRun[index].step.id] = result.output;
|
|
720
1147
|
}
|
|
721
1148
|
return acc;
|
|
@@ -726,4 +1153,4 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
726
1153
|
}
|
|
727
1154
|
};
|
|
728
1155
|
|
|
729
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
|
|
1156
|
+
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|