@mastra/inngest 0.0.0-cloud-transporter-20250513033346 → 0.0.0-cloud-storage-adapter-20251106204059
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 +1574 -2
- package/LICENSE.md +11 -42
- package/dist/index.cjs +1108 -317
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +312 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1106 -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,92 @@ 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
|
+
}
|
|
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
|
|
52
116
|
}) {
|
|
53
117
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
54
118
|
workflowName: this.workflowId,
|
|
55
119
|
runId: this.runId,
|
|
120
|
+
resourceId: this.resourceId,
|
|
56
121
|
snapshot: {
|
|
57
122
|
runId: this.runId,
|
|
123
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
58
124
|
value: {},
|
|
59
125
|
context: {},
|
|
60
126
|
activePaths: [],
|
|
61
127
|
suspendedPaths: {},
|
|
62
|
-
|
|
128
|
+
resumeLabels: {},
|
|
129
|
+
waitingPaths: {},
|
|
130
|
+
timestamp: Date.now(),
|
|
131
|
+
status: "running"
|
|
63
132
|
}
|
|
64
133
|
});
|
|
134
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
135
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
65
136
|
const eventOutput = await this.inngest.send({
|
|
66
137
|
name: `workflow.${this.workflowId}`,
|
|
67
138
|
data: {
|
|
68
|
-
inputData,
|
|
69
|
-
|
|
139
|
+
inputData: inputDataToUse,
|
|
140
|
+
initialState: initialStateToUse,
|
|
141
|
+
runId: this.runId,
|
|
142
|
+
resourceId: this.resourceId,
|
|
143
|
+
outputOptions,
|
|
144
|
+
tracingOptions,
|
|
145
|
+
format
|
|
70
146
|
}
|
|
71
147
|
});
|
|
72
148
|
const eventId = eventOutput.ids[0];
|
|
@@ -78,27 +154,45 @@ var InngestRun = class extends Run {
|
|
|
78
154
|
if (result.status === "failed") {
|
|
79
155
|
result.error = new Error(result.error);
|
|
80
156
|
}
|
|
81
|
-
|
|
157
|
+
if (result.status !== "suspended") {
|
|
158
|
+
this.cleanup?.();
|
|
159
|
+
}
|
|
82
160
|
return result;
|
|
83
161
|
}
|
|
84
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();
|
|
85
175
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
86
176
|
(step) => typeof step === "string" ? step : step?.id
|
|
87
177
|
);
|
|
88
|
-
const snapshot = await
|
|
178
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
89
179
|
workflowName: this.workflowId,
|
|
90
180
|
runId: this.runId
|
|
91
181
|
});
|
|
182
|
+
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
183
|
+
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
92
184
|
const eventOutput = await this.inngest.send({
|
|
93
185
|
name: `workflow.${this.workflowId}`,
|
|
94
186
|
data: {
|
|
95
|
-
inputData:
|
|
187
|
+
inputData: resumeDataToUse,
|
|
188
|
+
initialState: snapshot?.value ?? {},
|
|
96
189
|
runId: this.runId,
|
|
190
|
+
workflowId: this.workflowId,
|
|
97
191
|
stepResults: snapshot?.context,
|
|
98
192
|
resume: {
|
|
99
193
|
steps,
|
|
100
194
|
stepResults: snapshot?.context,
|
|
101
|
-
resumePayload:
|
|
195
|
+
resumePayload: resumeDataToUse,
|
|
102
196
|
// @ts-ignore
|
|
103
197
|
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
104
198
|
}
|
|
@@ -116,6 +210,7 @@ var InngestRun = class extends Run {
|
|
|
116
210
|
return result;
|
|
117
211
|
}
|
|
118
212
|
watch(cb) {
|
|
213
|
+
let active = true;
|
|
119
214
|
const streamPromise = subscribe(
|
|
120
215
|
{
|
|
121
216
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
@@ -123,40 +218,175 @@ var InngestRun = class extends Run {
|
|
|
123
218
|
app: this.inngest
|
|
124
219
|
},
|
|
125
220
|
(message) => {
|
|
126
|
-
|
|
221
|
+
if (active) {
|
|
222
|
+
cb(message.data);
|
|
223
|
+
}
|
|
127
224
|
}
|
|
128
225
|
);
|
|
129
226
|
return () => {
|
|
130
|
-
|
|
131
|
-
|
|
227
|
+
active = false;
|
|
228
|
+
streamPromise.then(async (stream) => {
|
|
229
|
+
return stream.cancel();
|
|
132
230
|
}).catch((err) => {
|
|
133
231
|
console.error(err);
|
|
134
232
|
});
|
|
135
233
|
};
|
|
136
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
|
+
}
|
|
137
361
|
};
|
|
138
|
-
var InngestWorkflow = class _InngestWorkflow extends
|
|
362
|
+
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
139
363
|
#mastra;
|
|
140
364
|
inngest;
|
|
141
365
|
function;
|
|
366
|
+
flowControlConfig;
|
|
142
367
|
constructor(params, inngest) {
|
|
143
|
-
|
|
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;
|
|
144
374
|
this.#mastra = params.mastra;
|
|
145
375
|
this.inngest = inngest;
|
|
146
376
|
}
|
|
147
|
-
async
|
|
377
|
+
async listWorkflowRuns(args) {
|
|
148
378
|
const storage = this.#mastra?.getStorage();
|
|
149
379
|
if (!storage) {
|
|
150
380
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
151
381
|
return { runs: [], total: 0 };
|
|
152
382
|
}
|
|
153
|
-
return storage.
|
|
383
|
+
return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
|
|
154
384
|
}
|
|
155
385
|
async getWorkflowRunById(runId) {
|
|
156
386
|
const storage = this.#mastra?.getStorage();
|
|
157
387
|
if (!storage) {
|
|
158
388
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
159
|
-
return null;
|
|
389
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
160
390
|
}
|
|
161
391
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
162
392
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
@@ -179,21 +409,51 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
179
409
|
}
|
|
180
410
|
}
|
|
181
411
|
}
|
|
182
|
-
createRun(options) {
|
|
412
|
+
async createRun(options) {
|
|
183
413
|
const runIdToUse = options?.runId || randomUUID();
|
|
184
414
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
185
415
|
{
|
|
186
416
|
workflowId: this.id,
|
|
187
417
|
runId: runIdToUse,
|
|
418
|
+
resourceId: options?.resourceId,
|
|
188
419
|
executionEngine: this.executionEngine,
|
|
189
420
|
executionGraph: this.executionGraph,
|
|
421
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
190
422
|
mastra: this.#mastra,
|
|
191
423
|
retryConfig: this.retryConfig,
|
|
192
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
424
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
425
|
+
workflowSteps: this.steps
|
|
193
426
|
},
|
|
194
427
|
this.inngest
|
|
195
428
|
);
|
|
196
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
|
+
}
|
|
197
457
|
return run;
|
|
198
458
|
}
|
|
199
459
|
getFunction() {
|
|
@@ -201,11 +461,17 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
201
461
|
return this.function;
|
|
202
462
|
}
|
|
203
463
|
this.function = this.inngest.createFunction(
|
|
204
|
-
|
|
205
|
-
|
|
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
|
+
},
|
|
206
472
|
{ event: `workflow.${this.id}` },
|
|
207
473
|
async ({ event, step, attempt, publish }) => {
|
|
208
|
-
let { inputData, runId, resume } = event.data;
|
|
474
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
209
475
|
if (!runId) {
|
|
210
476
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
211
477
|
return randomUUID();
|
|
@@ -219,25 +485,52 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
219
485
|
try {
|
|
220
486
|
await publish({
|
|
221
487
|
channel: `workflow:${this.id}:${runId}`,
|
|
222
|
-
topic:
|
|
488
|
+
topic: event2,
|
|
223
489
|
data
|
|
224
490
|
});
|
|
225
491
|
} catch (err) {
|
|
226
492
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
227
493
|
}
|
|
494
|
+
},
|
|
495
|
+
on: (_event, _callback) => {
|
|
496
|
+
},
|
|
497
|
+
off: (_event, _callback) => {
|
|
498
|
+
},
|
|
499
|
+
once: (_event, _callback) => {
|
|
228
500
|
}
|
|
229
501
|
};
|
|
230
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
502
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
231
503
|
const result = await engine.execute({
|
|
232
504
|
workflowId: this.id,
|
|
233
505
|
runId,
|
|
506
|
+
resourceId,
|
|
234
507
|
graph: this.executionGraph,
|
|
508
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
235
509
|
input: inputData,
|
|
510
|
+
initialState,
|
|
236
511
|
emitter,
|
|
237
512
|
retryConfig: this.retryConfig,
|
|
238
|
-
|
|
513
|
+
requestContext: new RequestContext(),
|
|
239
514
|
// TODO
|
|
240
|
-
resume
|
|
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;
|
|
241
534
|
});
|
|
242
535
|
return { result, runId };
|
|
243
536
|
}
|
|
@@ -261,118 +554,393 @@ var InngestWorkflow = class _InngestWorkflow extends NewWorkflow {
|
|
|
261
554
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
262
555
|
}
|
|
263
556
|
};
|
|
264
|
-
function
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
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
|
+
};
|
|
278
691
|
}
|
|
279
692
|
function init(inngest) {
|
|
280
693
|
return {
|
|
281
694
|
createWorkflow(params) {
|
|
282
|
-
return new InngestWorkflow(
|
|
695
|
+
return new InngestWorkflow(
|
|
696
|
+
params,
|
|
697
|
+
inngest
|
|
698
|
+
);
|
|
283
699
|
},
|
|
284
700
|
createStep,
|
|
285
|
-
cloneStep,
|
|
286
|
-
|
|
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
|
+
}
|
|
287
726
|
};
|
|
288
727
|
}
|
|
289
728
|
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
290
729
|
inngestStep;
|
|
291
730
|
inngestAttempts;
|
|
292
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
293
|
-
super({ mastra });
|
|
731
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
732
|
+
super({ mastra, options });
|
|
294
733
|
this.inngestStep = inngestStep;
|
|
295
734
|
this.inngestAttempts = inngestAttempts;
|
|
296
735
|
}
|
|
297
|
-
async fmtReturnValue(
|
|
736
|
+
async fmtReturnValue(emitter, stepResults, lastOutput, error) {
|
|
298
737
|
const base = {
|
|
299
738
|
status: lastOutput.status,
|
|
300
739
|
steps: stepResults
|
|
301
740
|
};
|
|
302
741
|
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
742
|
base.result = lastOutput.output;
|
|
315
743
|
} else if (lastOutput.status === "failed") {
|
|
316
744
|
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
745
|
} 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
746
|
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
343
747
|
if (stepResult?.status === "suspended") {
|
|
344
|
-
const nestedPath = stepResult?.
|
|
748
|
+
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
345
749
|
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
346
750
|
}
|
|
347
751
|
return [];
|
|
348
752
|
});
|
|
349
753
|
base.suspended = suspendedStepIds;
|
|
350
754
|
}
|
|
351
|
-
executionSpan?.end();
|
|
352
755
|
return base;
|
|
353
756
|
}
|
|
354
|
-
async
|
|
757
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
758
|
+
// await this.inngestStep.sleep(id, duration);
|
|
759
|
+
// }
|
|
760
|
+
async executeSleep({
|
|
355
761
|
workflowId,
|
|
356
762
|
runId,
|
|
357
|
-
|
|
763
|
+
entry,
|
|
764
|
+
prevOutput,
|
|
358
765
|
stepResults,
|
|
766
|
+
emitter,
|
|
767
|
+
abortController,
|
|
768
|
+
requestContext,
|
|
359
769
|
executionContext,
|
|
360
|
-
|
|
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,
|
|
361
852
|
prevOutput,
|
|
853
|
+
stepResults,
|
|
362
854
|
emitter,
|
|
363
|
-
|
|
855
|
+
abortController,
|
|
856
|
+
requestContext,
|
|
857
|
+
executionContext,
|
|
858
|
+
writableStream,
|
|
859
|
+
tracingContext
|
|
364
860
|
}) {
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
|
375
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
|
+
}
|
|
376
944
|
}
|
|
377
945
|
async executeStep({
|
|
378
946
|
step,
|
|
@@ -381,91 +949,113 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
381
949
|
resume,
|
|
382
950
|
prevOutput,
|
|
383
951
|
emitter,
|
|
384
|
-
|
|
952
|
+
abortController,
|
|
953
|
+
requestContext,
|
|
954
|
+
tracingContext,
|
|
955
|
+
writableStream,
|
|
956
|
+
disableScorers
|
|
385
957
|
}) {
|
|
386
|
-
|
|
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(
|
|
387
973
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
388
974
|
async () => {
|
|
975
|
+
const startedAt2 = Date.now();
|
|
389
976
|
await emitter.emit("watch", {
|
|
390
|
-
type: "
|
|
977
|
+
type: "workflow-step-start",
|
|
391
978
|
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()
|
|
979
|
+
id: step.id,
|
|
980
|
+
status: "running",
|
|
981
|
+
payload: inputData,
|
|
982
|
+
startedAt: startedAt2
|
|
983
|
+
}
|
|
409
984
|
});
|
|
985
|
+
return startedAt2;
|
|
410
986
|
}
|
|
411
987
|
);
|
|
412
988
|
if (step instanceof InngestWorkflow) {
|
|
413
989
|
const isResume = !!resume?.steps?.length;
|
|
414
990
|
let result;
|
|
415
991
|
let runId;
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
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 ?? {},
|
|
428
1004
|
runId,
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
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 }
|
|
434
1014
|
}
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
+
}
|
|
448
1046
|
}
|
|
449
1047
|
const res = await this.inngestStep.run(
|
|
450
1048
|
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
451
1049
|
async () => {
|
|
452
1050
|
if (result.status === "failed") {
|
|
453
1051
|
await emitter.emit("watch", {
|
|
454
|
-
type: "
|
|
1052
|
+
type: "workflow-step-result",
|
|
455
1053
|
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()
|
|
1054
|
+
id: step.id,
|
|
1055
|
+
status: "failed",
|
|
1056
|
+
error: result?.error,
|
|
1057
|
+
payload: prevOutput
|
|
1058
|
+
}
|
|
469
1059
|
});
|
|
470
1060
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
471
1061
|
} else if (result.status === "suspended") {
|
|
@@ -474,50 +1064,27 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
474
1064
|
return stepRes2?.status === "suspended";
|
|
475
1065
|
});
|
|
476
1066
|
for (const [stepName, stepResult] of suspendedSteps) {
|
|
477
|
-
const suspendPath = [stepName, ...stepResult?.
|
|
1067
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
478
1068
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
479
1069
|
await emitter.emit("watch", {
|
|
480
|
-
type: "
|
|
1070
|
+
type: "workflow-step-suspended",
|
|
481
1071
|
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()
|
|
1072
|
+
id: step.id,
|
|
1073
|
+
status: "suspended"
|
|
1074
|
+
}
|
|
495
1075
|
});
|
|
496
1076
|
return {
|
|
497
1077
|
executionContext,
|
|
498
1078
|
result: {
|
|
499
1079
|
status: "suspended",
|
|
500
|
-
payload:
|
|
1080
|
+
payload: stepResult.payload,
|
|
1081
|
+
suspendPayload: {
|
|
1082
|
+
...stepResult?.suspendPayload,
|
|
1083
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
1084
|
+
}
|
|
501
1085
|
}
|
|
502
1086
|
};
|
|
503
1087
|
}
|
|
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
1088
|
return {
|
|
522
1089
|
executionContext,
|
|
523
1090
|
result: {
|
|
@@ -527,110 +1094,243 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
527
1094
|
};
|
|
528
1095
|
}
|
|
529
1096
|
await emitter.emit("watch", {
|
|
530
|
-
type: "
|
|
1097
|
+
type: "workflow-step-result",
|
|
531
1098
|
payload: {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
},
|
|
544
|
-
eventTimestamp: Date.now()
|
|
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
|
+
}
|
|
545
1110
|
});
|
|
546
1111
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
547
1112
|
}
|
|
548
1113
|
);
|
|
549
1114
|
Object.assign(executionContext, res.executionContext);
|
|
550
|
-
return
|
|
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
|
+
};
|
|
551
1123
|
}
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
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
|
|
566
1240
|
}
|
|
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;
|
|
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
|
+
});
|
|
591
1257
|
}
|
|
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()
|
|
1258
|
+
stepSpan?.end({ output: execResults });
|
|
1259
|
+
return { result: execResults, executionContext, stepResults };
|
|
609
1260
|
});
|
|
610
|
-
|
|
611
|
-
|
|
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
|
+
}
|
|
612
1295
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
613
1296
|
Object.assign(stepResults, stepRes.stepResults);
|
|
1297
|
+
executionContext.state = stepRes.executionContext.state;
|
|
614
1298
|
return stepRes.result;
|
|
615
1299
|
}
|
|
616
1300
|
async persistStepUpdate({
|
|
617
1301
|
workflowId,
|
|
618
1302
|
runId,
|
|
619
1303
|
stepResults,
|
|
620
|
-
|
|
1304
|
+
resourceId,
|
|
1305
|
+
executionContext,
|
|
1306
|
+
serializedStepGraph,
|
|
1307
|
+
workflowStatus,
|
|
1308
|
+
result,
|
|
1309
|
+
error
|
|
621
1310
|
}) {
|
|
622
1311
|
await this.inngestStep.run(
|
|
623
1312
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
624
1313
|
async () => {
|
|
1314
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1315
|
+
if (!shouldPersistSnapshot) {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
625
1318
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
626
1319
|
workflowName: workflowId,
|
|
627
1320
|
runId,
|
|
1321
|
+
resourceId,
|
|
628
1322
|
snapshot: {
|
|
629
1323
|
runId,
|
|
630
|
-
value:
|
|
1324
|
+
value: executionContext.state,
|
|
631
1325
|
context: stepResults,
|
|
632
1326
|
activePaths: [],
|
|
633
1327
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1328
|
+
resumeLabels: executionContext.resumeLabels,
|
|
1329
|
+
waitingPaths: {},
|
|
1330
|
+
serializedStepGraph,
|
|
1331
|
+
status: workflowStatus,
|
|
1332
|
+
result,
|
|
1333
|
+
error,
|
|
634
1334
|
// @ts-ignore
|
|
635
1335
|
timestamp: Date.now()
|
|
636
1336
|
}
|
|
@@ -643,53 +1343,123 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
643
1343
|
runId,
|
|
644
1344
|
entry,
|
|
645
1345
|
prevOutput,
|
|
646
|
-
prevStep,
|
|
647
1346
|
stepResults,
|
|
648
1347
|
resume,
|
|
649
1348
|
executionContext,
|
|
650
1349
|
emitter,
|
|
651
|
-
|
|
1350
|
+
abortController,
|
|
1351
|
+
requestContext,
|
|
1352
|
+
writableStream,
|
|
1353
|
+
disableScorers,
|
|
1354
|
+
tracingContext
|
|
652
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
|
+
});
|
|
653
1365
|
let execResults;
|
|
654
1366
|
const truthyIndexes = (await Promise.all(
|
|
655
1367
|
entry.conditions.map(
|
|
656
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
|
+
});
|
|
657
1378
|
try {
|
|
658
|
-
const result = await cond(
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
|
670
1425
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
1426
|
+
)
|
|
1427
|
+
);
|
|
1428
|
+
evalSpan?.end({
|
|
1429
|
+
output: result,
|
|
1430
|
+
attributes: {
|
|
1431
|
+
result: !!result
|
|
1432
|
+
}
|
|
677
1433
|
});
|
|
678
1434
|
return result ? index : null;
|
|
679
1435
|
} catch (e) {
|
|
1436
|
+
evalSpan?.error({
|
|
1437
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1438
|
+
attributes: {
|
|
1439
|
+
result: false
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
680
1442
|
return null;
|
|
681
1443
|
}
|
|
682
1444
|
})
|
|
683
1445
|
)
|
|
684
1446
|
)).filter((index) => index !== null);
|
|
685
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
|
+
});
|
|
686
1454
|
const results = await Promise.all(
|
|
687
|
-
stepsToRun.map(
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
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,
|
|
693
1463
|
stepResults,
|
|
694
1464
|
resume,
|
|
695
1465
|
executionContext: {
|
|
@@ -697,20 +1467,29 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
697
1467
|
runId,
|
|
698
1468
|
executionPath: [...executionContext.executionPath, index],
|
|
699
1469
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1470
|
+
resumeLabels: executionContext.resumeLabels,
|
|
700
1471
|
retryConfig: executionContext.retryConfig,
|
|
701
|
-
|
|
1472
|
+
state: executionContext.state
|
|
702
1473
|
},
|
|
703
1474
|
emitter,
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
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
|
+
})
|
|
707
1486
|
);
|
|
708
1487
|
const hasFailed = results.find((result) => result.status === "failed");
|
|
709
1488
|
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
710
1489
|
if (hasFailed) {
|
|
711
1490
|
execResults = { status: "failed", error: hasFailed.error };
|
|
712
1491
|
} else if (hasSuspended) {
|
|
713
|
-
execResults = { status: "suspended",
|
|
1492
|
+
execResults = { status: "suspended", suspendPayload: hasSuspended.suspendPayload };
|
|
714
1493
|
} else {
|
|
715
1494
|
execResults = {
|
|
716
1495
|
status: "success",
|
|
@@ -722,8 +1501,19 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
|
722
1501
|
}, {})
|
|
723
1502
|
};
|
|
724
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
|
+
}
|
|
725
1513
|
return execResults;
|
|
726
1514
|
}
|
|
727
1515
|
};
|
|
728
1516
|
|
|
729
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, init, serve };
|
|
1517
|
+
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|
|
1518
|
+
//# sourceMappingURL=index.js.map
|
|
1519
|
+
//# sourceMappingURL=index.js.map
|