@mastra/inngest 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-transpile-packages-20250724123433
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 +388 -2
- package/LICENSE.md +11 -42
- package/dist/_tsup-dts-rollup.d.cts +151 -40
- package/dist/_tsup-dts-rollup.d.ts +151 -40
- package/dist/index.cjs +568 -53
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +568 -54
- package/docker-compose.yaml +3 -3
- package/package.json +21 -19
- package/src/index.test.ts +5702 -3435
- package/src/index.ts +848 -78
- package/vitest.config.ts +6 -0
package/dist/index.cjs
CHANGED
|
@@ -3,20 +3,26 @@
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
4
|
var realtime = require('@inngest/realtime');
|
|
5
5
|
var di = require('@mastra/core/di');
|
|
6
|
+
var tools = require('@mastra/core/tools');
|
|
6
7
|
var workflows = require('@mastra/core/workflows');
|
|
7
8
|
var _constants = require('@mastra/core/workflows/_constants');
|
|
8
9
|
var hono = require('inngest/hono');
|
|
10
|
+
var zod = require('zod');
|
|
9
11
|
|
|
10
12
|
// src/index.ts
|
|
11
13
|
function serve({ mastra, inngest }) {
|
|
12
14
|
const wfs = mastra.getWorkflows();
|
|
13
|
-
const functions =
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const functions = Array.from(
|
|
16
|
+
new Set(
|
|
17
|
+
Object.values(wfs).flatMap((wf) => {
|
|
18
|
+
if (wf instanceof InngestWorkflow) {
|
|
19
|
+
wf.__registerMastra(mastra);
|
|
20
|
+
return wf.getFunctions();
|
|
21
|
+
}
|
|
22
|
+
return [];
|
|
23
|
+
})
|
|
24
|
+
)
|
|
25
|
+
);
|
|
20
26
|
return hono.serve({
|
|
21
27
|
client: inngest,
|
|
22
28
|
functions
|
|
@@ -43,15 +49,50 @@ var InngestRun = class extends workflows.Run {
|
|
|
43
49
|
}
|
|
44
50
|
async getRunOutput(eventId) {
|
|
45
51
|
let runs = await this.getRuns(eventId);
|
|
46
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
52
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
47
53
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
48
54
|
runs = await this.getRuns(eventId);
|
|
49
|
-
if (runs?.[0]?.status === "Failed"
|
|
55
|
+
if (runs?.[0]?.status === "Failed") {
|
|
56
|
+
console.log("run", runs?.[0]);
|
|
50
57
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
58
|
+
} else if (runs?.[0]?.status === "Cancelled") {
|
|
59
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
60
|
+
workflowName: this.workflowId,
|
|
61
|
+
runId: this.runId
|
|
62
|
+
});
|
|
63
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
51
64
|
}
|
|
52
65
|
}
|
|
53
66
|
return runs?.[0];
|
|
54
67
|
}
|
|
68
|
+
async sendEvent(event, data) {
|
|
69
|
+
await this.inngest.send({
|
|
70
|
+
name: `user-event-${event}`,
|
|
71
|
+
data
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async cancel() {
|
|
75
|
+
await this.inngest.send({
|
|
76
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
77
|
+
data: {
|
|
78
|
+
runId: this.runId
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
82
|
+
workflowName: this.workflowId,
|
|
83
|
+
runId: this.runId
|
|
84
|
+
});
|
|
85
|
+
if (snapshot) {
|
|
86
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
87
|
+
workflowName: this.workflowId,
|
|
88
|
+
runId: this.runId,
|
|
89
|
+
snapshot: {
|
|
90
|
+
...snapshot,
|
|
91
|
+
status: "canceled"
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
55
96
|
async start({
|
|
56
97
|
inputData
|
|
57
98
|
}) {
|
|
@@ -65,7 +106,8 @@ var InngestRun = class extends workflows.Run {
|
|
|
65
106
|
context: {},
|
|
66
107
|
activePaths: [],
|
|
67
108
|
suspendedPaths: {},
|
|
68
|
-
timestamp: Date.now()
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
status: "running"
|
|
69
111
|
}
|
|
70
112
|
});
|
|
71
113
|
const eventOutput = await this.inngest.send({
|
|
@@ -84,10 +126,23 @@ var InngestRun = class extends workflows.Run {
|
|
|
84
126
|
if (result.status === "failed") {
|
|
85
127
|
result.error = new Error(result.error);
|
|
86
128
|
}
|
|
87
|
-
|
|
129
|
+
if (result.status !== "suspended") {
|
|
130
|
+
this.cleanup?.();
|
|
131
|
+
}
|
|
88
132
|
return result;
|
|
89
133
|
}
|
|
90
134
|
async resume(params) {
|
|
135
|
+
const p = this._resume(params).then((result) => {
|
|
136
|
+
if (result.status !== "suspended") {
|
|
137
|
+
this.closeStreamAction?.().catch(() => {
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
});
|
|
142
|
+
this.executionResults = p;
|
|
143
|
+
return p;
|
|
144
|
+
}
|
|
145
|
+
async _resume(params) {
|
|
91
146
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
92
147
|
(step) => typeof step === "string" ? step : step?.id
|
|
93
148
|
);
|
|
@@ -100,6 +155,7 @@ var InngestRun = class extends workflows.Run {
|
|
|
100
155
|
data: {
|
|
101
156
|
inputData: params.resumeData,
|
|
102
157
|
runId: this.runId,
|
|
158
|
+
workflowId: this.workflowId,
|
|
103
159
|
stepResults: snapshot?.context,
|
|
104
160
|
resume: {
|
|
105
161
|
steps,
|
|
@@ -121,25 +177,60 @@ var InngestRun = class extends workflows.Run {
|
|
|
121
177
|
}
|
|
122
178
|
return result;
|
|
123
179
|
}
|
|
124
|
-
watch(cb) {
|
|
180
|
+
watch(cb, type = "watch") {
|
|
181
|
+
let active = true;
|
|
125
182
|
const streamPromise = realtime.subscribe(
|
|
126
183
|
{
|
|
127
184
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
128
|
-
topics: [
|
|
185
|
+
topics: [type],
|
|
129
186
|
app: this.inngest
|
|
130
187
|
},
|
|
131
188
|
(message) => {
|
|
132
|
-
|
|
189
|
+
if (active) {
|
|
190
|
+
cb(message.data);
|
|
191
|
+
}
|
|
133
192
|
}
|
|
134
193
|
);
|
|
135
194
|
return () => {
|
|
136
|
-
|
|
137
|
-
|
|
195
|
+
active = false;
|
|
196
|
+
streamPromise.then(async (stream) => {
|
|
197
|
+
return stream.cancel();
|
|
138
198
|
}).catch((err) => {
|
|
139
199
|
console.error(err);
|
|
140
200
|
});
|
|
141
201
|
};
|
|
142
202
|
}
|
|
203
|
+
stream({ inputData, runtimeContext } = {}) {
|
|
204
|
+
const { readable, writable } = new TransformStream();
|
|
205
|
+
const writer = writable.getWriter();
|
|
206
|
+
const unwatch = this.watch(async (event) => {
|
|
207
|
+
try {
|
|
208
|
+
await writer.write(event);
|
|
209
|
+
} catch {
|
|
210
|
+
}
|
|
211
|
+
}, "watch-v2");
|
|
212
|
+
this.closeStreamAction = async () => {
|
|
213
|
+
unwatch();
|
|
214
|
+
try {
|
|
215
|
+
await writer.close();
|
|
216
|
+
} catch (err) {
|
|
217
|
+
console.error("Error closing stream:", err);
|
|
218
|
+
} finally {
|
|
219
|
+
writer.releaseLock();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
|
|
223
|
+
if (result.status !== "suspended") {
|
|
224
|
+
this.closeStreamAction?.().catch(() => {
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
});
|
|
229
|
+
return {
|
|
230
|
+
stream: readable,
|
|
231
|
+
getWorkflowState: () => this.executionResults
|
|
232
|
+
};
|
|
233
|
+
}
|
|
143
234
|
};
|
|
144
235
|
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
145
236
|
#mastra;
|
|
@@ -162,11 +253,32 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
162
253
|
const storage = this.#mastra?.getStorage();
|
|
163
254
|
if (!storage) {
|
|
164
255
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
165
|
-
return null;
|
|
256
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
166
257
|
}
|
|
167
258
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
168
259
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
169
260
|
}
|
|
261
|
+
async getWorkflowRunExecutionResult(runId) {
|
|
262
|
+
const storage = this.#mastra?.getStorage();
|
|
263
|
+
if (!storage) {
|
|
264
|
+
this.logger.debug("Cannot get workflow run execution result. Mastra storage is not initialized");
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
268
|
+
if (!run?.snapshot) {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
if (typeof run.snapshot === "string") {
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
return {
|
|
275
|
+
status: run.snapshot.status,
|
|
276
|
+
result: run.snapshot.result,
|
|
277
|
+
error: run.snapshot.error,
|
|
278
|
+
payload: run.snapshot.context?.input,
|
|
279
|
+
steps: run.snapshot.context
|
|
280
|
+
};
|
|
281
|
+
}
|
|
170
282
|
__registerMastra(mastra) {
|
|
171
283
|
this.#mastra = mastra;
|
|
172
284
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -203,13 +315,55 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
203
315
|
this.runs.set(runIdToUse, run);
|
|
204
316
|
return run;
|
|
205
317
|
}
|
|
318
|
+
async createRunAsync(options) {
|
|
319
|
+
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
320
|
+
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
321
|
+
{
|
|
322
|
+
workflowId: this.id,
|
|
323
|
+
runId: runIdToUse,
|
|
324
|
+
executionEngine: this.executionEngine,
|
|
325
|
+
executionGraph: this.executionGraph,
|
|
326
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
327
|
+
mastra: this.#mastra,
|
|
328
|
+
retryConfig: this.retryConfig,
|
|
329
|
+
cleanup: () => this.runs.delete(runIdToUse)
|
|
330
|
+
},
|
|
331
|
+
this.inngest
|
|
332
|
+
);
|
|
333
|
+
this.runs.set(runIdToUse, run);
|
|
334
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
|
|
335
|
+
if (!workflowSnapshotInStorage) {
|
|
336
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
337
|
+
workflowName: this.id,
|
|
338
|
+
runId: runIdToUse,
|
|
339
|
+
snapshot: {
|
|
340
|
+
runId: runIdToUse,
|
|
341
|
+
status: "pending",
|
|
342
|
+
value: {},
|
|
343
|
+
context: {},
|
|
344
|
+
activePaths: [],
|
|
345
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
346
|
+
suspendedPaths: {},
|
|
347
|
+
result: void 0,
|
|
348
|
+
error: void 0,
|
|
349
|
+
// @ts-ignore
|
|
350
|
+
timestamp: Date.now()
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
return run;
|
|
355
|
+
}
|
|
206
356
|
getFunction() {
|
|
207
357
|
if (this.function) {
|
|
208
358
|
return this.function;
|
|
209
359
|
}
|
|
210
360
|
this.function = this.inngest.createFunction(
|
|
211
|
-
|
|
212
|
-
|
|
361
|
+
{
|
|
362
|
+
id: `workflow.${this.id}`,
|
|
363
|
+
// @ts-ignore
|
|
364
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
365
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }]
|
|
366
|
+
},
|
|
213
367
|
{ event: `workflow.${this.id}` },
|
|
214
368
|
async ({ event, step, attempt, publish }) => {
|
|
215
369
|
let { inputData, runId, resume } = event.data;
|
|
@@ -226,12 +380,18 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
226
380
|
try {
|
|
227
381
|
await publish({
|
|
228
382
|
channel: `workflow:${this.id}:${runId}`,
|
|
229
|
-
topic:
|
|
383
|
+
topic: event2,
|
|
230
384
|
data
|
|
231
385
|
});
|
|
232
386
|
} catch (err) {
|
|
233
387
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
234
388
|
}
|
|
389
|
+
},
|
|
390
|
+
on: (_event, _callback) => {
|
|
391
|
+
},
|
|
392
|
+
off: (_event, _callback) => {
|
|
393
|
+
},
|
|
394
|
+
once: (_event, _callback) => {
|
|
235
395
|
}
|
|
236
396
|
};
|
|
237
397
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -245,7 +405,8 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
245
405
|
retryConfig: this.retryConfig,
|
|
246
406
|
runtimeContext: new di.RuntimeContext(),
|
|
247
407
|
// TODO
|
|
248
|
-
resume
|
|
408
|
+
resume,
|
|
409
|
+
abortController: new AbortController()
|
|
249
410
|
});
|
|
250
411
|
return { result, runId };
|
|
251
412
|
}
|
|
@@ -269,29 +430,138 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
|
269
430
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
270
431
|
}
|
|
271
432
|
};
|
|
272
|
-
function
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
433
|
+
function isAgent(params) {
|
|
434
|
+
return params?.component === "AGENT";
|
|
435
|
+
}
|
|
436
|
+
function isTool(params) {
|
|
437
|
+
return params instanceof tools.Tool;
|
|
438
|
+
}
|
|
439
|
+
function createStep(params) {
|
|
440
|
+
if (isAgent(params)) {
|
|
441
|
+
return {
|
|
442
|
+
id: params.name,
|
|
443
|
+
// @ts-ignore
|
|
444
|
+
inputSchema: zod.z.object({
|
|
445
|
+
prompt: zod.z.string()
|
|
446
|
+
// resourceId: z.string().optional(),
|
|
447
|
+
// threadId: z.string().optional(),
|
|
448
|
+
}),
|
|
449
|
+
// @ts-ignore
|
|
450
|
+
outputSchema: zod.z.object({
|
|
451
|
+
text: zod.z.string()
|
|
452
|
+
}),
|
|
453
|
+
execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
|
|
454
|
+
let streamPromise = {};
|
|
455
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
456
|
+
streamPromise.resolve = resolve;
|
|
457
|
+
streamPromise.reject = reject;
|
|
458
|
+
});
|
|
459
|
+
const toolData = {
|
|
460
|
+
name: params.name,
|
|
461
|
+
args: inputData
|
|
462
|
+
};
|
|
463
|
+
await emitter.emit("watch-v2", {
|
|
464
|
+
type: "tool-call-streaming-start",
|
|
465
|
+
...toolData
|
|
466
|
+
});
|
|
467
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
468
|
+
// resourceId: inputData.resourceId,
|
|
469
|
+
// threadId: inputData.threadId,
|
|
470
|
+
runtimeContext,
|
|
471
|
+
onFinish: (result) => {
|
|
472
|
+
streamPromise.resolve(result.text);
|
|
473
|
+
},
|
|
474
|
+
abortSignal
|
|
475
|
+
});
|
|
476
|
+
if (abortSignal.aborted) {
|
|
477
|
+
return abort();
|
|
478
|
+
}
|
|
479
|
+
for await (const chunk of fullStream) {
|
|
480
|
+
switch (chunk.type) {
|
|
481
|
+
case "text-delta":
|
|
482
|
+
await emitter.emit("watch-v2", {
|
|
483
|
+
type: "tool-call-delta",
|
|
484
|
+
...toolData,
|
|
485
|
+
argsTextDelta: chunk.textDelta
|
|
486
|
+
});
|
|
487
|
+
break;
|
|
488
|
+
case "step-start":
|
|
489
|
+
case "step-finish":
|
|
490
|
+
case "finish":
|
|
491
|
+
break;
|
|
492
|
+
case "tool-call":
|
|
493
|
+
case "tool-result":
|
|
494
|
+
case "tool-call-streaming-start":
|
|
495
|
+
case "tool-call-delta":
|
|
496
|
+
case "source":
|
|
497
|
+
case "file":
|
|
498
|
+
default:
|
|
499
|
+
await emitter.emit("watch-v2", chunk);
|
|
500
|
+
break;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
text: await streamPromise.promise
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
if (isTool(params)) {
|
|
510
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
511
|
+
throw new Error("Tool must have input and output schemas defined");
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
// TODO: tool probably should have strong id type
|
|
515
|
+
// @ts-ignore
|
|
516
|
+
id: params.id,
|
|
517
|
+
inputSchema: params.inputSchema,
|
|
518
|
+
outputSchema: params.outputSchema,
|
|
519
|
+
execute: async ({ inputData, mastra, runtimeContext }) => {
|
|
520
|
+
return params.execute({
|
|
521
|
+
context: inputData,
|
|
522
|
+
mastra,
|
|
523
|
+
runtimeContext
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
return {
|
|
529
|
+
id: params.id,
|
|
530
|
+
description: params.description,
|
|
531
|
+
inputSchema: params.inputSchema,
|
|
532
|
+
outputSchema: params.outputSchema,
|
|
533
|
+
resumeSchema: params.resumeSchema,
|
|
534
|
+
suspendSchema: params.suspendSchema,
|
|
535
|
+
execute: params.execute
|
|
536
|
+
};
|
|
286
537
|
}
|
|
287
538
|
function init(inngest) {
|
|
288
539
|
return {
|
|
289
540
|
createWorkflow(params) {
|
|
290
541
|
return new InngestWorkflow(params, inngest);
|
|
291
542
|
},
|
|
292
|
-
createStep
|
|
293
|
-
cloneStep
|
|
294
|
-
|
|
543
|
+
createStep,
|
|
544
|
+
cloneStep(step, opts) {
|
|
545
|
+
return {
|
|
546
|
+
id: opts.id,
|
|
547
|
+
description: step.description,
|
|
548
|
+
inputSchema: step.inputSchema,
|
|
549
|
+
outputSchema: step.outputSchema,
|
|
550
|
+
execute: step.execute
|
|
551
|
+
};
|
|
552
|
+
},
|
|
553
|
+
cloneWorkflow(workflow, opts) {
|
|
554
|
+
const wf = new workflows.Workflow({
|
|
555
|
+
id: opts.id,
|
|
556
|
+
inputSchema: workflow.inputSchema,
|
|
557
|
+
outputSchema: workflow.outputSchema,
|
|
558
|
+
steps: workflow.stepDefs,
|
|
559
|
+
mastra: workflow.mastra
|
|
560
|
+
});
|
|
561
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
562
|
+
wf.commit();
|
|
563
|
+
return wf;
|
|
564
|
+
}
|
|
295
565
|
};
|
|
296
566
|
}
|
|
297
567
|
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
@@ -302,6 +572,18 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
302
572
|
this.inngestStep = inngestStep;
|
|
303
573
|
this.inngestAttempts = inngestAttempts;
|
|
304
574
|
}
|
|
575
|
+
async execute(params) {
|
|
576
|
+
await params.emitter.emit("watch-v2", {
|
|
577
|
+
type: "start",
|
|
578
|
+
payload: { runId: params.runId }
|
|
579
|
+
});
|
|
580
|
+
const result = await super.execute(params);
|
|
581
|
+
await params.emitter.emit("watch-v2", {
|
|
582
|
+
type: "finish",
|
|
583
|
+
payload: { runId: params.runId }
|
|
584
|
+
});
|
|
585
|
+
return result;
|
|
586
|
+
}
|
|
305
587
|
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
306
588
|
const base = {
|
|
307
589
|
status: lastOutput.status,
|
|
@@ -368,6 +650,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
368
650
|
resume,
|
|
369
651
|
prevOutput,
|
|
370
652
|
emitter,
|
|
653
|
+
abortController,
|
|
371
654
|
runtimeContext
|
|
372
655
|
}) {
|
|
373
656
|
return super.executeStep({
|
|
@@ -379,9 +662,120 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
379
662
|
resume,
|
|
380
663
|
prevOutput,
|
|
381
664
|
emitter,
|
|
665
|
+
abortController,
|
|
382
666
|
runtimeContext
|
|
383
667
|
});
|
|
384
668
|
}
|
|
669
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
670
|
+
// await this.inngestStep.sleep(id, duration);
|
|
671
|
+
// }
|
|
672
|
+
async executeSleep({
|
|
673
|
+
workflowId,
|
|
674
|
+
runId,
|
|
675
|
+
entry,
|
|
676
|
+
prevOutput,
|
|
677
|
+
stepResults,
|
|
678
|
+
emitter,
|
|
679
|
+
abortController,
|
|
680
|
+
runtimeContext
|
|
681
|
+
}) {
|
|
682
|
+
let { duration, fn } = entry;
|
|
683
|
+
if (fn) {
|
|
684
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
685
|
+
return await fn({
|
|
686
|
+
runId,
|
|
687
|
+
workflowId,
|
|
688
|
+
mastra: this.mastra,
|
|
689
|
+
runtimeContext,
|
|
690
|
+
inputData: prevOutput,
|
|
691
|
+
runCount: -1,
|
|
692
|
+
getInitData: () => stepResults?.input,
|
|
693
|
+
getStepResult: (step) => {
|
|
694
|
+
if (!step?.id) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
const result = stepResults[step.id];
|
|
698
|
+
if (result?.status === "success") {
|
|
699
|
+
return result.output;
|
|
700
|
+
}
|
|
701
|
+
return null;
|
|
702
|
+
},
|
|
703
|
+
// TODO: this function shouldn't have suspend probably?
|
|
704
|
+
suspend: async (_suspendPayload) => {
|
|
705
|
+
},
|
|
706
|
+
bail: () => {
|
|
707
|
+
},
|
|
708
|
+
abort: () => {
|
|
709
|
+
abortController?.abort();
|
|
710
|
+
},
|
|
711
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
712
|
+
engine: { step: this.inngestStep },
|
|
713
|
+
abortSignal: abortController?.signal
|
|
714
|
+
});
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
718
|
+
}
|
|
719
|
+
async executeSleepUntil({
|
|
720
|
+
workflowId,
|
|
721
|
+
runId,
|
|
722
|
+
entry,
|
|
723
|
+
prevOutput,
|
|
724
|
+
stepResults,
|
|
725
|
+
emitter,
|
|
726
|
+
abortController,
|
|
727
|
+
runtimeContext
|
|
728
|
+
}) {
|
|
729
|
+
let { date, fn } = entry;
|
|
730
|
+
if (fn) {
|
|
731
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
732
|
+
return await fn({
|
|
733
|
+
runId,
|
|
734
|
+
workflowId,
|
|
735
|
+
mastra: this.mastra,
|
|
736
|
+
runtimeContext,
|
|
737
|
+
inputData: prevOutput,
|
|
738
|
+
runCount: -1,
|
|
739
|
+
getInitData: () => stepResults?.input,
|
|
740
|
+
getStepResult: (step) => {
|
|
741
|
+
if (!step?.id) {
|
|
742
|
+
return null;
|
|
743
|
+
}
|
|
744
|
+
const result = stepResults[step.id];
|
|
745
|
+
if (result?.status === "success") {
|
|
746
|
+
return result.output;
|
|
747
|
+
}
|
|
748
|
+
return null;
|
|
749
|
+
},
|
|
750
|
+
// TODO: this function shouldn't have suspend probably?
|
|
751
|
+
suspend: async (_suspendPayload) => {
|
|
752
|
+
},
|
|
753
|
+
bail: () => {
|
|
754
|
+
},
|
|
755
|
+
abort: () => {
|
|
756
|
+
abortController?.abort();
|
|
757
|
+
},
|
|
758
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
759
|
+
engine: { step: this.inngestStep },
|
|
760
|
+
abortSignal: abortController?.signal
|
|
761
|
+
});
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
if (!(date instanceof Date)) {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
768
|
+
}
|
|
769
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
770
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
771
|
+
event: `user-event-${event}`,
|
|
772
|
+
timeout: timeout ?? 5e3
|
|
773
|
+
});
|
|
774
|
+
if (eventData === null) {
|
|
775
|
+
throw "Timeout waiting for event";
|
|
776
|
+
}
|
|
777
|
+
return eventData?.data;
|
|
778
|
+
}
|
|
385
779
|
async executeStep({
|
|
386
780
|
step,
|
|
387
781
|
stepResults,
|
|
@@ -389,11 +783,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
389
783
|
resume,
|
|
390
784
|
prevOutput,
|
|
391
785
|
emitter,
|
|
786
|
+
abortController,
|
|
392
787
|
runtimeContext
|
|
393
788
|
}) {
|
|
394
|
-
await this.inngestStep.run(
|
|
789
|
+
const startedAt = await this.inngestStep.run(
|
|
395
790
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
396
791
|
async () => {
|
|
792
|
+
const startedAt2 = Date.now();
|
|
397
793
|
await emitter.emit("watch", {
|
|
398
794
|
type: "watch",
|
|
399
795
|
payload: {
|
|
@@ -415,6 +811,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
415
811
|
},
|
|
416
812
|
eventTimestamp: Date.now()
|
|
417
813
|
});
|
|
814
|
+
await emitter.emit("watch-v2", {
|
|
815
|
+
type: "step-start",
|
|
816
|
+
payload: {
|
|
817
|
+
id: step.id,
|
|
818
|
+
status: "running",
|
|
819
|
+
payload: prevOutput,
|
|
820
|
+
startedAt: startedAt2
|
|
821
|
+
}
|
|
822
|
+
});
|
|
823
|
+
return startedAt2;
|
|
418
824
|
}
|
|
419
825
|
);
|
|
420
826
|
if (step instanceof InngestWorkflow) {
|
|
@@ -475,6 +881,15 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
475
881
|
},
|
|
476
882
|
eventTimestamp: Date.now()
|
|
477
883
|
});
|
|
884
|
+
await emitter.emit("watch-v2", {
|
|
885
|
+
type: "step-result",
|
|
886
|
+
payload: {
|
|
887
|
+
id: step.id,
|
|
888
|
+
status: "failed",
|
|
889
|
+
error: result?.error,
|
|
890
|
+
payload: prevOutput
|
|
891
|
+
}
|
|
892
|
+
});
|
|
478
893
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
479
894
|
} else if (result.status === "suspended") {
|
|
480
895
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -501,6 +916,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
501
916
|
},
|
|
502
917
|
eventTimestamp: Date.now()
|
|
503
918
|
});
|
|
919
|
+
await emitter.emit("watch-v2", {
|
|
920
|
+
type: "step-suspended",
|
|
921
|
+
payload: {
|
|
922
|
+
id: step.id,
|
|
923
|
+
status: "suspended"
|
|
924
|
+
}
|
|
925
|
+
});
|
|
504
926
|
return {
|
|
505
927
|
executionContext,
|
|
506
928
|
result: {
|
|
@@ -551,6 +973,21 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
551
973
|
},
|
|
552
974
|
eventTimestamp: Date.now()
|
|
553
975
|
});
|
|
976
|
+
await emitter.emit("watch-v2", {
|
|
977
|
+
type: "step-result",
|
|
978
|
+
payload: {
|
|
979
|
+
id: step.id,
|
|
980
|
+
status: "success",
|
|
981
|
+
output: result?.result
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
await emitter.emit("watch-v2", {
|
|
985
|
+
type: "step-finish",
|
|
986
|
+
payload: {
|
|
987
|
+
id: step.id,
|
|
988
|
+
metadata: {}
|
|
989
|
+
}
|
|
990
|
+
});
|
|
554
991
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
555
992
|
}
|
|
556
993
|
);
|
|
@@ -560,6 +997,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
560
997
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
561
998
|
let execResults;
|
|
562
999
|
let suspended;
|
|
1000
|
+
let bailed;
|
|
563
1001
|
try {
|
|
564
1002
|
const result = await step.execute({
|
|
565
1003
|
runId: executionContext.runId,
|
|
@@ -579,20 +1017,54 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
579
1017
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
580
1018
|
suspended = { payload: suspendPayload };
|
|
581
1019
|
},
|
|
1020
|
+
bail: (result2) => {
|
|
1021
|
+
bailed = { payload: result2 };
|
|
1022
|
+
},
|
|
582
1023
|
resume: {
|
|
583
1024
|
steps: resume?.steps?.slice(1) || [],
|
|
584
1025
|
resumePayload: resume?.resumePayload,
|
|
585
1026
|
// @ts-ignore
|
|
586
1027
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
587
1028
|
},
|
|
588
|
-
emitter
|
|
1029
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1030
|
+
engine: {
|
|
1031
|
+
step: this.inngestStep
|
|
1032
|
+
},
|
|
1033
|
+
abortSignal: abortController.signal
|
|
589
1034
|
});
|
|
590
|
-
|
|
1035
|
+
const endedAt = Date.now();
|
|
1036
|
+
execResults = {
|
|
1037
|
+
status: "success",
|
|
1038
|
+
output: result,
|
|
1039
|
+
startedAt,
|
|
1040
|
+
endedAt,
|
|
1041
|
+
payload: prevOutput,
|
|
1042
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1043
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1044
|
+
};
|
|
591
1045
|
} catch (e) {
|
|
592
|
-
execResults = {
|
|
1046
|
+
execResults = {
|
|
1047
|
+
status: "failed",
|
|
1048
|
+
payload: prevOutput,
|
|
1049
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1050
|
+
endedAt: Date.now(),
|
|
1051
|
+
startedAt,
|
|
1052
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1053
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1054
|
+
};
|
|
593
1055
|
}
|
|
594
1056
|
if (suspended) {
|
|
595
|
-
execResults = {
|
|
1057
|
+
execResults = {
|
|
1058
|
+
status: "suspended",
|
|
1059
|
+
suspendedPayload: suspended.payload,
|
|
1060
|
+
payload: prevOutput,
|
|
1061
|
+
suspendedAt: Date.now(),
|
|
1062
|
+
startedAt,
|
|
1063
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1064
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1065
|
+
};
|
|
1066
|
+
} else if (bailed) {
|
|
1067
|
+
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
596
1068
|
}
|
|
597
1069
|
if (execResults.status === "failed") {
|
|
598
1070
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
@@ -604,18 +1076,41 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
604
1076
|
payload: {
|
|
605
1077
|
currentStep: {
|
|
606
1078
|
id: step.id,
|
|
607
|
-
|
|
608
|
-
output: execResults.output
|
|
1079
|
+
...execResults
|
|
609
1080
|
},
|
|
610
1081
|
workflowState: {
|
|
611
1082
|
status: "running",
|
|
612
|
-
steps: stepResults,
|
|
1083
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
613
1084
|
result: null,
|
|
614
1085
|
error: null
|
|
615
1086
|
}
|
|
616
1087
|
},
|
|
617
1088
|
eventTimestamp: Date.now()
|
|
618
1089
|
});
|
|
1090
|
+
if (execResults.status === "suspended") {
|
|
1091
|
+
await emitter.emit("watch-v2", {
|
|
1092
|
+
type: "step-suspended",
|
|
1093
|
+
payload: {
|
|
1094
|
+
id: step.id,
|
|
1095
|
+
...execResults
|
|
1096
|
+
}
|
|
1097
|
+
});
|
|
1098
|
+
} else {
|
|
1099
|
+
await emitter.emit("watch-v2", {
|
|
1100
|
+
type: "step-result",
|
|
1101
|
+
payload: {
|
|
1102
|
+
id: step.id,
|
|
1103
|
+
...execResults
|
|
1104
|
+
}
|
|
1105
|
+
});
|
|
1106
|
+
await emitter.emit("watch-v2", {
|
|
1107
|
+
type: "step-finish",
|
|
1108
|
+
payload: {
|
|
1109
|
+
id: step.id,
|
|
1110
|
+
metadata: {}
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
619
1114
|
return { result: execResults, executionContext, stepResults };
|
|
620
1115
|
});
|
|
621
1116
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
@@ -627,7 +1122,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
627
1122
|
runId,
|
|
628
1123
|
stepResults,
|
|
629
1124
|
executionContext,
|
|
630
|
-
serializedStepGraph
|
|
1125
|
+
serializedStepGraph,
|
|
1126
|
+
workflowStatus,
|
|
1127
|
+
result,
|
|
1128
|
+
error
|
|
631
1129
|
}) {
|
|
632
1130
|
await this.inngestStep.run(
|
|
633
1131
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -642,6 +1140,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
642
1140
|
activePaths: [],
|
|
643
1141
|
suspendedPaths: executionContext.suspendedPaths,
|
|
644
1142
|
serializedStepGraph,
|
|
1143
|
+
status: workflowStatus,
|
|
1144
|
+
result,
|
|
1145
|
+
error,
|
|
645
1146
|
// @ts-ignore
|
|
646
1147
|
timestamp: Date.now()
|
|
647
1148
|
}
|
|
@@ -660,6 +1161,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
660
1161
|
resume,
|
|
661
1162
|
executionContext,
|
|
662
1163
|
emitter,
|
|
1164
|
+
abortController,
|
|
663
1165
|
runtimeContext
|
|
664
1166
|
}) {
|
|
665
1167
|
let execResults;
|
|
@@ -669,8 +1171,10 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
669
1171
|
try {
|
|
670
1172
|
const result = await cond({
|
|
671
1173
|
runId,
|
|
1174
|
+
workflowId,
|
|
672
1175
|
mastra: this.mastra,
|
|
673
1176
|
runtimeContext,
|
|
1177
|
+
runCount: -1,
|
|
674
1178
|
inputData: prevOutput,
|
|
675
1179
|
getInitData: () => stepResults?.input,
|
|
676
1180
|
getStepResult: (step) => {
|
|
@@ -686,7 +1190,16 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
686
1190
|
// TODO: this function shouldn't have suspend probably?
|
|
687
1191
|
suspend: async (_suspendPayload) => {
|
|
688
1192
|
},
|
|
689
|
-
|
|
1193
|
+
bail: () => {
|
|
1194
|
+
},
|
|
1195
|
+
abort: () => {
|
|
1196
|
+
abortController.abort();
|
|
1197
|
+
},
|
|
1198
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1199
|
+
engine: {
|
|
1200
|
+
step: this.inngestStep
|
|
1201
|
+
},
|
|
1202
|
+
abortSignal: abortController.signal
|
|
690
1203
|
});
|
|
691
1204
|
return result ? index : null;
|
|
692
1205
|
} catch (e) {
|
|
@@ -715,21 +1228,22 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
715
1228
|
executionSpan: executionContext.executionSpan
|
|
716
1229
|
},
|
|
717
1230
|
emitter,
|
|
1231
|
+
abortController,
|
|
718
1232
|
runtimeContext
|
|
719
1233
|
})
|
|
720
1234
|
)
|
|
721
1235
|
);
|
|
722
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
723
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1236
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1237
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
724
1238
|
if (hasFailed) {
|
|
725
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1239
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
726
1240
|
} else if (hasSuspended) {
|
|
727
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1241
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
728
1242
|
} else {
|
|
729
1243
|
execResults = {
|
|
730
1244
|
status: "success",
|
|
731
1245
|
output: results.reduce((acc, result, index) => {
|
|
732
|
-
if (result.status === "success") {
|
|
1246
|
+
if (result.result.status === "success") {
|
|
733
1247
|
acc[stepsToRun[index].step.id] = result.output;
|
|
734
1248
|
}
|
|
735
1249
|
return acc;
|
|
@@ -743,5 +1257,6 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
|
743
1257
|
exports.InngestExecutionEngine = InngestExecutionEngine;
|
|
744
1258
|
exports.InngestRun = InngestRun;
|
|
745
1259
|
exports.InngestWorkflow = InngestWorkflow;
|
|
1260
|
+
exports.createStep = createStep;
|
|
746
1261
|
exports.init = init;
|
|
747
1262
|
exports.serve = serve;
|