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