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