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