@mastra/inngest 0.0.0-redis-cloud-transporter-20250508203756 → 0.0.0-share-agent-metadata-with-cloud-20250718110128
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 +595 -2
- package/LICENSE.md +11 -42
- package/dist/_tsup-dts-rollup.d.cts +179 -63
- package/dist/_tsup-dts-rollup.d.ts +179 -63
- package/dist/index.cjs +582 -59
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +579 -57
- package/docker-compose.yaml +3 -3
- package/package.json +23 -18
- package/src/index.test.ts +5809 -3549
- package/src/index.ts +884 -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,118 @@ 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 }: { 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
|
+
}
|
|
377
774
|
async executeStep({
|
|
378
775
|
step,
|
|
379
776
|
stepResults,
|
|
@@ -381,11 +778,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
381
778
|
resume,
|
|
382
779
|
prevOutput,
|
|
383
780
|
emitter,
|
|
781
|
+
abortController,
|
|
384
782
|
runtimeContext
|
|
385
783
|
}) {
|
|
386
|
-
await this.inngestStep.run(
|
|
784
|
+
const startedAt = await this.inngestStep.run(
|
|
387
785
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
388
786
|
async () => {
|
|
787
|
+
const startedAt2 = Date.now();
|
|
389
788
|
await emitter.emit("watch", {
|
|
390
789
|
type: "watch",
|
|
391
790
|
payload: {
|
|
@@ -407,6 +806,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
407
806
|
},
|
|
408
807
|
eventTimestamp: Date.now()
|
|
409
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;
|
|
410
819
|
}
|
|
411
820
|
);
|
|
412
821
|
if (step instanceof InngestWorkflow) {
|
|
@@ -467,6 +876,15 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
467
876
|
},
|
|
468
877
|
eventTimestamp: Date.now()
|
|
469
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
|
+
});
|
|
470
888
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
471
889
|
} else if (result.status === "suspended") {
|
|
472
890
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -493,6 +911,13 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
493
911
|
},
|
|
494
912
|
eventTimestamp: Date.now()
|
|
495
913
|
});
|
|
914
|
+
await emitter.emit("watch-v2", {
|
|
915
|
+
type: "step-suspended",
|
|
916
|
+
payload: {
|
|
917
|
+
id: step.id,
|
|
918
|
+
status: "suspended"
|
|
919
|
+
}
|
|
920
|
+
});
|
|
496
921
|
return {
|
|
497
922
|
executionContext,
|
|
498
923
|
result: {
|
|
@@ -543,6 +968,21 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
543
968
|
},
|
|
544
969
|
eventTimestamp: Date.now()
|
|
545
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
|
+
});
|
|
546
986
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
547
987
|
}
|
|
548
988
|
);
|
|
@@ -552,8 +992,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
552
992
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
553
993
|
let execResults;
|
|
554
994
|
let suspended;
|
|
995
|
+
let bailed;
|
|
555
996
|
try {
|
|
556
997
|
const result = await step.execute({
|
|
998
|
+
runId: executionContext.runId,
|
|
557
999
|
mastra: this.mastra,
|
|
558
1000
|
runtimeContext,
|
|
559
1001
|
inputData: prevOutput,
|
|
@@ -570,20 +1012,54 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
570
1012
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
571
1013
|
suspended = { payload: suspendPayload };
|
|
572
1014
|
},
|
|
1015
|
+
bail: (result2) => {
|
|
1016
|
+
bailed = { payload: result2 };
|
|
1017
|
+
},
|
|
573
1018
|
resume: {
|
|
574
1019
|
steps: resume?.steps?.slice(1) || [],
|
|
575
1020
|
resumePayload: resume?.resumePayload,
|
|
576
1021
|
// @ts-ignore
|
|
577
1022
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
578
1023
|
},
|
|
579
|
-
emitter
|
|
1024
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1025
|
+
engine: {
|
|
1026
|
+
step: this.inngestStep
|
|
1027
|
+
},
|
|
1028
|
+
abortSignal: abortController.signal
|
|
580
1029
|
});
|
|
581
|
-
|
|
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
|
+
};
|
|
582
1040
|
} catch (e) {
|
|
583
|
-
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
|
+
};
|
|
584
1050
|
}
|
|
585
1051
|
if (suspended) {
|
|
586
|
-
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 };
|
|
587
1063
|
}
|
|
588
1064
|
if (execResults.status === "failed") {
|
|
589
1065
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
@@ -595,18 +1071,41 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
595
1071
|
payload: {
|
|
596
1072
|
currentStep: {
|
|
597
1073
|
id: step.id,
|
|
598
|
-
|
|
599
|
-
output: execResults.output
|
|
1074
|
+
...execResults
|
|
600
1075
|
},
|
|
601
1076
|
workflowState: {
|
|
602
1077
|
status: "running",
|
|
603
|
-
steps: stepResults,
|
|
1078
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
604
1079
|
result: null,
|
|
605
1080
|
error: null
|
|
606
1081
|
}
|
|
607
1082
|
},
|
|
608
1083
|
eventTimestamp: Date.now()
|
|
609
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
|
+
}
|
|
610
1109
|
return { result: execResults, executionContext, stepResults };
|
|
611
1110
|
});
|
|
612
1111
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
@@ -617,7 +1116,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
617
1116
|
workflowId,
|
|
618
1117
|
runId,
|
|
619
1118
|
stepResults,
|
|
620
|
-
executionContext
|
|
1119
|
+
executionContext,
|
|
1120
|
+
serializedStepGraph,
|
|
1121
|
+
workflowStatus,
|
|
1122
|
+
result,
|
|
1123
|
+
error
|
|
621
1124
|
}) {
|
|
622
1125
|
await this.inngestStep.run(
|
|
623
1126
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -631,6 +1134,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
631
1134
|
context: stepResults,
|
|
632
1135
|
activePaths: [],
|
|
633
1136
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1137
|
+
serializedStepGraph,
|
|
1138
|
+
status: workflowStatus,
|
|
1139
|
+
result,
|
|
1140
|
+
error,
|
|
634
1141
|
// @ts-ignore
|
|
635
1142
|
timestamp: Date.now()
|
|
636
1143
|
}
|
|
@@ -645,9 +1152,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
645
1152
|
prevOutput,
|
|
646
1153
|
prevStep,
|
|
647
1154
|
stepResults,
|
|
1155
|
+
serializedStepGraph,
|
|
648
1156
|
resume,
|
|
649
1157
|
executionContext,
|
|
650
1158
|
emitter,
|
|
1159
|
+
abortController,
|
|
651
1160
|
runtimeContext
|
|
652
1161
|
}) {
|
|
653
1162
|
let execResults;
|
|
@@ -656,8 +1165,10 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
656
1165
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
657
1166
|
try {
|
|
658
1167
|
const result = await cond({
|
|
1168
|
+
runId,
|
|
659
1169
|
mastra: this.mastra,
|
|
660
1170
|
runtimeContext,
|
|
1171
|
+
runCount: -1,
|
|
661
1172
|
inputData: prevOutput,
|
|
662
1173
|
getInitData: () => stepResults?.input,
|
|
663
1174
|
getStepResult: (step) => {
|
|
@@ -673,7 +1184,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
673
1184
|
// TODO: this function shouldn't have suspend probably?
|
|
674
1185
|
suspend: async (_suspendPayload) => {
|
|
675
1186
|
},
|
|
676
|
-
|
|
1187
|
+
bail: () => {
|
|
1188
|
+
},
|
|
1189
|
+
abort: () => {
|
|
1190
|
+
abortController.abort();
|
|
1191
|
+
},
|
|
1192
|
+
[EMITTER_SYMBOL]: emitter,
|
|
1193
|
+
engine: {
|
|
1194
|
+
step: this.inngestStep
|
|
1195
|
+
},
|
|
1196
|
+
abortSignal: abortController.signal
|
|
677
1197
|
});
|
|
678
1198
|
return result ? index : null;
|
|
679
1199
|
} catch (e) {
|
|
@@ -692,6 +1212,7 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
692
1212
|
prevStep,
|
|
693
1213
|
stepResults,
|
|
694
1214
|
resume,
|
|
1215
|
+
serializedStepGraph,
|
|
695
1216
|
executionContext: {
|
|
696
1217
|
workflowId,
|
|
697
1218
|
runId,
|
|
@@ -701,21 +1222,22 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
701
1222
|
executionSpan: executionContext.executionSpan
|
|
702
1223
|
},
|
|
703
1224
|
emitter,
|
|
1225
|
+
abortController,
|
|
704
1226
|
runtimeContext
|
|
705
1227
|
})
|
|
706
1228
|
)
|
|
707
1229
|
);
|
|
708
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
709
|
-
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");
|
|
710
1232
|
if (hasFailed) {
|
|
711
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1233
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
712
1234
|
} else if (hasSuspended) {
|
|
713
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1235
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
714
1236
|
} else {
|
|
715
1237
|
execResults = {
|
|
716
1238
|
status: "success",
|
|
717
1239
|
output: results.reduce((acc, result, index) => {
|
|
718
|
-
if (result.status === "success") {
|
|
1240
|
+
if (result.result.status === "success") {
|
|
719
1241
|
acc[stepsToRun[index].step.id] = result.output;
|
|
720
1242
|
}
|
|
721
1243
|
return acc;
|
|
@@ -726,4 +1248,4 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
726
1248
|
}
|
|
727
1249
|
};
|
|
728
1250
|
|
|
729
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
|
|
1251
|
+
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|