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