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