@mastra/inngest 0.0.0-scorers-api-v2-20250801171841 → 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 +1070 -3
- package/dist/execution-engine.d.ts +85 -0
- package/dist/execution-engine.d.ts.map +1 -0
- package/dist/index.cjs +837 -909
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +28 -271
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +813 -886
- 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 +38 -19
- 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 -22
- package/vitest.config.ts +0 -14
package/dist/index.js
CHANGED
|
@@ -1,31 +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 { ToolStream, Tool } from '@mastra/core/tools';
|
|
5
|
-
import { Run, Workflow, DefaultExecutionEngine } from '@mastra/core/workflows';
|
|
6
|
-
import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
10
|
+
import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
|
|
7
11
|
import { serve as serve$1 } from 'inngest/hono';
|
|
8
|
-
import { z } from 'zod';
|
|
9
12
|
|
|
10
13
|
// src/index.ts
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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()
|
|
19
81
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
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
|
+
};
|
|
29
298
|
var InngestRun = class extends Run {
|
|
30
299
|
inngest;
|
|
31
300
|
serializedStepGraph;
|
|
@@ -47,14 +316,21 @@ var InngestRun = class extends Run {
|
|
|
47
316
|
}
|
|
48
317
|
async getRunOutput(eventId) {
|
|
49
318
|
let runs = await this.getRuns(eventId);
|
|
319
|
+
const storage = this.#mastra?.getStorage();
|
|
50
320
|
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
51
321
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
52
322
|
runs = await this.getRuns(eventId);
|
|
53
323
|
if (runs?.[0]?.status === "Failed") {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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({
|
|
58
334
|
workflowName: this.workflowId,
|
|
59
335
|
runId: this.runId
|
|
60
336
|
});
|
|
@@ -63,56 +339,73 @@ var InngestRun = class extends Run {
|
|
|
63
339
|
}
|
|
64
340
|
return runs?.[0];
|
|
65
341
|
}
|
|
66
|
-
async sendEvent(event, data) {
|
|
67
|
-
await this.inngest.send({
|
|
68
|
-
name: `user-event-${event}`,
|
|
69
|
-
data
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
342
|
async cancel() {
|
|
343
|
+
const storage = this.#mastra?.getStorage();
|
|
73
344
|
await this.inngest.send({
|
|
74
345
|
name: `cancel.workflow.${this.workflowId}`,
|
|
75
346
|
data: {
|
|
76
347
|
runId: this.runId
|
|
77
348
|
}
|
|
78
349
|
});
|
|
79
|
-
const snapshot = await
|
|
350
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
80
351
|
workflowName: this.workflowId,
|
|
81
352
|
runId: this.runId
|
|
82
353
|
});
|
|
83
354
|
if (snapshot) {
|
|
84
|
-
await
|
|
355
|
+
await storage?.persistWorkflowSnapshot({
|
|
85
356
|
workflowName: this.workflowId,
|
|
86
357
|
runId: this.runId,
|
|
358
|
+
resourceId: this.resourceId,
|
|
87
359
|
snapshot: {
|
|
88
360
|
...snapshot,
|
|
89
|
-
status: "canceled"
|
|
361
|
+
status: "canceled",
|
|
362
|
+
value: snapshot.value
|
|
90
363
|
}
|
|
91
364
|
});
|
|
92
365
|
}
|
|
93
366
|
}
|
|
94
|
-
async start({
|
|
95
|
-
|
|
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
|
|
96
377
|
}) {
|
|
97
378
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
98
379
|
workflowName: this.workflowId,
|
|
99
380
|
runId: this.runId,
|
|
381
|
+
resourceId: this.resourceId,
|
|
100
382
|
snapshot: {
|
|
101
383
|
runId: this.runId,
|
|
102
384
|
serializedStepGraph: this.serializedStepGraph,
|
|
385
|
+
status: "running",
|
|
103
386
|
value: {},
|
|
104
387
|
context: {},
|
|
105
388
|
activePaths: [],
|
|
106
389
|
suspendedPaths: {},
|
|
107
|
-
|
|
108
|
-
|
|
390
|
+
activeStepsPath: {},
|
|
391
|
+
resumeLabels: {},
|
|
392
|
+
waitingPaths: {},
|
|
393
|
+
timestamp: Date.now()
|
|
109
394
|
}
|
|
110
395
|
});
|
|
396
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
397
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
111
398
|
const eventOutput = await this.inngest.send({
|
|
112
399
|
name: `workflow.${this.workflowId}`,
|
|
113
400
|
data: {
|
|
114
|
-
inputData,
|
|
115
|
-
|
|
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()) : {}
|
|
116
409
|
}
|
|
117
410
|
});
|
|
118
411
|
const eventId = eventOutput.ids[0];
|
|
@@ -141,27 +434,131 @@ var InngestRun = class extends Run {
|
|
|
141
434
|
return p;
|
|
142
435
|
}
|
|
143
436
|
async _resume(params) {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
)
|
|
147
|
-
|
|
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({
|
|
148
447
|
workflowName: this.workflowId,
|
|
149
448
|
runId: this.runId
|
|
150
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 };
|
|
151
455
|
const eventOutput = await this.inngest.send({
|
|
152
456
|
name: `workflow.${this.workflowId}`,
|
|
153
457
|
data: {
|
|
154
|
-
inputData:
|
|
458
|
+
inputData: resumeDataToUse,
|
|
459
|
+
initialState: snapshot?.value ?? {},
|
|
155
460
|
runId: this.runId,
|
|
156
461
|
workflowId: this.workflowId,
|
|
157
462
|
stepResults: snapshot?.context,
|
|
158
463
|
resume: {
|
|
159
464
|
steps,
|
|
160
465
|
stepResults: snapshot?.context,
|
|
161
|
-
resumePayload:
|
|
162
|
-
|
|
163
|
-
|
|
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()
|
|
164
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()) : {}
|
|
165
562
|
}
|
|
166
563
|
});
|
|
167
564
|
const eventId = eventOutput.ids[0];
|
|
@@ -175,12 +572,12 @@ var InngestRun = class extends Run {
|
|
|
175
572
|
}
|
|
176
573
|
return result;
|
|
177
574
|
}
|
|
178
|
-
watch(cb
|
|
575
|
+
watch(cb) {
|
|
179
576
|
let active = true;
|
|
180
577
|
const streamPromise = subscribe(
|
|
181
578
|
{
|
|
182
579
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
183
|
-
topics: [
|
|
580
|
+
topics: ["watch"],
|
|
184
581
|
app: this.inngest
|
|
185
582
|
},
|
|
186
583
|
(message) => {
|
|
@@ -198,16 +595,35 @@ var InngestRun = class extends Run {
|
|
|
198
595
|
});
|
|
199
596
|
};
|
|
200
597
|
}
|
|
201
|
-
|
|
598
|
+
streamLegacy({ inputData, requestContext } = {}) {
|
|
202
599
|
const { readable, writable } = new TransformStream();
|
|
203
600
|
const writer = writable.getWriter();
|
|
601
|
+
void writer.write({
|
|
602
|
+
// @ts-ignore
|
|
603
|
+
type: "start",
|
|
604
|
+
// @ts-ignore
|
|
605
|
+
payload: { runId: this.runId }
|
|
606
|
+
});
|
|
204
607
|
const unwatch = this.watch(async (event) => {
|
|
205
608
|
try {
|
|
206
|
-
|
|
609
|
+
const e = {
|
|
610
|
+
...event,
|
|
611
|
+
type: event.type.replace("workflow-", "")
|
|
612
|
+
};
|
|
613
|
+
if (e.type === "step-output") {
|
|
614
|
+
e.type = e.payload.output.type;
|
|
615
|
+
e.payload = e.payload.output.payload;
|
|
616
|
+
}
|
|
617
|
+
await writer.write(e);
|
|
207
618
|
} catch {
|
|
208
619
|
}
|
|
209
|
-
}
|
|
620
|
+
});
|
|
210
621
|
this.closeStreamAction = async () => {
|
|
622
|
+
await writer.write({
|
|
623
|
+
type: "finish",
|
|
624
|
+
// @ts-ignore
|
|
625
|
+
payload: { runId: this.runId }
|
|
626
|
+
});
|
|
211
627
|
unwatch();
|
|
212
628
|
try {
|
|
213
629
|
await writer.close();
|
|
@@ -217,7 +633,7 @@ var InngestRun = class extends Run {
|
|
|
217
633
|
writer.releaseLock();
|
|
218
634
|
}
|
|
219
635
|
};
|
|
220
|
-
this.executionResults = this.
|
|
636
|
+
this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
|
|
221
637
|
if (result.status !== "suspended") {
|
|
222
638
|
this.closeStreamAction?.().catch(() => {
|
|
223
639
|
});
|
|
@@ -229,23 +645,177 @@ var InngestRun = class extends Run {
|
|
|
229
645
|
getWorkflowState: () => this.executionResults
|
|
230
646
|
};
|
|
231
647
|
}
|
|
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;
|
|
658
|
+
}
|
|
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
|
+
}
|
|
232
793
|
};
|
|
794
|
+
|
|
795
|
+
// src/workflow.ts
|
|
233
796
|
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
234
797
|
#mastra;
|
|
235
798
|
inngest;
|
|
236
799
|
function;
|
|
800
|
+
flowControlConfig;
|
|
237
801
|
constructor(params, inngest) {
|
|
238
|
-
|
|
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;
|
|
239
809
|
this.#mastra = params.mastra;
|
|
240
810
|
this.inngest = inngest;
|
|
241
811
|
}
|
|
242
|
-
async
|
|
812
|
+
async listWorkflowRuns(args) {
|
|
243
813
|
const storage = this.#mastra?.getStorage();
|
|
244
814
|
if (!storage) {
|
|
245
815
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
246
816
|
return { runs: [], total: 0 };
|
|
247
817
|
}
|
|
248
|
-
return storage.
|
|
818
|
+
return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
|
|
249
819
|
}
|
|
250
820
|
async getWorkflowRunById(runId) {
|
|
251
821
|
const storage = this.#mastra?.getStorage();
|
|
@@ -256,27 +826,6 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
256
826
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
257
827
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
258
828
|
}
|
|
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
829
|
__registerMastra(mastra) {
|
|
281
830
|
this.#mastra = mastra;
|
|
282
831
|
this.executionEngine.__registerMastra(mastra);
|
|
@@ -295,56 +844,49 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
295
844
|
}
|
|
296
845
|
}
|
|
297
846
|
}
|
|
298
|
-
createRun(options) {
|
|
847
|
+
async createRun(options) {
|
|
299
848
|
const runIdToUse = options?.runId || randomUUID();
|
|
300
849
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
301
850
|
{
|
|
302
851
|
workflowId: this.id,
|
|
303
852
|
runId: runIdToUse,
|
|
853
|
+
resourceId: options?.resourceId,
|
|
304
854
|
executionEngine: this.executionEngine,
|
|
305
855
|
executionGraph: this.executionGraph,
|
|
306
856
|
serializedStepGraph: this.serializedStepGraph,
|
|
307
857
|
mastra: this.#mastra,
|
|
308
858
|
retryConfig: this.retryConfig,
|
|
309
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
859
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
860
|
+
workflowSteps: this.steps,
|
|
861
|
+
workflowEngineType: this.engineType,
|
|
862
|
+
validateInputs: this.options.validateInputs
|
|
310
863
|
},
|
|
311
864
|
this.inngest
|
|
312
865
|
);
|
|
313
866
|
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) {
|
|
867
|
+
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
|
|
868
|
+
workflowStatus: run.workflowRunStatus,
|
|
869
|
+
stepResults: {}
|
|
870
|
+
});
|
|
871
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
872
|
+
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
334
873
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
335
874
|
workflowName: this.id,
|
|
336
875
|
runId: runIdToUse,
|
|
876
|
+
resourceId: options?.resourceId,
|
|
337
877
|
snapshot: {
|
|
338
878
|
runId: runIdToUse,
|
|
339
879
|
status: "pending",
|
|
340
880
|
value: {},
|
|
341
881
|
context: {},
|
|
342
882
|
activePaths: [],
|
|
883
|
+
activeStepsPath: {},
|
|
884
|
+
waitingPaths: {},
|
|
343
885
|
serializedStepGraph: this.serializedStepGraph,
|
|
344
886
|
suspendedPaths: {},
|
|
887
|
+
resumeLabels: {},
|
|
345
888
|
result: void 0,
|
|
346
889
|
error: void 0,
|
|
347
|
-
// @ts-ignore
|
|
348
890
|
timestamp: Date.now()
|
|
349
891
|
}
|
|
350
892
|
});
|
|
@@ -358,13 +900,14 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
358
900
|
this.function = this.inngest.createFunction(
|
|
359
901
|
{
|
|
360
902
|
id: `workflow.${this.id}`,
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
903
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
904
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
905
|
+
// Spread flow control configuration
|
|
906
|
+
...this.flowControlConfig
|
|
364
907
|
},
|
|
365
908
|
{ event: `workflow.${this.id}` },
|
|
366
909
|
async ({ event, step, attempt, publish }) => {
|
|
367
|
-
let { inputData, runId, resume } = event.data;
|
|
910
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
368
911
|
if (!runId) {
|
|
369
912
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
370
913
|
return randomUUID();
|
|
@@ -392,19 +935,38 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
392
935
|
once: (_event, _callback) => {
|
|
393
936
|
}
|
|
394
937
|
};
|
|
395
|
-
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
938
|
+
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
396
939
|
const result = await engine.execute({
|
|
397
940
|
workflowId: this.id,
|
|
398
941
|
runId,
|
|
942
|
+
resourceId,
|
|
399
943
|
graph: this.executionGraph,
|
|
400
944
|
serializedStepGraph: this.serializedStepGraph,
|
|
401
945
|
input: inputData,
|
|
946
|
+
initialState,
|
|
402
947
|
emitter,
|
|
403
948
|
retryConfig: this.retryConfig,
|
|
404
|
-
|
|
405
|
-
// TODO
|
|
949
|
+
requestContext: new RequestContext(Object.entries(event.data.requestContext ?? {})),
|
|
406
950
|
resume,
|
|
407
|
-
|
|
951
|
+
timeTravel,
|
|
952
|
+
format,
|
|
953
|
+
abortController: new AbortController(),
|
|
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;
|
|
408
970
|
});
|
|
409
971
|
return { result, runId };
|
|
410
972
|
}
|
|
@@ -428,27 +990,70 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
428
990
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
429
991
|
}
|
|
430
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
|
|
431
1022
|
function isAgent(params) {
|
|
432
1023
|
return params?.component === "AGENT";
|
|
433
1024
|
}
|
|
434
1025
|
function isTool(params) {
|
|
435
1026
|
return params instanceof Tool;
|
|
436
1027
|
}
|
|
437
|
-
function
|
|
1028
|
+
function isInngestWorkflow(params) {
|
|
1029
|
+
return params instanceof InngestWorkflow;
|
|
1030
|
+
}
|
|
1031
|
+
function createStep(params, agentOptions) {
|
|
1032
|
+
if (isInngestWorkflow(params)) {
|
|
1033
|
+
return params;
|
|
1034
|
+
}
|
|
438
1035
|
if (isAgent(params)) {
|
|
439
1036
|
return {
|
|
440
1037
|
id: params.name,
|
|
441
|
-
|
|
1038
|
+
description: params.getDescription(),
|
|
442
1039
|
inputSchema: z.object({
|
|
443
1040
|
prompt: z.string()
|
|
444
1041
|
// resourceId: z.string().optional(),
|
|
445
1042
|
// threadId: z.string().optional(),
|
|
446
1043
|
}),
|
|
447
|
-
// @ts-ignore
|
|
448
1044
|
outputSchema: z.object({
|
|
449
1045
|
text: z.string()
|
|
450
1046
|
}),
|
|
451
|
-
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
|
+
}) => {
|
|
452
1057
|
let streamPromise = {};
|
|
453
1058
|
streamPromise.promise = new Promise((resolve, reject) => {
|
|
454
1059
|
streamPromise.resolve = resolve;
|
|
@@ -458,50 +1063,65 @@ function createStep(params) {
|
|
|
458
1063
|
name: params.name,
|
|
459
1064
|
args: inputData
|
|
460
1065
|
};
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
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;
|
|
476
1093
|
}
|
|
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", {
|
|
481
1102
|
type: "tool-call-delta",
|
|
482
|
-
...toolData,
|
|
1103
|
+
...toolData ?? {},
|
|
483
1104
|
argsTextDelta: chunk.textDelta
|
|
484
1105
|
});
|
|
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;
|
|
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);
|
|
499
1115
|
}
|
|
500
1116
|
}
|
|
1117
|
+
if (abortSignal.aborted) {
|
|
1118
|
+
return abort();
|
|
1119
|
+
}
|
|
501
1120
|
return {
|
|
502
1121
|
text: await streamPromise.promise
|
|
503
1122
|
};
|
|
504
|
-
}
|
|
1123
|
+
},
|
|
1124
|
+
component: params.component
|
|
505
1125
|
};
|
|
506
1126
|
}
|
|
507
1127
|
if (isTool(params)) {
|
|
@@ -510,17 +1130,40 @@ function createStep(params) {
|
|
|
510
1130
|
}
|
|
511
1131
|
return {
|
|
512
1132
|
// TODO: tool probably should have strong id type
|
|
513
|
-
// @ts-ignore
|
|
514
1133
|
id: params.id,
|
|
1134
|
+
description: params.description,
|
|
515
1135
|
inputSchema: params.inputSchema,
|
|
516
1136
|
outputSchema: params.outputSchema,
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
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 = {
|
|
520
1152
|
mastra,
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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"
|
|
524
1167
|
};
|
|
525
1168
|
}
|
|
526
1169
|
return {
|
|
@@ -536,7 +1179,10 @@ function createStep(params) {
|
|
|
536
1179
|
function init(inngest) {
|
|
537
1180
|
return {
|
|
538
1181
|
createWorkflow(params) {
|
|
539
|
-
return new InngestWorkflow(
|
|
1182
|
+
return new InngestWorkflow(
|
|
1183
|
+
params,
|
|
1184
|
+
inngest
|
|
1185
|
+
);
|
|
540
1186
|
},
|
|
541
1187
|
createStep,
|
|
542
1188
|
cloneStep(step, opts) {
|
|
@@ -545,7 +1191,13 @@ function init(inngest) {
|
|
|
545
1191
|
description: step.description,
|
|
546
1192
|
inputSchema: step.inputSchema,
|
|
547
1193
|
outputSchema: step.outputSchema,
|
|
548
|
-
|
|
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
|
|
549
1201
|
};
|
|
550
1202
|
},
|
|
551
1203
|
cloneWorkflow(workflow, opts) {
|
|
@@ -554,7 +1206,8 @@ function init(inngest) {
|
|
|
554
1206
|
inputSchema: workflow.inputSchema,
|
|
555
1207
|
outputSchema: workflow.outputSchema,
|
|
556
1208
|
steps: workflow.stepDefs,
|
|
557
|
-
mastra: workflow.mastra
|
|
1209
|
+
mastra: workflow.mastra,
|
|
1210
|
+
options: workflow.options
|
|
558
1211
|
});
|
|
559
1212
|
wf.setStepFlow(workflow.stepGraph);
|
|
560
1213
|
wf.commit();
|
|
@@ -562,733 +1215,7 @@ function init(inngest) {
|
|
|
562
1215
|
}
|
|
563
1216
|
};
|
|
564
1217
|
}
|
|
565
|
-
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
566
|
-
inngestStep;
|
|
567
|
-
inngestAttempts;
|
|
568
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
569
|
-
super({ mastra });
|
|
570
|
-
this.inngestStep = inngestStep;
|
|
571
|
-
this.inngestAttempts = inngestAttempts;
|
|
572
|
-
}
|
|
573
|
-
async execute(params) {
|
|
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) {
|
|
586
|
-
const base = {
|
|
587
|
-
status: lastOutput.status,
|
|
588
|
-
steps: stepResults
|
|
589
|
-
};
|
|
590
|
-
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
|
-
base.result = lastOutput.output;
|
|
603
|
-
} else if (lastOutput.status === "failed") {
|
|
604
|
-
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
|
-
} 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
|
-
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
631
|
-
if (stepResult?.status === "suspended") {
|
|
632
|
-
const nestedPath = stepResult?.payload?.__workflow_meta?.path;
|
|
633
|
-
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
634
|
-
}
|
|
635
|
-
return [];
|
|
636
|
-
});
|
|
637
|
-
base.suspended = suspendedStepIds;
|
|
638
|
-
}
|
|
639
|
-
executionSpan?.end();
|
|
640
|
-
return base;
|
|
641
|
-
}
|
|
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
|
-
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
670
|
-
// await this.inngestStep.sleep(id, duration);
|
|
671
|
-
// }
|
|
672
|
-
async executeSleep({
|
|
673
|
-
workflowId,
|
|
674
|
-
runId,
|
|
675
|
-
entry,
|
|
676
|
-
prevOutput,
|
|
677
|
-
stepResults,
|
|
678
|
-
emitter,
|
|
679
|
-
abortController,
|
|
680
|
-
runtimeContext,
|
|
681
|
-
writableStream
|
|
682
|
-
}) {
|
|
683
|
-
let { duration, fn } = entry;
|
|
684
|
-
if (fn) {
|
|
685
|
-
const stepCallId = randomUUID();
|
|
686
|
-
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
687
|
-
return await fn({
|
|
688
|
-
runId,
|
|
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(
|
|
717
|
-
{
|
|
718
|
-
prefix: "step",
|
|
719
|
-
callId: stepCallId,
|
|
720
|
-
name: "sleep",
|
|
721
|
-
runId
|
|
722
|
-
},
|
|
723
|
-
writableStream
|
|
724
|
-
)
|
|
725
|
-
});
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
729
|
-
}
|
|
730
|
-
async executeSleepUntil({
|
|
731
|
-
workflowId,
|
|
732
|
-
runId,
|
|
733
|
-
entry,
|
|
734
|
-
prevOutput,
|
|
735
|
-
stepResults,
|
|
736
|
-
emitter,
|
|
737
|
-
abortController,
|
|
738
|
-
runtimeContext,
|
|
739
|
-
writableStream
|
|
740
|
-
}) {
|
|
741
|
-
let { date, fn } = entry;
|
|
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
|
-
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(
|
|
775
|
-
{
|
|
776
|
-
prefix: "step",
|
|
777
|
-
callId: stepCallId,
|
|
778
|
-
name: "sleep",
|
|
779
|
-
runId
|
|
780
|
-
},
|
|
781
|
-
writableStream
|
|
782
|
-
)
|
|
783
|
-
});
|
|
784
|
-
});
|
|
785
|
-
}
|
|
786
|
-
if (!(date instanceof Date)) {
|
|
787
|
-
return;
|
|
788
|
-
}
|
|
789
|
-
await this.inngestStep.sleepUntil(entry.id, date);
|
|
790
|
-
}
|
|
791
|
-
async executeWaitForEvent({ event, timeout }) {
|
|
792
|
-
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
793
|
-
event: `user-event-${event}`,
|
|
794
|
-
timeout: timeout ?? 5e3
|
|
795
|
-
});
|
|
796
|
-
if (eventData === null) {
|
|
797
|
-
throw "Timeout waiting for event";
|
|
798
|
-
}
|
|
799
|
-
return eventData?.data;
|
|
800
|
-
}
|
|
801
|
-
async executeStep({
|
|
802
|
-
step,
|
|
803
|
-
stepResults,
|
|
804
|
-
executionContext,
|
|
805
|
-
resume,
|
|
806
|
-
prevOutput,
|
|
807
|
-
emitter,
|
|
808
|
-
abortController,
|
|
809
|
-
runtimeContext,
|
|
810
|
-
writableStream
|
|
811
|
-
}) {
|
|
812
|
-
const startedAt = await this.inngestStep.run(
|
|
813
|
-
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
814
|
-
async () => {
|
|
815
|
-
const startedAt2 = Date.now();
|
|
816
|
-
await emitter.emit("watch", {
|
|
817
|
-
type: "watch",
|
|
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",
|
|
839
|
-
payload: {
|
|
840
|
-
id: step.id,
|
|
841
|
-
status: "running",
|
|
842
|
-
payload: prevOutput,
|
|
843
|
-
startedAt: startedAt2
|
|
844
|
-
}
|
|
845
|
-
});
|
|
846
|
-
return startedAt2;
|
|
847
|
-
}
|
|
848
|
-
);
|
|
849
|
-
if (step instanceof InngestWorkflow) {
|
|
850
|
-
const isResume = !!resume?.steps?.length;
|
|
851
|
-
let result;
|
|
852
|
-
let runId;
|
|
853
|
-
if (isResume) {
|
|
854
|
-
runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? randomUUID();
|
|
855
|
-
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
856
|
-
workflowName: step.id,
|
|
857
|
-
runId
|
|
858
|
-
});
|
|
859
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
860
|
-
function: step.getFunction(),
|
|
861
|
-
data: {
|
|
862
|
-
inputData: prevOutput,
|
|
863
|
-
runId,
|
|
864
|
-
resume: {
|
|
865
|
-
runId,
|
|
866
|
-
steps: resume.steps.slice(1),
|
|
867
|
-
stepResults: snapshot?.context,
|
|
868
|
-
resumePayload: resume.resumePayload,
|
|
869
|
-
// @ts-ignore
|
|
870
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
});
|
|
874
|
-
result = invokeResp.result;
|
|
875
|
-
runId = invokeResp.runId;
|
|
876
|
-
} else {
|
|
877
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
878
|
-
function: step.getFunction(),
|
|
879
|
-
data: {
|
|
880
|
-
inputData: prevOutput
|
|
881
|
-
}
|
|
882
|
-
});
|
|
883
|
-
result = invokeResp.result;
|
|
884
|
-
runId = invokeResp.runId;
|
|
885
|
-
}
|
|
886
|
-
const res = await this.inngestStep.run(
|
|
887
|
-
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
888
|
-
async () => {
|
|
889
|
-
if (result.status === "failed") {
|
|
890
|
-
await emitter.emit("watch", {
|
|
891
|
-
type: "watch",
|
|
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",
|
|
909
|
-
payload: {
|
|
910
|
-
id: step.id,
|
|
911
|
-
status: "failed",
|
|
912
|
-
error: result?.error,
|
|
913
|
-
payload: prevOutput
|
|
914
|
-
}
|
|
915
|
-
});
|
|
916
|
-
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
917
|
-
} else if (result.status === "suspended") {
|
|
918
|
-
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
919
|
-
const stepRes2 = stepResult;
|
|
920
|
-
return stepRes2?.status === "suspended";
|
|
921
|
-
});
|
|
922
|
-
for (const [stepName, stepResult] of suspendedSteps) {
|
|
923
|
-
const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
|
|
924
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
925
|
-
await emitter.emit("watch", {
|
|
926
|
-
type: "watch",
|
|
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",
|
|
944
|
-
payload: {
|
|
945
|
-
id: step.id,
|
|
946
|
-
status: "suspended"
|
|
947
|
-
}
|
|
948
|
-
});
|
|
949
|
-
return {
|
|
950
|
-
executionContext,
|
|
951
|
-
result: {
|
|
952
|
-
status: "suspended",
|
|
953
|
-
payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
|
|
954
|
-
}
|
|
955
|
-
};
|
|
956
|
-
}
|
|
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
|
-
return {
|
|
975
|
-
executionContext,
|
|
976
|
-
result: {
|
|
977
|
-
status: "suspended",
|
|
978
|
-
payload: {}
|
|
979
|
-
}
|
|
980
|
-
};
|
|
981
|
-
}
|
|
982
|
-
await emitter.emit("watch", {
|
|
983
|
-
type: "watch",
|
|
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",
|
|
1001
|
-
payload: {
|
|
1002
|
-
id: step.id,
|
|
1003
|
-
status: "success",
|
|
1004
|
-
output: result?.result
|
|
1005
|
-
}
|
|
1006
|
-
});
|
|
1007
|
-
await emitter.emit("watch-v2", {
|
|
1008
|
-
type: "step-finish",
|
|
1009
|
-
payload: {
|
|
1010
|
-
id: step.id,
|
|
1011
|
-
metadata: {}
|
|
1012
|
-
}
|
|
1013
|
-
});
|
|
1014
|
-
return { executionContext, result: { status: "success", output: result?.result } };
|
|
1015
|
-
}
|
|
1016
|
-
);
|
|
1017
|
-
Object.assign(executionContext, res.executionContext);
|
|
1018
|
-
return res.result;
|
|
1019
|
-
}
|
|
1020
|
-
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1021
|
-
let execResults;
|
|
1022
|
-
let suspended;
|
|
1023
|
-
let bailed;
|
|
1024
|
-
try {
|
|
1025
|
-
const result = await step.execute({
|
|
1026
|
-
runId: executionContext.runId,
|
|
1027
|
-
mastra: this.mastra,
|
|
1028
|
-
runtimeContext,
|
|
1029
|
-
writableStream,
|
|
1030
|
-
inputData: prevOutput,
|
|
1031
|
-
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1032
|
-
getInitData: () => stepResults?.input,
|
|
1033
|
-
getStepResult: (step2) => {
|
|
1034
|
-
const result2 = stepResults[step2.id];
|
|
1035
|
-
if (result2?.status === "success") {
|
|
1036
|
-
return result2.output;
|
|
1037
|
-
}
|
|
1038
|
-
return null;
|
|
1039
|
-
},
|
|
1040
|
-
suspend: async (suspendPayload) => {
|
|
1041
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1042
|
-
suspended = { payload: suspendPayload };
|
|
1043
|
-
},
|
|
1044
|
-
bail: (result2) => {
|
|
1045
|
-
bailed = { payload: result2 };
|
|
1046
|
-
},
|
|
1047
|
-
resume: {
|
|
1048
|
-
steps: resume?.steps?.slice(1) || [],
|
|
1049
|
-
resumePayload: resume?.resumePayload,
|
|
1050
|
-
// @ts-ignore
|
|
1051
|
-
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
1052
|
-
},
|
|
1053
|
-
[EMITTER_SYMBOL]: emitter,
|
|
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;
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1098
|
-
await emitter.emit("watch", {
|
|
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()
|
|
1113
|
-
});
|
|
1114
|
-
if (execResults.status === "suspended") {
|
|
1115
|
-
await emitter.emit("watch-v2", {
|
|
1116
|
-
type: "step-suspended",
|
|
1117
|
-
payload: {
|
|
1118
|
-
id: step.id,
|
|
1119
|
-
...execResults
|
|
1120
|
-
}
|
|
1121
|
-
});
|
|
1122
|
-
} else {
|
|
1123
|
-
await emitter.emit("watch-v2", {
|
|
1124
|
-
type: "step-result",
|
|
1125
|
-
payload: {
|
|
1126
|
-
id: step.id,
|
|
1127
|
-
...execResults
|
|
1128
|
-
}
|
|
1129
|
-
});
|
|
1130
|
-
await emitter.emit("watch-v2", {
|
|
1131
|
-
type: "step-finish",
|
|
1132
|
-
payload: {
|
|
1133
|
-
id: step.id,
|
|
1134
|
-
metadata: {}
|
|
1135
|
-
}
|
|
1136
|
-
});
|
|
1137
|
-
}
|
|
1138
|
-
return { result: execResults, executionContext, stepResults };
|
|
1139
|
-
});
|
|
1140
|
-
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1141
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1142
|
-
return stepRes.result;
|
|
1143
|
-
}
|
|
1144
|
-
async persistStepUpdate({
|
|
1145
|
-
workflowId,
|
|
1146
|
-
runId,
|
|
1147
|
-
stepResults,
|
|
1148
|
-
executionContext,
|
|
1149
|
-
serializedStepGraph,
|
|
1150
|
-
workflowStatus,
|
|
1151
|
-
result,
|
|
1152
|
-
error
|
|
1153
|
-
}) {
|
|
1154
|
-
await this.inngestStep.run(
|
|
1155
|
-
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1156
|
-
async () => {
|
|
1157
|
-
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1158
|
-
workflowName: workflowId,
|
|
1159
|
-
runId,
|
|
1160
|
-
snapshot: {
|
|
1161
|
-
runId,
|
|
1162
|
-
value: {},
|
|
1163
|
-
context: stepResults,
|
|
1164
|
-
activePaths: [],
|
|
1165
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1166
|
-
serializedStepGraph,
|
|
1167
|
-
status: workflowStatus,
|
|
1168
|
-
result,
|
|
1169
|
-
error,
|
|
1170
|
-
// @ts-ignore
|
|
1171
|
-
timestamp: Date.now()
|
|
1172
|
-
}
|
|
1173
|
-
});
|
|
1174
|
-
}
|
|
1175
|
-
);
|
|
1176
|
-
}
|
|
1177
|
-
async executeConditional({
|
|
1178
|
-
workflowId,
|
|
1179
|
-
runId,
|
|
1180
|
-
entry,
|
|
1181
|
-
prevOutput,
|
|
1182
|
-
prevStep,
|
|
1183
|
-
stepResults,
|
|
1184
|
-
serializedStepGraph,
|
|
1185
|
-
resume,
|
|
1186
|
-
executionContext,
|
|
1187
|
-
emitter,
|
|
1188
|
-
abortController,
|
|
1189
|
-
runtimeContext,
|
|
1190
|
-
writableStream
|
|
1191
|
-
}) {
|
|
1192
|
-
let execResults;
|
|
1193
|
-
const truthyIndexes = (await Promise.all(
|
|
1194
|
-
entry.conditions.map(
|
|
1195
|
-
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1196
|
-
try {
|
|
1197
|
-
const result = await cond({
|
|
1198
|
-
runId,
|
|
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(
|
|
1229
|
-
{
|
|
1230
|
-
prefix: "step",
|
|
1231
|
-
callId: randomUUID(),
|
|
1232
|
-
name: "conditional",
|
|
1233
|
-
runId
|
|
1234
|
-
},
|
|
1235
|
-
writableStream
|
|
1236
|
-
)
|
|
1237
|
-
});
|
|
1238
|
-
return result ? index : null;
|
|
1239
|
-
} catch (e) {
|
|
1240
|
-
return null;
|
|
1241
|
-
}
|
|
1242
|
-
})
|
|
1243
|
-
)
|
|
1244
|
-
)).filter((index) => index !== null);
|
|
1245
|
-
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1246
|
-
const results = await Promise.all(
|
|
1247
|
-
stepsToRun.map(
|
|
1248
|
-
(step, index) => this.executeEntry({
|
|
1249
|
-
workflowId,
|
|
1250
|
-
runId,
|
|
1251
|
-
entry: step,
|
|
1252
|
-
prevStep,
|
|
1253
|
-
stepResults,
|
|
1254
|
-
resume,
|
|
1255
|
-
serializedStepGraph,
|
|
1256
|
-
executionContext: {
|
|
1257
|
-
workflowId,
|
|
1258
|
-
runId,
|
|
1259
|
-
executionPath: [...executionContext.executionPath, index],
|
|
1260
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1261
|
-
retryConfig: executionContext.retryConfig,
|
|
1262
|
-
executionSpan: executionContext.executionSpan
|
|
1263
|
-
},
|
|
1264
|
-
emitter,
|
|
1265
|
-
abortController,
|
|
1266
|
-
runtimeContext,
|
|
1267
|
-
writableStream
|
|
1268
|
-
})
|
|
1269
|
-
)
|
|
1270
|
-
);
|
|
1271
|
-
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1272
|
-
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
1273
|
-
if (hasFailed) {
|
|
1274
|
-
execResults = { status: "failed", error: hasFailed.result.error };
|
|
1275
|
-
} else if (hasSuspended) {
|
|
1276
|
-
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
1277
|
-
} else {
|
|
1278
|
-
execResults = {
|
|
1279
|
-
status: "success",
|
|
1280
|
-
output: results.reduce((acc, result, index) => {
|
|
1281
|
-
if (result.result.status === "success") {
|
|
1282
|
-
acc[stepsToRun[index].step.id] = result.output;
|
|
1283
|
-
}
|
|
1284
|
-
return acc;
|
|
1285
|
-
}, {})
|
|
1286
|
-
};
|
|
1287
|
-
}
|
|
1288
|
-
return execResults;
|
|
1289
|
-
}
|
|
1290
|
-
};
|
|
1291
1218
|
|
|
1292
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|
|
1219
|
+
export { InngestExecutionEngine, InngestRun, InngestWorkflow, _compatibilityCheck, createStep, init, serve };
|
|
1293
1220
|
//# sourceMappingURL=index.js.map
|
|
1294
1221
|
//# sourceMappingURL=index.js.map
|