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