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