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