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