@mastra/inngest 0.0.0-generate-message-id-20250512171942 → 0.0.0-interpolate-reporter-url-20250910180021
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 +970 -3
- package/LICENSE.md +11 -42
- package/dist/index.cjs +765 -78
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +281 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +762 -76
- package/dist/index.js.map +1 -0
- package/package.json +39 -20
- package/dist/_tsup-dts-rollup.d.cts +0 -194
- package/dist/_tsup-dts-rollup.d.ts +0 -194
- package/dist/index.d.cts +0 -5
- package/docker-compose.yaml +0 -10
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -5437
- package/src/index.ts +0 -956
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -8
package/dist/index.cjs
CHANGED
|
@@ -2,35 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
4
|
var realtime = require('@inngest/realtime');
|
|
5
|
+
var aiTracing = require('@mastra/core/ai-tracing');
|
|
5
6
|
var di = require('@mastra/core/di');
|
|
6
|
-
var
|
|
7
|
+
var tools = require('@mastra/core/tools');
|
|
8
|
+
var workflows = require('@mastra/core/workflows');
|
|
9
|
+
var _constants = require('@mastra/core/workflows/_constants');
|
|
7
10
|
var hono = require('inngest/hono');
|
|
11
|
+
var zod = require('zod');
|
|
8
12
|
|
|
9
13
|
// src/index.ts
|
|
10
14
|
function serve({ mastra, inngest }) {
|
|
11
|
-
const wfs = mastra.
|
|
12
|
-
const functions =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
const wfs = mastra.getWorkflows();
|
|
16
|
+
const functions = Array.from(
|
|
17
|
+
new Set(
|
|
18
|
+
Object.values(wfs).flatMap((wf) => {
|
|
19
|
+
if (wf instanceof InngestWorkflow) {
|
|
20
|
+
wf.__registerMastra(mastra);
|
|
21
|
+
return wf.getFunctions();
|
|
22
|
+
}
|
|
23
|
+
return [];
|
|
24
|
+
})
|
|
25
|
+
)
|
|
26
|
+
);
|
|
19
27
|
return hono.serve({
|
|
20
28
|
client: inngest,
|
|
21
29
|
functions
|
|
22
30
|
});
|
|
23
31
|
}
|
|
24
|
-
var InngestRun = class extends
|
|
32
|
+
var InngestRun = class extends workflows.Run {
|
|
25
33
|
inngest;
|
|
34
|
+
serializedStepGraph;
|
|
26
35
|
#mastra;
|
|
27
36
|
constructor(params, inngest) {
|
|
28
37
|
super(params);
|
|
29
38
|
this.inngest = inngest;
|
|
39
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
30
40
|
this.#mastra = params.mastra;
|
|
31
41
|
}
|
|
32
42
|
async getRuns(eventId) {
|
|
33
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
43
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
|
|
34
44
|
headers: {
|
|
35
45
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
36
46
|
}
|
|
@@ -40,15 +50,50 @@ var InngestRun = class extends vNext.Run {
|
|
|
40
50
|
}
|
|
41
51
|
async getRunOutput(eventId) {
|
|
42
52
|
let runs = await this.getRuns(eventId);
|
|
43
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
53
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
44
54
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
45
55
|
runs = await this.getRuns(eventId);
|
|
46
|
-
if (runs?.[0]?.status === "Failed"
|
|
56
|
+
if (runs?.[0]?.status === "Failed") {
|
|
57
|
+
console.log("run", runs?.[0]);
|
|
47
58
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
59
|
+
} else if (runs?.[0]?.status === "Cancelled") {
|
|
60
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
61
|
+
workflowName: this.workflowId,
|
|
62
|
+
runId: this.runId
|
|
63
|
+
});
|
|
64
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
48
65
|
}
|
|
49
66
|
}
|
|
50
67
|
return runs?.[0];
|
|
51
68
|
}
|
|
69
|
+
async sendEvent(event, data) {
|
|
70
|
+
await this.inngest.send({
|
|
71
|
+
name: `user-event-${event}`,
|
|
72
|
+
data
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
async cancel() {
|
|
76
|
+
await this.inngest.send({
|
|
77
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
78
|
+
data: {
|
|
79
|
+
runId: this.runId
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
83
|
+
workflowName: this.workflowId,
|
|
84
|
+
runId: this.runId
|
|
85
|
+
});
|
|
86
|
+
if (snapshot) {
|
|
87
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
88
|
+
workflowName: this.workflowId,
|
|
89
|
+
runId: this.runId,
|
|
90
|
+
snapshot: {
|
|
91
|
+
...snapshot,
|
|
92
|
+
status: "canceled"
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
52
97
|
async start({
|
|
53
98
|
inputData
|
|
54
99
|
}) {
|
|
@@ -57,11 +102,14 @@ var InngestRun = class extends vNext.Run {
|
|
|
57
102
|
runId: this.runId,
|
|
58
103
|
snapshot: {
|
|
59
104
|
runId: this.runId,
|
|
105
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
60
106
|
value: {},
|
|
61
107
|
context: {},
|
|
62
108
|
activePaths: [],
|
|
63
109
|
suspendedPaths: {},
|
|
64
|
-
|
|
110
|
+
waitingPaths: {},
|
|
111
|
+
timestamp: Date.now(),
|
|
112
|
+
status: "running"
|
|
65
113
|
}
|
|
66
114
|
});
|
|
67
115
|
const eventOutput = await this.inngest.send({
|
|
@@ -80,10 +128,23 @@ var InngestRun = class extends vNext.Run {
|
|
|
80
128
|
if (result.status === "failed") {
|
|
81
129
|
result.error = new Error(result.error);
|
|
82
130
|
}
|
|
83
|
-
|
|
131
|
+
if (result.status !== "suspended") {
|
|
132
|
+
this.cleanup?.();
|
|
133
|
+
}
|
|
84
134
|
return result;
|
|
85
135
|
}
|
|
86
136
|
async resume(params) {
|
|
137
|
+
const p = this._resume(params).then((result) => {
|
|
138
|
+
if (result.status !== "suspended") {
|
|
139
|
+
this.closeStreamAction?.().catch(() => {
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return result;
|
|
143
|
+
});
|
|
144
|
+
this.executionResults = p;
|
|
145
|
+
return p;
|
|
146
|
+
}
|
|
147
|
+
async _resume(params) {
|
|
87
148
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
88
149
|
(step) => typeof step === "string" ? step : step?.id
|
|
89
150
|
);
|
|
@@ -96,6 +157,7 @@ var InngestRun = class extends vNext.Run {
|
|
|
96
157
|
data: {
|
|
97
158
|
inputData: params.resumeData,
|
|
98
159
|
runId: this.runId,
|
|
160
|
+
workflowId: this.workflowId,
|
|
99
161
|
stepResults: snapshot?.context,
|
|
100
162
|
resume: {
|
|
101
163
|
steps,
|
|
@@ -117,32 +179,101 @@ var InngestRun = class extends vNext.Run {
|
|
|
117
179
|
}
|
|
118
180
|
return result;
|
|
119
181
|
}
|
|
120
|
-
watch(cb) {
|
|
182
|
+
watch(cb, type = "watch") {
|
|
183
|
+
let active = true;
|
|
121
184
|
const streamPromise = realtime.subscribe(
|
|
122
185
|
{
|
|
123
186
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
124
|
-
topics: [
|
|
187
|
+
topics: [type],
|
|
125
188
|
app: this.inngest
|
|
126
189
|
},
|
|
127
190
|
(message) => {
|
|
128
|
-
|
|
191
|
+
if (active) {
|
|
192
|
+
cb(message.data);
|
|
193
|
+
}
|
|
129
194
|
}
|
|
130
195
|
);
|
|
131
196
|
return () => {
|
|
132
|
-
|
|
133
|
-
|
|
197
|
+
active = false;
|
|
198
|
+
streamPromise.then(async (stream) => {
|
|
199
|
+
return stream.cancel();
|
|
134
200
|
}).catch((err) => {
|
|
135
201
|
console.error(err);
|
|
136
202
|
});
|
|
137
203
|
};
|
|
138
204
|
}
|
|
205
|
+
stream({ inputData, runtimeContext } = {}) {
|
|
206
|
+
const { readable, writable } = new TransformStream();
|
|
207
|
+
let currentToolData = void 0;
|
|
208
|
+
const writer = writable.getWriter();
|
|
209
|
+
const unwatch = this.watch(async (event) => {
|
|
210
|
+
if (event.type === "workflow-agent-call-start") {
|
|
211
|
+
currentToolData = {
|
|
212
|
+
name: event.payload.name,
|
|
213
|
+
args: event.payload.args
|
|
214
|
+
};
|
|
215
|
+
await writer.write({
|
|
216
|
+
...event.payload,
|
|
217
|
+
type: "tool-call-streaming-start"
|
|
218
|
+
});
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
if (event.type === "workflow-agent-call-finish") {
|
|
223
|
+
return;
|
|
224
|
+
} else if (!event.type.startsWith("workflow-")) {
|
|
225
|
+
if (event.type === "text-delta") {
|
|
226
|
+
await writer.write({
|
|
227
|
+
type: "tool-call-delta",
|
|
228
|
+
...currentToolData ?? {},
|
|
229
|
+
argsTextDelta: event.textDelta
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
const e = {
|
|
235
|
+
...event,
|
|
236
|
+
type: event.type.replace("workflow-", "")
|
|
237
|
+
};
|
|
238
|
+
await writer.write(e);
|
|
239
|
+
} catch {
|
|
240
|
+
}
|
|
241
|
+
}, "watch-v2");
|
|
242
|
+
this.closeStreamAction = async () => {
|
|
243
|
+
unwatch();
|
|
244
|
+
try {
|
|
245
|
+
await writer.close();
|
|
246
|
+
} catch (err) {
|
|
247
|
+
console.error("Error closing stream:", err);
|
|
248
|
+
} finally {
|
|
249
|
+
writer.releaseLock();
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
|
|
253
|
+
if (result.status !== "suspended") {
|
|
254
|
+
this.closeStreamAction?.().catch(() => {
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
});
|
|
259
|
+
return {
|
|
260
|
+
stream: readable,
|
|
261
|
+
getWorkflowState: () => this.executionResults
|
|
262
|
+
};
|
|
263
|
+
}
|
|
139
264
|
};
|
|
140
|
-
var InngestWorkflow = class _InngestWorkflow extends
|
|
265
|
+
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
141
266
|
#mastra;
|
|
142
267
|
inngest;
|
|
143
268
|
function;
|
|
269
|
+
flowControlConfig;
|
|
144
270
|
constructor(params, inngest) {
|
|
145
|
-
|
|
271
|
+
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
272
|
+
super(workflowParams);
|
|
273
|
+
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
274
|
+
([_, value]) => value !== void 0
|
|
275
|
+
);
|
|
276
|
+
this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
|
|
146
277
|
this.#mastra = params.mastra;
|
|
147
278
|
this.inngest = inngest;
|
|
148
279
|
}
|
|
@@ -158,7 +289,7 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
158
289
|
const storage = this.#mastra?.getStorage();
|
|
159
290
|
if (!storage) {
|
|
160
291
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
161
|
-
return null;
|
|
292
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
162
293
|
}
|
|
163
294
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
164
295
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
@@ -189,6 +320,25 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
189
320
|
runId: runIdToUse,
|
|
190
321
|
executionEngine: this.executionEngine,
|
|
191
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
|
+
return run;
|
|
332
|
+
}
|
|
333
|
+
async createRunAsync(options) {
|
|
334
|
+
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
335
|
+
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
336
|
+
{
|
|
337
|
+
workflowId: this.id,
|
|
338
|
+
runId: runIdToUse,
|
|
339
|
+
executionEngine: this.executionEngine,
|
|
340
|
+
executionGraph: this.executionGraph,
|
|
341
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
192
342
|
mastra: this.#mastra,
|
|
193
343
|
retryConfig: this.retryConfig,
|
|
194
344
|
cleanup: () => this.runs.delete(runIdToUse)
|
|
@@ -196,6 +346,27 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
196
346
|
this.inngest
|
|
197
347
|
);
|
|
198
348
|
this.runs.set(runIdToUse, run);
|
|
349
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
350
|
+
if (!workflowSnapshotInStorage) {
|
|
351
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
352
|
+
workflowName: this.id,
|
|
353
|
+
runId: runIdToUse,
|
|
354
|
+
snapshot: {
|
|
355
|
+
runId: runIdToUse,
|
|
356
|
+
status: "pending",
|
|
357
|
+
value: {},
|
|
358
|
+
context: {},
|
|
359
|
+
activePaths: [],
|
|
360
|
+
waitingPaths: {},
|
|
361
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
362
|
+
suspendedPaths: {},
|
|
363
|
+
result: void 0,
|
|
364
|
+
error: void 0,
|
|
365
|
+
// @ts-ignore
|
|
366
|
+
timestamp: Date.now()
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
}
|
|
199
370
|
return run;
|
|
200
371
|
}
|
|
201
372
|
getFunction() {
|
|
@@ -203,8 +374,14 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
203
374
|
return this.function;
|
|
204
375
|
}
|
|
205
376
|
this.function = this.inngest.createFunction(
|
|
206
|
-
|
|
207
|
-
|
|
377
|
+
{
|
|
378
|
+
id: `workflow.${this.id}`,
|
|
379
|
+
// @ts-ignore
|
|
380
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
381
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
382
|
+
// Spread flow control configuration
|
|
383
|
+
...this.flowControlConfig
|
|
384
|
+
},
|
|
208
385
|
{ event: `workflow.${this.id}` },
|
|
209
386
|
async ({ event, step, attempt, publish }) => {
|
|
210
387
|
let { inputData, runId, resume } = event.data;
|
|
@@ -221,12 +398,18 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
221
398
|
try {
|
|
222
399
|
await publish({
|
|
223
400
|
channel: `workflow:${this.id}:${runId}`,
|
|
224
|
-
topic:
|
|
401
|
+
topic: event2,
|
|
225
402
|
data
|
|
226
403
|
});
|
|
227
404
|
} catch (err) {
|
|
228
405
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
229
406
|
}
|
|
407
|
+
},
|
|
408
|
+
on: (_event, _callback) => {
|
|
409
|
+
},
|
|
410
|
+
off: (_event, _callback) => {
|
|
411
|
+
},
|
|
412
|
+
once: (_event, _callback) => {
|
|
230
413
|
}
|
|
231
414
|
};
|
|
232
415
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
@@ -234,12 +417,16 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
234
417
|
workflowId: this.id,
|
|
235
418
|
runId,
|
|
236
419
|
graph: this.executionGraph,
|
|
420
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
237
421
|
input: inputData,
|
|
238
422
|
emitter,
|
|
239
423
|
retryConfig: this.retryConfig,
|
|
240
424
|
runtimeContext: new di.RuntimeContext(),
|
|
241
425
|
// TODO
|
|
242
|
-
resume
|
|
426
|
+
resume,
|
|
427
|
+
abortController: new AbortController(),
|
|
428
|
+
currentSpan: void 0
|
|
429
|
+
// TODO: Pass actual parent AI span from workflow execution context
|
|
243
430
|
});
|
|
244
431
|
return { result, runId };
|
|
245
432
|
}
|
|
@@ -263,32 +450,126 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
263
450
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
264
451
|
}
|
|
265
452
|
};
|
|
266
|
-
function
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
453
|
+
function isAgent(params) {
|
|
454
|
+
return params?.component === "AGENT";
|
|
455
|
+
}
|
|
456
|
+
function isTool(params) {
|
|
457
|
+
return params instanceof tools.Tool;
|
|
458
|
+
}
|
|
459
|
+
function createStep(params) {
|
|
460
|
+
if (isAgent(params)) {
|
|
461
|
+
return {
|
|
462
|
+
id: params.name,
|
|
463
|
+
// @ts-ignore
|
|
464
|
+
inputSchema: zod.z.object({
|
|
465
|
+
prompt: zod.z.string()
|
|
466
|
+
// resourceId: z.string().optional(),
|
|
467
|
+
// threadId: z.string().optional(),
|
|
468
|
+
}),
|
|
469
|
+
// @ts-ignore
|
|
470
|
+
outputSchema: zod.z.object({
|
|
471
|
+
text: zod.z.string()
|
|
472
|
+
}),
|
|
473
|
+
execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
|
|
474
|
+
let streamPromise = {};
|
|
475
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
476
|
+
streamPromise.resolve = resolve;
|
|
477
|
+
streamPromise.reject = reject;
|
|
478
|
+
});
|
|
479
|
+
const toolData = {
|
|
480
|
+
name: params.name,
|
|
481
|
+
args: inputData
|
|
482
|
+
};
|
|
483
|
+
await emitter.emit("watch-v2", {
|
|
484
|
+
type: "workflow-agent-call-start",
|
|
485
|
+
payload: toolData
|
|
486
|
+
});
|
|
487
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
488
|
+
// resourceId: inputData.resourceId,
|
|
489
|
+
// threadId: inputData.threadId,
|
|
490
|
+
runtimeContext,
|
|
491
|
+
tracingContext,
|
|
492
|
+
onFinish: (result) => {
|
|
493
|
+
streamPromise.resolve(result.text);
|
|
494
|
+
},
|
|
495
|
+
abortSignal
|
|
496
|
+
});
|
|
497
|
+
if (abortSignal.aborted) {
|
|
498
|
+
return abort();
|
|
499
|
+
}
|
|
500
|
+
for await (const chunk of fullStream) {
|
|
501
|
+
await emitter.emit("watch-v2", chunk);
|
|
502
|
+
}
|
|
503
|
+
await emitter.emit("watch-v2", {
|
|
504
|
+
type: "workflow-agent-call-finish",
|
|
505
|
+
payload: toolData
|
|
506
|
+
});
|
|
507
|
+
return {
|
|
508
|
+
text: await streamPromise.promise
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
if (isTool(params)) {
|
|
514
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
515
|
+
throw new Error("Tool must have input and output schemas defined");
|
|
516
|
+
}
|
|
517
|
+
return {
|
|
518
|
+
// TODO: tool probably should have strong id type
|
|
519
|
+
// @ts-ignore
|
|
520
|
+
id: params.id,
|
|
521
|
+
inputSchema: params.inputSchema,
|
|
522
|
+
outputSchema: params.outputSchema,
|
|
523
|
+
execute: async ({ inputData, mastra, runtimeContext, tracingContext }) => {
|
|
524
|
+
return params.execute({
|
|
525
|
+
context: inputData,
|
|
526
|
+
mastra: aiTracing.wrapMastra(mastra, tracingContext),
|
|
527
|
+
runtimeContext,
|
|
528
|
+
tracingContext
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
return {
|
|
534
|
+
id: params.id,
|
|
535
|
+
description: params.description,
|
|
536
|
+
inputSchema: params.inputSchema,
|
|
537
|
+
outputSchema: params.outputSchema,
|
|
538
|
+
resumeSchema: params.resumeSchema,
|
|
539
|
+
suspendSchema: params.suspendSchema,
|
|
540
|
+
execute: params.execute
|
|
541
|
+
};
|
|
280
542
|
}
|
|
281
543
|
function init(inngest) {
|
|
282
544
|
return {
|
|
283
545
|
createWorkflow(params) {
|
|
284
546
|
return new InngestWorkflow(params, inngest);
|
|
285
547
|
},
|
|
286
|
-
createStep
|
|
287
|
-
cloneStep
|
|
288
|
-
|
|
548
|
+
createStep,
|
|
549
|
+
cloneStep(step, opts) {
|
|
550
|
+
return {
|
|
551
|
+
id: opts.id,
|
|
552
|
+
description: step.description,
|
|
553
|
+
inputSchema: step.inputSchema,
|
|
554
|
+
outputSchema: step.outputSchema,
|
|
555
|
+
execute: step.execute
|
|
556
|
+
};
|
|
557
|
+
},
|
|
558
|
+
cloneWorkflow(workflow, opts) {
|
|
559
|
+
const wf = new workflows.Workflow({
|
|
560
|
+
id: opts.id,
|
|
561
|
+
inputSchema: workflow.inputSchema,
|
|
562
|
+
outputSchema: workflow.outputSchema,
|
|
563
|
+
steps: workflow.stepDefs,
|
|
564
|
+
mastra: workflow.mastra
|
|
565
|
+
});
|
|
566
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
567
|
+
wf.commit();
|
|
568
|
+
return wf;
|
|
569
|
+
}
|
|
289
570
|
};
|
|
290
571
|
}
|
|
291
|
-
var InngestExecutionEngine = class extends
|
|
572
|
+
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
292
573
|
inngestStep;
|
|
293
574
|
inngestAttempts;
|
|
294
575
|
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
@@ -296,6 +577,18 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
296
577
|
this.inngestStep = inngestStep;
|
|
297
578
|
this.inngestAttempts = inngestAttempts;
|
|
298
579
|
}
|
|
580
|
+
async execute(params) {
|
|
581
|
+
await params.emitter.emit("watch-v2", {
|
|
582
|
+
type: "workflow-start",
|
|
583
|
+
payload: { runId: params.runId }
|
|
584
|
+
});
|
|
585
|
+
const result = await super.execute(params);
|
|
586
|
+
await params.emitter.emit("watch-v2", {
|
|
587
|
+
type: "workflow-finish",
|
|
588
|
+
payload: { runId: params.runId }
|
|
589
|
+
});
|
|
590
|
+
return result;
|
|
591
|
+
}
|
|
299
592
|
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
300
593
|
const base = {
|
|
301
594
|
status: lastOutput.status,
|
|
@@ -353,28 +646,192 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
353
646
|
executionSpan?.end();
|
|
354
647
|
return base;
|
|
355
648
|
}
|
|
356
|
-
async
|
|
649
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
650
|
+
// await this.inngestStep.sleep(id, duration);
|
|
651
|
+
// }
|
|
652
|
+
async executeSleep({
|
|
357
653
|
workflowId,
|
|
358
654
|
runId,
|
|
359
|
-
|
|
655
|
+
entry,
|
|
656
|
+
prevOutput,
|
|
360
657
|
stepResults,
|
|
658
|
+
emitter,
|
|
659
|
+
abortController,
|
|
660
|
+
runtimeContext,
|
|
361
661
|
executionContext,
|
|
362
|
-
|
|
662
|
+
writableStream,
|
|
663
|
+
tracingContext
|
|
664
|
+
}) {
|
|
665
|
+
let { duration, fn } = entry;
|
|
666
|
+
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
667
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
668
|
+
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
669
|
+
attributes: {
|
|
670
|
+
durationMs: duration,
|
|
671
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
if (fn) {
|
|
675
|
+
const stepCallId = crypto.randomUUID();
|
|
676
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
677
|
+
return await fn({
|
|
678
|
+
runId,
|
|
679
|
+
workflowId,
|
|
680
|
+
mastra: this.mastra,
|
|
681
|
+
runtimeContext,
|
|
682
|
+
inputData: prevOutput,
|
|
683
|
+
runCount: -1,
|
|
684
|
+
tracingContext: {
|
|
685
|
+
currentSpan: sleepSpan
|
|
686
|
+
},
|
|
687
|
+
getInitData: () => stepResults?.input,
|
|
688
|
+
getStepResult: (step) => {
|
|
689
|
+
if (!step?.id) {
|
|
690
|
+
return null;
|
|
691
|
+
}
|
|
692
|
+
const result = stepResults[step.id];
|
|
693
|
+
if (result?.status === "success") {
|
|
694
|
+
return result.output;
|
|
695
|
+
}
|
|
696
|
+
return null;
|
|
697
|
+
},
|
|
698
|
+
// TODO: this function shouldn't have suspend probably?
|
|
699
|
+
suspend: async (_suspendPayload) => {
|
|
700
|
+
},
|
|
701
|
+
bail: () => {
|
|
702
|
+
},
|
|
703
|
+
abort: () => {
|
|
704
|
+
abortController?.abort();
|
|
705
|
+
},
|
|
706
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
707
|
+
// TODO: add streamVNext support
|
|
708
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
709
|
+
engine: { step: this.inngestStep },
|
|
710
|
+
abortSignal: abortController?.signal,
|
|
711
|
+
writer: new tools.ToolStream(
|
|
712
|
+
{
|
|
713
|
+
prefix: "workflow-step",
|
|
714
|
+
callId: stepCallId,
|
|
715
|
+
name: "sleep",
|
|
716
|
+
runId
|
|
717
|
+
},
|
|
718
|
+
writableStream
|
|
719
|
+
)
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
sleepSpan?.update({
|
|
723
|
+
attributes: {
|
|
724
|
+
durationMs: duration
|
|
725
|
+
}
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
try {
|
|
729
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
730
|
+
sleepSpan?.end();
|
|
731
|
+
} catch (e) {
|
|
732
|
+
sleepSpan?.error({ error: e });
|
|
733
|
+
throw e;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
async executeSleepUntil({
|
|
737
|
+
workflowId,
|
|
738
|
+
runId,
|
|
739
|
+
entry,
|
|
363
740
|
prevOutput,
|
|
741
|
+
stepResults,
|
|
364
742
|
emitter,
|
|
365
|
-
|
|
743
|
+
abortController,
|
|
744
|
+
runtimeContext,
|
|
745
|
+
executionContext,
|
|
746
|
+
writableStream,
|
|
747
|
+
tracingContext
|
|
366
748
|
}) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
runtimeContext
|
|
749
|
+
let { date, fn } = entry;
|
|
750
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
751
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
752
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
753
|
+
attributes: {
|
|
754
|
+
untilDate: date,
|
|
755
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
756
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
757
|
+
}
|
|
377
758
|
});
|
|
759
|
+
if (fn) {
|
|
760
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
761
|
+
const stepCallId = crypto.randomUUID();
|
|
762
|
+
return await fn({
|
|
763
|
+
runId,
|
|
764
|
+
workflowId,
|
|
765
|
+
mastra: this.mastra,
|
|
766
|
+
runtimeContext,
|
|
767
|
+
inputData: prevOutput,
|
|
768
|
+
runCount: -1,
|
|
769
|
+
tracingContext: {
|
|
770
|
+
currentSpan: sleepUntilSpan
|
|
771
|
+
},
|
|
772
|
+
getInitData: () => stepResults?.input,
|
|
773
|
+
getStepResult: (step) => {
|
|
774
|
+
if (!step?.id) {
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const result = stepResults[step.id];
|
|
778
|
+
if (result?.status === "success") {
|
|
779
|
+
return result.output;
|
|
780
|
+
}
|
|
781
|
+
return null;
|
|
782
|
+
},
|
|
783
|
+
// TODO: this function shouldn't have suspend probably?
|
|
784
|
+
suspend: async (_suspendPayload) => {
|
|
785
|
+
},
|
|
786
|
+
bail: () => {
|
|
787
|
+
},
|
|
788
|
+
abort: () => {
|
|
789
|
+
abortController?.abort();
|
|
790
|
+
},
|
|
791
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
792
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
793
|
+
// TODO: add streamVNext support
|
|
794
|
+
engine: { step: this.inngestStep },
|
|
795
|
+
abortSignal: abortController?.signal,
|
|
796
|
+
writer: new tools.ToolStream(
|
|
797
|
+
{
|
|
798
|
+
prefix: "workflow-step",
|
|
799
|
+
callId: stepCallId,
|
|
800
|
+
name: "sleep",
|
|
801
|
+
runId
|
|
802
|
+
},
|
|
803
|
+
writableStream
|
|
804
|
+
)
|
|
805
|
+
});
|
|
806
|
+
});
|
|
807
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
808
|
+
sleepUntilSpan?.update({
|
|
809
|
+
attributes: {
|
|
810
|
+
durationMs: Math.max(0, time)
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
if (!(date instanceof Date)) {
|
|
815
|
+
sleepUntilSpan?.end();
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
try {
|
|
819
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
820
|
+
sleepUntilSpan?.end();
|
|
821
|
+
} catch (e) {
|
|
822
|
+
sleepUntilSpan?.error({ error: e });
|
|
823
|
+
throw e;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
827
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
828
|
+
event: `user-event-${event}`,
|
|
829
|
+
timeout: timeout ?? 5e3
|
|
830
|
+
});
|
|
831
|
+
if (eventData === null) {
|
|
832
|
+
throw "Timeout waiting for event";
|
|
833
|
+
}
|
|
834
|
+
return eventData?.data;
|
|
378
835
|
}
|
|
379
836
|
async executeStep({
|
|
380
837
|
step,
|
|
@@ -383,11 +840,24 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
383
840
|
resume,
|
|
384
841
|
prevOutput,
|
|
385
842
|
emitter,
|
|
386
|
-
|
|
843
|
+
abortController,
|
|
844
|
+
runtimeContext,
|
|
845
|
+
tracingContext,
|
|
846
|
+
writableStream,
|
|
847
|
+
disableScorers
|
|
387
848
|
}) {
|
|
388
|
-
|
|
849
|
+
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
850
|
+
name: `workflow step: '${step.id}'`,
|
|
851
|
+
type: aiTracing.AISpanType.WORKFLOW_STEP,
|
|
852
|
+
input: prevOutput,
|
|
853
|
+
attributes: {
|
|
854
|
+
stepId: step.id
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
const startedAt = await this.inngestStep.run(
|
|
389
858
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
390
859
|
async () => {
|
|
860
|
+
const startedAt2 = Date.now();
|
|
391
861
|
await emitter.emit("watch", {
|
|
392
862
|
type: "watch",
|
|
393
863
|
payload: {
|
|
@@ -409,6 +879,16 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
409
879
|
},
|
|
410
880
|
eventTimestamp: Date.now()
|
|
411
881
|
});
|
|
882
|
+
await emitter.emit("watch-v2", {
|
|
883
|
+
type: "workflow-step-start",
|
|
884
|
+
payload: {
|
|
885
|
+
id: step.id,
|
|
886
|
+
status: "running",
|
|
887
|
+
payload: prevOutput,
|
|
888
|
+
startedAt: startedAt2
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
return startedAt2;
|
|
412
892
|
}
|
|
413
893
|
);
|
|
414
894
|
if (step instanceof InngestWorkflow) {
|
|
@@ -469,6 +949,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
469
949
|
},
|
|
470
950
|
eventTimestamp: Date.now()
|
|
471
951
|
});
|
|
952
|
+
await emitter.emit("watch-v2", {
|
|
953
|
+
type: "workflow-step-result",
|
|
954
|
+
payload: {
|
|
955
|
+
id: step.id,
|
|
956
|
+
status: "failed",
|
|
957
|
+
error: result?.error,
|
|
958
|
+
payload: prevOutput
|
|
959
|
+
}
|
|
960
|
+
});
|
|
472
961
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
473
962
|
} else if (result.status === "suspended") {
|
|
474
963
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -495,6 +984,13 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
495
984
|
},
|
|
496
985
|
eventTimestamp: Date.now()
|
|
497
986
|
});
|
|
987
|
+
await emitter.emit("watch-v2", {
|
|
988
|
+
type: "workflow-step-suspended",
|
|
989
|
+
payload: {
|
|
990
|
+
id: step.id,
|
|
991
|
+
status: "suspended"
|
|
992
|
+
}
|
|
993
|
+
});
|
|
498
994
|
return {
|
|
499
995
|
executionContext,
|
|
500
996
|
result: {
|
|
@@ -545,6 +1041,21 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
545
1041
|
},
|
|
546
1042
|
eventTimestamp: Date.now()
|
|
547
1043
|
});
|
|
1044
|
+
await emitter.emit("watch-v2", {
|
|
1045
|
+
type: "workflow-step-result",
|
|
1046
|
+
payload: {
|
|
1047
|
+
id: step.id,
|
|
1048
|
+
status: "success",
|
|
1049
|
+
output: result?.result
|
|
1050
|
+
}
|
|
1051
|
+
});
|
|
1052
|
+
await emitter.emit("watch-v2", {
|
|
1053
|
+
type: "workflow-step-finish",
|
|
1054
|
+
payload: {
|
|
1055
|
+
id: step.id,
|
|
1056
|
+
metadata: {}
|
|
1057
|
+
}
|
|
1058
|
+
});
|
|
548
1059
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
549
1060
|
}
|
|
550
1061
|
);
|
|
@@ -554,12 +1065,18 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
554
1065
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
555
1066
|
let execResults;
|
|
556
1067
|
let suspended;
|
|
1068
|
+
let bailed;
|
|
557
1069
|
try {
|
|
558
1070
|
const result = await step.execute({
|
|
1071
|
+
runId: executionContext.runId,
|
|
559
1072
|
mastra: this.mastra,
|
|
560
1073
|
runtimeContext,
|
|
1074
|
+
writableStream,
|
|
561
1075
|
inputData: prevOutput,
|
|
562
1076
|
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1077
|
+
tracingContext: {
|
|
1078
|
+
currentSpan: stepAISpan
|
|
1079
|
+
},
|
|
563
1080
|
getInitData: () => stepResults?.input,
|
|
564
1081
|
getStepResult: (step2) => {
|
|
565
1082
|
const result2 = stepResults[step2.id];
|
|
@@ -572,24 +1089,60 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
572
1089
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
573
1090
|
suspended = { payload: suspendPayload };
|
|
574
1091
|
},
|
|
1092
|
+
bail: (result2) => {
|
|
1093
|
+
bailed = { payload: result2 };
|
|
1094
|
+
},
|
|
575
1095
|
resume: {
|
|
576
1096
|
steps: resume?.steps?.slice(1) || [],
|
|
577
1097
|
resumePayload: resume?.resumePayload,
|
|
578
1098
|
// @ts-ignore
|
|
579
1099
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
580
1100
|
},
|
|
581
|
-
emitter
|
|
1101
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1102
|
+
engine: {
|
|
1103
|
+
step: this.inngestStep
|
|
1104
|
+
},
|
|
1105
|
+
abortSignal: abortController.signal
|
|
582
1106
|
});
|
|
583
|
-
|
|
1107
|
+
const endedAt = Date.now();
|
|
1108
|
+
execResults = {
|
|
1109
|
+
status: "success",
|
|
1110
|
+
output: result,
|
|
1111
|
+
startedAt,
|
|
1112
|
+
endedAt,
|
|
1113
|
+
payload: prevOutput,
|
|
1114
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1115
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1116
|
+
};
|
|
584
1117
|
} catch (e) {
|
|
585
|
-
execResults = {
|
|
1118
|
+
execResults = {
|
|
1119
|
+
status: "failed",
|
|
1120
|
+
payload: prevOutput,
|
|
1121
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1122
|
+
endedAt: Date.now(),
|
|
1123
|
+
startedAt,
|
|
1124
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1125
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1126
|
+
};
|
|
586
1127
|
}
|
|
587
1128
|
if (suspended) {
|
|
588
|
-
execResults = {
|
|
1129
|
+
execResults = {
|
|
1130
|
+
status: "suspended",
|
|
1131
|
+
suspendedPayload: suspended.payload,
|
|
1132
|
+
payload: prevOutput,
|
|
1133
|
+
suspendedAt: Date.now(),
|
|
1134
|
+
startedAt,
|
|
1135
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1136
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1137
|
+
};
|
|
1138
|
+
} else if (bailed) {
|
|
1139
|
+
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
589
1140
|
}
|
|
590
1141
|
if (execResults.status === "failed") {
|
|
591
1142
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
592
|
-
|
|
1143
|
+
const error = new Error(execResults.error);
|
|
1144
|
+
stepAISpan?.error({ error });
|
|
1145
|
+
throw error;
|
|
593
1146
|
}
|
|
594
1147
|
}
|
|
595
1148
|
await emitter.emit("watch", {
|
|
@@ -597,20 +1150,61 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
597
1150
|
payload: {
|
|
598
1151
|
currentStep: {
|
|
599
1152
|
id: step.id,
|
|
600
|
-
|
|
601
|
-
output: execResults.output
|
|
1153
|
+
...execResults
|
|
602
1154
|
},
|
|
603
1155
|
workflowState: {
|
|
604
1156
|
status: "running",
|
|
605
|
-
steps: stepResults,
|
|
1157
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
606
1158
|
result: null,
|
|
607
1159
|
error: null
|
|
608
1160
|
}
|
|
609
1161
|
},
|
|
610
1162
|
eventTimestamp: Date.now()
|
|
611
1163
|
});
|
|
1164
|
+
if (execResults.status === "suspended") {
|
|
1165
|
+
await emitter.emit("watch-v2", {
|
|
1166
|
+
type: "workflow-step-suspended",
|
|
1167
|
+
payload: {
|
|
1168
|
+
id: step.id,
|
|
1169
|
+
...execResults
|
|
1170
|
+
}
|
|
1171
|
+
});
|
|
1172
|
+
} else {
|
|
1173
|
+
await emitter.emit("watch-v2", {
|
|
1174
|
+
type: "workflow-step-result",
|
|
1175
|
+
payload: {
|
|
1176
|
+
id: step.id,
|
|
1177
|
+
...execResults
|
|
1178
|
+
}
|
|
1179
|
+
});
|
|
1180
|
+
await emitter.emit("watch-v2", {
|
|
1181
|
+
type: "workflow-step-finish",
|
|
1182
|
+
payload: {
|
|
1183
|
+
id: step.id,
|
|
1184
|
+
metadata: {}
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
}
|
|
1188
|
+
stepAISpan?.end({ output: execResults });
|
|
612
1189
|
return { result: execResults, executionContext, stepResults };
|
|
613
1190
|
});
|
|
1191
|
+
if (disableScorers !== false) {
|
|
1192
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1193
|
+
if (step.scorers) {
|
|
1194
|
+
await this.runScorers({
|
|
1195
|
+
scorers: step.scorers,
|
|
1196
|
+
runId: executionContext.runId,
|
|
1197
|
+
input: prevOutput,
|
|
1198
|
+
output: stepRes.result,
|
|
1199
|
+
workflowId: executionContext.workflowId,
|
|
1200
|
+
stepId: step.id,
|
|
1201
|
+
runtimeContext,
|
|
1202
|
+
disableScorers,
|
|
1203
|
+
tracingContext: { currentSpan: stepAISpan }
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
614
1208
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
615
1209
|
Object.assign(stepResults, stepRes.stepResults);
|
|
616
1210
|
return stepRes.result;
|
|
@@ -619,7 +1213,11 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
619
1213
|
workflowId,
|
|
620
1214
|
runId,
|
|
621
1215
|
stepResults,
|
|
622
|
-
executionContext
|
|
1216
|
+
executionContext,
|
|
1217
|
+
serializedStepGraph,
|
|
1218
|
+
workflowStatus,
|
|
1219
|
+
result,
|
|
1220
|
+
error
|
|
623
1221
|
}) {
|
|
624
1222
|
await this.inngestStep.run(
|
|
625
1223
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -633,6 +1231,11 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
633
1231
|
context: stepResults,
|
|
634
1232
|
activePaths: [],
|
|
635
1233
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1234
|
+
waitingPaths: {},
|
|
1235
|
+
serializedStepGraph,
|
|
1236
|
+
status: workflowStatus,
|
|
1237
|
+
result,
|
|
1238
|
+
error,
|
|
636
1239
|
// @ts-ignore
|
|
637
1240
|
timestamp: Date.now()
|
|
638
1241
|
}
|
|
@@ -647,20 +1250,47 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
647
1250
|
prevOutput,
|
|
648
1251
|
prevStep,
|
|
649
1252
|
stepResults,
|
|
1253
|
+
serializedStepGraph,
|
|
650
1254
|
resume,
|
|
651
1255
|
executionContext,
|
|
652
1256
|
emitter,
|
|
653
|
-
|
|
1257
|
+
abortController,
|
|
1258
|
+
runtimeContext,
|
|
1259
|
+
writableStream,
|
|
1260
|
+
disableScorers,
|
|
1261
|
+
tracingContext
|
|
654
1262
|
}) {
|
|
1263
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1264
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
|
|
1265
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1266
|
+
input: prevOutput,
|
|
1267
|
+
attributes: {
|
|
1268
|
+
conditionCount: entry.conditions.length
|
|
1269
|
+
}
|
|
1270
|
+
});
|
|
655
1271
|
let execResults;
|
|
656
1272
|
const truthyIndexes = (await Promise.all(
|
|
657
1273
|
entry.conditions.map(
|
|
658
1274
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1275
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1276
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1277
|
+
name: `condition: '${index}'`,
|
|
1278
|
+
input: prevOutput,
|
|
1279
|
+
attributes: {
|
|
1280
|
+
conditionIndex: index
|
|
1281
|
+
}
|
|
1282
|
+
});
|
|
659
1283
|
try {
|
|
660
1284
|
const result = await cond({
|
|
1285
|
+
runId,
|
|
1286
|
+
workflowId,
|
|
661
1287
|
mastra: this.mastra,
|
|
662
1288
|
runtimeContext,
|
|
1289
|
+
runCount: -1,
|
|
663
1290
|
inputData: prevOutput,
|
|
1291
|
+
tracingContext: {
|
|
1292
|
+
currentSpan: evalSpan
|
|
1293
|
+
},
|
|
664
1294
|
getInitData: () => stepResults?.input,
|
|
665
1295
|
getStepResult: (step) => {
|
|
666
1296
|
if (!step?.id) {
|
|
@@ -675,22 +1305,61 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
675
1305
|
// TODO: this function shouldn't have suspend probably?
|
|
676
1306
|
suspend: async (_suspendPayload) => {
|
|
677
1307
|
},
|
|
678
|
-
|
|
1308
|
+
bail: () => {
|
|
1309
|
+
},
|
|
1310
|
+
abort: () => {
|
|
1311
|
+
abortController.abort();
|
|
1312
|
+
},
|
|
1313
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1314
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1315
|
+
// TODO: add streamVNext support
|
|
1316
|
+
engine: {
|
|
1317
|
+
step: this.inngestStep
|
|
1318
|
+
},
|
|
1319
|
+
abortSignal: abortController.signal,
|
|
1320
|
+
writer: new tools.ToolStream(
|
|
1321
|
+
{
|
|
1322
|
+
prefix: "workflow-step",
|
|
1323
|
+
callId: crypto.randomUUID(),
|
|
1324
|
+
name: "conditional",
|
|
1325
|
+
runId
|
|
1326
|
+
},
|
|
1327
|
+
writableStream
|
|
1328
|
+
)
|
|
1329
|
+
});
|
|
1330
|
+
evalSpan?.end({
|
|
1331
|
+
output: result,
|
|
1332
|
+
attributes: {
|
|
1333
|
+
result: !!result
|
|
1334
|
+
}
|
|
679
1335
|
});
|
|
680
1336
|
return result ? index : null;
|
|
681
1337
|
} catch (e) {
|
|
1338
|
+
evalSpan?.error({
|
|
1339
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1340
|
+
attributes: {
|
|
1341
|
+
result: false
|
|
1342
|
+
}
|
|
1343
|
+
});
|
|
682
1344
|
return null;
|
|
683
1345
|
}
|
|
684
1346
|
})
|
|
685
1347
|
)
|
|
686
1348
|
)).filter((index) => index !== null);
|
|
687
1349
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1350
|
+
conditionalSpan?.update({
|
|
1351
|
+
attributes: {
|
|
1352
|
+
truthyIndexes,
|
|
1353
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1354
|
+
}
|
|
1355
|
+
});
|
|
688
1356
|
const results = await Promise.all(
|
|
689
1357
|
stepsToRun.map(
|
|
690
1358
|
(step, index) => this.executeEntry({
|
|
691
1359
|
workflowId,
|
|
692
1360
|
runId,
|
|
693
1361
|
entry: step,
|
|
1362
|
+
serializedStepGraph,
|
|
694
1363
|
prevStep,
|
|
695
1364
|
stepResults,
|
|
696
1365
|
resume,
|
|
@@ -703,27 +1372,42 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
703
1372
|
executionSpan: executionContext.executionSpan
|
|
704
1373
|
},
|
|
705
1374
|
emitter,
|
|
706
|
-
|
|
1375
|
+
abortController,
|
|
1376
|
+
runtimeContext,
|
|
1377
|
+
writableStream,
|
|
1378
|
+
disableScorers,
|
|
1379
|
+
tracingContext: {
|
|
1380
|
+
currentSpan: conditionalSpan
|
|
1381
|
+
}
|
|
707
1382
|
})
|
|
708
1383
|
)
|
|
709
1384
|
);
|
|
710
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
711
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1385
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1386
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
712
1387
|
if (hasFailed) {
|
|
713
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1388
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
714
1389
|
} else if (hasSuspended) {
|
|
715
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1390
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
716
1391
|
} else {
|
|
717
1392
|
execResults = {
|
|
718
1393
|
status: "success",
|
|
719
1394
|
output: results.reduce((acc, result, index) => {
|
|
720
|
-
if (result.status === "success") {
|
|
1395
|
+
if (result.result.status === "success") {
|
|
721
1396
|
acc[stepsToRun[index].step.id] = result.output;
|
|
722
1397
|
}
|
|
723
1398
|
return acc;
|
|
724
1399
|
}, {})
|
|
725
1400
|
};
|
|
726
1401
|
}
|
|
1402
|
+
if (execResults.status === "failed") {
|
|
1403
|
+
conditionalSpan?.error({
|
|
1404
|
+
error: new Error(execResults.error)
|
|
1405
|
+
});
|
|
1406
|
+
} else {
|
|
1407
|
+
conditionalSpan?.end({
|
|
1408
|
+
output: execResults.output || execResults
|
|
1409
|
+
});
|
|
1410
|
+
}
|
|
727
1411
|
return execResults;
|
|
728
1412
|
}
|
|
729
1413
|
};
|
|
@@ -731,5 +1415,8 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
731
1415
|
exports.InngestExecutionEngine = InngestExecutionEngine;
|
|
732
1416
|
exports.InngestRun = InngestRun;
|
|
733
1417
|
exports.InngestWorkflow = InngestWorkflow;
|
|
1418
|
+
exports.createStep = createStep;
|
|
734
1419
|
exports.init = init;
|
|
735
1420
|
exports.serve = serve;
|
|
1421
|
+
//# sourceMappingURL=index.cjs.map
|
|
1422
|
+
//# sourceMappingURL=index.cjs.map
|