@mastra/inngest 0.0.0-bundle-recursion-20251030002519 → 0.0.0-bundle-studio-cloud-20251222034739
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 +874 -3
- package/dist/execution-engine.d.ts +109 -0
- package/dist/execution-engine.d.ts.map +1 -0
- package/dist/index.cjs +924 -1112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +20 -298
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +926 -1116
- package/dist/index.js.map +1 -1
- package/dist/pubsub.d.ts +56 -0
- package/dist/pubsub.d.ts.map +1 -0
- package/dist/run.d.ts +167 -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 +18 -14
package/dist/index.js
CHANGED
|
@@ -1,41 +1,473 @@
|
|
|
1
|
+
import { Tool } from '@mastra/core/tools';
|
|
2
|
+
import { DefaultExecutionEngine, createTimeTravelExecutionParams, Run, hydrateSerializedStepErrors, Workflow } from '@mastra/core/workflows';
|
|
3
|
+
import { PUBSUB_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
4
|
+
import { z } from 'zod';
|
|
1
5
|
import { randomUUID } from 'crypto';
|
|
2
|
-
import {
|
|
6
|
+
import { RequestContext } from '@mastra/core/di';
|
|
7
|
+
import { RetryAfterError, NonRetriableError } from 'inngest';
|
|
8
|
+
import { getErrorFromUnknown } from '@mastra/core/error';
|
|
3
9
|
import { subscribe } from '@inngest/realtime';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
10
|
+
import { PubSub } from '@mastra/core/events';
|
|
11
|
+
import { ReadableStream } from 'stream/web';
|
|
6
12
|
import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
|
|
7
|
-
import { ToolStream, Tool } from '@mastra/core/tools';
|
|
8
|
-
import { Run, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput } from '@mastra/core/workflows';
|
|
9
|
-
import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
|
|
10
|
-
import { NonRetriableError, RetryAfterError } from 'inngest';
|
|
11
13
|
import { serve as serve$1 } from 'inngest/hono';
|
|
12
|
-
import { z } from 'zod';
|
|
13
14
|
|
|
14
15
|
// src/index.ts
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
16
|
+
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
17
|
+
inngestStep;
|
|
18
|
+
inngestAttempts;
|
|
19
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
20
|
+
super({ mastra, options });
|
|
21
|
+
this.inngestStep = inngestStep;
|
|
22
|
+
this.inngestAttempts = inngestAttempts;
|
|
23
|
+
}
|
|
24
|
+
// =============================================================================
|
|
25
|
+
// Hook Overrides
|
|
26
|
+
// =============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Format errors while preserving Error instances and their custom properties.
|
|
29
|
+
* Uses getErrorFromUnknown to ensure all error properties are preserved.
|
|
30
|
+
*/
|
|
31
|
+
formatResultError(error, lastOutput) {
|
|
32
|
+
const outputError = lastOutput?.error;
|
|
33
|
+
const errorSource = error || outputError;
|
|
34
|
+
const errorInstance = getErrorFromUnknown(errorSource, {
|
|
35
|
+
serializeStack: true,
|
|
36
|
+
// Include stack in JSON for better debugging in Inngest
|
|
37
|
+
fallbackMessage: "Unknown workflow error"
|
|
38
|
+
});
|
|
39
|
+
return errorInstance.toJSON();
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Detect InngestWorkflow instances for special nested workflow handling
|
|
43
|
+
*/
|
|
44
|
+
isNestedWorkflowStep(step) {
|
|
45
|
+
return step instanceof InngestWorkflow;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Inngest requires requestContext serialization for memoization.
|
|
49
|
+
* When steps are replayed, the original function doesn't re-execute,
|
|
50
|
+
* so requestContext modifications must be captured and restored.
|
|
51
|
+
*/
|
|
52
|
+
requiresDurableContextSerialization() {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Execute a step with retry logic for Inngest.
|
|
57
|
+
* Retries are handled via step-level retry (RetryAfterError thrown INSIDE step.run()).
|
|
58
|
+
* After retries exhausted, error propagates here and we return a failed result.
|
|
59
|
+
*/
|
|
60
|
+
async executeStepWithRetry(stepId, runStep, params) {
|
|
61
|
+
try {
|
|
62
|
+
const result = await this.wrapDurableOperation(stepId, runStep, { delay: params.delay });
|
|
63
|
+
return { ok: true, result };
|
|
64
|
+
} catch (e) {
|
|
65
|
+
const cause = e?.cause;
|
|
66
|
+
if (cause?.status === "failed") {
|
|
67
|
+
params.stepSpan?.error({
|
|
68
|
+
error: e,
|
|
69
|
+
attributes: { status: "failed" }
|
|
70
|
+
});
|
|
71
|
+
if (cause.error && !(cause.error instanceof Error)) {
|
|
72
|
+
cause.error = getErrorFromUnknown(cause.error, { serializeStack: false });
|
|
28
73
|
}
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
74
|
+
return { ok: false, error: cause };
|
|
75
|
+
}
|
|
76
|
+
const errorInstance = getErrorFromUnknown(e, {
|
|
77
|
+
serializeStack: false,
|
|
78
|
+
fallbackMessage: "Unknown step execution error"
|
|
79
|
+
});
|
|
80
|
+
params.stepSpan?.error({
|
|
81
|
+
error: errorInstance,
|
|
82
|
+
attributes: { status: "failed" }
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
ok: false,
|
|
86
|
+
error: {
|
|
87
|
+
status: "failed",
|
|
88
|
+
error: errorInstance,
|
|
89
|
+
endedAt: Date.now()
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Use Inngest's sleep primitive for durability
|
|
96
|
+
*/
|
|
97
|
+
async executeSleepDuration(duration, sleepId, workflowId) {
|
|
98
|
+
await this.inngestStep.sleep(`workflow.${workflowId}.sleep.${sleepId}`, duration < 0 ? 0 : duration);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Use Inngest's sleepUntil primitive for durability
|
|
102
|
+
*/
|
|
103
|
+
async executeSleepUntilDate(date, sleepUntilId, workflowId) {
|
|
104
|
+
await this.inngestStep.sleepUntil(`workflow.${workflowId}.sleepUntil.${sleepUntilId}`, date);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Wrap durable operations in Inngest step.run() for durability.
|
|
108
|
+
* If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
|
|
109
|
+
* Inngest's step-level retry mechanism (not function-level retry).
|
|
110
|
+
*/
|
|
111
|
+
async wrapDurableOperation(operationId, operationFn, retryConfig) {
|
|
112
|
+
return this.inngestStep.run(operationId, async () => {
|
|
113
|
+
try {
|
|
114
|
+
return await operationFn();
|
|
115
|
+
} catch (e) {
|
|
116
|
+
if (retryConfig) {
|
|
117
|
+
const errorInstance = getErrorFromUnknown(e, {
|
|
118
|
+
serializeStack: false,
|
|
119
|
+
fallbackMessage: "Unknown step execution error"
|
|
120
|
+
});
|
|
121
|
+
throw new RetryAfterError(errorInstance.message, retryConfig.delay, {
|
|
122
|
+
cause: {
|
|
123
|
+
status: "failed",
|
|
124
|
+
error: errorInstance,
|
|
125
|
+
endedAt: Date.now()
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
throw e;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Provide Inngest step primitive in engine context
|
|
135
|
+
*/
|
|
136
|
+
getEngineContext() {
|
|
137
|
+
return { step: this.inngestStep };
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* For Inngest, lifecycle callbacks are invoked in the workflow's finalize step
|
|
141
|
+
* (wrapped in step.run for durability), not in execute(). Override to skip.
|
|
142
|
+
*/
|
|
143
|
+
async invokeLifecycleCallbacks(_result) {
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Actually invoke the lifecycle callbacks. Called from workflow.ts finalize step.
|
|
147
|
+
*/
|
|
148
|
+
async invokeLifecycleCallbacksInternal(result) {
|
|
149
|
+
return super.invokeLifecycleCallbacks(result);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Execute nested InngestWorkflow using inngestStep.invoke() for durability.
|
|
153
|
+
* This MUST be called directly (not inside step.run()) due to Inngest constraints.
|
|
154
|
+
*/
|
|
155
|
+
async executeWorkflowStep(params) {
|
|
156
|
+
if (!(params.step instanceof InngestWorkflow)) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
const { step, stepResults, executionContext, resume, timeTravel, prevOutput, inputData, pubsub, startedAt } = params;
|
|
160
|
+
const isResume = !!resume?.steps?.length;
|
|
161
|
+
let result;
|
|
162
|
+
let runId;
|
|
163
|
+
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
164
|
+
try {
|
|
165
|
+
if (isResume) {
|
|
166
|
+
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
167
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
168
|
+
workflowName: step.id,
|
|
169
|
+
runId
|
|
170
|
+
});
|
|
171
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
172
|
+
function: step.getFunction(),
|
|
173
|
+
data: {
|
|
174
|
+
inputData,
|
|
175
|
+
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
176
|
+
runId,
|
|
177
|
+
resume: {
|
|
178
|
+
runId,
|
|
179
|
+
steps: resume.steps.slice(1),
|
|
180
|
+
stepResults: snapshot?.context,
|
|
181
|
+
resumePayload: resume.resumePayload,
|
|
182
|
+
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
183
|
+
},
|
|
184
|
+
outputOptions: { includeState: true }
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
result = invokeResp.result;
|
|
188
|
+
runId = invokeResp.runId;
|
|
189
|
+
executionContext.state = invokeResp.result.state;
|
|
190
|
+
} else if (isTimeTravel) {
|
|
191
|
+
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
192
|
+
workflowName: step.id,
|
|
193
|
+
runId: executionContext.runId
|
|
194
|
+
}) ?? { context: {} };
|
|
195
|
+
const timeTravelParams = createTimeTravelExecutionParams({
|
|
196
|
+
steps: timeTravel.steps.slice(1),
|
|
197
|
+
inputData: timeTravel.inputData,
|
|
198
|
+
resumeData: timeTravel.resumeData,
|
|
199
|
+
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
200
|
+
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
201
|
+
snapshot,
|
|
202
|
+
graph: step.buildExecutionGraph()
|
|
203
|
+
});
|
|
204
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
205
|
+
function: step.getFunction(),
|
|
206
|
+
data: {
|
|
207
|
+
timeTravel: timeTravelParams,
|
|
208
|
+
initialState: executionContext.state ?? {},
|
|
209
|
+
runId: executionContext.runId,
|
|
210
|
+
outputOptions: { includeState: true }
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
result = invokeResp.result;
|
|
214
|
+
runId = invokeResp.runId;
|
|
215
|
+
executionContext.state = invokeResp.result.state;
|
|
216
|
+
} else {
|
|
217
|
+
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
218
|
+
function: step.getFunction(),
|
|
219
|
+
data: {
|
|
220
|
+
inputData,
|
|
221
|
+
initialState: executionContext.state ?? {},
|
|
222
|
+
outputOptions: { includeState: true }
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
result = invokeResp.result;
|
|
226
|
+
runId = invokeResp.runId;
|
|
227
|
+
executionContext.state = invokeResp.result.state;
|
|
228
|
+
}
|
|
229
|
+
} catch (e) {
|
|
230
|
+
const errorCause = e?.cause;
|
|
231
|
+
if (errorCause && typeof errorCause === "object") {
|
|
232
|
+
result = errorCause;
|
|
233
|
+
runId = errorCause.runId || randomUUID();
|
|
234
|
+
} else {
|
|
235
|
+
runId = randomUUID();
|
|
236
|
+
result = {
|
|
237
|
+
status: "failed",
|
|
238
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
239
|
+
steps: {},
|
|
240
|
+
input: inputData
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const res = await this.inngestStep.run(
|
|
245
|
+
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
246
|
+
async () => {
|
|
247
|
+
if (result.status === "failed") {
|
|
248
|
+
await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
|
|
249
|
+
type: "watch",
|
|
250
|
+
runId: executionContext.runId,
|
|
251
|
+
data: {
|
|
252
|
+
type: "workflow-step-result",
|
|
253
|
+
payload: {
|
|
254
|
+
id: step.id,
|
|
255
|
+
status: "failed",
|
|
256
|
+
error: result?.error,
|
|
257
|
+
payload: prevOutput
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
262
|
+
} else if (result.status === "suspended") {
|
|
263
|
+
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
264
|
+
const stepRes = stepResult;
|
|
265
|
+
return stepRes?.status === "suspended";
|
|
266
|
+
});
|
|
267
|
+
for (const [stepName, stepResult] of suspendedSteps) {
|
|
268
|
+
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
269
|
+
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
270
|
+
await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
|
|
271
|
+
type: "watch",
|
|
272
|
+
runId: executionContext.runId,
|
|
273
|
+
data: {
|
|
274
|
+
type: "workflow-step-suspended",
|
|
275
|
+
payload: {
|
|
276
|
+
id: step.id,
|
|
277
|
+
status: "suspended"
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
return {
|
|
282
|
+
executionContext,
|
|
283
|
+
result: {
|
|
284
|
+
status: "suspended",
|
|
285
|
+
payload: stepResult.payload,
|
|
286
|
+
suspendPayload: {
|
|
287
|
+
...stepResult?.suspendPayload,
|
|
288
|
+
__workflow_meta: { runId, path: suspendPath }
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
executionContext,
|
|
295
|
+
result: {
|
|
296
|
+
status: "suspended",
|
|
297
|
+
payload: {}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
} else if (result.status === "tripwire") {
|
|
301
|
+
await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
|
|
302
|
+
type: "watch",
|
|
303
|
+
runId: executionContext.runId,
|
|
304
|
+
data: {
|
|
305
|
+
type: "workflow-step-result",
|
|
306
|
+
payload: {
|
|
307
|
+
id: step.id,
|
|
308
|
+
status: "tripwire",
|
|
309
|
+
error: result?.tripwire?.reason,
|
|
310
|
+
payload: prevOutput
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
return {
|
|
315
|
+
executionContext,
|
|
316
|
+
result: {
|
|
317
|
+
status: "tripwire",
|
|
318
|
+
tripwire: result?.tripwire
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
|
|
323
|
+
type: "watch",
|
|
324
|
+
runId: executionContext.runId,
|
|
325
|
+
data: {
|
|
326
|
+
type: "workflow-step-result",
|
|
327
|
+
payload: {
|
|
328
|
+
id: step.id,
|
|
329
|
+
status: "success",
|
|
330
|
+
output: result?.result
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
|
|
335
|
+
type: "watch",
|
|
336
|
+
runId: executionContext.runId,
|
|
337
|
+
data: {
|
|
338
|
+
type: "workflow-step-finish",
|
|
339
|
+
payload: {
|
|
340
|
+
id: step.id,
|
|
341
|
+
metadata: {}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
return { executionContext, result: { status: "success", output: result?.result } };
|
|
346
|
+
}
|
|
347
|
+
);
|
|
348
|
+
Object.assign(executionContext, res.executionContext);
|
|
349
|
+
return {
|
|
350
|
+
...res.result,
|
|
351
|
+
startedAt,
|
|
352
|
+
endedAt: Date.now(),
|
|
353
|
+
payload: inputData,
|
|
354
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
355
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
var InngestPubSub = class extends PubSub {
|
|
360
|
+
inngest;
|
|
361
|
+
workflowId;
|
|
362
|
+
publishFn;
|
|
363
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
364
|
+
constructor(inngest, workflowId, publishFn) {
|
|
365
|
+
super();
|
|
366
|
+
this.inngest = inngest;
|
|
367
|
+
this.workflowId = workflowId;
|
|
368
|
+
this.publishFn = publishFn;
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Publish an event to Inngest's realtime system.
|
|
372
|
+
*
|
|
373
|
+
* Topic format: "workflow.events.v2.{runId}"
|
|
374
|
+
* Maps to Inngest channel: "workflow:{workflowId}:{runId}"
|
|
375
|
+
*/
|
|
376
|
+
async publish(topic, event) {
|
|
377
|
+
if (!this.publishFn) {
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
|
|
381
|
+
if (!match) {
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const runId = match[1];
|
|
385
|
+
try {
|
|
386
|
+
await this.publishFn({
|
|
387
|
+
channel: `workflow:${this.workflowId}:${runId}`,
|
|
388
|
+
topic: "watch",
|
|
389
|
+
data: event.data
|
|
390
|
+
});
|
|
391
|
+
} catch (err) {
|
|
392
|
+
console.error("InngestPubSub publish error:", err?.message ?? err);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Subscribe to events from Inngest's realtime system.
|
|
397
|
+
*
|
|
398
|
+
* Topic format: "workflow.events.v2.{runId}"
|
|
399
|
+
* Maps to Inngest channel: "workflow:{workflowId}:{runId}"
|
|
400
|
+
*/
|
|
401
|
+
async subscribe(topic, cb) {
|
|
402
|
+
const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
|
|
403
|
+
if (!match || !match[1]) {
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
const runId = match[1];
|
|
407
|
+
if (this.subscriptions.has(topic)) {
|
|
408
|
+
this.subscriptions.get(topic).callbacks.add(cb);
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const callbacks = /* @__PURE__ */ new Set([cb]);
|
|
412
|
+
const channel = `workflow:${this.workflowId}:${runId}`;
|
|
413
|
+
const streamPromise = subscribe(
|
|
414
|
+
{
|
|
415
|
+
channel,
|
|
416
|
+
topics: ["watch"],
|
|
417
|
+
app: this.inngest
|
|
418
|
+
},
|
|
419
|
+
(message) => {
|
|
420
|
+
const event = {
|
|
421
|
+
id: crypto.randomUUID(),
|
|
422
|
+
type: "watch",
|
|
423
|
+
runId,
|
|
424
|
+
data: message.data,
|
|
425
|
+
createdAt: /* @__PURE__ */ new Date()
|
|
426
|
+
};
|
|
427
|
+
for (const callback of callbacks) {
|
|
428
|
+
callback(event);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
this.subscriptions.set(topic, {
|
|
433
|
+
unsubscribe: () => {
|
|
434
|
+
streamPromise.then((stream) => stream.cancel()).catch((err) => {
|
|
435
|
+
console.error("InngestPubSub unsubscribe error:", err);
|
|
436
|
+
});
|
|
437
|
+
},
|
|
438
|
+
callbacks
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Unsubscribe a callback from a topic.
|
|
443
|
+
* If no callbacks remain, the underlying Inngest subscription is cancelled.
|
|
444
|
+
*/
|
|
445
|
+
async unsubscribe(topic, cb) {
|
|
446
|
+
const sub = this.subscriptions.get(topic);
|
|
447
|
+
if (!sub) {
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
sub.callbacks.delete(cb);
|
|
451
|
+
if (sub.callbacks.size === 0) {
|
|
452
|
+
sub.unsubscribe();
|
|
453
|
+
this.subscriptions.delete(topic);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* Flush any pending operations. No-op for Inngest.
|
|
458
|
+
*/
|
|
459
|
+
async flush() {
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* Clean up all subscriptions during graceful shutdown.
|
|
463
|
+
*/
|
|
464
|
+
async close() {
|
|
465
|
+
for (const [, sub] of this.subscriptions) {
|
|
466
|
+
sub.unsubscribe();
|
|
467
|
+
}
|
|
468
|
+
this.subscriptions.clear();
|
|
469
|
+
}
|
|
470
|
+
};
|
|
39
471
|
var InngestRun = class extends Run {
|
|
40
472
|
inngest;
|
|
41
473
|
serializedStepGraph;
|
|
@@ -47,63 +479,111 @@ var InngestRun = class extends Run {
|
|
|
47
479
|
this.#mastra = params.mastra;
|
|
48
480
|
}
|
|
49
481
|
async getRuns(eventId) {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
482
|
+
const maxRetries = 3;
|
|
483
|
+
let lastError = null;
|
|
484
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
485
|
+
try {
|
|
486
|
+
const response = await fetch(
|
|
487
|
+
`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`,
|
|
488
|
+
{
|
|
489
|
+
headers: {
|
|
490
|
+
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
);
|
|
494
|
+
if (response.status === 429) {
|
|
495
|
+
const retryAfter = parseInt(response.headers.get("retry-after") || "2", 10);
|
|
496
|
+
await new Promise((resolve) => setTimeout(resolve, retryAfter * 1e3));
|
|
497
|
+
continue;
|
|
498
|
+
}
|
|
499
|
+
if (!response.ok) {
|
|
500
|
+
throw new Error(`Inngest API error: ${response.status} ${response.statusText}`);
|
|
501
|
+
}
|
|
502
|
+
const text = await response.text();
|
|
503
|
+
if (!text) {
|
|
504
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
const json = JSON.parse(text);
|
|
508
|
+
return json.data;
|
|
509
|
+
} catch (error) {
|
|
510
|
+
lastError = error;
|
|
511
|
+
if (attempt < maxRetries - 1) {
|
|
512
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 * Math.pow(2, attempt)));
|
|
513
|
+
}
|
|
53
514
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return json.data;
|
|
515
|
+
}
|
|
516
|
+
throw new NonRetriableError(`Failed to get runs after ${maxRetries} attempts: ${lastError?.message}`);
|
|
57
517
|
}
|
|
58
|
-
async getRunOutput(eventId) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
runs
|
|
518
|
+
async getRunOutput(eventId, maxWaitMs = 3e5) {
|
|
519
|
+
const startTime = Date.now();
|
|
520
|
+
const storage = this.#mastra?.getStorage();
|
|
521
|
+
while (Date.now() - startTime < maxWaitMs) {
|
|
522
|
+
let runs;
|
|
523
|
+
try {
|
|
524
|
+
runs = await this.getRuns(eventId);
|
|
525
|
+
} catch (error) {
|
|
526
|
+
if (error instanceof NonRetriableError) {
|
|
527
|
+
throw error;
|
|
528
|
+
}
|
|
529
|
+
throw new NonRetriableError(
|
|
530
|
+
`Failed to poll workflow status: ${error instanceof Error ? error.message : String(error)}`
|
|
531
|
+
);
|
|
532
|
+
}
|
|
533
|
+
if (runs?.[0]?.status === "Completed" && runs?.[0]?.event_id === eventId) {
|
|
534
|
+
return runs[0];
|
|
535
|
+
}
|
|
63
536
|
if (runs?.[0]?.status === "Failed") {
|
|
64
|
-
const snapshot = await
|
|
537
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
65
538
|
workflowName: this.workflowId,
|
|
66
539
|
runId: this.runId
|
|
67
540
|
});
|
|
541
|
+
if (snapshot?.context) {
|
|
542
|
+
snapshot.context = hydrateSerializedStepErrors(snapshot.context);
|
|
543
|
+
}
|
|
68
544
|
return {
|
|
69
|
-
output: {
|
|
545
|
+
output: {
|
|
546
|
+
result: {
|
|
547
|
+
steps: snapshot?.context,
|
|
548
|
+
status: "failed",
|
|
549
|
+
// Get the original error from NonRetriableError's cause (which contains the workflow result)
|
|
550
|
+
error: getErrorFromUnknown(runs?.[0]?.output?.cause?.error, { serializeStack: false })
|
|
551
|
+
}
|
|
552
|
+
}
|
|
70
553
|
};
|
|
71
554
|
}
|
|
72
555
|
if (runs?.[0]?.status === "Cancelled") {
|
|
73
|
-
const snapshot = await
|
|
556
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
74
557
|
workflowName: this.workflowId,
|
|
75
558
|
runId: this.runId
|
|
76
559
|
});
|
|
77
560
|
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
78
561
|
}
|
|
562
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 + Math.random() * 1e3));
|
|
79
563
|
}
|
|
80
|
-
|
|
81
|
-
}
|
|
82
|
-
async sendEvent(event, data) {
|
|
83
|
-
await this.inngest.send({
|
|
84
|
-
name: `user-event-${event}`,
|
|
85
|
-
data
|
|
86
|
-
});
|
|
564
|
+
throw new NonRetriableError(`Workflow did not complete within ${maxWaitMs}ms`);
|
|
87
565
|
}
|
|
88
566
|
async cancel() {
|
|
567
|
+
const storage = this.#mastra?.getStorage();
|
|
89
568
|
await this.inngest.send({
|
|
90
569
|
name: `cancel.workflow.${this.workflowId}`,
|
|
91
570
|
data: {
|
|
92
571
|
runId: this.runId
|
|
93
572
|
}
|
|
94
573
|
});
|
|
95
|
-
const snapshot = await
|
|
574
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
96
575
|
workflowName: this.workflowId,
|
|
97
576
|
runId: this.runId
|
|
98
577
|
});
|
|
99
578
|
if (snapshot) {
|
|
100
|
-
await
|
|
579
|
+
await storage?.persistWorkflowSnapshot({
|
|
101
580
|
workflowName: this.workflowId,
|
|
102
581
|
runId: this.runId,
|
|
103
582
|
resourceId: this.resourceId,
|
|
104
583
|
snapshot: {
|
|
105
584
|
...snapshot,
|
|
106
|
-
status: "canceled"
|
|
585
|
+
status: "canceled",
|
|
586
|
+
value: snapshot.value
|
|
107
587
|
}
|
|
108
588
|
});
|
|
109
589
|
}
|
|
@@ -111,13 +591,13 @@ var InngestRun = class extends Run {
|
|
|
111
591
|
async start(params) {
|
|
112
592
|
return this._start(params);
|
|
113
593
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
594
|
+
/**
|
|
595
|
+
* Starts the workflow execution without waiting for completion (fire-and-forget).
|
|
596
|
+
* Returns immediately with the runId after sending the event to Inngest.
|
|
597
|
+
* The workflow executes independently in Inngest.
|
|
598
|
+
* Use this when you don't need to wait for the result or want to avoid polling failures.
|
|
599
|
+
*/
|
|
600
|
+
async startAsync(params) {
|
|
121
601
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
122
602
|
workflowName: this.workflowId,
|
|
123
603
|
runId: this.runId,
|
|
@@ -125,18 +605,65 @@ var InngestRun = class extends Run {
|
|
|
125
605
|
snapshot: {
|
|
126
606
|
runId: this.runId,
|
|
127
607
|
serializedStepGraph: this.serializedStepGraph,
|
|
608
|
+
status: "running",
|
|
128
609
|
value: {},
|
|
129
610
|
context: {},
|
|
130
611
|
activePaths: [],
|
|
131
612
|
suspendedPaths: {},
|
|
613
|
+
activeStepsPath: {},
|
|
132
614
|
resumeLabels: {},
|
|
133
615
|
waitingPaths: {},
|
|
134
|
-
timestamp: Date.now()
|
|
135
|
-
status: "running"
|
|
616
|
+
timestamp: Date.now()
|
|
136
617
|
}
|
|
137
618
|
});
|
|
138
|
-
const inputDataToUse = await this._validateInput(inputData);
|
|
139
|
-
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
619
|
+
const inputDataToUse = await this._validateInput(params.inputData);
|
|
620
|
+
const initialStateToUse = await this._validateInitialState(params.initialState ?? {});
|
|
621
|
+
const eventOutput = await this.inngest.send({
|
|
622
|
+
name: `workflow.${this.workflowId}`,
|
|
623
|
+
data: {
|
|
624
|
+
inputData: inputDataToUse,
|
|
625
|
+
initialState: initialStateToUse,
|
|
626
|
+
runId: this.runId,
|
|
627
|
+
resourceId: this.resourceId,
|
|
628
|
+
outputOptions: params.outputOptions,
|
|
629
|
+
tracingOptions: params.tracingOptions,
|
|
630
|
+
requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
const eventId = eventOutput.ids[0];
|
|
634
|
+
if (!eventId) {
|
|
635
|
+
throw new Error("Event ID is not set");
|
|
636
|
+
}
|
|
637
|
+
return { runId: this.runId };
|
|
638
|
+
}
|
|
639
|
+
async _start({
|
|
640
|
+
inputData,
|
|
641
|
+
initialState,
|
|
642
|
+
outputOptions,
|
|
643
|
+
tracingOptions,
|
|
644
|
+
format,
|
|
645
|
+
requestContext
|
|
646
|
+
}) {
|
|
647
|
+
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
648
|
+
workflowName: this.workflowId,
|
|
649
|
+
runId: this.runId,
|
|
650
|
+
resourceId: this.resourceId,
|
|
651
|
+
snapshot: {
|
|
652
|
+
runId: this.runId,
|
|
653
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
654
|
+
status: "running",
|
|
655
|
+
value: {},
|
|
656
|
+
context: {},
|
|
657
|
+
activePaths: [],
|
|
658
|
+
suspendedPaths: {},
|
|
659
|
+
activeStepsPath: {},
|
|
660
|
+
resumeLabels: {},
|
|
661
|
+
waitingPaths: {},
|
|
662
|
+
timestamp: Date.now()
|
|
663
|
+
}
|
|
664
|
+
});
|
|
665
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
666
|
+
const initialStateToUse = await this._validateInitialState(initialState ?? {});
|
|
140
667
|
const eventOutput = await this.inngest.send({
|
|
141
668
|
name: `workflow.${this.workflowId}`,
|
|
142
669
|
data: {
|
|
@@ -146,7 +673,8 @@ var InngestRun = class extends Run {
|
|
|
146
673
|
resourceId: this.resourceId,
|
|
147
674
|
outputOptions,
|
|
148
675
|
tracingOptions,
|
|
149
|
-
format
|
|
676
|
+
format,
|
|
677
|
+
requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
|
|
150
678
|
}
|
|
151
679
|
});
|
|
152
680
|
const eventId = eventOutput.ids[0];
|
|
@@ -155,9 +683,7 @@ var InngestRun = class extends Run {
|
|
|
155
683
|
}
|
|
156
684
|
const runOutput = await this.getRunOutput(eventId);
|
|
157
685
|
const result = runOutput?.output?.result;
|
|
158
|
-
|
|
159
|
-
result.error = new Error(result.error);
|
|
160
|
-
}
|
|
686
|
+
this.hydrateFailedResult(result);
|
|
161
687
|
if (result.status !== "suspended") {
|
|
162
688
|
this.cleanup?.();
|
|
163
689
|
}
|
|
@@ -175,15 +701,24 @@ var InngestRun = class extends Run {
|
|
|
175
701
|
return p;
|
|
176
702
|
}
|
|
177
703
|
async _resume(params) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
|
|
704
|
+
const storage = this.#mastra?.getStorage();
|
|
705
|
+
let steps = [];
|
|
706
|
+
if (typeof params.step === "string") {
|
|
707
|
+
steps = params.step.split(".");
|
|
708
|
+
} else {
|
|
709
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
710
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
182
714
|
workflowName: this.workflowId,
|
|
183
715
|
runId: this.runId
|
|
184
716
|
});
|
|
185
717
|
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
186
718
|
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
719
|
+
const persistedRequestContext = snapshot?.requestContext ?? {};
|
|
720
|
+
const newRequestContext = params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {};
|
|
721
|
+
const mergedRequestContext = { ...persistedRequestContext, ...newRequestContext };
|
|
187
722
|
const eventOutput = await this.inngest.send({
|
|
188
723
|
name: `workflow.${this.workflowId}`,
|
|
189
724
|
data: {
|
|
@@ -196,9 +731,9 @@ var InngestRun = class extends Run {
|
|
|
196
731
|
steps,
|
|
197
732
|
stepResults: snapshot?.context,
|
|
198
733
|
resumePayload: resumeDataToUse,
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
734
|
+
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
735
|
+
},
|
|
736
|
+
requestContext: mergedRequestContext
|
|
202
737
|
}
|
|
203
738
|
});
|
|
204
739
|
const eventId = eventOutput.ids[0];
|
|
@@ -207,17 +742,105 @@ var InngestRun = class extends Run {
|
|
|
207
742
|
}
|
|
208
743
|
const runOutput = await this.getRunOutput(eventId);
|
|
209
744
|
const result = runOutput?.output?.result;
|
|
210
|
-
|
|
211
|
-
|
|
745
|
+
this.hydrateFailedResult(result);
|
|
746
|
+
return result;
|
|
747
|
+
}
|
|
748
|
+
async timeTravel(params) {
|
|
749
|
+
const p = this._timeTravel(params).then((result) => {
|
|
750
|
+
if (result.status !== "suspended") {
|
|
751
|
+
this.closeStreamAction?.().catch(() => {
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
return result;
|
|
755
|
+
});
|
|
756
|
+
this.executionResults = p;
|
|
757
|
+
return p;
|
|
758
|
+
}
|
|
759
|
+
async _timeTravel(params) {
|
|
760
|
+
if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
|
|
761
|
+
throw new Error("Step is required and must be a valid step or array of steps");
|
|
762
|
+
}
|
|
763
|
+
let steps = [];
|
|
764
|
+
if (typeof params.step === "string") {
|
|
765
|
+
steps = params.step.split(".");
|
|
766
|
+
} else {
|
|
767
|
+
steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
768
|
+
(step) => typeof step === "string" ? step : step?.id
|
|
769
|
+
);
|
|
212
770
|
}
|
|
771
|
+
if (steps.length === 0) {
|
|
772
|
+
throw new Error("No steps provided to timeTravel");
|
|
773
|
+
}
|
|
774
|
+
const storage = this.#mastra?.getStorage();
|
|
775
|
+
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
776
|
+
workflowName: this.workflowId,
|
|
777
|
+
runId: this.runId
|
|
778
|
+
});
|
|
779
|
+
if (!snapshot) {
|
|
780
|
+
await storage?.persistWorkflowSnapshot({
|
|
781
|
+
workflowName: this.workflowId,
|
|
782
|
+
runId: this.runId,
|
|
783
|
+
resourceId: this.resourceId,
|
|
784
|
+
snapshot: {
|
|
785
|
+
runId: this.runId,
|
|
786
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
787
|
+
status: "pending",
|
|
788
|
+
value: {},
|
|
789
|
+
context: {},
|
|
790
|
+
activePaths: [],
|
|
791
|
+
suspendedPaths: {},
|
|
792
|
+
activeStepsPath: {},
|
|
793
|
+
resumeLabels: {},
|
|
794
|
+
waitingPaths: {},
|
|
795
|
+
timestamp: Date.now()
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
if (snapshot?.status === "running") {
|
|
800
|
+
throw new Error("This workflow run is still running, cannot time travel");
|
|
801
|
+
}
|
|
802
|
+
let inputDataToUse = params.inputData;
|
|
803
|
+
if (inputDataToUse && steps.length === 1) {
|
|
804
|
+
inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
|
|
805
|
+
}
|
|
806
|
+
const timeTravelData = createTimeTravelExecutionParams({
|
|
807
|
+
steps,
|
|
808
|
+
inputData: inputDataToUse,
|
|
809
|
+
resumeData: params.resumeData,
|
|
810
|
+
context: params.context,
|
|
811
|
+
nestedStepsContext: params.nestedStepsContext,
|
|
812
|
+
snapshot: snapshot ?? { context: {} },
|
|
813
|
+
graph: this.executionGraph,
|
|
814
|
+
initialState: params.initialState
|
|
815
|
+
});
|
|
816
|
+
const eventOutput = await this.inngest.send({
|
|
817
|
+
name: `workflow.${this.workflowId}`,
|
|
818
|
+
data: {
|
|
819
|
+
initialState: timeTravelData.state,
|
|
820
|
+
runId: this.runId,
|
|
821
|
+
workflowId: this.workflowId,
|
|
822
|
+
stepResults: timeTravelData.stepResults,
|
|
823
|
+
timeTravel: timeTravelData,
|
|
824
|
+
tracingOptions: params.tracingOptions,
|
|
825
|
+
outputOptions: params.outputOptions,
|
|
826
|
+
requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
const eventId = eventOutput.ids[0];
|
|
830
|
+
if (!eventId) {
|
|
831
|
+
throw new Error("Event ID is not set");
|
|
832
|
+
}
|
|
833
|
+
const runOutput = await this.getRunOutput(eventId);
|
|
834
|
+
const result = runOutput?.output?.result;
|
|
835
|
+
this.hydrateFailedResult(result);
|
|
213
836
|
return result;
|
|
214
837
|
}
|
|
215
|
-
watch(cb
|
|
838
|
+
watch(cb) {
|
|
216
839
|
let active = true;
|
|
217
840
|
const streamPromise = subscribe(
|
|
218
841
|
{
|
|
219
842
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
220
|
-
topics: [
|
|
843
|
+
topics: ["watch"],
|
|
221
844
|
app: this.inngest
|
|
222
845
|
},
|
|
223
846
|
(message) => {
|
|
@@ -235,17 +858,17 @@ var InngestRun = class extends Run {
|
|
|
235
858
|
});
|
|
236
859
|
};
|
|
237
860
|
}
|
|
238
|
-
streamLegacy({ inputData,
|
|
861
|
+
streamLegacy({ inputData, requestContext } = {}) {
|
|
239
862
|
const { readable, writable } = new TransformStream();
|
|
240
863
|
const writer = writable.getWriter();
|
|
864
|
+
void writer.write({
|
|
865
|
+
// @ts-ignore
|
|
866
|
+
type: "start",
|
|
867
|
+
// @ts-ignore
|
|
868
|
+
payload: { runId: this.runId }
|
|
869
|
+
});
|
|
241
870
|
const unwatch = this.watch(async (event) => {
|
|
242
871
|
try {
|
|
243
|
-
await writer.write({
|
|
244
|
-
// @ts-ignore
|
|
245
|
-
type: "start",
|
|
246
|
-
// @ts-ignore
|
|
247
|
-
payload: { runId: this.runId }
|
|
248
|
-
});
|
|
249
872
|
const e = {
|
|
250
873
|
...event,
|
|
251
874
|
type: event.type.replace("workflow-", "")
|
|
@@ -257,7 +880,7 @@ var InngestRun = class extends Run {
|
|
|
257
880
|
await writer.write(e);
|
|
258
881
|
} catch {
|
|
259
882
|
}
|
|
260
|
-
}
|
|
883
|
+
});
|
|
261
884
|
this.closeStreamAction = async () => {
|
|
262
885
|
await writer.write({
|
|
263
886
|
type: "finish",
|
|
@@ -273,7 +896,7 @@ var InngestRun = class extends Run {
|
|
|
273
896
|
writer.releaseLock();
|
|
274
897
|
}
|
|
275
898
|
};
|
|
276
|
-
this.executionResults = this._start({ inputData,
|
|
899
|
+
this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
|
|
277
900
|
if (result.status !== "suspended") {
|
|
278
901
|
this.closeStreamAction?.().catch(() => {
|
|
279
902
|
});
|
|
@@ -287,7 +910,7 @@ var InngestRun = class extends Run {
|
|
|
287
910
|
}
|
|
288
911
|
stream({
|
|
289
912
|
inputData,
|
|
290
|
-
|
|
913
|
+
requestContext,
|
|
291
914
|
tracingOptions,
|
|
292
915
|
closeOnSuspend = true,
|
|
293
916
|
initialState,
|
|
@@ -311,7 +934,7 @@ var InngestRun = class extends Run {
|
|
|
311
934
|
...payload
|
|
312
935
|
}
|
|
313
936
|
});
|
|
314
|
-
}
|
|
937
|
+
});
|
|
315
938
|
self.closeStreamAction = async () => {
|
|
316
939
|
unwatch();
|
|
317
940
|
try {
|
|
@@ -322,7 +945,7 @@ var InngestRun = class extends Run {
|
|
|
322
945
|
};
|
|
323
946
|
const executionResultsPromise = self._start({
|
|
324
947
|
inputData,
|
|
325
|
-
|
|
948
|
+
requestContext,
|
|
326
949
|
// tracingContext, // We are not able to pass a reference to a span here, what to do?
|
|
327
950
|
initialState,
|
|
328
951
|
tracingOptions,
|
|
@@ -361,7 +984,90 @@ var InngestRun = class extends Run {
|
|
|
361
984
|
streamVNext(args = {}) {
|
|
362
985
|
return this.stream(args);
|
|
363
986
|
}
|
|
987
|
+
timeTravelStream({
|
|
988
|
+
inputData,
|
|
989
|
+
resumeData,
|
|
990
|
+
initialState,
|
|
991
|
+
step,
|
|
992
|
+
context,
|
|
993
|
+
nestedStepsContext,
|
|
994
|
+
requestContext,
|
|
995
|
+
tracingOptions,
|
|
996
|
+
outputOptions
|
|
997
|
+
}) {
|
|
998
|
+
this.closeStreamAction = async () => {
|
|
999
|
+
};
|
|
1000
|
+
const self = this;
|
|
1001
|
+
const stream = new ReadableStream({
|
|
1002
|
+
async start(controller) {
|
|
1003
|
+
const unwatch = self.watch(async ({ type, from = ChunkFrom.WORKFLOW, payload }) => {
|
|
1004
|
+
controller.enqueue({
|
|
1005
|
+
type,
|
|
1006
|
+
runId: self.runId,
|
|
1007
|
+
from,
|
|
1008
|
+
payload: {
|
|
1009
|
+
stepName: payload?.id,
|
|
1010
|
+
...payload
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
self.closeStreamAction = async () => {
|
|
1015
|
+
unwatch();
|
|
1016
|
+
try {
|
|
1017
|
+
controller.close();
|
|
1018
|
+
} catch (err) {
|
|
1019
|
+
console.error("Error closing stream:", err);
|
|
1020
|
+
}
|
|
1021
|
+
};
|
|
1022
|
+
const executionResultsPromise = self._timeTravel({
|
|
1023
|
+
inputData,
|
|
1024
|
+
step,
|
|
1025
|
+
context,
|
|
1026
|
+
nestedStepsContext,
|
|
1027
|
+
resumeData,
|
|
1028
|
+
initialState,
|
|
1029
|
+
requestContext,
|
|
1030
|
+
tracingOptions,
|
|
1031
|
+
outputOptions
|
|
1032
|
+
});
|
|
1033
|
+
self.executionResults = executionResultsPromise;
|
|
1034
|
+
let executionResults;
|
|
1035
|
+
try {
|
|
1036
|
+
executionResults = await executionResultsPromise;
|
|
1037
|
+
self.closeStreamAction?.().catch(() => {
|
|
1038
|
+
});
|
|
1039
|
+
if (self.streamOutput) {
|
|
1040
|
+
self.streamOutput.updateResults(executionResults);
|
|
1041
|
+
}
|
|
1042
|
+
} catch (err) {
|
|
1043
|
+
self.streamOutput?.rejectResults(err);
|
|
1044
|
+
self.closeStreamAction?.().catch(() => {
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
this.streamOutput = new WorkflowRunOutput({
|
|
1050
|
+
runId: this.runId,
|
|
1051
|
+
workflowId: this.workflowId,
|
|
1052
|
+
stream
|
|
1053
|
+
});
|
|
1054
|
+
return this.streamOutput;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Hydrates errors in a failed workflow result back to proper Error instances.
|
|
1058
|
+
* This ensures error.cause chains and custom properties are preserved.
|
|
1059
|
+
*/
|
|
1060
|
+
hydrateFailedResult(result) {
|
|
1061
|
+
if (result.status === "failed") {
|
|
1062
|
+
result.error = getErrorFromUnknown(result.error, { serializeStack: false });
|
|
1063
|
+
if (result.steps) {
|
|
1064
|
+
hydrateSerializedStepErrors(result.steps);
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
364
1068
|
};
|
|
1069
|
+
|
|
1070
|
+
// src/workflow.ts
|
|
365
1071
|
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
366
1072
|
#mastra;
|
|
367
1073
|
inngest;
|
|
@@ -370,6 +1076,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
370
1076
|
constructor(params, inngest) {
|
|
371
1077
|
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
372
1078
|
super(workflowParams);
|
|
1079
|
+
this.engineType = "inngest";
|
|
373
1080
|
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
374
1081
|
([_, value]) => value !== void 0
|
|
375
1082
|
);
|
|
@@ -377,13 +1084,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
377
1084
|
this.#mastra = params.mastra;
|
|
378
1085
|
this.inngest = inngest;
|
|
379
1086
|
}
|
|
380
|
-
async
|
|
1087
|
+
async listWorkflowRuns(args) {
|
|
381
1088
|
const storage = this.#mastra?.getStorage();
|
|
382
1089
|
if (!storage) {
|
|
383
1090
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
384
1091
|
return { runs: [], total: 0 };
|
|
385
1092
|
}
|
|
386
|
-
return storage.
|
|
1093
|
+
return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
|
|
387
1094
|
}
|
|
388
1095
|
async getWorkflowRunById(runId) {
|
|
389
1096
|
const storage = this.#mastra?.getStorage();
|
|
@@ -395,6 +1102,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
395
1102
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
396
1103
|
}
|
|
397
1104
|
__registerMastra(mastra) {
|
|
1105
|
+
super.__registerMastra(mastra);
|
|
398
1106
|
this.#mastra = mastra;
|
|
399
1107
|
this.executionEngine.__registerMastra(mastra);
|
|
400
1108
|
const updateNested = (step) => {
|
|
@@ -412,16 +1120,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
412
1120
|
}
|
|
413
1121
|
}
|
|
414
1122
|
}
|
|
415
|
-
|
|
416
|
-
* @deprecated Use createRunAsync() instead.
|
|
417
|
-
* @throws {Error} Always throws an error directing users to use createRunAsync()
|
|
418
|
-
*/
|
|
419
|
-
createRun(_options) {
|
|
420
|
-
throw new Error(
|
|
421
|
-
"createRun() has been deprecated. Please use createRunAsync() instead.\n\nMigration guide:\n Before: const run = workflow.createRun();\n After: const run = await workflow.createRunAsync();\n\nNote: createRunAsync() is an async method, so make sure your calling function is async."
|
|
422
|
-
);
|
|
423
|
-
}
|
|
424
|
-
async createRunAsync(options) {
|
|
1123
|
+
async createRun(options) {
|
|
425
1124
|
const runIdToUse = options?.runId || randomUUID();
|
|
426
1125
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
427
1126
|
{
|
|
@@ -434,7 +1133,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
434
1133
|
mastra: this.#mastra,
|
|
435
1134
|
retryConfig: this.retryConfig,
|
|
436
1135
|
cleanup: () => this.runs.delete(runIdToUse),
|
|
437
|
-
workflowSteps: this.steps
|
|
1136
|
+
workflowSteps: this.steps,
|
|
1137
|
+
workflowEngineType: this.engineType,
|
|
1138
|
+
validateInputs: this.options.validateInputs
|
|
438
1139
|
},
|
|
439
1140
|
this.inngest
|
|
440
1141
|
);
|
|
@@ -443,7 +1144,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
443
1144
|
workflowStatus: run.workflowRunStatus,
|
|
444
1145
|
stepResults: {}
|
|
445
1146
|
});
|
|
446
|
-
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse,
|
|
1147
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, {
|
|
1148
|
+
withNestedWorkflows: false
|
|
1149
|
+
});
|
|
447
1150
|
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
448
1151
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
449
1152
|
workflowName: this.id,
|
|
@@ -455,13 +1158,13 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
455
1158
|
value: {},
|
|
456
1159
|
context: {},
|
|
457
1160
|
activePaths: [],
|
|
1161
|
+
activeStepsPath: {},
|
|
458
1162
|
waitingPaths: {},
|
|
459
1163
|
serializedStepGraph: this.serializedStepGraph,
|
|
460
1164
|
suspendedPaths: {},
|
|
461
1165
|
resumeLabels: {},
|
|
462
1166
|
result: void 0,
|
|
463
1167
|
error: void 0,
|
|
464
|
-
// @ts-ignore
|
|
465
1168
|
timestamp: Date.now()
|
|
466
1169
|
}
|
|
467
1170
|
});
|
|
@@ -475,42 +1178,20 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
475
1178
|
this.function = this.inngest.createFunction(
|
|
476
1179
|
{
|
|
477
1180
|
id: `workflow.${this.id}`,
|
|
478
|
-
|
|
479
|
-
retries: this.retryConfig?.attempts ?? 0,
|
|
1181
|
+
retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
|
|
480
1182
|
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
481
1183
|
// Spread flow control configuration
|
|
482
1184
|
...this.flowControlConfig
|
|
483
1185
|
},
|
|
484
1186
|
{ event: `workflow.${this.id}` },
|
|
485
1187
|
async ({ event, step, attempt, publish }) => {
|
|
486
|
-
let { inputData, initialState, runId, resourceId, resume, outputOptions, format } = event.data;
|
|
1188
|
+
let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
|
|
487
1189
|
if (!runId) {
|
|
488
1190
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
489
1191
|
return randomUUID();
|
|
490
1192
|
});
|
|
491
1193
|
}
|
|
492
|
-
const
|
|
493
|
-
emit: async (event2, data) => {
|
|
494
|
-
if (!publish) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
try {
|
|
498
|
-
await publish({
|
|
499
|
-
channel: `workflow:${this.id}:${runId}`,
|
|
500
|
-
topic: event2,
|
|
501
|
-
data
|
|
502
|
-
});
|
|
503
|
-
} catch (err) {
|
|
504
|
-
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
505
|
-
}
|
|
506
|
-
},
|
|
507
|
-
on: (_event, _callback) => {
|
|
508
|
-
},
|
|
509
|
-
off: (_event, _callback) => {
|
|
510
|
-
},
|
|
511
|
-
once: (_event, _callback) => {
|
|
512
|
-
}
|
|
513
|
-
};
|
|
1194
|
+
const pubsub = new InngestPubSub(this.inngest, this.id, publish);
|
|
514
1195
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
515
1196
|
const result = await engine.execute({
|
|
516
1197
|
workflowId: this.id,
|
|
@@ -520,23 +1201,29 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
520
1201
|
serializedStepGraph: this.serializedStepGraph,
|
|
521
1202
|
input: inputData,
|
|
522
1203
|
initialState,
|
|
523
|
-
|
|
1204
|
+
pubsub,
|
|
524
1205
|
retryConfig: this.retryConfig,
|
|
525
|
-
|
|
526
|
-
// TODO
|
|
1206
|
+
requestContext: new RequestContext(Object.entries(event.data.requestContext ?? {})),
|
|
527
1207
|
resume,
|
|
1208
|
+
timeTravel,
|
|
528
1209
|
format,
|
|
529
1210
|
abortController: new AbortController(),
|
|
530
|
-
// currentSpan: undefined, // TODO: Pass actual parent
|
|
1211
|
+
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
531
1212
|
outputOptions,
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
1213
|
+
outputWriter: async (chunk) => {
|
|
1214
|
+
try {
|
|
1215
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1216
|
+
type: "watch",
|
|
1217
|
+
runId,
|
|
1218
|
+
data: chunk
|
|
535
1219
|
});
|
|
1220
|
+
} catch (err) {
|
|
1221
|
+
this.logger.debug?.("Failed to publish watch event:", err);
|
|
536
1222
|
}
|
|
537
|
-
}
|
|
1223
|
+
}
|
|
538
1224
|
});
|
|
539
1225
|
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
1226
|
+
await engine.invokeLifecycleCallbacksInternal(result);
|
|
540
1227
|
if (result.status === "failed") {
|
|
541
1228
|
throw new NonRetriableError(`Workflow failed`, {
|
|
542
1229
|
cause: result
|
|
@@ -566,32 +1253,65 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
566
1253
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
567
1254
|
}
|
|
568
1255
|
};
|
|
1256
|
+
function serve({
|
|
1257
|
+
mastra,
|
|
1258
|
+
inngest,
|
|
1259
|
+
functions: userFunctions = [],
|
|
1260
|
+
registerOptions
|
|
1261
|
+
}) {
|
|
1262
|
+
const wfs = mastra.listWorkflows();
|
|
1263
|
+
const workflowFunctions = Array.from(
|
|
1264
|
+
new Set(
|
|
1265
|
+
Object.values(wfs).flatMap((wf) => {
|
|
1266
|
+
if (wf instanceof InngestWorkflow) {
|
|
1267
|
+
wf.__registerMastra(mastra);
|
|
1268
|
+
return wf.getFunctions();
|
|
1269
|
+
}
|
|
1270
|
+
return [];
|
|
1271
|
+
})
|
|
1272
|
+
)
|
|
1273
|
+
);
|
|
1274
|
+
return serve$1({
|
|
1275
|
+
...registerOptions,
|
|
1276
|
+
client: inngest,
|
|
1277
|
+
functions: [...workflowFunctions, ...userFunctions]
|
|
1278
|
+
});
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/types.ts
|
|
1282
|
+
var _compatibilityCheck = true;
|
|
1283
|
+
|
|
1284
|
+
// src/index.ts
|
|
569
1285
|
function isAgent(params) {
|
|
570
1286
|
return params?.component === "AGENT";
|
|
571
1287
|
}
|
|
572
1288
|
function isTool(params) {
|
|
573
1289
|
return params instanceof Tool;
|
|
574
1290
|
}
|
|
1291
|
+
function isInngestWorkflow(params) {
|
|
1292
|
+
return params instanceof InngestWorkflow;
|
|
1293
|
+
}
|
|
575
1294
|
function createStep(params, agentOptions) {
|
|
1295
|
+
if (isInngestWorkflow(params)) {
|
|
1296
|
+
return params;
|
|
1297
|
+
}
|
|
576
1298
|
if (isAgent(params)) {
|
|
1299
|
+
const outputSchema = agentOptions?.structuredOutput?.schema ?? z.object({ text: z.string() });
|
|
577
1300
|
return {
|
|
578
1301
|
id: params.name,
|
|
579
1302
|
description: params.getDescription(),
|
|
580
|
-
// @ts-ignore
|
|
581
1303
|
inputSchema: z.object({
|
|
582
1304
|
prompt: z.string()
|
|
583
1305
|
// resourceId: z.string().optional(),
|
|
584
1306
|
// threadId: z.string().optional(),
|
|
585
1307
|
}),
|
|
586
|
-
|
|
587
|
-
outputSchema: z.object({
|
|
588
|
-
text: z.string()
|
|
589
|
-
}),
|
|
1308
|
+
outputSchema,
|
|
590
1309
|
execute: async ({
|
|
591
1310
|
inputData,
|
|
592
|
-
|
|
1311
|
+
runId,
|
|
1312
|
+
[PUBSUB_SYMBOL]: pubsub,
|
|
593
1313
|
[STREAM_FORMAT_SYMBOL]: streamFormat,
|
|
594
|
-
|
|
1314
|
+
requestContext,
|
|
595
1315
|
tracingContext,
|
|
596
1316
|
abortSignal,
|
|
597
1317
|
abort,
|
|
@@ -602,6 +1322,7 @@ function createStep(params, agentOptions) {
|
|
|
602
1322
|
streamPromise.resolve = resolve;
|
|
603
1323
|
streamPromise.reject = reject;
|
|
604
1324
|
});
|
|
1325
|
+
let structuredResult = null;
|
|
605
1326
|
const toolData = {
|
|
606
1327
|
name: params.name,
|
|
607
1328
|
args: inputData
|
|
@@ -612,9 +1333,13 @@ function createStep(params, agentOptions) {
|
|
|
612
1333
|
...agentOptions ?? {},
|
|
613
1334
|
// resourceId: inputData.resourceId,
|
|
614
1335
|
// threadId: inputData.threadId,
|
|
615
|
-
|
|
1336
|
+
requestContext,
|
|
616
1337
|
tracingContext,
|
|
617
1338
|
onFinish: (result) => {
|
|
1339
|
+
const resultWithObject = result;
|
|
1340
|
+
if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
|
|
1341
|
+
structuredResult = resultWithObject.object;
|
|
1342
|
+
}
|
|
618
1343
|
streamPromise.resolve(result.text);
|
|
619
1344
|
void agentOptions?.onFinish?.(result);
|
|
620
1345
|
},
|
|
@@ -624,9 +1349,13 @@ function createStep(params, agentOptions) {
|
|
|
624
1349
|
} else {
|
|
625
1350
|
const modelOutput = await params.stream(inputData.prompt, {
|
|
626
1351
|
...agentOptions ?? {},
|
|
627
|
-
|
|
1352
|
+
requestContext,
|
|
628
1353
|
tracingContext,
|
|
629
1354
|
onFinish: (result) => {
|
|
1355
|
+
const resultWithObject = result;
|
|
1356
|
+
if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
|
|
1357
|
+
structuredResult = resultWithObject.object;
|
|
1358
|
+
}
|
|
630
1359
|
streamPromise.resolve(result.text);
|
|
631
1360
|
void agentOptions?.onFinish?.(result);
|
|
632
1361
|
},
|
|
@@ -635,22 +1364,24 @@ function createStep(params, agentOptions) {
|
|
|
635
1364
|
stream = modelOutput.fullStream;
|
|
636
1365
|
}
|
|
637
1366
|
if (streamFormat === "legacy") {
|
|
638
|
-
await
|
|
639
|
-
type: "
|
|
640
|
-
|
|
1367
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1368
|
+
type: "watch",
|
|
1369
|
+
runId,
|
|
1370
|
+
data: { type: "tool-call-streaming-start", ...toolData ?? {} }
|
|
641
1371
|
});
|
|
642
1372
|
for await (const chunk of stream) {
|
|
643
1373
|
if (chunk.type === "text-delta") {
|
|
644
|
-
await
|
|
645
|
-
type: "
|
|
646
|
-
|
|
647
|
-
argsTextDelta: chunk.textDelta
|
|
1374
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1375
|
+
type: "watch",
|
|
1376
|
+
runId,
|
|
1377
|
+
data: { type: "tool-call-delta", ...toolData ?? {}, argsTextDelta: chunk.textDelta }
|
|
648
1378
|
});
|
|
649
1379
|
}
|
|
650
1380
|
}
|
|
651
|
-
await
|
|
652
|
-
type: "
|
|
653
|
-
|
|
1381
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1382
|
+
type: "watch",
|
|
1383
|
+
runId,
|
|
1384
|
+
data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
|
|
654
1385
|
});
|
|
655
1386
|
} else {
|
|
656
1387
|
for await (const chunk of stream) {
|
|
@@ -660,6 +1391,9 @@ function createStep(params, agentOptions) {
|
|
|
660
1391
|
if (abortSignal.aborted) {
|
|
661
1392
|
return abort();
|
|
662
1393
|
}
|
|
1394
|
+
if (structuredResult !== null) {
|
|
1395
|
+
return structuredResult;
|
|
1396
|
+
}
|
|
663
1397
|
return {
|
|
664
1398
|
text: await streamPromise.promise
|
|
665
1399
|
};
|
|
@@ -673,20 +1407,38 @@ function createStep(params, agentOptions) {
|
|
|
673
1407
|
}
|
|
674
1408
|
return {
|
|
675
1409
|
// TODO: tool probably should have strong id type
|
|
676
|
-
// @ts-ignore
|
|
677
1410
|
id: params.id,
|
|
678
1411
|
description: params.description,
|
|
679
1412
|
inputSchema: params.inputSchema,
|
|
680
1413
|
outputSchema: params.outputSchema,
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
1414
|
+
suspendSchema: params.suspendSchema,
|
|
1415
|
+
resumeSchema: params.resumeSchema,
|
|
1416
|
+
execute: async ({
|
|
1417
|
+
inputData,
|
|
1418
|
+
mastra,
|
|
1419
|
+
requestContext,
|
|
1420
|
+
tracingContext,
|
|
1421
|
+
suspend,
|
|
1422
|
+
resumeData,
|
|
1423
|
+
runId,
|
|
1424
|
+
workflowId,
|
|
1425
|
+
state,
|
|
1426
|
+
setState
|
|
1427
|
+
}) => {
|
|
1428
|
+
const toolContext = {
|
|
1429
|
+
mastra,
|
|
1430
|
+
requestContext,
|
|
686
1431
|
tracingContext,
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
1432
|
+
workflow: {
|
|
1433
|
+
runId,
|
|
1434
|
+
resumeData,
|
|
1435
|
+
suspend,
|
|
1436
|
+
workflowId,
|
|
1437
|
+
state,
|
|
1438
|
+
setState
|
|
1439
|
+
}
|
|
1440
|
+
};
|
|
1441
|
+
return params.execute(inputData, toolContext);
|
|
690
1442
|
},
|
|
691
1443
|
component: "TOOL"
|
|
692
1444
|
};
|
|
@@ -720,6 +1472,8 @@ function init(inngest) {
|
|
|
720
1472
|
suspendSchema: step.suspendSchema,
|
|
721
1473
|
stateSchema: step.stateSchema,
|
|
722
1474
|
execute: step.execute,
|
|
1475
|
+
retries: step.retries,
|
|
1476
|
+
scorers: step.scorers,
|
|
723
1477
|
component: step.component
|
|
724
1478
|
};
|
|
725
1479
|
},
|
|
@@ -729,7 +1483,8 @@ function init(inngest) {
|
|
|
729
1483
|
inputSchema: workflow.inputSchema,
|
|
730
1484
|
outputSchema: workflow.outputSchema,
|
|
731
1485
|
steps: workflow.stepDefs,
|
|
732
|
-
mastra: workflow.mastra
|
|
1486
|
+
mastra: workflow.mastra,
|
|
1487
|
+
options: workflow.options
|
|
733
1488
|
});
|
|
734
1489
|
wf.setStepFlow(workflow.stepGraph);
|
|
735
1490
|
wf.commit();
|
|
@@ -737,952 +1492,7 @@ function init(inngest) {
|
|
|
737
1492
|
}
|
|
738
1493
|
};
|
|
739
1494
|
}
|
|
740
|
-
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
741
|
-
inngestStep;
|
|
742
|
-
inngestAttempts;
|
|
743
|
-
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
744
|
-
super({ mastra, options });
|
|
745
|
-
this.inngestStep = inngestStep;
|
|
746
|
-
this.inngestAttempts = inngestAttempts;
|
|
747
|
-
}
|
|
748
|
-
async fmtReturnValue(emitter, stepResults, lastOutput, error) {
|
|
749
|
-
const base = {
|
|
750
|
-
status: lastOutput.status,
|
|
751
|
-
steps: stepResults
|
|
752
|
-
};
|
|
753
|
-
if (lastOutput.status === "success") {
|
|
754
|
-
await emitter.emit("watch", {
|
|
755
|
-
type: "watch",
|
|
756
|
-
payload: {
|
|
757
|
-
workflowState: {
|
|
758
|
-
status: lastOutput.status,
|
|
759
|
-
steps: stepResults,
|
|
760
|
-
result: lastOutput.output
|
|
761
|
-
}
|
|
762
|
-
},
|
|
763
|
-
eventTimestamp: Date.now()
|
|
764
|
-
});
|
|
765
|
-
base.result = lastOutput.output;
|
|
766
|
-
} else if (lastOutput.status === "failed") {
|
|
767
|
-
base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
|
|
768
|
-
await emitter.emit("watch", {
|
|
769
|
-
type: "watch",
|
|
770
|
-
payload: {
|
|
771
|
-
workflowState: {
|
|
772
|
-
status: lastOutput.status,
|
|
773
|
-
steps: stepResults,
|
|
774
|
-
result: null,
|
|
775
|
-
error: base.error
|
|
776
|
-
}
|
|
777
|
-
},
|
|
778
|
-
eventTimestamp: Date.now()
|
|
779
|
-
});
|
|
780
|
-
} else if (lastOutput.status === "suspended") {
|
|
781
|
-
await emitter.emit("watch", {
|
|
782
|
-
type: "watch",
|
|
783
|
-
payload: {
|
|
784
|
-
workflowState: {
|
|
785
|
-
status: lastOutput.status,
|
|
786
|
-
steps: stepResults,
|
|
787
|
-
result: null,
|
|
788
|
-
error: null
|
|
789
|
-
}
|
|
790
|
-
},
|
|
791
|
-
eventTimestamp: Date.now()
|
|
792
|
-
});
|
|
793
|
-
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
794
|
-
if (stepResult?.status === "suspended") {
|
|
795
|
-
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
796
|
-
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
797
|
-
}
|
|
798
|
-
return [];
|
|
799
|
-
});
|
|
800
|
-
base.suspended = suspendedStepIds;
|
|
801
|
-
}
|
|
802
|
-
return base;
|
|
803
|
-
}
|
|
804
|
-
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
805
|
-
// await this.inngestStep.sleep(id, duration);
|
|
806
|
-
// }
|
|
807
|
-
async executeSleep({
|
|
808
|
-
workflowId,
|
|
809
|
-
runId,
|
|
810
|
-
entry,
|
|
811
|
-
prevOutput,
|
|
812
|
-
stepResults,
|
|
813
|
-
emitter,
|
|
814
|
-
abortController,
|
|
815
|
-
runtimeContext,
|
|
816
|
-
executionContext,
|
|
817
|
-
writableStream,
|
|
818
|
-
tracingContext
|
|
819
|
-
}) {
|
|
820
|
-
let { duration, fn } = entry;
|
|
821
|
-
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
822
|
-
type: AISpanType.WORKFLOW_SLEEP,
|
|
823
|
-
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
824
|
-
attributes: {
|
|
825
|
-
durationMs: duration,
|
|
826
|
-
sleepType: fn ? "dynamic" : "fixed"
|
|
827
|
-
},
|
|
828
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
829
|
-
});
|
|
830
|
-
if (fn) {
|
|
831
|
-
const stepCallId = randomUUID();
|
|
832
|
-
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
833
|
-
return await fn(
|
|
834
|
-
createDeprecationProxy(
|
|
835
|
-
{
|
|
836
|
-
runId,
|
|
837
|
-
workflowId,
|
|
838
|
-
mastra: this.mastra,
|
|
839
|
-
runtimeContext,
|
|
840
|
-
inputData: prevOutput,
|
|
841
|
-
state: executionContext.state,
|
|
842
|
-
setState: (state) => {
|
|
843
|
-
executionContext.state = state;
|
|
844
|
-
},
|
|
845
|
-
runCount: -1,
|
|
846
|
-
retryCount: -1,
|
|
847
|
-
tracingContext: {
|
|
848
|
-
currentSpan: sleepSpan
|
|
849
|
-
},
|
|
850
|
-
getInitData: () => stepResults?.input,
|
|
851
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
852
|
-
// TODO: this function shouldn't have suspend probably?
|
|
853
|
-
suspend: async (_suspendPayload) => {
|
|
854
|
-
},
|
|
855
|
-
bail: () => {
|
|
856
|
-
},
|
|
857
|
-
abort: () => {
|
|
858
|
-
abortController?.abort();
|
|
859
|
-
},
|
|
860
|
-
[EMITTER_SYMBOL]: emitter,
|
|
861
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
862
|
-
engine: { step: this.inngestStep },
|
|
863
|
-
abortSignal: abortController?.signal,
|
|
864
|
-
writer: new ToolStream(
|
|
865
|
-
{
|
|
866
|
-
prefix: "workflow-step",
|
|
867
|
-
callId: stepCallId,
|
|
868
|
-
name: "sleep",
|
|
869
|
-
runId
|
|
870
|
-
},
|
|
871
|
-
writableStream
|
|
872
|
-
)
|
|
873
|
-
},
|
|
874
|
-
{
|
|
875
|
-
paramName: "runCount",
|
|
876
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
877
|
-
logger: this.logger
|
|
878
|
-
}
|
|
879
|
-
)
|
|
880
|
-
);
|
|
881
|
-
});
|
|
882
|
-
sleepSpan?.update({
|
|
883
|
-
attributes: {
|
|
884
|
-
durationMs: duration
|
|
885
|
-
}
|
|
886
|
-
});
|
|
887
|
-
}
|
|
888
|
-
try {
|
|
889
|
-
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
890
|
-
sleepSpan?.end();
|
|
891
|
-
} catch (e) {
|
|
892
|
-
sleepSpan?.error({ error: e });
|
|
893
|
-
throw e;
|
|
894
|
-
}
|
|
895
|
-
}
|
|
896
|
-
async executeSleepUntil({
|
|
897
|
-
workflowId,
|
|
898
|
-
runId,
|
|
899
|
-
entry,
|
|
900
|
-
prevOutput,
|
|
901
|
-
stepResults,
|
|
902
|
-
emitter,
|
|
903
|
-
abortController,
|
|
904
|
-
runtimeContext,
|
|
905
|
-
executionContext,
|
|
906
|
-
writableStream,
|
|
907
|
-
tracingContext
|
|
908
|
-
}) {
|
|
909
|
-
let { date, fn } = entry;
|
|
910
|
-
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
911
|
-
type: AISpanType.WORKFLOW_SLEEP,
|
|
912
|
-
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
913
|
-
attributes: {
|
|
914
|
-
untilDate: date,
|
|
915
|
-
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
916
|
-
sleepType: fn ? "dynamic" : "fixed"
|
|
917
|
-
},
|
|
918
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
919
|
-
});
|
|
920
|
-
if (fn) {
|
|
921
|
-
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
922
|
-
const stepCallId = randomUUID();
|
|
923
|
-
return await fn(
|
|
924
|
-
createDeprecationProxy(
|
|
925
|
-
{
|
|
926
|
-
runId,
|
|
927
|
-
workflowId,
|
|
928
|
-
mastra: this.mastra,
|
|
929
|
-
runtimeContext,
|
|
930
|
-
inputData: prevOutput,
|
|
931
|
-
state: executionContext.state,
|
|
932
|
-
setState: (state) => {
|
|
933
|
-
executionContext.state = state;
|
|
934
|
-
},
|
|
935
|
-
runCount: -1,
|
|
936
|
-
retryCount: -1,
|
|
937
|
-
tracingContext: {
|
|
938
|
-
currentSpan: sleepUntilSpan
|
|
939
|
-
},
|
|
940
|
-
getInitData: () => stepResults?.input,
|
|
941
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
942
|
-
// TODO: this function shouldn't have suspend probably?
|
|
943
|
-
suspend: async (_suspendPayload) => {
|
|
944
|
-
},
|
|
945
|
-
bail: () => {
|
|
946
|
-
},
|
|
947
|
-
abort: () => {
|
|
948
|
-
abortController?.abort();
|
|
949
|
-
},
|
|
950
|
-
[EMITTER_SYMBOL]: emitter,
|
|
951
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
952
|
-
engine: { step: this.inngestStep },
|
|
953
|
-
abortSignal: abortController?.signal,
|
|
954
|
-
writer: new ToolStream(
|
|
955
|
-
{
|
|
956
|
-
prefix: "workflow-step",
|
|
957
|
-
callId: stepCallId,
|
|
958
|
-
name: "sleep",
|
|
959
|
-
runId
|
|
960
|
-
},
|
|
961
|
-
writableStream
|
|
962
|
-
)
|
|
963
|
-
},
|
|
964
|
-
{
|
|
965
|
-
paramName: "runCount",
|
|
966
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
967
|
-
logger: this.logger
|
|
968
|
-
}
|
|
969
|
-
)
|
|
970
|
-
);
|
|
971
|
-
});
|
|
972
|
-
if (date && !(date instanceof Date)) {
|
|
973
|
-
date = new Date(date);
|
|
974
|
-
}
|
|
975
|
-
const time = !date ? 0 : date.getTime() - Date.now();
|
|
976
|
-
sleepUntilSpan?.update({
|
|
977
|
-
attributes: {
|
|
978
|
-
durationMs: Math.max(0, time)
|
|
979
|
-
}
|
|
980
|
-
});
|
|
981
|
-
}
|
|
982
|
-
if (!(date instanceof Date)) {
|
|
983
|
-
sleepUntilSpan?.end();
|
|
984
|
-
return;
|
|
985
|
-
}
|
|
986
|
-
try {
|
|
987
|
-
await this.inngestStep.sleepUntil(entry.id, date);
|
|
988
|
-
sleepUntilSpan?.end();
|
|
989
|
-
} catch (e) {
|
|
990
|
-
sleepUntilSpan?.error({ error: e });
|
|
991
|
-
throw e;
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
|
-
async executeWaitForEvent({ event, timeout }) {
|
|
995
|
-
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
996
|
-
event: `user-event-${event}`,
|
|
997
|
-
timeout: timeout ?? 5e3
|
|
998
|
-
});
|
|
999
|
-
if (eventData === null) {
|
|
1000
|
-
throw "Timeout waiting for event";
|
|
1001
|
-
}
|
|
1002
|
-
return eventData?.data;
|
|
1003
|
-
}
|
|
1004
|
-
async executeStep({
|
|
1005
|
-
step,
|
|
1006
|
-
stepResults,
|
|
1007
|
-
executionContext,
|
|
1008
|
-
resume,
|
|
1009
|
-
prevOutput,
|
|
1010
|
-
emitter,
|
|
1011
|
-
abortController,
|
|
1012
|
-
runtimeContext,
|
|
1013
|
-
tracingContext,
|
|
1014
|
-
writableStream,
|
|
1015
|
-
disableScorers
|
|
1016
|
-
}) {
|
|
1017
|
-
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1018
|
-
name: `workflow step: '${step.id}'`,
|
|
1019
|
-
type: AISpanType.WORKFLOW_STEP,
|
|
1020
|
-
input: prevOutput,
|
|
1021
|
-
attributes: {
|
|
1022
|
-
stepId: step.id
|
|
1023
|
-
},
|
|
1024
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1025
|
-
});
|
|
1026
|
-
const { inputData, validationError } = await validateStepInput({
|
|
1027
|
-
prevOutput,
|
|
1028
|
-
step,
|
|
1029
|
-
validateInputs: this.options?.validateInputs ?? false
|
|
1030
|
-
});
|
|
1031
|
-
const startedAt = await this.inngestStep.run(
|
|
1032
|
-
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
1033
|
-
async () => {
|
|
1034
|
-
const startedAt2 = Date.now();
|
|
1035
|
-
await emitter.emit("watch", {
|
|
1036
|
-
type: "watch",
|
|
1037
|
-
payload: {
|
|
1038
|
-
currentStep: {
|
|
1039
|
-
id: step.id,
|
|
1040
|
-
status: "running"
|
|
1041
|
-
},
|
|
1042
|
-
workflowState: {
|
|
1043
|
-
status: "running",
|
|
1044
|
-
steps: {
|
|
1045
|
-
...stepResults,
|
|
1046
|
-
[step.id]: {
|
|
1047
|
-
status: "running"
|
|
1048
|
-
}
|
|
1049
|
-
},
|
|
1050
|
-
result: null,
|
|
1051
|
-
error: null
|
|
1052
|
-
}
|
|
1053
|
-
},
|
|
1054
|
-
eventTimestamp: Date.now()
|
|
1055
|
-
});
|
|
1056
|
-
await emitter.emit("watch-v2", {
|
|
1057
|
-
type: "workflow-step-start",
|
|
1058
|
-
payload: {
|
|
1059
|
-
id: step.id,
|
|
1060
|
-
status: "running",
|
|
1061
|
-
payload: inputData,
|
|
1062
|
-
startedAt: startedAt2
|
|
1063
|
-
}
|
|
1064
|
-
});
|
|
1065
|
-
return startedAt2;
|
|
1066
|
-
}
|
|
1067
|
-
);
|
|
1068
|
-
if (step instanceof InngestWorkflow) {
|
|
1069
|
-
const isResume = !!resume?.steps?.length;
|
|
1070
|
-
let result;
|
|
1071
|
-
let runId;
|
|
1072
|
-
try {
|
|
1073
|
-
if (isResume) {
|
|
1074
|
-
runId = stepResults[resume?.steps?.[0]]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
1075
|
-
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1076
|
-
workflowName: step.id,
|
|
1077
|
-
runId
|
|
1078
|
-
});
|
|
1079
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1080
|
-
function: step.getFunction(),
|
|
1081
|
-
data: {
|
|
1082
|
-
inputData,
|
|
1083
|
-
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
1084
|
-
runId,
|
|
1085
|
-
resume: {
|
|
1086
|
-
runId,
|
|
1087
|
-
steps: resume.steps.slice(1),
|
|
1088
|
-
stepResults: snapshot?.context,
|
|
1089
|
-
resumePayload: resume.resumePayload,
|
|
1090
|
-
// @ts-ignore
|
|
1091
|
-
resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
|
|
1092
|
-
},
|
|
1093
|
-
outputOptions: { includeState: true }
|
|
1094
|
-
}
|
|
1095
|
-
});
|
|
1096
|
-
result = invokeResp.result;
|
|
1097
|
-
runId = invokeResp.runId;
|
|
1098
|
-
executionContext.state = invokeResp.result.state;
|
|
1099
|
-
} else {
|
|
1100
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1101
|
-
function: step.getFunction(),
|
|
1102
|
-
data: {
|
|
1103
|
-
inputData,
|
|
1104
|
-
initialState: executionContext.state ?? {},
|
|
1105
|
-
outputOptions: { includeState: true }
|
|
1106
|
-
}
|
|
1107
|
-
});
|
|
1108
|
-
result = invokeResp.result;
|
|
1109
|
-
runId = invokeResp.runId;
|
|
1110
|
-
executionContext.state = invokeResp.result.state;
|
|
1111
|
-
}
|
|
1112
|
-
} catch (e) {
|
|
1113
|
-
const errorCause = e?.cause;
|
|
1114
|
-
if (errorCause && typeof errorCause === "object") {
|
|
1115
|
-
result = errorCause;
|
|
1116
|
-
runId = errorCause.runId || randomUUID();
|
|
1117
|
-
} else {
|
|
1118
|
-
runId = randomUUID();
|
|
1119
|
-
result = {
|
|
1120
|
-
status: "failed",
|
|
1121
|
-
error: e instanceof Error ? e : new Error(String(e)),
|
|
1122
|
-
steps: {},
|
|
1123
|
-
input: inputData
|
|
1124
|
-
};
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
const res = await this.inngestStep.run(
|
|
1128
|
-
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
1129
|
-
async () => {
|
|
1130
|
-
if (result.status === "failed") {
|
|
1131
|
-
await emitter.emit("watch", {
|
|
1132
|
-
type: "watch",
|
|
1133
|
-
payload: {
|
|
1134
|
-
currentStep: {
|
|
1135
|
-
id: step.id,
|
|
1136
|
-
status: "failed",
|
|
1137
|
-
error: result?.error
|
|
1138
|
-
},
|
|
1139
|
-
workflowState: {
|
|
1140
|
-
status: "running",
|
|
1141
|
-
steps: stepResults,
|
|
1142
|
-
result: null,
|
|
1143
|
-
error: null
|
|
1144
|
-
}
|
|
1145
|
-
},
|
|
1146
|
-
eventTimestamp: Date.now()
|
|
1147
|
-
});
|
|
1148
|
-
await emitter.emit("watch-v2", {
|
|
1149
|
-
type: "workflow-step-result",
|
|
1150
|
-
payload: {
|
|
1151
|
-
id: step.id,
|
|
1152
|
-
status: "failed",
|
|
1153
|
-
error: result?.error,
|
|
1154
|
-
payload: prevOutput
|
|
1155
|
-
}
|
|
1156
|
-
});
|
|
1157
|
-
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
1158
|
-
} else if (result.status === "suspended") {
|
|
1159
|
-
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
1160
|
-
const stepRes2 = stepResult;
|
|
1161
|
-
return stepRes2?.status === "suspended";
|
|
1162
|
-
});
|
|
1163
|
-
for (const [stepName, stepResult] of suspendedSteps) {
|
|
1164
|
-
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
1165
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1166
|
-
await emitter.emit("watch", {
|
|
1167
|
-
type: "watch",
|
|
1168
|
-
payload: {
|
|
1169
|
-
currentStep: {
|
|
1170
|
-
id: step.id,
|
|
1171
|
-
status: "suspended",
|
|
1172
|
-
payload: stepResult.payload,
|
|
1173
|
-
suspendPayload: {
|
|
1174
|
-
...stepResult?.suspendPayload,
|
|
1175
|
-
__workflow_meta: { runId, path: suspendPath }
|
|
1176
|
-
}
|
|
1177
|
-
},
|
|
1178
|
-
workflowState: {
|
|
1179
|
-
status: "running",
|
|
1180
|
-
steps: stepResults,
|
|
1181
|
-
result: null,
|
|
1182
|
-
error: null
|
|
1183
|
-
}
|
|
1184
|
-
},
|
|
1185
|
-
eventTimestamp: Date.now()
|
|
1186
|
-
});
|
|
1187
|
-
await emitter.emit("watch-v2", {
|
|
1188
|
-
type: "workflow-step-suspended",
|
|
1189
|
-
payload: {
|
|
1190
|
-
id: step.id,
|
|
1191
|
-
status: "suspended"
|
|
1192
|
-
}
|
|
1193
|
-
});
|
|
1194
|
-
return {
|
|
1195
|
-
executionContext,
|
|
1196
|
-
result: {
|
|
1197
|
-
status: "suspended",
|
|
1198
|
-
payload: stepResult.payload,
|
|
1199
|
-
suspendPayload: {
|
|
1200
|
-
...stepResult?.suspendPayload,
|
|
1201
|
-
__workflow_meta: { runId, path: suspendPath }
|
|
1202
|
-
}
|
|
1203
|
-
}
|
|
1204
|
-
};
|
|
1205
|
-
}
|
|
1206
|
-
await emitter.emit("watch", {
|
|
1207
|
-
type: "watch",
|
|
1208
|
-
payload: {
|
|
1209
|
-
currentStep: {
|
|
1210
|
-
id: step.id,
|
|
1211
|
-
status: "suspended",
|
|
1212
|
-
payload: {}
|
|
1213
|
-
},
|
|
1214
|
-
workflowState: {
|
|
1215
|
-
status: "running",
|
|
1216
|
-
steps: stepResults,
|
|
1217
|
-
result: null,
|
|
1218
|
-
error: null
|
|
1219
|
-
}
|
|
1220
|
-
},
|
|
1221
|
-
eventTimestamp: Date.now()
|
|
1222
|
-
});
|
|
1223
|
-
return {
|
|
1224
|
-
executionContext,
|
|
1225
|
-
result: {
|
|
1226
|
-
status: "suspended",
|
|
1227
|
-
payload: {}
|
|
1228
|
-
}
|
|
1229
|
-
};
|
|
1230
|
-
}
|
|
1231
|
-
await emitter.emit("watch", {
|
|
1232
|
-
type: "watch",
|
|
1233
|
-
payload: {
|
|
1234
|
-
currentStep: {
|
|
1235
|
-
id: step.id,
|
|
1236
|
-
status: "success",
|
|
1237
|
-
output: result?.result
|
|
1238
|
-
},
|
|
1239
|
-
workflowState: {
|
|
1240
|
-
status: "running",
|
|
1241
|
-
steps: stepResults,
|
|
1242
|
-
result: null,
|
|
1243
|
-
error: null
|
|
1244
|
-
}
|
|
1245
|
-
},
|
|
1246
|
-
eventTimestamp: Date.now()
|
|
1247
|
-
});
|
|
1248
|
-
await emitter.emit("watch-v2", {
|
|
1249
|
-
type: "workflow-step-result",
|
|
1250
|
-
payload: {
|
|
1251
|
-
id: step.id,
|
|
1252
|
-
status: "success",
|
|
1253
|
-
output: result?.result
|
|
1254
|
-
}
|
|
1255
|
-
});
|
|
1256
|
-
await emitter.emit("watch-v2", {
|
|
1257
|
-
type: "workflow-step-finish",
|
|
1258
|
-
payload: {
|
|
1259
|
-
id: step.id,
|
|
1260
|
-
metadata: {}
|
|
1261
|
-
}
|
|
1262
|
-
});
|
|
1263
|
-
return { executionContext, result: { status: "success", output: result?.result } };
|
|
1264
|
-
}
|
|
1265
|
-
);
|
|
1266
|
-
Object.assign(executionContext, res.executionContext);
|
|
1267
|
-
return {
|
|
1268
|
-
...res.result,
|
|
1269
|
-
startedAt,
|
|
1270
|
-
endedAt: Date.now(),
|
|
1271
|
-
payload: inputData,
|
|
1272
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1273
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1274
|
-
};
|
|
1275
|
-
}
|
|
1276
|
-
const stepCallId = randomUUID();
|
|
1277
|
-
let stepRes;
|
|
1278
|
-
try {
|
|
1279
|
-
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1280
|
-
let execResults;
|
|
1281
|
-
let suspended;
|
|
1282
|
-
let bailed;
|
|
1283
|
-
try {
|
|
1284
|
-
if (validationError) {
|
|
1285
|
-
throw validationError;
|
|
1286
|
-
}
|
|
1287
|
-
const result = await step.execute({
|
|
1288
|
-
runId: executionContext.runId,
|
|
1289
|
-
mastra: this.mastra,
|
|
1290
|
-
runtimeContext,
|
|
1291
|
-
writer: new ToolStream(
|
|
1292
|
-
{
|
|
1293
|
-
prefix: "workflow-step",
|
|
1294
|
-
callId: stepCallId,
|
|
1295
|
-
name: step.id,
|
|
1296
|
-
runId: executionContext.runId
|
|
1297
|
-
},
|
|
1298
|
-
writableStream
|
|
1299
|
-
),
|
|
1300
|
-
state: executionContext?.state ?? {},
|
|
1301
|
-
setState: (state) => {
|
|
1302
|
-
executionContext.state = state;
|
|
1303
|
-
},
|
|
1304
|
-
inputData,
|
|
1305
|
-
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
1306
|
-
tracingContext: {
|
|
1307
|
-
currentSpan: stepAISpan
|
|
1308
|
-
},
|
|
1309
|
-
getInitData: () => stepResults?.input,
|
|
1310
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
1311
|
-
suspend: async (suspendPayload, suspendOptions) => {
|
|
1312
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1313
|
-
if (suspendOptions?.resumeLabel) {
|
|
1314
|
-
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
1315
|
-
for (const label of resumeLabel) {
|
|
1316
|
-
executionContext.resumeLabels[label] = {
|
|
1317
|
-
stepId: step.id,
|
|
1318
|
-
foreachIndex: executionContext.foreachIndex
|
|
1319
|
-
};
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
suspended = { payload: suspendPayload };
|
|
1323
|
-
},
|
|
1324
|
-
bail: (result2) => {
|
|
1325
|
-
bailed = { payload: result2 };
|
|
1326
|
-
},
|
|
1327
|
-
resume: {
|
|
1328
|
-
steps: resume?.steps?.slice(1) || [],
|
|
1329
|
-
resumePayload: resume?.resumePayload,
|
|
1330
|
-
// @ts-ignore
|
|
1331
|
-
runId: stepResults[step.id]?.suspendPayload?.__workflow_meta?.runId
|
|
1332
|
-
},
|
|
1333
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1334
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1335
|
-
engine: {
|
|
1336
|
-
step: this.inngestStep
|
|
1337
|
-
},
|
|
1338
|
-
abortSignal: abortController.signal
|
|
1339
|
-
});
|
|
1340
|
-
const endedAt = Date.now();
|
|
1341
|
-
execResults = {
|
|
1342
|
-
status: "success",
|
|
1343
|
-
output: result,
|
|
1344
|
-
startedAt,
|
|
1345
|
-
endedAt,
|
|
1346
|
-
payload: inputData,
|
|
1347
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1348
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1349
|
-
};
|
|
1350
|
-
} catch (e) {
|
|
1351
|
-
const stepFailure = {
|
|
1352
|
-
status: "failed",
|
|
1353
|
-
payload: inputData,
|
|
1354
|
-
error: e instanceof Error ? e.message : String(e),
|
|
1355
|
-
endedAt: Date.now(),
|
|
1356
|
-
startedAt,
|
|
1357
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1358
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1359
|
-
};
|
|
1360
|
-
execResults = stepFailure;
|
|
1361
|
-
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1362
|
-
stepAISpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1363
|
-
throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1364
|
-
cause: execResults
|
|
1365
|
-
});
|
|
1366
|
-
}
|
|
1367
|
-
if (suspended) {
|
|
1368
|
-
execResults = {
|
|
1369
|
-
status: "suspended",
|
|
1370
|
-
suspendPayload: suspended.payload,
|
|
1371
|
-
payload: inputData,
|
|
1372
|
-
suspendedAt: Date.now(),
|
|
1373
|
-
startedAt,
|
|
1374
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1375
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1376
|
-
};
|
|
1377
|
-
} else if (bailed) {
|
|
1378
|
-
execResults = {
|
|
1379
|
-
status: "bailed",
|
|
1380
|
-
output: bailed.payload,
|
|
1381
|
-
payload: inputData,
|
|
1382
|
-
endedAt: Date.now(),
|
|
1383
|
-
startedAt
|
|
1384
|
-
};
|
|
1385
|
-
}
|
|
1386
|
-
await emitter.emit("watch", {
|
|
1387
|
-
type: "watch",
|
|
1388
|
-
payload: {
|
|
1389
|
-
currentStep: {
|
|
1390
|
-
id: step.id,
|
|
1391
|
-
...execResults
|
|
1392
|
-
},
|
|
1393
|
-
workflowState: {
|
|
1394
|
-
status: "running",
|
|
1395
|
-
steps: { ...stepResults, [step.id]: execResults },
|
|
1396
|
-
result: null,
|
|
1397
|
-
error: null
|
|
1398
|
-
}
|
|
1399
|
-
},
|
|
1400
|
-
eventTimestamp: Date.now()
|
|
1401
|
-
});
|
|
1402
|
-
if (execResults.status === "suspended") {
|
|
1403
|
-
await emitter.emit("watch-v2", {
|
|
1404
|
-
type: "workflow-step-suspended",
|
|
1405
|
-
payload: {
|
|
1406
|
-
id: step.id,
|
|
1407
|
-
...execResults
|
|
1408
|
-
}
|
|
1409
|
-
});
|
|
1410
|
-
} else {
|
|
1411
|
-
await emitter.emit("watch-v2", {
|
|
1412
|
-
type: "workflow-step-result",
|
|
1413
|
-
payload: {
|
|
1414
|
-
id: step.id,
|
|
1415
|
-
...execResults
|
|
1416
|
-
}
|
|
1417
|
-
});
|
|
1418
|
-
await emitter.emit("watch-v2", {
|
|
1419
|
-
type: "workflow-step-finish",
|
|
1420
|
-
payload: {
|
|
1421
|
-
id: step.id,
|
|
1422
|
-
metadata: {}
|
|
1423
|
-
}
|
|
1424
|
-
});
|
|
1425
|
-
}
|
|
1426
|
-
stepAISpan?.end({ output: execResults });
|
|
1427
|
-
return { result: execResults, executionContext, stepResults };
|
|
1428
|
-
});
|
|
1429
|
-
} catch (e) {
|
|
1430
|
-
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1431
|
-
status: "failed",
|
|
1432
|
-
error: e instanceof Error ? e.message : String(e),
|
|
1433
|
-
payload: inputData,
|
|
1434
|
-
startedAt,
|
|
1435
|
-
endedAt: Date.now()
|
|
1436
|
-
};
|
|
1437
|
-
stepRes = {
|
|
1438
|
-
result: stepFailure,
|
|
1439
|
-
executionContext,
|
|
1440
|
-
stepResults: {
|
|
1441
|
-
...stepResults,
|
|
1442
|
-
[step.id]: stepFailure
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1445
|
-
}
|
|
1446
|
-
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1447
|
-
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1448
|
-
if (step.scorers) {
|
|
1449
|
-
await this.runScorers({
|
|
1450
|
-
scorers: step.scorers,
|
|
1451
|
-
runId: executionContext.runId,
|
|
1452
|
-
input: inputData,
|
|
1453
|
-
output: stepRes.result,
|
|
1454
|
-
workflowId: executionContext.workflowId,
|
|
1455
|
-
stepId: step.id,
|
|
1456
|
-
runtimeContext,
|
|
1457
|
-
disableScorers,
|
|
1458
|
-
tracingContext: { currentSpan: stepAISpan }
|
|
1459
|
-
});
|
|
1460
|
-
}
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1464
|
-
Object.assign(stepResults, stepRes.stepResults);
|
|
1465
|
-
executionContext.state = stepRes.executionContext.state;
|
|
1466
|
-
return stepRes.result;
|
|
1467
|
-
}
|
|
1468
|
-
async persistStepUpdate({
|
|
1469
|
-
workflowId,
|
|
1470
|
-
runId,
|
|
1471
|
-
stepResults,
|
|
1472
|
-
resourceId,
|
|
1473
|
-
executionContext,
|
|
1474
|
-
serializedStepGraph,
|
|
1475
|
-
workflowStatus,
|
|
1476
|
-
result,
|
|
1477
|
-
error
|
|
1478
|
-
}) {
|
|
1479
|
-
await this.inngestStep.run(
|
|
1480
|
-
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1481
|
-
async () => {
|
|
1482
|
-
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1483
|
-
if (!shouldPersistSnapshot) {
|
|
1484
|
-
return;
|
|
1485
|
-
}
|
|
1486
|
-
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1487
|
-
workflowName: workflowId,
|
|
1488
|
-
runId,
|
|
1489
|
-
resourceId,
|
|
1490
|
-
snapshot: {
|
|
1491
|
-
runId,
|
|
1492
|
-
value: executionContext.state,
|
|
1493
|
-
context: stepResults,
|
|
1494
|
-
activePaths: [],
|
|
1495
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1496
|
-
resumeLabels: executionContext.resumeLabels,
|
|
1497
|
-
waitingPaths: {},
|
|
1498
|
-
serializedStepGraph,
|
|
1499
|
-
status: workflowStatus,
|
|
1500
|
-
result,
|
|
1501
|
-
error,
|
|
1502
|
-
// @ts-ignore
|
|
1503
|
-
timestamp: Date.now()
|
|
1504
|
-
}
|
|
1505
|
-
});
|
|
1506
|
-
}
|
|
1507
|
-
);
|
|
1508
|
-
}
|
|
1509
|
-
async executeConditional({
|
|
1510
|
-
workflowId,
|
|
1511
|
-
runId,
|
|
1512
|
-
entry,
|
|
1513
|
-
prevOutput,
|
|
1514
|
-
stepResults,
|
|
1515
|
-
resume,
|
|
1516
|
-
executionContext,
|
|
1517
|
-
emitter,
|
|
1518
|
-
abortController,
|
|
1519
|
-
runtimeContext,
|
|
1520
|
-
writableStream,
|
|
1521
|
-
disableScorers,
|
|
1522
|
-
tracingContext
|
|
1523
|
-
}) {
|
|
1524
|
-
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1525
|
-
type: AISpanType.WORKFLOW_CONDITIONAL,
|
|
1526
|
-
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1527
|
-
input: prevOutput,
|
|
1528
|
-
attributes: {
|
|
1529
|
-
conditionCount: entry.conditions.length
|
|
1530
|
-
},
|
|
1531
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1532
|
-
});
|
|
1533
|
-
let execResults;
|
|
1534
|
-
const truthyIndexes = (await Promise.all(
|
|
1535
|
-
entry.conditions.map(
|
|
1536
|
-
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1537
|
-
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1538
|
-
type: AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1539
|
-
name: `condition: '${index}'`,
|
|
1540
|
-
input: prevOutput,
|
|
1541
|
-
attributes: {
|
|
1542
|
-
conditionIndex: index
|
|
1543
|
-
},
|
|
1544
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1545
|
-
});
|
|
1546
|
-
try {
|
|
1547
|
-
const result = await cond(
|
|
1548
|
-
createDeprecationProxy(
|
|
1549
|
-
{
|
|
1550
|
-
runId,
|
|
1551
|
-
workflowId,
|
|
1552
|
-
mastra: this.mastra,
|
|
1553
|
-
runtimeContext,
|
|
1554
|
-
runCount: -1,
|
|
1555
|
-
retryCount: -1,
|
|
1556
|
-
inputData: prevOutput,
|
|
1557
|
-
state: executionContext.state,
|
|
1558
|
-
setState: (state) => {
|
|
1559
|
-
executionContext.state = state;
|
|
1560
|
-
},
|
|
1561
|
-
tracingContext: {
|
|
1562
|
-
currentSpan: evalSpan
|
|
1563
|
-
},
|
|
1564
|
-
getInitData: () => stepResults?.input,
|
|
1565
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
1566
|
-
// TODO: this function shouldn't have suspend probably?
|
|
1567
|
-
suspend: async (_suspendPayload) => {
|
|
1568
|
-
},
|
|
1569
|
-
bail: () => {
|
|
1570
|
-
},
|
|
1571
|
-
abort: () => {
|
|
1572
|
-
abortController.abort();
|
|
1573
|
-
},
|
|
1574
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1575
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1576
|
-
engine: {
|
|
1577
|
-
step: this.inngestStep
|
|
1578
|
-
},
|
|
1579
|
-
abortSignal: abortController.signal,
|
|
1580
|
-
writer: new ToolStream(
|
|
1581
|
-
{
|
|
1582
|
-
prefix: "workflow-step",
|
|
1583
|
-
callId: randomUUID(),
|
|
1584
|
-
name: "conditional",
|
|
1585
|
-
runId
|
|
1586
|
-
},
|
|
1587
|
-
writableStream
|
|
1588
|
-
)
|
|
1589
|
-
},
|
|
1590
|
-
{
|
|
1591
|
-
paramName: "runCount",
|
|
1592
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
1593
|
-
logger: this.logger
|
|
1594
|
-
}
|
|
1595
|
-
)
|
|
1596
|
-
);
|
|
1597
|
-
evalSpan?.end({
|
|
1598
|
-
output: result,
|
|
1599
|
-
attributes: {
|
|
1600
|
-
result: !!result
|
|
1601
|
-
}
|
|
1602
|
-
});
|
|
1603
|
-
return result ? index : null;
|
|
1604
|
-
} catch (e) {
|
|
1605
|
-
evalSpan?.error({
|
|
1606
|
-
error: e instanceof Error ? e : new Error(String(e)),
|
|
1607
|
-
attributes: {
|
|
1608
|
-
result: false
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
return null;
|
|
1612
|
-
}
|
|
1613
|
-
})
|
|
1614
|
-
)
|
|
1615
|
-
)).filter((index) => index !== null);
|
|
1616
|
-
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1617
|
-
conditionalSpan?.update({
|
|
1618
|
-
attributes: {
|
|
1619
|
-
truthyIndexes,
|
|
1620
|
-
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1621
|
-
}
|
|
1622
|
-
});
|
|
1623
|
-
const results = await Promise.all(
|
|
1624
|
-
stepsToRun.map(async (step, index) => {
|
|
1625
|
-
const currStepResult = stepResults[step.step.id];
|
|
1626
|
-
if (currStepResult && currStepResult.status === "success") {
|
|
1627
|
-
return currStepResult;
|
|
1628
|
-
}
|
|
1629
|
-
const result = await this.executeStep({
|
|
1630
|
-
step: step.step,
|
|
1631
|
-
prevOutput,
|
|
1632
|
-
stepResults,
|
|
1633
|
-
resume,
|
|
1634
|
-
executionContext: {
|
|
1635
|
-
workflowId,
|
|
1636
|
-
runId,
|
|
1637
|
-
executionPath: [...executionContext.executionPath, index],
|
|
1638
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1639
|
-
resumeLabels: executionContext.resumeLabels,
|
|
1640
|
-
retryConfig: executionContext.retryConfig,
|
|
1641
|
-
state: executionContext.state
|
|
1642
|
-
},
|
|
1643
|
-
emitter,
|
|
1644
|
-
abortController,
|
|
1645
|
-
runtimeContext,
|
|
1646
|
-
writableStream,
|
|
1647
|
-
disableScorers,
|
|
1648
|
-
tracingContext: {
|
|
1649
|
-
currentSpan: conditionalSpan
|
|
1650
|
-
}
|
|
1651
|
-
});
|
|
1652
|
-
stepResults[step.step.id] = result;
|
|
1653
|
-
return result;
|
|
1654
|
-
})
|
|
1655
|
-
);
|
|
1656
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
1657
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1658
|
-
if (hasFailed) {
|
|
1659
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1660
|
-
} else if (hasSuspended) {
|
|
1661
|
-
execResults = { status: "suspended", suspendPayload: hasSuspended.suspendPayload };
|
|
1662
|
-
} else {
|
|
1663
|
-
execResults = {
|
|
1664
|
-
status: "success",
|
|
1665
|
-
output: results.reduce((acc, result, index) => {
|
|
1666
|
-
if (result.status === "success") {
|
|
1667
|
-
acc[stepsToRun[index].step.id] = result.output;
|
|
1668
|
-
}
|
|
1669
|
-
return acc;
|
|
1670
|
-
}, {})
|
|
1671
|
-
};
|
|
1672
|
-
}
|
|
1673
|
-
if (execResults.status === "failed") {
|
|
1674
|
-
conditionalSpan?.error({
|
|
1675
|
-
error: new Error(execResults.error)
|
|
1676
|
-
});
|
|
1677
|
-
} else {
|
|
1678
|
-
conditionalSpan?.end({
|
|
1679
|
-
output: execResults.output || execResults
|
|
1680
|
-
});
|
|
1681
|
-
}
|
|
1682
|
-
return execResults;
|
|
1683
|
-
}
|
|
1684
|
-
};
|
|
1685
1495
|
|
|
1686
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|
|
1496
|
+
export { InngestExecutionEngine, InngestPubSub, InngestRun, InngestWorkflow, _compatibilityCheck, createStep, init, serve };
|
|
1687
1497
|
//# sourceMappingURL=index.js.map
|
|
1688
1498
|
//# sourceMappingURL=index.js.map
|