@mastra/inngest 0.0.0-vector-sources-20250516175436 → 0.0.0-vector-extension-schema-20250922130418
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 +1022 -2
- package/LICENSE.md +11 -42
- package/dist/index.cjs +744 -102
- 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 +741 -100
- 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 -958
- 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,179 @@ 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: workflows.getStepResult.bind(this, stepResults),
|
|
668
|
+
// TODO: this function shouldn't have suspend probably?
|
|
669
|
+
suspend: async (_suspendPayload) => {
|
|
670
|
+
},
|
|
671
|
+
bail: () => {
|
|
672
|
+
},
|
|
673
|
+
abort: () => {
|
|
674
|
+
abortController?.abort();
|
|
675
|
+
},
|
|
676
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
677
|
+
// TODO: add streamVNext support
|
|
678
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
679
|
+
engine: { step: this.inngestStep },
|
|
680
|
+
abortSignal: abortController?.signal,
|
|
681
|
+
writer: new tools.ToolStream(
|
|
682
|
+
{
|
|
683
|
+
prefix: "workflow-step",
|
|
684
|
+
callId: stepCallId,
|
|
685
|
+
name: "sleep",
|
|
686
|
+
runId
|
|
687
|
+
},
|
|
688
|
+
writableStream
|
|
689
|
+
)
|
|
690
|
+
});
|
|
691
|
+
});
|
|
692
|
+
sleepSpan?.update({
|
|
693
|
+
attributes: {
|
|
694
|
+
durationMs: duration
|
|
695
|
+
}
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
try {
|
|
699
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
700
|
+
sleepSpan?.end();
|
|
701
|
+
} catch (e) {
|
|
702
|
+
sleepSpan?.error({ error: e });
|
|
703
|
+
throw e;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
async executeSleepUntil({
|
|
707
|
+
workflowId,
|
|
708
|
+
runId,
|
|
709
|
+
entry,
|
|
363
710
|
prevOutput,
|
|
711
|
+
stepResults,
|
|
364
712
|
emitter,
|
|
365
|
-
|
|
713
|
+
abortController,
|
|
714
|
+
runtimeContext,
|
|
715
|
+
executionContext,
|
|
716
|
+
writableStream,
|
|
717
|
+
tracingContext
|
|
366
718
|
}) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
719
|
+
let { date, fn } = entry;
|
|
720
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
721
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
722
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
723
|
+
attributes: {
|
|
724
|
+
untilDate: date,
|
|
725
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
726
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
727
|
+
},
|
|
728
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
377
729
|
});
|
|
730
|
+
if (fn) {
|
|
731
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
732
|
+
const stepCallId = crypto.randomUUID();
|
|
733
|
+
return await fn({
|
|
734
|
+
runId,
|
|
735
|
+
workflowId,
|
|
736
|
+
mastra: this.mastra,
|
|
737
|
+
runtimeContext,
|
|
738
|
+
inputData: prevOutput,
|
|
739
|
+
runCount: -1,
|
|
740
|
+
tracingContext: {
|
|
741
|
+
currentSpan: sleepUntilSpan
|
|
742
|
+
},
|
|
743
|
+
getInitData: () => stepResults?.input,
|
|
744
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
745
|
+
// TODO: this function shouldn't have suspend probably?
|
|
746
|
+
suspend: async (_suspendPayload) => {
|
|
747
|
+
},
|
|
748
|
+
bail: () => {
|
|
749
|
+
},
|
|
750
|
+
abort: () => {
|
|
751
|
+
abortController?.abort();
|
|
752
|
+
},
|
|
753
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
754
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
755
|
+
// TODO: add streamVNext support
|
|
756
|
+
engine: { step: this.inngestStep },
|
|
757
|
+
abortSignal: abortController?.signal,
|
|
758
|
+
writer: new tools.ToolStream(
|
|
759
|
+
{
|
|
760
|
+
prefix: "workflow-step",
|
|
761
|
+
callId: stepCallId,
|
|
762
|
+
name: "sleep",
|
|
763
|
+
runId
|
|
764
|
+
},
|
|
765
|
+
writableStream
|
|
766
|
+
)
|
|
767
|
+
});
|
|
768
|
+
});
|
|
769
|
+
if (date && !(date instanceof Date)) {
|
|
770
|
+
date = new Date(date);
|
|
771
|
+
}
|
|
772
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
773
|
+
sleepUntilSpan?.update({
|
|
774
|
+
attributes: {
|
|
775
|
+
durationMs: Math.max(0, time)
|
|
776
|
+
}
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
if (!(date instanceof Date)) {
|
|
780
|
+
sleepUntilSpan?.end();
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
try {
|
|
784
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
785
|
+
sleepUntilSpan?.end();
|
|
786
|
+
} catch (e) {
|
|
787
|
+
sleepUntilSpan?.error({ error: e });
|
|
788
|
+
throw e;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
792
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
793
|
+
event: `user-event-${event}`,
|
|
794
|
+
timeout: timeout ?? 5e3
|
|
795
|
+
});
|
|
796
|
+
if (eventData === null) {
|
|
797
|
+
throw "Timeout waiting for event";
|
|
798
|
+
}
|
|
799
|
+
return eventData?.data;
|
|
378
800
|
}
|
|
379
801
|
async executeStep({
|
|
380
802
|
step,
|
|
@@ -383,11 +805,25 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
383
805
|
resume,
|
|
384
806
|
prevOutput,
|
|
385
807
|
emitter,
|
|
386
|
-
|
|
808
|
+
abortController,
|
|
809
|
+
runtimeContext,
|
|
810
|
+
tracingContext,
|
|
811
|
+
writableStream,
|
|
812
|
+
disableScorers
|
|
387
813
|
}) {
|
|
388
|
-
|
|
814
|
+
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
815
|
+
name: `workflow step: '${step.id}'`,
|
|
816
|
+
type: aiTracing.AISpanType.WORKFLOW_STEP,
|
|
817
|
+
input: prevOutput,
|
|
818
|
+
attributes: {
|
|
819
|
+
stepId: step.id
|
|
820
|
+
},
|
|
821
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
822
|
+
});
|
|
823
|
+
const startedAt = await this.inngestStep.run(
|
|
389
824
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
390
825
|
async () => {
|
|
826
|
+
const startedAt2 = Date.now();
|
|
391
827
|
await emitter.emit("watch", {
|
|
392
828
|
type: "watch",
|
|
393
829
|
payload: {
|
|
@@ -409,6 +845,16 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
409
845
|
},
|
|
410
846
|
eventTimestamp: Date.now()
|
|
411
847
|
});
|
|
848
|
+
await emitter.emit("watch-v2", {
|
|
849
|
+
type: "workflow-step-start",
|
|
850
|
+
payload: {
|
|
851
|
+
id: step.id,
|
|
852
|
+
status: "running",
|
|
853
|
+
payload: prevOutput,
|
|
854
|
+
startedAt: startedAt2
|
|
855
|
+
}
|
|
856
|
+
});
|
|
857
|
+
return startedAt2;
|
|
412
858
|
}
|
|
413
859
|
);
|
|
414
860
|
if (step instanceof InngestWorkflow) {
|
|
@@ -469,6 +915,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
469
915
|
},
|
|
470
916
|
eventTimestamp: Date.now()
|
|
471
917
|
});
|
|
918
|
+
await emitter.emit("watch-v2", {
|
|
919
|
+
type: "workflow-step-result",
|
|
920
|
+
payload: {
|
|
921
|
+
id: step.id,
|
|
922
|
+
status: "failed",
|
|
923
|
+
error: result?.error,
|
|
924
|
+
payload: prevOutput
|
|
925
|
+
}
|
|
926
|
+
});
|
|
472
927
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
473
928
|
} else if (result.status === "suspended") {
|
|
474
929
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -495,6 +950,13 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
495
950
|
},
|
|
496
951
|
eventTimestamp: Date.now()
|
|
497
952
|
});
|
|
953
|
+
await emitter.emit("watch-v2", {
|
|
954
|
+
type: "workflow-step-suspended",
|
|
955
|
+
payload: {
|
|
956
|
+
id: step.id,
|
|
957
|
+
status: "suspended"
|
|
958
|
+
}
|
|
959
|
+
});
|
|
498
960
|
return {
|
|
499
961
|
executionContext,
|
|
500
962
|
result: {
|
|
@@ -545,6 +1007,21 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
545
1007
|
},
|
|
546
1008
|
eventTimestamp: Date.now()
|
|
547
1009
|
});
|
|
1010
|
+
await emitter.emit("watch-v2", {
|
|
1011
|
+
type: "workflow-step-result",
|
|
1012
|
+
payload: {
|
|
1013
|
+
id: step.id,
|
|
1014
|
+
status: "success",
|
|
1015
|
+
output: result?.result
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
await emitter.emit("watch-v2", {
|
|
1019
|
+
type: "workflow-step-finish",
|
|
1020
|
+
payload: {
|
|
1021
|
+
id: step.id,
|
|
1022
|
+
metadata: {}
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
548
1025
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
549
1026
|
}
|
|
550
1027
|
);
|
|
@@ -554,42 +1031,78 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
554
1031
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
555
1032
|
let execResults;
|
|
556
1033
|
let suspended;
|
|
1034
|
+
let bailed;
|
|
557
1035
|
try {
|
|
558
1036
|
const result = await step.execute({
|
|
1037
|
+
runId: executionContext.runId,
|
|
559
1038
|
mastra: this.mastra,
|
|
560
1039
|
runtimeContext,
|
|
1040
|
+
writableStream,
|
|
561
1041
|
inputData: prevOutput,
|
|
562
1042
|
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const result2 = stepResults[step2.id];
|
|
566
|
-
if (result2?.status === "success") {
|
|
567
|
-
return result2.output;
|
|
568
|
-
}
|
|
569
|
-
return null;
|
|
1043
|
+
tracingContext: {
|
|
1044
|
+
currentSpan: stepAISpan
|
|
570
1045
|
},
|
|
1046
|
+
getInitData: () => stepResults?.input,
|
|
1047
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
571
1048
|
suspend: async (suspendPayload) => {
|
|
572
1049
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
573
1050
|
suspended = { payload: suspendPayload };
|
|
574
1051
|
},
|
|
1052
|
+
bail: (result2) => {
|
|
1053
|
+
bailed = { payload: result2 };
|
|
1054
|
+
},
|
|
575
1055
|
resume: {
|
|
576
1056
|
steps: resume?.steps?.slice(1) || [],
|
|
577
1057
|
resumePayload: resume?.resumePayload,
|
|
578
1058
|
// @ts-ignore
|
|
579
1059
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
580
1060
|
},
|
|
581
|
-
emitter
|
|
1061
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1062
|
+
engine: {
|
|
1063
|
+
step: this.inngestStep
|
|
1064
|
+
},
|
|
1065
|
+
abortSignal: abortController.signal
|
|
582
1066
|
});
|
|
583
|
-
|
|
1067
|
+
const endedAt = Date.now();
|
|
1068
|
+
execResults = {
|
|
1069
|
+
status: "success",
|
|
1070
|
+
output: result,
|
|
1071
|
+
startedAt,
|
|
1072
|
+
endedAt,
|
|
1073
|
+
payload: prevOutput,
|
|
1074
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1075
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1076
|
+
};
|
|
584
1077
|
} catch (e) {
|
|
585
|
-
execResults = {
|
|
1078
|
+
execResults = {
|
|
1079
|
+
status: "failed",
|
|
1080
|
+
payload: prevOutput,
|
|
1081
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1082
|
+
endedAt: Date.now(),
|
|
1083
|
+
startedAt,
|
|
1084
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1085
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1086
|
+
};
|
|
586
1087
|
}
|
|
587
1088
|
if (suspended) {
|
|
588
|
-
execResults = {
|
|
1089
|
+
execResults = {
|
|
1090
|
+
status: "suspended",
|
|
1091
|
+
suspendedPayload: suspended.payload,
|
|
1092
|
+
payload: prevOutput,
|
|
1093
|
+
suspendedAt: Date.now(),
|
|
1094
|
+
startedAt,
|
|
1095
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1096
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1097
|
+
};
|
|
1098
|
+
} else if (bailed) {
|
|
1099
|
+
execResults = { status: "bailed", output: bailed.payload, payload: prevOutput, endedAt: Date.now(), startedAt };
|
|
589
1100
|
}
|
|
590
1101
|
if (execResults.status === "failed") {
|
|
591
1102
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
592
|
-
|
|
1103
|
+
const error = new Error(execResults.error);
|
|
1104
|
+
stepAISpan?.error({ error });
|
|
1105
|
+
throw error;
|
|
593
1106
|
}
|
|
594
1107
|
}
|
|
595
1108
|
await emitter.emit("watch", {
|
|
@@ -597,20 +1110,61 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
597
1110
|
payload: {
|
|
598
1111
|
currentStep: {
|
|
599
1112
|
id: step.id,
|
|
600
|
-
|
|
601
|
-
output: execResults.output
|
|
1113
|
+
...execResults
|
|
602
1114
|
},
|
|
603
1115
|
workflowState: {
|
|
604
1116
|
status: "running",
|
|
605
|
-
steps: stepResults,
|
|
1117
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
606
1118
|
result: null,
|
|
607
1119
|
error: null
|
|
608
1120
|
}
|
|
609
1121
|
},
|
|
610
1122
|
eventTimestamp: Date.now()
|
|
611
1123
|
});
|
|
1124
|
+
if (execResults.status === "suspended") {
|
|
1125
|
+
await emitter.emit("watch-v2", {
|
|
1126
|
+
type: "workflow-step-suspended",
|
|
1127
|
+
payload: {
|
|
1128
|
+
id: step.id,
|
|
1129
|
+
...execResults
|
|
1130
|
+
}
|
|
1131
|
+
});
|
|
1132
|
+
} else {
|
|
1133
|
+
await emitter.emit("watch-v2", {
|
|
1134
|
+
type: "workflow-step-result",
|
|
1135
|
+
payload: {
|
|
1136
|
+
id: step.id,
|
|
1137
|
+
...execResults
|
|
1138
|
+
}
|
|
1139
|
+
});
|
|
1140
|
+
await emitter.emit("watch-v2", {
|
|
1141
|
+
type: "workflow-step-finish",
|
|
1142
|
+
payload: {
|
|
1143
|
+
id: step.id,
|
|
1144
|
+
metadata: {}
|
|
1145
|
+
}
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
stepAISpan?.end({ output: execResults });
|
|
612
1149
|
return { result: execResults, executionContext, stepResults };
|
|
613
1150
|
});
|
|
1151
|
+
if (disableScorers !== false) {
|
|
1152
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1153
|
+
if (step.scorers) {
|
|
1154
|
+
await this.runScorers({
|
|
1155
|
+
scorers: step.scorers,
|
|
1156
|
+
runId: executionContext.runId,
|
|
1157
|
+
input: prevOutput,
|
|
1158
|
+
output: stepRes.result,
|
|
1159
|
+
workflowId: executionContext.workflowId,
|
|
1160
|
+
stepId: step.id,
|
|
1161
|
+
runtimeContext,
|
|
1162
|
+
disableScorers,
|
|
1163
|
+
tracingContext: { currentSpan: stepAISpan }
|
|
1164
|
+
});
|
|
1165
|
+
}
|
|
1166
|
+
});
|
|
1167
|
+
}
|
|
614
1168
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
615
1169
|
Object.assign(stepResults, stepRes.stepResults);
|
|
616
1170
|
return stepRes.result;
|
|
@@ -619,7 +1173,12 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
619
1173
|
workflowId,
|
|
620
1174
|
runId,
|
|
621
1175
|
stepResults,
|
|
622
|
-
|
|
1176
|
+
resourceId,
|
|
1177
|
+
executionContext,
|
|
1178
|
+
serializedStepGraph,
|
|
1179
|
+
workflowStatus,
|
|
1180
|
+
result,
|
|
1181
|
+
error
|
|
623
1182
|
}) {
|
|
624
1183
|
await this.inngestStep.run(
|
|
625
1184
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -627,12 +1186,18 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
627
1186
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
628
1187
|
workflowName: workflowId,
|
|
629
1188
|
runId,
|
|
1189
|
+
resourceId,
|
|
630
1190
|
snapshot: {
|
|
631
1191
|
runId,
|
|
632
1192
|
value: {},
|
|
633
1193
|
context: stepResults,
|
|
634
1194
|
activePaths: [],
|
|
635
1195
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1196
|
+
waitingPaths: {},
|
|
1197
|
+
serializedStepGraph,
|
|
1198
|
+
status: workflowStatus,
|
|
1199
|
+
result,
|
|
1200
|
+
error,
|
|
636
1201
|
// @ts-ignore
|
|
637
1202
|
timestamp: Date.now()
|
|
638
1203
|
}
|
|
@@ -647,50 +1212,109 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
647
1212
|
prevOutput,
|
|
648
1213
|
prevStep,
|
|
649
1214
|
stepResults,
|
|
1215
|
+
serializedStepGraph,
|
|
650
1216
|
resume,
|
|
651
1217
|
executionContext,
|
|
652
1218
|
emitter,
|
|
653
|
-
|
|
1219
|
+
abortController,
|
|
1220
|
+
runtimeContext,
|
|
1221
|
+
writableStream,
|
|
1222
|
+
disableScorers,
|
|
1223
|
+
tracingContext
|
|
654
1224
|
}) {
|
|
1225
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1226
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
|
|
1227
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1228
|
+
input: prevOutput,
|
|
1229
|
+
attributes: {
|
|
1230
|
+
conditionCount: entry.conditions.length
|
|
1231
|
+
},
|
|
1232
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1233
|
+
});
|
|
655
1234
|
let execResults;
|
|
656
1235
|
const truthyIndexes = (await Promise.all(
|
|
657
1236
|
entry.conditions.map(
|
|
658
1237
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1238
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1239
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1240
|
+
name: `condition: '${index}'`,
|
|
1241
|
+
input: prevOutput,
|
|
1242
|
+
attributes: {
|
|
1243
|
+
conditionIndex: index
|
|
1244
|
+
},
|
|
1245
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1246
|
+
});
|
|
659
1247
|
try {
|
|
660
1248
|
const result = await cond({
|
|
1249
|
+
runId,
|
|
1250
|
+
workflowId,
|
|
661
1251
|
mastra: this.mastra,
|
|
662
1252
|
runtimeContext,
|
|
1253
|
+
runCount: -1,
|
|
663
1254
|
inputData: prevOutput,
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if (!step?.id) {
|
|
667
|
-
return null;
|
|
668
|
-
}
|
|
669
|
-
const result2 = stepResults[step.id];
|
|
670
|
-
if (result2?.status === "success") {
|
|
671
|
-
return result2.output;
|
|
672
|
-
}
|
|
673
|
-
return null;
|
|
1255
|
+
tracingContext: {
|
|
1256
|
+
currentSpan: evalSpan
|
|
674
1257
|
},
|
|
1258
|
+
getInitData: () => stepResults?.input,
|
|
1259
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
675
1260
|
// TODO: this function shouldn't have suspend probably?
|
|
676
1261
|
suspend: async (_suspendPayload) => {
|
|
677
1262
|
},
|
|
678
|
-
|
|
1263
|
+
bail: () => {
|
|
1264
|
+
},
|
|
1265
|
+
abort: () => {
|
|
1266
|
+
abortController.abort();
|
|
1267
|
+
},
|
|
1268
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1269
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1270
|
+
// TODO: add streamVNext support
|
|
1271
|
+
engine: {
|
|
1272
|
+
step: this.inngestStep
|
|
1273
|
+
},
|
|
1274
|
+
abortSignal: abortController.signal,
|
|
1275
|
+
writer: new tools.ToolStream(
|
|
1276
|
+
{
|
|
1277
|
+
prefix: "workflow-step",
|
|
1278
|
+
callId: crypto.randomUUID(),
|
|
1279
|
+
name: "conditional",
|
|
1280
|
+
runId
|
|
1281
|
+
},
|
|
1282
|
+
writableStream
|
|
1283
|
+
)
|
|
1284
|
+
});
|
|
1285
|
+
evalSpan?.end({
|
|
1286
|
+
output: result,
|
|
1287
|
+
attributes: {
|
|
1288
|
+
result: !!result
|
|
1289
|
+
}
|
|
679
1290
|
});
|
|
680
1291
|
return result ? index : null;
|
|
681
1292
|
} catch (e) {
|
|
1293
|
+
evalSpan?.error({
|
|
1294
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1295
|
+
attributes: {
|
|
1296
|
+
result: false
|
|
1297
|
+
}
|
|
1298
|
+
});
|
|
682
1299
|
return null;
|
|
683
1300
|
}
|
|
684
1301
|
})
|
|
685
1302
|
)
|
|
686
1303
|
)).filter((index) => index !== null);
|
|
687
1304
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1305
|
+
conditionalSpan?.update({
|
|
1306
|
+
attributes: {
|
|
1307
|
+
truthyIndexes,
|
|
1308
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1309
|
+
}
|
|
1310
|
+
});
|
|
688
1311
|
const results = await Promise.all(
|
|
689
1312
|
stepsToRun.map(
|
|
690
1313
|
(step, index) => this.executeEntry({
|
|
691
1314
|
workflowId,
|
|
692
1315
|
runId,
|
|
693
1316
|
entry: step,
|
|
1317
|
+
serializedStepGraph,
|
|
694
1318
|
prevStep,
|
|
695
1319
|
stepResults,
|
|
696
1320
|
resume,
|
|
@@ -703,27 +1327,42 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
703
1327
|
executionSpan: executionContext.executionSpan
|
|
704
1328
|
},
|
|
705
1329
|
emitter,
|
|
706
|
-
|
|
1330
|
+
abortController,
|
|
1331
|
+
runtimeContext,
|
|
1332
|
+
writableStream,
|
|
1333
|
+
disableScorers,
|
|
1334
|
+
tracingContext: {
|
|
1335
|
+
currentSpan: conditionalSpan
|
|
1336
|
+
}
|
|
707
1337
|
})
|
|
708
1338
|
)
|
|
709
1339
|
);
|
|
710
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
711
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1340
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1341
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
712
1342
|
if (hasFailed) {
|
|
713
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1343
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
714
1344
|
} else if (hasSuspended) {
|
|
715
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1345
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
716
1346
|
} else {
|
|
717
1347
|
execResults = {
|
|
718
1348
|
status: "success",
|
|
719
1349
|
output: results.reduce((acc, result, index) => {
|
|
720
|
-
if (result.status === "success") {
|
|
1350
|
+
if (result.result.status === "success") {
|
|
721
1351
|
acc[stepsToRun[index].step.id] = result.output;
|
|
722
1352
|
}
|
|
723
1353
|
return acc;
|
|
724
1354
|
}, {})
|
|
725
1355
|
};
|
|
726
1356
|
}
|
|
1357
|
+
if (execResults.status === "failed") {
|
|
1358
|
+
conditionalSpan?.error({
|
|
1359
|
+
error: new Error(execResults.error)
|
|
1360
|
+
});
|
|
1361
|
+
} else {
|
|
1362
|
+
conditionalSpan?.end({
|
|
1363
|
+
output: execResults.output || execResults
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
727
1366
|
return execResults;
|
|
728
1367
|
}
|
|
729
1368
|
};
|
|
@@ -731,5 +1370,8 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
731
1370
|
exports.InngestExecutionEngine = InngestExecutionEngine;
|
|
732
1371
|
exports.InngestRun = InngestRun;
|
|
733
1372
|
exports.InngestWorkflow = InngestWorkflow;
|
|
1373
|
+
exports.createStep = createStep;
|
|
734
1374
|
exports.init = init;
|
|
735
1375
|
exports.serve = serve;
|
|
1376
|
+
//# sourceMappingURL=index.cjs.map
|
|
1377
|
+
//# sourceMappingURL=index.cjs.map
|