@mastra/inngest 0.0.0-redis-cloud-transporter-20250508203756 → 0.0.0-remove-unused-model-providers-api-20251030210744
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 +1390 -2
- package/LICENSE.md +11 -42
- package/dist/index.cjs +1165 -205
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +325 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1163 -204
- package/dist/index.js.map +1 -0
- package/package.json +40 -21
- 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
|
@@ -1,36 +1,55 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
|
+
var web = require('stream/web');
|
|
4
5
|
var realtime = require('@inngest/realtime');
|
|
6
|
+
var aiTracing = require('@mastra/core/ai-tracing');
|
|
5
7
|
var di = require('@mastra/core/di');
|
|
6
|
-
var
|
|
8
|
+
var stream = require('@mastra/core/stream');
|
|
9
|
+
var tools = require('@mastra/core/tools');
|
|
10
|
+
var workflows = require('@mastra/core/workflows');
|
|
11
|
+
var _constants = require('@mastra/core/workflows/_constants');
|
|
12
|
+
var inngest = require('inngest');
|
|
7
13
|
var hono = require('inngest/hono');
|
|
14
|
+
var zod = require('zod');
|
|
8
15
|
|
|
9
16
|
// src/index.ts
|
|
10
|
-
function serve({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
function serve({
|
|
18
|
+
mastra,
|
|
19
|
+
inngest,
|
|
20
|
+
functions: userFunctions = [],
|
|
21
|
+
registerOptions
|
|
22
|
+
}) {
|
|
23
|
+
const wfs = mastra.listWorkflows();
|
|
24
|
+
const workflowFunctions = Array.from(
|
|
25
|
+
new Set(
|
|
26
|
+
Object.values(wfs).flatMap((wf) => {
|
|
27
|
+
if (wf instanceof InngestWorkflow) {
|
|
28
|
+
wf.__registerMastra(mastra);
|
|
29
|
+
return wf.getFunctions();
|
|
30
|
+
}
|
|
31
|
+
return [];
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
);
|
|
19
35
|
return hono.serve({
|
|
36
|
+
...registerOptions,
|
|
20
37
|
client: inngest,
|
|
21
|
-
functions
|
|
38
|
+
functions: [...workflowFunctions, ...userFunctions]
|
|
22
39
|
});
|
|
23
40
|
}
|
|
24
|
-
var InngestRun = class extends
|
|
41
|
+
var InngestRun = class extends workflows.Run {
|
|
25
42
|
inngest;
|
|
43
|
+
serializedStepGraph;
|
|
26
44
|
#mastra;
|
|
27
45
|
constructor(params, inngest) {
|
|
28
46
|
super(params);
|
|
29
47
|
this.inngest = inngest;
|
|
48
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
30
49
|
this.#mastra = params.mastra;
|
|
31
50
|
}
|
|
32
51
|
async getRuns(eventId) {
|
|
33
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
52
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
|
|
34
53
|
headers: {
|
|
35
54
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
36
55
|
}
|
|
@@ -40,35 +59,96 @@ var InngestRun = class extends vNext.Run {
|
|
|
40
59
|
}
|
|
41
60
|
async getRunOutput(eventId) {
|
|
42
61
|
let runs = await this.getRuns(eventId);
|
|
43
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
62
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
44
63
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
45
64
|
runs = await this.getRuns(eventId);
|
|
46
|
-
if (runs?.[0]?.status === "Failed"
|
|
47
|
-
|
|
65
|
+
if (runs?.[0]?.status === "Failed") {
|
|
66
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
67
|
+
workflowName: this.workflowId,
|
|
68
|
+
runId: this.runId
|
|
69
|
+
});
|
|
70
|
+
return {
|
|
71
|
+
output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
if (runs?.[0]?.status === "Cancelled") {
|
|
75
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
76
|
+
workflowName: this.workflowId,
|
|
77
|
+
runId: this.runId
|
|
78
|
+
});
|
|
79
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
48
80
|
}
|
|
49
81
|
}
|
|
50
82
|
return runs?.[0];
|
|
51
83
|
}
|
|
52
|
-
async
|
|
53
|
-
|
|
84
|
+
async sendEvent(event, data) {
|
|
85
|
+
await this.inngest.send({
|
|
86
|
+
name: `user-event-${event}`,
|
|
87
|
+
data
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async cancel() {
|
|
91
|
+
await this.inngest.send({
|
|
92
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
93
|
+
data: {
|
|
94
|
+
runId: this.runId
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
98
|
+
workflowName: this.workflowId,
|
|
99
|
+
runId: this.runId
|
|
100
|
+
});
|
|
101
|
+
if (snapshot) {
|
|
102
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
103
|
+
workflowName: this.workflowId,
|
|
104
|
+
runId: this.runId,
|
|
105
|
+
resourceId: this.resourceId,
|
|
106
|
+
snapshot: {
|
|
107
|
+
...snapshot,
|
|
108
|
+
status: "canceled"
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async start(params) {
|
|
114
|
+
return this._start(params);
|
|
115
|
+
}
|
|
116
|
+
async _start({
|
|
117
|
+
inputData,
|
|
118
|
+
initialState,
|
|
119
|
+
outputOptions,
|
|
120
|
+
tracingOptions,
|
|
121
|
+
format
|
|
54
122
|
}) {
|
|
55
123
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
56
124
|
workflowName: this.workflowId,
|
|
57
125
|
runId: this.runId,
|
|
126
|
+
resourceId: this.resourceId,
|
|
58
127
|
snapshot: {
|
|
59
128
|
runId: this.runId,
|
|
129
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
60
130
|
value: {},
|
|
61
131
|
context: {},
|
|
62
132
|
activePaths: [],
|
|
63
133
|
suspendedPaths: {},
|
|
64
|
-
|
|
134
|
+
resumeLabels: {},
|
|
135
|
+
waitingPaths: {},
|
|
136
|
+
timestamp: Date.now(),
|
|
137
|
+
status: "running"
|
|
65
138
|
}
|
|
66
139
|
});
|
|
140
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
141
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
67
142
|
const eventOutput = await this.inngest.send({
|
|
68
143
|
name: `workflow.${this.workflowId}`,
|
|
69
144
|
data: {
|
|
70
|
-
inputData,
|
|
71
|
-
|
|
145
|
+
inputData: inputDataToUse,
|
|
146
|
+
initialState: initialStateToUse,
|
|
147
|
+
runId: this.runId,
|
|
148
|
+
resourceId: this.resourceId,
|
|
149
|
+
outputOptions,
|
|
150
|
+
tracingOptions,
|
|
151
|
+
format
|
|
72
152
|
}
|
|
73
153
|
});
|
|
74
154
|
const eventId = eventOutput.ids[0];
|
|
@@ -80,10 +160,23 @@ var InngestRun = class extends vNext.Run {
|
|
|
80
160
|
if (result.status === "failed") {
|
|
81
161
|
result.error = new Error(result.error);
|
|
82
162
|
}
|
|
83
|
-
|
|
163
|
+
if (result.status !== "suspended") {
|
|
164
|
+
this.cleanup?.();
|
|
165
|
+
}
|
|
84
166
|
return result;
|
|
85
167
|
}
|
|
86
168
|
async resume(params) {
|
|
169
|
+
const p = this._resume(params).then((result) => {
|
|
170
|
+
if (result.status !== "suspended") {
|
|
171
|
+
this.closeStreamAction?.().catch(() => {
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
});
|
|
176
|
+
this.executionResults = p;
|
|
177
|
+
return p;
|
|
178
|
+
}
|
|
179
|
+
async _resume(params) {
|
|
87
180
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
88
181
|
(step) => typeof step === "string" ? step : step?.id
|
|
89
182
|
);
|
|
@@ -91,16 +184,20 @@ var InngestRun = class extends vNext.Run {
|
|
|
91
184
|
workflowName: this.workflowId,
|
|
92
185
|
runId: this.runId
|
|
93
186
|
});
|
|
187
|
+
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
188
|
+
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
94
189
|
const eventOutput = await this.inngest.send({
|
|
95
190
|
name: `workflow.${this.workflowId}`,
|
|
96
191
|
data: {
|
|
97
|
-
inputData:
|
|
192
|
+
inputData: resumeDataToUse,
|
|
193
|
+
initialState: snapshot?.value ?? {},
|
|
98
194
|
runId: this.runId,
|
|
195
|
+
workflowId: this.workflowId,
|
|
99
196
|
stepResults: snapshot?.context,
|
|
100
197
|
resume: {
|
|
101
198
|
steps,
|
|
102
199
|
stepResults: snapshot?.context,
|
|
103
|
-
resumePayload:
|
|
200
|
+
resumePayload: resumeDataToUse,
|
|
104
201
|
// @ts-ignore
|
|
105
202
|
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
106
203
|
}
|
|
@@ -117,48 +214,184 @@ var InngestRun = class extends vNext.Run {
|
|
|
117
214
|
}
|
|
118
215
|
return result;
|
|
119
216
|
}
|
|
120
|
-
watch(cb) {
|
|
217
|
+
watch(cb, type = "watch") {
|
|
218
|
+
let active = true;
|
|
121
219
|
const streamPromise = realtime.subscribe(
|
|
122
220
|
{
|
|
123
221
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
124
|
-
topics: [
|
|
222
|
+
topics: [type],
|
|
125
223
|
app: this.inngest
|
|
126
224
|
},
|
|
127
225
|
(message) => {
|
|
128
|
-
|
|
226
|
+
if (active) {
|
|
227
|
+
cb(message.data);
|
|
228
|
+
}
|
|
129
229
|
}
|
|
130
230
|
);
|
|
131
231
|
return () => {
|
|
132
|
-
|
|
133
|
-
|
|
232
|
+
active = false;
|
|
233
|
+
streamPromise.then(async (stream) => {
|
|
234
|
+
return stream.cancel();
|
|
134
235
|
}).catch((err) => {
|
|
135
236
|
console.error(err);
|
|
136
237
|
});
|
|
137
238
|
};
|
|
138
239
|
}
|
|
240
|
+
streamLegacy({ inputData, requestContext } = {}) {
|
|
241
|
+
const { readable, writable } = new TransformStream();
|
|
242
|
+
const writer = writable.getWriter();
|
|
243
|
+
const unwatch = this.watch(async (event) => {
|
|
244
|
+
try {
|
|
245
|
+
await writer.write({
|
|
246
|
+
// @ts-ignore
|
|
247
|
+
type: "start",
|
|
248
|
+
// @ts-ignore
|
|
249
|
+
payload: { runId: this.runId }
|
|
250
|
+
});
|
|
251
|
+
const e = {
|
|
252
|
+
...event,
|
|
253
|
+
type: event.type.replace("workflow-", "")
|
|
254
|
+
};
|
|
255
|
+
if (e.type === "step-output") {
|
|
256
|
+
e.type = e.payload.output.type;
|
|
257
|
+
e.payload = e.payload.output.payload;
|
|
258
|
+
}
|
|
259
|
+
await writer.write(e);
|
|
260
|
+
} catch {
|
|
261
|
+
}
|
|
262
|
+
}, "watch-v2");
|
|
263
|
+
this.closeStreamAction = async () => {
|
|
264
|
+
await writer.write({
|
|
265
|
+
type: "finish",
|
|
266
|
+
// @ts-ignore
|
|
267
|
+
payload: { runId: this.runId }
|
|
268
|
+
});
|
|
269
|
+
unwatch();
|
|
270
|
+
try {
|
|
271
|
+
await writer.close();
|
|
272
|
+
} catch (err) {
|
|
273
|
+
console.error("Error closing stream:", err);
|
|
274
|
+
} finally {
|
|
275
|
+
writer.releaseLock();
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
|
|
279
|
+
if (result.status !== "suspended") {
|
|
280
|
+
this.closeStreamAction?.().catch(() => {
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return result;
|
|
284
|
+
});
|
|
285
|
+
return {
|
|
286
|
+
stream: readable,
|
|
287
|
+
getWorkflowState: () => this.executionResults
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
stream({
|
|
291
|
+
inputData,
|
|
292
|
+
requestContext,
|
|
293
|
+
tracingOptions,
|
|
294
|
+
closeOnSuspend = true,
|
|
295
|
+
initialState,
|
|
296
|
+
outputOptions
|
|
297
|
+
} = {}) {
|
|
298
|
+
if (this.closeStreamAction && this.streamOutput) {
|
|
299
|
+
return this.streamOutput;
|
|
300
|
+
}
|
|
301
|
+
this.closeStreamAction = async () => {
|
|
302
|
+
};
|
|
303
|
+
const self = this;
|
|
304
|
+
const stream$1 = new web.ReadableStream({
|
|
305
|
+
async start(controller) {
|
|
306
|
+
const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
|
|
307
|
+
controller.enqueue({
|
|
308
|
+
type,
|
|
309
|
+
runId: self.runId,
|
|
310
|
+
from,
|
|
311
|
+
payload: {
|
|
312
|
+
stepName: payload?.id,
|
|
313
|
+
...payload
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}, "watch-v2");
|
|
317
|
+
self.closeStreamAction = async () => {
|
|
318
|
+
unwatch();
|
|
319
|
+
try {
|
|
320
|
+
await controller.close();
|
|
321
|
+
} catch (err) {
|
|
322
|
+
console.error("Error closing stream:", err);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
const executionResultsPromise = self._start({
|
|
326
|
+
inputData,
|
|
327
|
+
requestContext,
|
|
328
|
+
// tracingContext, // We are not able to pass a reference to a span here, what to do?
|
|
329
|
+
initialState,
|
|
330
|
+
tracingOptions,
|
|
331
|
+
outputOptions,
|
|
332
|
+
format: "vnext"
|
|
333
|
+
});
|
|
334
|
+
let executionResults;
|
|
335
|
+
try {
|
|
336
|
+
executionResults = await executionResultsPromise;
|
|
337
|
+
if (closeOnSuspend) {
|
|
338
|
+
self.closeStreamAction?.().catch(() => {
|
|
339
|
+
});
|
|
340
|
+
} else if (executionResults.status !== "suspended") {
|
|
341
|
+
self.closeStreamAction?.().catch(() => {
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
if (self.streamOutput) {
|
|
345
|
+
self.streamOutput.updateResults(
|
|
346
|
+
executionResults
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
} catch (err) {
|
|
350
|
+
self.streamOutput?.rejectResults(err);
|
|
351
|
+
self.closeStreamAction?.().catch(() => {
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
this.streamOutput = new stream.WorkflowRunOutput({
|
|
357
|
+
runId: this.runId,
|
|
358
|
+
workflowId: this.workflowId,
|
|
359
|
+
stream: stream$1
|
|
360
|
+
});
|
|
361
|
+
return this.streamOutput;
|
|
362
|
+
}
|
|
363
|
+
streamVNext(args = {}) {
|
|
364
|
+
return this.stream(args);
|
|
365
|
+
}
|
|
139
366
|
};
|
|
140
|
-
var InngestWorkflow = class _InngestWorkflow extends
|
|
367
|
+
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
141
368
|
#mastra;
|
|
142
369
|
inngest;
|
|
143
370
|
function;
|
|
371
|
+
flowControlConfig;
|
|
144
372
|
constructor(params, inngest) {
|
|
145
|
-
|
|
373
|
+
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
374
|
+
super(workflowParams);
|
|
375
|
+
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
376
|
+
([_, value]) => value !== void 0
|
|
377
|
+
);
|
|
378
|
+
this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
|
|
146
379
|
this.#mastra = params.mastra;
|
|
147
380
|
this.inngest = inngest;
|
|
148
381
|
}
|
|
149
|
-
async
|
|
382
|
+
async listWorkflowRuns(args) {
|
|
150
383
|
const storage = this.#mastra?.getStorage();
|
|
151
384
|
if (!storage) {
|
|
152
385
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
153
386
|
return { runs: [], total: 0 };
|
|
154
387
|
}
|
|
155
|
-
return storage.
|
|
388
|
+
return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
|
|
156
389
|
}
|
|
157
390
|
async getWorkflowRunById(runId) {
|
|
158
391
|
const storage = this.#mastra?.getStorage();
|
|
159
392
|
if (!storage) {
|
|
160
393
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
161
|
-
return null;
|
|
394
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
162
395
|
}
|
|
163
396
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
164
397
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
@@ -181,21 +414,60 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
181
414
|
}
|
|
182
415
|
}
|
|
183
416
|
}
|
|
184
|
-
|
|
417
|
+
/**
|
|
418
|
+
* @deprecated Use createRunAsync() instead.
|
|
419
|
+
* @throws {Error} Always throws an error directing users to use createRunAsync()
|
|
420
|
+
*/
|
|
421
|
+
createRun(_options) {
|
|
422
|
+
throw new Error(
|
|
423
|
+
"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."
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
async createRunAsync(options) {
|
|
185
427
|
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
186
428
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
187
429
|
{
|
|
188
430
|
workflowId: this.id,
|
|
189
431
|
runId: runIdToUse,
|
|
432
|
+
resourceId: options?.resourceId,
|
|
190
433
|
executionEngine: this.executionEngine,
|
|
191
434
|
executionGraph: this.executionGraph,
|
|
435
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
192
436
|
mastra: this.#mastra,
|
|
193
437
|
retryConfig: this.retryConfig,
|
|
194
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
438
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
439
|
+
workflowSteps: this.steps
|
|
195
440
|
},
|
|
196
441
|
this.inngest
|
|
197
442
|
);
|
|
198
443
|
this.runs.set(runIdToUse, run);
|
|
444
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
|
|
445
|
+
workflowStatus: run.workflowRunStatus,
|
|
446
|
+
stepResults: {}
|
|
447
|
+
});
|
|
448
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
449
|
+
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
450
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
451
|
+
workflowName: this.id,
|
|
452
|
+
runId: runIdToUse,
|
|
453
|
+
resourceId: options?.resourceId,
|
|
454
|
+
snapshot: {
|
|
455
|
+
runId: runIdToUse,
|
|
456
|
+
status: "pending",
|
|
457
|
+
value: {},
|
|
458
|
+
context: {},
|
|
459
|
+
activePaths: [],
|
|
460
|
+
waitingPaths: {},
|
|
461
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
462
|
+
suspendedPaths: {},
|
|
463
|
+
resumeLabels: {},
|
|
464
|
+
result: void 0,
|
|
465
|
+
error: void 0,
|
|
466
|
+
// @ts-ignore
|
|
467
|
+
timestamp: Date.now()
|
|
468
|
+
}
|
|
469
|
+
});
|
|
470
|
+
}
|
|
199
471
|
return run;
|
|
200
472
|
}
|
|
201
473
|
getFunction() {
|
|
@@ -203,11 +475,17 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
203
475
|
return this.function;
|
|
204
476
|
}
|
|
205
477
|
this.function = this.inngest.createFunction(
|
|
206
|
-
|
|
207
|
-
|
|
478
|
+
{
|
|
479
|
+
id: `workflow.${this.id}`,
|
|
480
|
+
// @ts-ignore
|
|
481
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
482
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
483
|
+
// Spread flow control configuration
|
|
484
|
+
...this.flowControlConfig
|
|
485
|
+
},
|
|
208
486
|
{ event: `workflow.${this.id}` },
|
|
209
487
|
async ({ event, step, attempt, publish }) => {
|
|
210
|
-
let { inputData, runId, resume } = event.data;
|
|
488
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
211
489
|
if (!runId) {
|
|
212
490
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
213
491
|
return crypto.randomUUID();
|
|
@@ -221,25 +499,52 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
221
499
|
try {
|
|
222
500
|
await publish({
|
|
223
501
|
channel: `workflow:${this.id}:${runId}`,
|
|
224
|
-
topic:
|
|
502
|
+
topic: event2,
|
|
225
503
|
data
|
|
226
504
|
});
|
|
227
505
|
} catch (err) {
|
|
228
506
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
229
507
|
}
|
|
508
|
+
},
|
|
509
|
+
on: (_event, _callback) => {
|
|
510
|
+
},
|
|
511
|
+
off: (_event, _callback) => {
|
|
512
|
+
},
|
|
513
|
+
once: (_event, _callback) => {
|
|
230
514
|
}
|
|
231
515
|
};
|
|
232
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
516
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
233
517
|
const result = await engine.execute({
|
|
234
518
|
workflowId: this.id,
|
|
235
519
|
runId,
|
|
520
|
+
resourceId,
|
|
236
521
|
graph: this.executionGraph,
|
|
522
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
237
523
|
input: inputData,
|
|
524
|
+
initialState,
|
|
238
525
|
emitter,
|
|
239
526
|
retryConfig: this.retryConfig,
|
|
240
|
-
|
|
527
|
+
requestContext: new di.RequestContext(),
|
|
241
528
|
// TODO
|
|
242
|
-
resume
|
|
529
|
+
resume,
|
|
530
|
+
format,
|
|
531
|
+
abortController: new AbortController(),
|
|
532
|
+
// currentSpan: undefined, // TODO: Pass actual parent AI span from workflow execution context
|
|
533
|
+
outputOptions,
|
|
534
|
+
writableStream: new WritableStream({
|
|
535
|
+
write(chunk) {
|
|
536
|
+
void emitter.emit("watch-v2", chunk).catch(() => {
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
})
|
|
540
|
+
});
|
|
541
|
+
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
542
|
+
if (result.status === "failed") {
|
|
543
|
+
throw new inngest.NonRetriableError(`Workflow failed`, {
|
|
544
|
+
cause: result
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
return result;
|
|
243
548
|
});
|
|
244
549
|
return { result, runId };
|
|
245
550
|
}
|
|
@@ -263,40 +568,186 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
263
568
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
264
569
|
}
|
|
265
570
|
};
|
|
266
|
-
function
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
571
|
+
function isAgent(params) {
|
|
572
|
+
return params?.component === "AGENT";
|
|
573
|
+
}
|
|
574
|
+
function isTool(params) {
|
|
575
|
+
return params instanceof tools.Tool;
|
|
576
|
+
}
|
|
577
|
+
function createStep(params, agentOptions) {
|
|
578
|
+
if (isAgent(params)) {
|
|
579
|
+
return {
|
|
580
|
+
id: params.name,
|
|
581
|
+
description: params.getDescription(),
|
|
582
|
+
// @ts-ignore
|
|
583
|
+
inputSchema: zod.z.object({
|
|
584
|
+
prompt: zod.z.string()
|
|
585
|
+
// resourceId: z.string().optional(),
|
|
586
|
+
// threadId: z.string().optional(),
|
|
587
|
+
}),
|
|
588
|
+
// @ts-ignore
|
|
589
|
+
outputSchema: zod.z.object({
|
|
590
|
+
text: zod.z.string()
|
|
591
|
+
}),
|
|
592
|
+
execute: async ({
|
|
593
|
+
inputData,
|
|
594
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
595
|
+
[_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
|
|
596
|
+
requestContext,
|
|
597
|
+
tracingContext,
|
|
598
|
+
abortSignal,
|
|
599
|
+
abort,
|
|
600
|
+
writer
|
|
601
|
+
}) => {
|
|
602
|
+
let streamPromise = {};
|
|
603
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
604
|
+
streamPromise.resolve = resolve;
|
|
605
|
+
streamPromise.reject = reject;
|
|
606
|
+
});
|
|
607
|
+
const toolData = {
|
|
608
|
+
name: params.name,
|
|
609
|
+
args: inputData
|
|
610
|
+
};
|
|
611
|
+
let stream;
|
|
612
|
+
if ((await params.getModel()).specificationVersion === "v1") {
|
|
613
|
+
const { fullStream } = await params.streamLegacy(inputData.prompt, {
|
|
614
|
+
...agentOptions ?? {},
|
|
615
|
+
// resourceId: inputData.resourceId,
|
|
616
|
+
// threadId: inputData.threadId,
|
|
617
|
+
requestContext,
|
|
618
|
+
tracingContext,
|
|
619
|
+
onFinish: (result) => {
|
|
620
|
+
streamPromise.resolve(result.text);
|
|
621
|
+
void agentOptions?.onFinish?.(result);
|
|
622
|
+
},
|
|
623
|
+
abortSignal
|
|
624
|
+
});
|
|
625
|
+
stream = fullStream;
|
|
626
|
+
} else {
|
|
627
|
+
const modelOutput = await params.stream(inputData.prompt, {
|
|
628
|
+
...agentOptions ?? {},
|
|
629
|
+
requestContext,
|
|
630
|
+
tracingContext,
|
|
631
|
+
onFinish: (result) => {
|
|
632
|
+
streamPromise.resolve(result.text);
|
|
633
|
+
void agentOptions?.onFinish?.(result);
|
|
634
|
+
},
|
|
635
|
+
abortSignal
|
|
636
|
+
});
|
|
637
|
+
stream = modelOutput.fullStream;
|
|
638
|
+
}
|
|
639
|
+
if (streamFormat === "legacy") {
|
|
640
|
+
await emitter.emit("watch-v2", {
|
|
641
|
+
type: "tool-call-streaming-start",
|
|
642
|
+
...toolData ?? {}
|
|
643
|
+
});
|
|
644
|
+
for await (const chunk of stream) {
|
|
645
|
+
if (chunk.type === "text-delta") {
|
|
646
|
+
await emitter.emit("watch-v2", {
|
|
647
|
+
type: "tool-call-delta",
|
|
648
|
+
...toolData ?? {},
|
|
649
|
+
argsTextDelta: chunk.textDelta
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
await emitter.emit("watch-v2", {
|
|
654
|
+
type: "tool-call-streaming-finish",
|
|
655
|
+
...toolData ?? {}
|
|
656
|
+
});
|
|
657
|
+
} else {
|
|
658
|
+
for await (const chunk of stream) {
|
|
659
|
+
await writer.write(chunk);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (abortSignal.aborted) {
|
|
663
|
+
return abort();
|
|
664
|
+
}
|
|
665
|
+
return {
|
|
666
|
+
text: await streamPromise.promise
|
|
667
|
+
};
|
|
668
|
+
},
|
|
669
|
+
component: params.component
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
if (isTool(params)) {
|
|
673
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
674
|
+
throw new Error("Tool must have input and output schemas defined");
|
|
675
|
+
}
|
|
676
|
+
return {
|
|
677
|
+
// TODO: tool probably should have strong id type
|
|
678
|
+
// @ts-ignore
|
|
679
|
+
id: params.id,
|
|
680
|
+
description: params.description,
|
|
681
|
+
inputSchema: params.inputSchema,
|
|
682
|
+
outputSchema: params.outputSchema,
|
|
683
|
+
execute: async ({ inputData, mastra, requestContext, tracingContext, suspend, resumeData }) => {
|
|
684
|
+
return params.execute({
|
|
685
|
+
context: inputData,
|
|
686
|
+
mastra: aiTracing.wrapMastra(mastra, tracingContext),
|
|
687
|
+
requestContext,
|
|
688
|
+
tracingContext,
|
|
689
|
+
suspend,
|
|
690
|
+
resumeData
|
|
691
|
+
});
|
|
692
|
+
},
|
|
693
|
+
component: "TOOL"
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
return {
|
|
697
|
+
id: params.id,
|
|
698
|
+
description: params.description,
|
|
699
|
+
inputSchema: params.inputSchema,
|
|
700
|
+
outputSchema: params.outputSchema,
|
|
701
|
+
resumeSchema: params.resumeSchema,
|
|
702
|
+
suspendSchema: params.suspendSchema,
|
|
703
|
+
execute: params.execute
|
|
704
|
+
};
|
|
280
705
|
}
|
|
281
706
|
function init(inngest) {
|
|
282
707
|
return {
|
|
283
708
|
createWorkflow(params) {
|
|
284
|
-
return new InngestWorkflow(
|
|
709
|
+
return new InngestWorkflow(
|
|
710
|
+
params,
|
|
711
|
+
inngest
|
|
712
|
+
);
|
|
713
|
+
},
|
|
714
|
+
createStep,
|
|
715
|
+
cloneStep(step, opts) {
|
|
716
|
+
return {
|
|
717
|
+
id: opts.id,
|
|
718
|
+
description: step.description,
|
|
719
|
+
inputSchema: step.inputSchema,
|
|
720
|
+
outputSchema: step.outputSchema,
|
|
721
|
+
resumeSchema: step.resumeSchema,
|
|
722
|
+
suspendSchema: step.suspendSchema,
|
|
723
|
+
stateSchema: step.stateSchema,
|
|
724
|
+
execute: step.execute,
|
|
725
|
+
component: step.component
|
|
726
|
+
};
|
|
285
727
|
},
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
728
|
+
cloneWorkflow(workflow, opts) {
|
|
729
|
+
const wf = new workflows.Workflow({
|
|
730
|
+
id: opts.id,
|
|
731
|
+
inputSchema: workflow.inputSchema,
|
|
732
|
+
outputSchema: workflow.outputSchema,
|
|
733
|
+
steps: workflow.stepDefs,
|
|
734
|
+
mastra: workflow.mastra
|
|
735
|
+
});
|
|
736
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
737
|
+
wf.commit();
|
|
738
|
+
return wf;
|
|
739
|
+
}
|
|
289
740
|
};
|
|
290
741
|
}
|
|
291
|
-
var InngestExecutionEngine = class extends
|
|
742
|
+
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
292
743
|
inngestStep;
|
|
293
744
|
inngestAttempts;
|
|
294
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
295
|
-
super({ mastra });
|
|
745
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
746
|
+
super({ mastra, options });
|
|
296
747
|
this.inngestStep = inngestStep;
|
|
297
748
|
this.inngestAttempts = inngestAttempts;
|
|
298
749
|
}
|
|
299
|
-
async fmtReturnValue(
|
|
750
|
+
async fmtReturnValue(emitter, stepResults, lastOutput, error) {
|
|
300
751
|
const base = {
|
|
301
752
|
status: lastOutput.status,
|
|
302
753
|
steps: stepResults
|
|
@@ -343,38 +794,214 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
343
794
|
});
|
|
344
795
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
345
796
|
if (stepResult?.status === "suspended") {
|
|
346
|
-
const nestedPath = stepResult?.
|
|
797
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
347
798
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
348
799
|
}
|
|
349
800
|
return [];
|
|
350
801
|
});
|
|
351
802
|
base.suspended = suspendedStepIds;
|
|
352
803
|
}
|
|
353
|
-
executionSpan?.end();
|
|
354
804
|
return base;
|
|
355
805
|
}
|
|
356
|
-
async
|
|
806
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
807
|
+
// await this.inngestStep.sleep(id, duration);
|
|
808
|
+
// }
|
|
809
|
+
async executeSleep({
|
|
357
810
|
workflowId,
|
|
358
811
|
runId,
|
|
359
|
-
|
|
812
|
+
entry,
|
|
813
|
+
prevOutput,
|
|
360
814
|
stepResults,
|
|
815
|
+
emitter,
|
|
816
|
+
abortController,
|
|
817
|
+
requestContext,
|
|
361
818
|
executionContext,
|
|
362
|
-
|
|
819
|
+
writableStream,
|
|
820
|
+
tracingContext
|
|
821
|
+
}) {
|
|
822
|
+
let { duration, fn } = entry;
|
|
823
|
+
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
824
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
825
|
+
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
826
|
+
attributes: {
|
|
827
|
+
durationMs: duration,
|
|
828
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
829
|
+
},
|
|
830
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
831
|
+
});
|
|
832
|
+
if (fn) {
|
|
833
|
+
const stepCallId = crypto.randomUUID();
|
|
834
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
835
|
+
return await fn(
|
|
836
|
+
workflows.createDeprecationProxy(
|
|
837
|
+
{
|
|
838
|
+
runId,
|
|
839
|
+
workflowId,
|
|
840
|
+
mastra: this.mastra,
|
|
841
|
+
requestContext,
|
|
842
|
+
inputData: prevOutput,
|
|
843
|
+
state: executionContext.state,
|
|
844
|
+
setState: (state) => {
|
|
845
|
+
executionContext.state = state;
|
|
846
|
+
},
|
|
847
|
+
runCount: -1,
|
|
848
|
+
retryCount: -1,
|
|
849
|
+
tracingContext: {
|
|
850
|
+
currentSpan: sleepSpan
|
|
851
|
+
},
|
|
852
|
+
getInitData: () => stepResults?.input,
|
|
853
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
854
|
+
// TODO: this function shouldn't have suspend probably?
|
|
855
|
+
suspend: async (_suspendPayload) => {
|
|
856
|
+
},
|
|
857
|
+
bail: () => {
|
|
858
|
+
},
|
|
859
|
+
abort: () => {
|
|
860
|
+
abortController?.abort();
|
|
861
|
+
},
|
|
862
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
863
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
864
|
+
engine: { step: this.inngestStep },
|
|
865
|
+
abortSignal: abortController?.signal,
|
|
866
|
+
writer: new tools.ToolStream(
|
|
867
|
+
{
|
|
868
|
+
prefix: "workflow-step",
|
|
869
|
+
callId: stepCallId,
|
|
870
|
+
name: "sleep",
|
|
871
|
+
runId
|
|
872
|
+
},
|
|
873
|
+
writableStream
|
|
874
|
+
)
|
|
875
|
+
},
|
|
876
|
+
{
|
|
877
|
+
paramName: "runCount",
|
|
878
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
879
|
+
logger: this.logger
|
|
880
|
+
}
|
|
881
|
+
)
|
|
882
|
+
);
|
|
883
|
+
});
|
|
884
|
+
sleepSpan?.update({
|
|
885
|
+
attributes: {
|
|
886
|
+
durationMs: duration
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
try {
|
|
891
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
892
|
+
sleepSpan?.end();
|
|
893
|
+
} catch (e) {
|
|
894
|
+
sleepSpan?.error({ error: e });
|
|
895
|
+
throw e;
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
async executeSleepUntil({
|
|
899
|
+
workflowId,
|
|
900
|
+
runId,
|
|
901
|
+
entry,
|
|
363
902
|
prevOutput,
|
|
903
|
+
stepResults,
|
|
364
904
|
emitter,
|
|
365
|
-
|
|
905
|
+
abortController,
|
|
906
|
+
requestContext,
|
|
907
|
+
executionContext,
|
|
908
|
+
writableStream,
|
|
909
|
+
tracingContext
|
|
366
910
|
}) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
911
|
+
let { date, fn } = entry;
|
|
912
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
913
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
914
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
915
|
+
attributes: {
|
|
916
|
+
untilDate: date,
|
|
917
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
918
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
919
|
+
},
|
|
920
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
921
|
+
});
|
|
922
|
+
if (fn) {
|
|
923
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
924
|
+
const stepCallId = crypto.randomUUID();
|
|
925
|
+
return await fn(
|
|
926
|
+
workflows.createDeprecationProxy(
|
|
927
|
+
{
|
|
928
|
+
runId,
|
|
929
|
+
workflowId,
|
|
930
|
+
mastra: this.mastra,
|
|
931
|
+
requestContext,
|
|
932
|
+
inputData: prevOutput,
|
|
933
|
+
state: executionContext.state,
|
|
934
|
+
setState: (state) => {
|
|
935
|
+
executionContext.state = state;
|
|
936
|
+
},
|
|
937
|
+
runCount: -1,
|
|
938
|
+
retryCount: -1,
|
|
939
|
+
tracingContext: {
|
|
940
|
+
currentSpan: sleepUntilSpan
|
|
941
|
+
},
|
|
942
|
+
getInitData: () => stepResults?.input,
|
|
943
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
944
|
+
// TODO: this function shouldn't have suspend probably?
|
|
945
|
+
suspend: async (_suspendPayload) => {
|
|
946
|
+
},
|
|
947
|
+
bail: () => {
|
|
948
|
+
},
|
|
949
|
+
abort: () => {
|
|
950
|
+
abortController?.abort();
|
|
951
|
+
},
|
|
952
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
953
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
954
|
+
engine: { step: this.inngestStep },
|
|
955
|
+
abortSignal: abortController?.signal,
|
|
956
|
+
writer: new tools.ToolStream(
|
|
957
|
+
{
|
|
958
|
+
prefix: "workflow-step",
|
|
959
|
+
callId: stepCallId,
|
|
960
|
+
name: "sleep",
|
|
961
|
+
runId
|
|
962
|
+
},
|
|
963
|
+
writableStream
|
|
964
|
+
)
|
|
965
|
+
},
|
|
966
|
+
{
|
|
967
|
+
paramName: "runCount",
|
|
968
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
969
|
+
logger: this.logger
|
|
970
|
+
}
|
|
971
|
+
)
|
|
972
|
+
);
|
|
973
|
+
});
|
|
974
|
+
if (date && !(date instanceof Date)) {
|
|
975
|
+
date = new Date(date);
|
|
976
|
+
}
|
|
977
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
978
|
+
sleepUntilSpan?.update({
|
|
979
|
+
attributes: {
|
|
980
|
+
durationMs: Math.max(0, time)
|
|
981
|
+
}
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
if (!(date instanceof Date)) {
|
|
985
|
+
sleepUntilSpan?.end();
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
try {
|
|
989
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
990
|
+
sleepUntilSpan?.end();
|
|
991
|
+
} catch (e) {
|
|
992
|
+
sleepUntilSpan?.error({ error: e });
|
|
993
|
+
throw e;
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
997
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
998
|
+
event: `user-event-${event}`,
|
|
999
|
+
timeout: timeout ?? 5e3
|
|
377
1000
|
});
|
|
1001
|
+
if (eventData === null) {
|
|
1002
|
+
throw "Timeout waiting for event";
|
|
1003
|
+
}
|
|
1004
|
+
return eventData?.data;
|
|
378
1005
|
}
|
|
379
1006
|
async executeStep({
|
|
380
1007
|
step,
|
|
@@ -383,11 +1010,30 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
383
1010
|
resume,
|
|
384
1011
|
prevOutput,
|
|
385
1012
|
emitter,
|
|
386
|
-
|
|
1013
|
+
abortController,
|
|
1014
|
+
requestContext,
|
|
1015
|
+
tracingContext,
|
|
1016
|
+
writableStream,
|
|
1017
|
+
disableScorers
|
|
387
1018
|
}) {
|
|
388
|
-
|
|
1019
|
+
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1020
|
+
name: `workflow step: '${step.id}'`,
|
|
1021
|
+
type: aiTracing.AISpanType.WORKFLOW_STEP,
|
|
1022
|
+
input: prevOutput,
|
|
1023
|
+
attributes: {
|
|
1024
|
+
stepId: step.id
|
|
1025
|
+
},
|
|
1026
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1027
|
+
});
|
|
1028
|
+
const { inputData, validationError } = await workflows.validateStepInput({
|
|
1029
|
+
prevOutput,
|
|
1030
|
+
step,
|
|
1031
|
+
validateInputs: this.options?.validateInputs ?? false
|
|
1032
|
+
});
|
|
1033
|
+
const startedAt = await this.inngestStep.run(
|
|
389
1034
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
390
1035
|
async () => {
|
|
1036
|
+
const startedAt2 = Date.now();
|
|
391
1037
|
await emitter.emit("watch", {
|
|
392
1038
|
type: "watch",
|
|
393
1039
|
payload: {
|
|
@@ -409,44 +1055,76 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
409
1055
|
},
|
|
410
1056
|
eventTimestamp: Date.now()
|
|
411
1057
|
});
|
|
1058
|
+
await emitter.emit("watch-v2", {
|
|
1059
|
+
type: "workflow-step-start",
|
|
1060
|
+
payload: {
|
|
1061
|
+
id: step.id,
|
|
1062
|
+
status: "running",
|
|
1063
|
+
payload: inputData,
|
|
1064
|
+
startedAt: startedAt2
|
|
1065
|
+
}
|
|
1066
|
+
});
|
|
1067
|
+
return startedAt2;
|
|
412
1068
|
}
|
|
413
1069
|
);
|
|
414
1070
|
if (step instanceof InngestWorkflow) {
|
|
415
1071
|
const isResume = !!resume?.steps?.length;
|
|
416
1072
|
let result;
|
|
417
1073
|
let runId;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
1074
|
+
try {
|
|
1075
|
+
if (isResume) {
|
|
1076
|
+
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? crypto.randomUUID();
|
|
1077
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1078
|
+
workflowName: step.id,
|
|
1079
|
+
runId
|
|
1080
|
+
});
|
|
1081
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1082
|
+
function: step.getFunction(),
|
|
1083
|
+
data: {
|
|
1084
|
+
inputData,
|
|
1085
|
+
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
430
1086
|
runId,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
1087
|
+
resume: {
|
|
1088
|
+
runId,
|
|
1089
|
+
steps: resume.steps.slice(1),
|
|
1090
|
+
stepResults: snapshot?.context,
|
|
1091
|
+
resumePayload: resume.resumePayload,
|
|
1092
|
+
// @ts-ignore
|
|
1093
|
+
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1094
|
+
},
|
|
1095
|
+
outputOptions: { includeState: true }
|
|
436
1096
|
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
1097
|
+
});
|
|
1098
|
+
result = invokeResp.result;
|
|
1099
|
+
runId = invokeResp.runId;
|
|
1100
|
+
executionContext.state = invokeResp.result.state;
|
|
1101
|
+
} else {
|
|
1102
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1103
|
+
function: step.getFunction(),
|
|
1104
|
+
data: {
|
|
1105
|
+
inputData,
|
|
1106
|
+
initialState: executionContext.state ?? {},
|
|
1107
|
+
outputOptions: { includeState: true }
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
result = invokeResp.result;
|
|
1111
|
+
runId = invokeResp.runId;
|
|
1112
|
+
executionContext.state = invokeResp.result.state;
|
|
1113
|
+
}
|
|
1114
|
+
} catch (e) {
|
|
1115
|
+
const errorCause = e?.cause;
|
|
1116
|
+
if (errorCause && typeof errorCause === "object") {
|
|
1117
|
+
result = errorCause;
|
|
1118
|
+
runId = errorCause.runId || crypto.randomUUID();
|
|
1119
|
+
} else {
|
|
1120
|
+
runId = crypto.randomUUID();
|
|
1121
|
+
result = {
|
|
1122
|
+
status: "failed",
|
|
1123
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1124
|
+
steps: {},
|
|
1125
|
+
input: inputData
|
|
1126
|
+
};
|
|
1127
|
+
}
|
|
450
1128
|
}
|
|
451
1129
|
const res = await this.inngestStep.run(
|
|
452
1130
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
@@ -469,6 +1147,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
469
1147
|
},
|
|
470
1148
|
eventTimestamp: Date.now()
|
|
471
1149
|
});
|
|
1150
|
+
await emitter.emit("watch-v2", {
|
|
1151
|
+
type: "workflow-step-result",
|
|
1152
|
+
payload: {
|
|
1153
|
+
id: step.id,
|
|
1154
|
+
status: "failed",
|
|
1155
|
+
error: result?.error,
|
|
1156
|
+
payload: prevOutput
|
|
1157
|
+
}
|
|
1158
|
+
});
|
|
472
1159
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
473
1160
|
} else if (result.status === "suspended") {
|
|
474
1161
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -476,7 +1163,7 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
476
1163
|
return stepRes2?.status === "suspended";
|
|
477
1164
|
});
|
|
478
1165
|
for (const [stepName, stepResult] of suspendedSteps) {
|
|
479
|
-
const suspendPath = [stepName, ...stepResult?.
|
|
1166
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
480
1167
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
481
1168
|
await emitter.emit("watch", {
|
|
482
1169
|
type: "watch",
|
|
@@ -484,7 +1171,11 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
484
1171
|
currentStep: {
|
|
485
1172
|
id: step.id,
|
|
486
1173
|
status: "suspended",
|
|
487
|
-
payload:
|
|
1174
|
+
payload: stepResult.payload,
|
|
1175
|
+
suspendPayload: {
|
|
1176
|
+
...stepResult?.suspendPayload,
|
|
1177
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1178
|
+
}
|
|
488
1179
|
},
|
|
489
1180
|
workflowState: {
|
|
490
1181
|
status: "running",
|
|
@@ -495,11 +1186,22 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
495
1186
|
},
|
|
496
1187
|
eventTimestamp: Date.now()
|
|
497
1188
|
});
|
|
1189
|
+
await emitter.emit("watch-v2", {
|
|
1190
|
+
type: "workflow-step-suspended",
|
|
1191
|
+
payload: {
|
|
1192
|
+
id: step.id,
|
|
1193
|
+
status: "suspended"
|
|
1194
|
+
}
|
|
1195
|
+
});
|
|
498
1196
|
return {
|
|
499
1197
|
executionContext,
|
|
500
1198
|
result: {
|
|
501
1199
|
status: "suspended",
|
|
502
|
-
payload:
|
|
1200
|
+
payload: stepResult.payload,
|
|
1201
|
+
suspendPayload: {
|
|
1202
|
+
...stepResult?.suspendPayload,
|
|
1203
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1204
|
+
}
|
|
503
1205
|
}
|
|
504
1206
|
};
|
|
505
1207
|
}
|
|
@@ -545,94 +1247,260 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
545
1247
|
},
|
|
546
1248
|
eventTimestamp: Date.now()
|
|
547
1249
|
});
|
|
1250
|
+
await emitter.emit("watch-v2", {
|
|
1251
|
+
type: "workflow-step-result",
|
|
1252
|
+
payload: {
|
|
1253
|
+
id: step.id,
|
|
1254
|
+
status: "success",
|
|
1255
|
+
output: result?.result
|
|
1256
|
+
}
|
|
1257
|
+
});
|
|
1258
|
+
await emitter.emit("watch-v2", {
|
|
1259
|
+
type: "workflow-step-finish",
|
|
1260
|
+
payload: {
|
|
1261
|
+
id: step.id,
|
|
1262
|
+
metadata: {}
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
548
1265
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
549
1266
|
}
|
|
550
1267
|
);
|
|
551
1268
|
Object.assign(executionContext, res.executionContext);
|
|
552
|
-
return
|
|
1269
|
+
return {
|
|
1270
|
+
...res.result,
|
|
1271
|
+
startedAt,
|
|
1272
|
+
endedAt: Date.now(),
|
|
1273
|
+
payload: inputData,
|
|
1274
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1275
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1276
|
+
};
|
|
553
1277
|
}
|
|
554
|
-
const
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
1278
|
+
const stepCallId = crypto.randomUUID();
|
|
1279
|
+
let stepRes;
|
|
1280
|
+
try {
|
|
1281
|
+
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1282
|
+
let execResults;
|
|
1283
|
+
let suspended;
|
|
1284
|
+
let bailed;
|
|
1285
|
+
try {
|
|
1286
|
+
if (validationError) {
|
|
1287
|
+
throw validationError;
|
|
1288
|
+
}
|
|
1289
|
+
const result = await step.execute({
|
|
1290
|
+
runId: executionContext.runId,
|
|
1291
|
+
mastra: this.mastra,
|
|
1292
|
+
requestContext,
|
|
1293
|
+
writer: new tools.ToolStream(
|
|
1294
|
+
{
|
|
1295
|
+
prefix: "workflow-step",
|
|
1296
|
+
callId: stepCallId,
|
|
1297
|
+
name: step.id,
|
|
1298
|
+
runId: executionContext.runId
|
|
1299
|
+
},
|
|
1300
|
+
writableStream
|
|
1301
|
+
),
|
|
1302
|
+
state: executionContext?.state ?? {},
|
|
1303
|
+
setState: (state) => {
|
|
1304
|
+
executionContext.state = state;
|
|
1305
|
+
},
|
|
1306
|
+
inputData,
|
|
1307
|
+
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1308
|
+
tracingContext: {
|
|
1309
|
+
currentSpan: stepAISpan
|
|
1310
|
+
},
|
|
1311
|
+
getInitData: () => stepResults?.input,
|
|
1312
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1313
|
+
suspend: async (suspendPayload, suspendOptions) => {
|
|
1314
|
+
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1315
|
+
if (suspendOptions?.resumeLabel) {
|
|
1316
|
+
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
1317
|
+
for (const label of resumeLabel) {
|
|
1318
|
+
executionContext.resumeLabels[label] = {
|
|
1319
|
+
stepId: step.id,
|
|
1320
|
+
foreachIndex: executionContext.foreachIndex
|
|
1321
|
+
};
|
|
1322
|
+
}
|
|
1323
|
+
}
|
|
1324
|
+
suspended = { payload: suspendPayload };
|
|
1325
|
+
},
|
|
1326
|
+
bail: (result2) => {
|
|
1327
|
+
bailed = { payload: result2 };
|
|
1328
|
+
},
|
|
1329
|
+
resume: {
|
|
1330
|
+
steps: resume?.steps?.slice(1) || [],
|
|
1331
|
+
resumePayload: resume?.resumePayload,
|
|
1332
|
+
// @ts-ignore
|
|
1333
|
+
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1334
|
+
},
|
|
1335
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1336
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1337
|
+
engine: {
|
|
1338
|
+
step: this.inngestStep
|
|
1339
|
+
},
|
|
1340
|
+
abortSignal: abortController.signal
|
|
1341
|
+
});
|
|
1342
|
+
const endedAt = Date.now();
|
|
1343
|
+
execResults = {
|
|
1344
|
+
status: "success",
|
|
1345
|
+
output: result,
|
|
1346
|
+
startedAt,
|
|
1347
|
+
endedAt,
|
|
1348
|
+
payload: inputData,
|
|
1349
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1350
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1351
|
+
};
|
|
1352
|
+
} catch (e) {
|
|
1353
|
+
const stepFailure = {
|
|
1354
|
+
status: "failed",
|
|
1355
|
+
payload: inputData,
|
|
1356
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1357
|
+
endedAt: Date.now(),
|
|
1358
|
+
startedAt,
|
|
1359
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1360
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1361
|
+
};
|
|
1362
|
+
execResults = stepFailure;
|
|
1363
|
+
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1364
|
+
stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1365
|
+
throw new inngest.RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1366
|
+
cause: execResults
|
|
1367
|
+
});
|
|
1368
|
+
}
|
|
1369
|
+
if (suspended) {
|
|
1370
|
+
execResults = {
|
|
1371
|
+
status: "suspended",
|
|
1372
|
+
suspendPayload: suspended.payload,
|
|
1373
|
+
payload: inputData,
|
|
1374
|
+
suspendedAt: Date.now(),
|
|
1375
|
+
startedAt,
|
|
1376
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1377
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1378
|
+
};
|
|
1379
|
+
} else if (bailed) {
|
|
1380
|
+
execResults = {
|
|
1381
|
+
status: "bailed",
|
|
1382
|
+
output: bailed.payload,
|
|
1383
|
+
payload: inputData,
|
|
1384
|
+
endedAt: Date.now(),
|
|
1385
|
+
startedAt
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
await emitter.emit("watch", {
|
|
1389
|
+
type: "watch",
|
|
1390
|
+
payload: {
|
|
1391
|
+
currentStep: {
|
|
1392
|
+
id: step.id,
|
|
1393
|
+
...execResults
|
|
1394
|
+
},
|
|
1395
|
+
workflowState: {
|
|
1396
|
+
status: "running",
|
|
1397
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
1398
|
+
result: null,
|
|
1399
|
+
error: null
|
|
568
1400
|
}
|
|
569
|
-
return null;
|
|
570
|
-
},
|
|
571
|
-
suspend: async (suspendPayload) => {
|
|
572
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
573
|
-
suspended = { payload: suspendPayload };
|
|
574
|
-
},
|
|
575
|
-
resume: {
|
|
576
|
-
steps: resume?.steps?.slice(1) || [],
|
|
577
|
-
resumePayload: resume?.resumePayload,
|
|
578
|
-
// @ts-ignore
|
|
579
|
-
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
580
1401
|
},
|
|
581
|
-
|
|
1402
|
+
eventTimestamp: Date.now()
|
|
582
1403
|
});
|
|
583
|
-
execResults
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
1404
|
+
if (execResults.status === "suspended") {
|
|
1405
|
+
await emitter.emit("watch-v2", {
|
|
1406
|
+
type: "workflow-step-suspended",
|
|
1407
|
+
payload: {
|
|
1408
|
+
id: step.id,
|
|
1409
|
+
...execResults
|
|
1410
|
+
}
|
|
1411
|
+
});
|
|
1412
|
+
} else {
|
|
1413
|
+
await emitter.emit("watch-v2", {
|
|
1414
|
+
type: "workflow-step-result",
|
|
1415
|
+
payload: {
|
|
1416
|
+
id: step.id,
|
|
1417
|
+
...execResults
|
|
1418
|
+
}
|
|
1419
|
+
});
|
|
1420
|
+
await emitter.emit("watch-v2", {
|
|
1421
|
+
type: "workflow-step-finish",
|
|
1422
|
+
payload: {
|
|
1423
|
+
id: step.id,
|
|
1424
|
+
metadata: {}
|
|
1425
|
+
}
|
|
1426
|
+
});
|
|
593
1427
|
}
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
type: "watch",
|
|
597
|
-
payload: {
|
|
598
|
-
currentStep: {
|
|
599
|
-
id: step.id,
|
|
600
|
-
status: execResults.status,
|
|
601
|
-
output: execResults.output
|
|
602
|
-
},
|
|
603
|
-
workflowState: {
|
|
604
|
-
status: "running",
|
|
605
|
-
steps: stepResults,
|
|
606
|
-
result: null,
|
|
607
|
-
error: null
|
|
608
|
-
}
|
|
609
|
-
},
|
|
610
|
-
eventTimestamp: Date.now()
|
|
1428
|
+
stepAISpan?.end({ output: execResults });
|
|
1429
|
+
return { result: execResults, executionContext, stepResults };
|
|
611
1430
|
});
|
|
612
|
-
|
|
613
|
-
|
|
1431
|
+
} catch (e) {
|
|
1432
|
+
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1433
|
+
status: "failed",
|
|
1434
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1435
|
+
payload: inputData,
|
|
1436
|
+
startedAt,
|
|
1437
|
+
endedAt: Date.now()
|
|
1438
|
+
};
|
|
1439
|
+
stepRes = {
|
|
1440
|
+
result: stepFailure,
|
|
1441
|
+
executionContext,
|
|
1442
|
+
stepResults: {
|
|
1443
|
+
...stepResults,
|
|
1444
|
+
[step.id]: stepFailure
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1449
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1450
|
+
if (step.scorers) {
|
|
1451
|
+
await this.runScorers({
|
|
1452
|
+
scorers: step.scorers,
|
|
1453
|
+
runId: executionContext.runId,
|
|
1454
|
+
input: inputData,
|
|
1455
|
+
output: stepRes.result,
|
|
1456
|
+
workflowId: executionContext.workflowId,
|
|
1457
|
+
stepId: step.id,
|
|
1458
|
+
requestContext,
|
|
1459
|
+
disableScorers,
|
|
1460
|
+
tracingContext: { currentSpan: stepAISpan }
|
|
1461
|
+
});
|
|
1462
|
+
}
|
|
1463
|
+
});
|
|
1464
|
+
}
|
|
614
1465
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
615
1466
|
Object.assign(stepResults, stepRes.stepResults);
|
|
1467
|
+
executionContext.state = stepRes.executionContext.state;
|
|
616
1468
|
return stepRes.result;
|
|
617
1469
|
}
|
|
618
1470
|
async persistStepUpdate({
|
|
619
1471
|
workflowId,
|
|
620
1472
|
runId,
|
|
621
1473
|
stepResults,
|
|
622
|
-
|
|
1474
|
+
resourceId,
|
|
1475
|
+
executionContext,
|
|
1476
|
+
serializedStepGraph,
|
|
1477
|
+
workflowStatus,
|
|
1478
|
+
result,
|
|
1479
|
+
error
|
|
623
1480
|
}) {
|
|
624
1481
|
await this.inngestStep.run(
|
|
625
1482
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
626
1483
|
async () => {
|
|
1484
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1485
|
+
if (!shouldPersistSnapshot) {
|
|
1486
|
+
return;
|
|
1487
|
+
}
|
|
627
1488
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
628
1489
|
workflowName: workflowId,
|
|
629
1490
|
runId,
|
|
1491
|
+
resourceId,
|
|
630
1492
|
snapshot: {
|
|
631
1493
|
runId,
|
|
632
|
-
value:
|
|
1494
|
+
value: executionContext.state,
|
|
633
1495
|
context: stepResults,
|
|
634
1496
|
activePaths: [],
|
|
635
1497
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1498
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1499
|
+
waitingPaths: {},
|
|
1500
|
+
serializedStepGraph,
|
|
1501
|
+
status: workflowStatus,
|
|
1502
|
+
result,
|
|
1503
|
+
error,
|
|
636
1504
|
// @ts-ignore
|
|
637
1505
|
timestamp: Date.now()
|
|
638
1506
|
}
|
|
@@ -645,53 +1513,124 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
645
1513
|
runId,
|
|
646
1514
|
entry,
|
|
647
1515
|
prevOutput,
|
|
648
|
-
prevStep,
|
|
649
1516
|
stepResults,
|
|
650
1517
|
resume,
|
|
651
1518
|
executionContext,
|
|
652
1519
|
emitter,
|
|
653
|
-
|
|
1520
|
+
abortController,
|
|
1521
|
+
requestContext,
|
|
1522
|
+
writableStream,
|
|
1523
|
+
disableScorers,
|
|
1524
|
+
tracingContext
|
|
654
1525
|
}) {
|
|
1526
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1527
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
|
|
1528
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1529
|
+
input: prevOutput,
|
|
1530
|
+
attributes: {
|
|
1531
|
+
conditionCount: entry.conditions.length
|
|
1532
|
+
},
|
|
1533
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1534
|
+
});
|
|
655
1535
|
let execResults;
|
|
656
1536
|
const truthyIndexes = (await Promise.all(
|
|
657
1537
|
entry.conditions.map(
|
|
658
1538
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1539
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1540
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1541
|
+
name: `condition: '${index}'`,
|
|
1542
|
+
input: prevOutput,
|
|
1543
|
+
attributes: {
|
|
1544
|
+
conditionIndex: index
|
|
1545
|
+
},
|
|
1546
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1547
|
+
});
|
|
659
1548
|
try {
|
|
660
|
-
const result = await cond(
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
1549
|
+
const result = await cond(
|
|
1550
|
+
workflows.createDeprecationProxy(
|
|
1551
|
+
{
|
|
1552
|
+
runId,
|
|
1553
|
+
workflowId,
|
|
1554
|
+
mastra: this.mastra,
|
|
1555
|
+
requestContext,
|
|
1556
|
+
runCount: -1,
|
|
1557
|
+
retryCount: -1,
|
|
1558
|
+
inputData: prevOutput,
|
|
1559
|
+
state: executionContext.state,
|
|
1560
|
+
setState: (state) => {
|
|
1561
|
+
executionContext.state = state;
|
|
1562
|
+
},
|
|
1563
|
+
tracingContext: {
|
|
1564
|
+
currentSpan: evalSpan
|
|
1565
|
+
},
|
|
1566
|
+
getInitData: () => stepResults?.input,
|
|
1567
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
1568
|
+
// TODO: this function shouldn't have suspend probably?
|
|
1569
|
+
suspend: async (_suspendPayload) => {
|
|
1570
|
+
},
|
|
1571
|
+
bail: () => {
|
|
1572
|
+
},
|
|
1573
|
+
abort: () => {
|
|
1574
|
+
abortController.abort();
|
|
1575
|
+
},
|
|
1576
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1577
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1578
|
+
engine: {
|
|
1579
|
+
step: this.inngestStep
|
|
1580
|
+
},
|
|
1581
|
+
abortSignal: abortController.signal,
|
|
1582
|
+
writer: new tools.ToolStream(
|
|
1583
|
+
{
|
|
1584
|
+
prefix: "workflow-step",
|
|
1585
|
+
callId: crypto.randomUUID(),
|
|
1586
|
+
name: "conditional",
|
|
1587
|
+
runId
|
|
1588
|
+
},
|
|
1589
|
+
writableStream
|
|
1590
|
+
)
|
|
1591
|
+
},
|
|
1592
|
+
{
|
|
1593
|
+
paramName: "runCount",
|
|
1594
|
+
deprecationMessage: workflows.runCountDeprecationMessage,
|
|
1595
|
+
logger: this.logger
|
|
672
1596
|
}
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
1597
|
+
)
|
|
1598
|
+
);
|
|
1599
|
+
evalSpan?.end({
|
|
1600
|
+
output: result,
|
|
1601
|
+
attributes: {
|
|
1602
|
+
result: !!result
|
|
1603
|
+
}
|
|
679
1604
|
});
|
|
680
1605
|
return result ? index : null;
|
|
681
1606
|
} catch (e) {
|
|
1607
|
+
evalSpan?.error({
|
|
1608
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1609
|
+
attributes: {
|
|
1610
|
+
result: false
|
|
1611
|
+
}
|
|
1612
|
+
});
|
|
682
1613
|
return null;
|
|
683
1614
|
}
|
|
684
1615
|
})
|
|
685
1616
|
)
|
|
686
1617
|
)).filter((index) => index !== null);
|
|
687
1618
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1619
|
+
conditionalSpan?.update({
|
|
1620
|
+
attributes: {
|
|
1621
|
+
truthyIndexes,
|
|
1622
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1623
|
+
}
|
|
1624
|
+
});
|
|
688
1625
|
const results = await Promise.all(
|
|
689
|
-
stepsToRun.map(
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
1626
|
+
stepsToRun.map(async (step, index) => {
|
|
1627
|
+
const currStepResult = stepResults[step.step.id];
|
|
1628
|
+
if (currStepResult && currStepResult.status === "success") {
|
|
1629
|
+
return currStepResult;
|
|
1630
|
+
}
|
|
1631
|
+
const result = await this.executeStep({
|
|
1632
|
+
step: step.step,
|
|
1633
|
+
prevOutput,
|
|
695
1634
|
stepResults,
|
|
696
1635
|
resume,
|
|
697
1636
|
executionContext: {
|
|
@@ -699,20 +1638,29 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
699
1638
|
runId,
|
|
700
1639
|
executionPath: [...executionContext.executionPath, index],
|
|
701
1640
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1641
|
+
resumeLabels: executionContext.resumeLabels,
|
|
702
1642
|
retryConfig: executionContext.retryConfig,
|
|
703
|
-
|
|
1643
|
+
state: executionContext.state
|
|
704
1644
|
},
|
|
705
1645
|
emitter,
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
1646
|
+
abortController,
|
|
1647
|
+
requestContext,
|
|
1648
|
+
writableStream,
|
|
1649
|
+
disableScorers,
|
|
1650
|
+
tracingContext: {
|
|
1651
|
+
currentSpan: conditionalSpan
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
stepResults[step.step.id] = result;
|
|
1655
|
+
return result;
|
|
1656
|
+
})
|
|
709
1657
|
);
|
|
710
1658
|
const hasFailed = results.find((result) => result.status === "failed");
|
|
711
1659
|
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
712
1660
|
if (hasFailed) {
|
|
713
1661
|
execResults = { status: "failed", error: hasFailed.error };
|
|
714
1662
|
} else if (hasSuspended) {
|
|
715
|
-
execResults = { status: "suspended",
|
|
1663
|
+
execResults = { status: "suspended", suspendPayload: hasSuspended.suspendPayload };
|
|
716
1664
|
} else {
|
|
717
1665
|
execResults = {
|
|
718
1666
|
status: "success",
|
|
@@ -724,6 +1672,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
724
1672
|
}, {})
|
|
725
1673
|
};
|
|
726
1674
|
}
|
|
1675
|
+
if (execResults.status === "failed") {
|
|
1676
|
+
conditionalSpan?.error({
|
|
1677
|
+
error: new Error(execResults.error)
|
|
1678
|
+
});
|
|
1679
|
+
} else {
|
|
1680
|
+
conditionalSpan?.end({
|
|
1681
|
+
output: execResults.output || execResults
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
727
1684
|
return execResults;
|
|
728
1685
|
}
|
|
729
1686
|
};
|
|
@@ -731,5 +1688,8 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
731
1688
|
exports.InngestExecutionEngine = InngestExecutionEngine;
|
|
732
1689
|
exports.InngestRun = InngestRun;
|
|
733
1690
|
exports.InngestWorkflow = InngestWorkflow;
|
|
1691
|
+
exports.createStep = createStep;
|
|
734
1692
|
exports.init = init;
|
|
735
1693
|
exports.serve = serve;
|
|
1694
|
+
//# sourceMappingURL=index.cjs.map
|
|
1695
|
+
//# sourceMappingURL=index.cjs.map
|