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