@mastra/inngest 0.0.0-netlify-no-bundle-20251127120354 → 0.0.0-new-button-export-20251219130424
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 +517 -12
- package/dist/execution-engine.d.ts +109 -0
- package/dist/execution-engine.d.ts.map +1 -0
- package/dist/index.cjs +684 -963
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +18 -319
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +682 -963
- 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 +7 -8
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 { ReadableStream, WritableStream } from 'stream/web';
|
|
3
|
-
import { subscribe } from '@inngest/realtime';
|
|
4
6
|
import { RequestContext } from '@mastra/core/di';
|
|
5
|
-
import {
|
|
7
|
+
import { RetryAfterError, NonRetriableError } from 'inngest';
|
|
8
|
+
import { getErrorFromUnknown } from '@mastra/core/error';
|
|
9
|
+
import { subscribe } from '@inngest/realtime';
|
|
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, createTimeTravelExecutionParams, Workflow, DefaultExecutionEngine, createDeprecationProxy, getStepResult, runCountDeprecationMessage, validateStepInput, validateStepResumeData, validateStepSuspendData } 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,27 +479,77 @@ 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
|
-
|
|
518
|
+
async getRunOutput(eventId, maxWaitMs = 3e5) {
|
|
519
|
+
const startTime = Date.now();
|
|
60
520
|
const storage = this.#mastra?.getStorage();
|
|
61
|
-
while (
|
|
62
|
-
|
|
63
|
-
|
|
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
|
+
}
|
|
64
536
|
if (runs?.[0]?.status === "Failed") {
|
|
65
537
|
const snapshot = await storage?.loadWorkflowSnapshot({
|
|
66
538
|
workflowName: this.workflowId,
|
|
67
539
|
runId: this.runId
|
|
68
540
|
});
|
|
541
|
+
if (snapshot?.context) {
|
|
542
|
+
snapshot.context = hydrateSerializedStepErrors(snapshot.context);
|
|
543
|
+
}
|
|
69
544
|
return {
|
|
70
|
-
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
|
+
}
|
|
71
553
|
};
|
|
72
554
|
}
|
|
73
555
|
if (runs?.[0]?.status === "Cancelled") {
|
|
@@ -77,8 +559,9 @@ var InngestRun = class extends Run {
|
|
|
77
559
|
});
|
|
78
560
|
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
79
561
|
}
|
|
562
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 + Math.random() * 1e3));
|
|
80
563
|
}
|
|
81
|
-
|
|
564
|
+
throw new NonRetriableError(`Workflow did not complete within ${maxWaitMs}ms`);
|
|
82
565
|
}
|
|
83
566
|
async cancel() {
|
|
84
567
|
const storage = this.#mastra?.getStorage();
|
|
@@ -108,12 +591,58 @@ var InngestRun = class extends Run {
|
|
|
108
591
|
async start(params) {
|
|
109
592
|
return this._start(params);
|
|
110
593
|
}
|
|
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) {
|
|
601
|
+
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
602
|
+
workflowName: this.workflowId,
|
|
603
|
+
runId: this.runId,
|
|
604
|
+
resourceId: this.resourceId,
|
|
605
|
+
snapshot: {
|
|
606
|
+
runId: this.runId,
|
|
607
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
608
|
+
status: "running",
|
|
609
|
+
value: {},
|
|
610
|
+
context: {},
|
|
611
|
+
activePaths: [],
|
|
612
|
+
suspendedPaths: {},
|
|
613
|
+
activeStepsPath: {},
|
|
614
|
+
resumeLabels: {},
|
|
615
|
+
waitingPaths: {},
|
|
616
|
+
timestamp: Date.now()
|
|
617
|
+
}
|
|
618
|
+
});
|
|
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
|
+
}
|
|
111
639
|
async _start({
|
|
112
640
|
inputData,
|
|
113
641
|
initialState,
|
|
114
642
|
outputOptions,
|
|
115
643
|
tracingOptions,
|
|
116
|
-
format
|
|
644
|
+
format,
|
|
645
|
+
requestContext
|
|
117
646
|
}) {
|
|
118
647
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
119
648
|
workflowName: this.workflowId,
|
|
@@ -144,7 +673,8 @@ var InngestRun = class extends Run {
|
|
|
144
673
|
resourceId: this.resourceId,
|
|
145
674
|
outputOptions,
|
|
146
675
|
tracingOptions,
|
|
147
|
-
format
|
|
676
|
+
format,
|
|
677
|
+
requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
|
|
148
678
|
}
|
|
149
679
|
});
|
|
150
680
|
const eventId = eventOutput.ids[0];
|
|
@@ -153,9 +683,7 @@ var InngestRun = class extends Run {
|
|
|
153
683
|
}
|
|
154
684
|
const runOutput = await this.getRunOutput(eventId);
|
|
155
685
|
const result = runOutput?.output?.result;
|
|
156
|
-
|
|
157
|
-
result.error = new Error(result.error);
|
|
158
|
-
}
|
|
686
|
+
this.hydrateFailedResult(result);
|
|
159
687
|
if (result.status !== "suspended") {
|
|
160
688
|
this.cleanup?.();
|
|
161
689
|
}
|
|
@@ -188,6 +716,9 @@ var InngestRun = class extends Run {
|
|
|
188
716
|
});
|
|
189
717
|
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
190
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 };
|
|
191
722
|
const eventOutput = await this.inngest.send({
|
|
192
723
|
name: `workflow.${this.workflowId}`,
|
|
193
724
|
data: {
|
|
@@ -201,7 +732,8 @@ var InngestRun = class extends Run {
|
|
|
201
732
|
stepResults: snapshot?.context,
|
|
202
733
|
resumePayload: resumeDataToUse,
|
|
203
734
|
resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
|
|
204
|
-
}
|
|
735
|
+
},
|
|
736
|
+
requestContext: mergedRequestContext
|
|
205
737
|
}
|
|
206
738
|
});
|
|
207
739
|
const eventId = eventOutput.ids[0];
|
|
@@ -210,9 +742,7 @@ var InngestRun = class extends Run {
|
|
|
210
742
|
}
|
|
211
743
|
const runOutput = await this.getRunOutput(eventId);
|
|
212
744
|
const result = runOutput?.output?.result;
|
|
213
|
-
|
|
214
|
-
result.error = new Error(result.error);
|
|
215
|
-
}
|
|
745
|
+
this.hydrateFailedResult(result);
|
|
216
746
|
return result;
|
|
217
747
|
}
|
|
218
748
|
async timeTravel(params) {
|
|
@@ -292,7 +822,8 @@ var InngestRun = class extends Run {
|
|
|
292
822
|
stepResults: timeTravelData.stepResults,
|
|
293
823
|
timeTravel: timeTravelData,
|
|
294
824
|
tracingOptions: params.tracingOptions,
|
|
295
|
-
outputOptions: params.outputOptions
|
|
825
|
+
outputOptions: params.outputOptions,
|
|
826
|
+
requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
|
|
296
827
|
}
|
|
297
828
|
});
|
|
298
829
|
const eventId = eventOutput.ids[0];
|
|
@@ -301,9 +832,7 @@ var InngestRun = class extends Run {
|
|
|
301
832
|
}
|
|
302
833
|
const runOutput = await this.getRunOutput(eventId);
|
|
303
834
|
const result = runOutput?.output?.result;
|
|
304
|
-
|
|
305
|
-
result.error = new Error(result.error);
|
|
306
|
-
}
|
|
835
|
+
this.hydrateFailedResult(result);
|
|
307
836
|
return result;
|
|
308
837
|
}
|
|
309
838
|
watch(cb) {
|
|
@@ -485,7 +1014,7 @@ var InngestRun = class extends Run {
|
|
|
485
1014
|
self.closeStreamAction = async () => {
|
|
486
1015
|
unwatch();
|
|
487
1016
|
try {
|
|
488
|
-
|
|
1017
|
+
controller.close();
|
|
489
1018
|
} catch (err) {
|
|
490
1019
|
console.error("Error closing stream:", err);
|
|
491
1020
|
}
|
|
@@ -524,7 +1053,21 @@ var InngestRun = class extends Run {
|
|
|
524
1053
|
});
|
|
525
1054
|
return this.streamOutput;
|
|
526
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
|
+
}
|
|
527
1068
|
};
|
|
1069
|
+
|
|
1070
|
+
// src/workflow.ts
|
|
528
1071
|
var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
529
1072
|
#mastra;
|
|
530
1073
|
inngest;
|
|
@@ -559,6 +1102,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
559
1102
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
560
1103
|
}
|
|
561
1104
|
__registerMastra(mastra) {
|
|
1105
|
+
super.__registerMastra(mastra);
|
|
562
1106
|
this.#mastra = mastra;
|
|
563
1107
|
this.executionEngine.__registerMastra(mastra);
|
|
564
1108
|
const updateNested = (step) => {
|
|
@@ -600,7 +1144,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
600
1144
|
workflowStatus: run.workflowRunStatus,
|
|
601
1145
|
stepResults: {}
|
|
602
1146
|
});
|
|
603
|
-
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse,
|
|
1147
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, {
|
|
1148
|
+
withNestedWorkflows: false
|
|
1149
|
+
});
|
|
604
1150
|
if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
|
|
605
1151
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
606
1152
|
workflowName: this.id,
|
|
@@ -645,28 +1191,7 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
645
1191
|
return randomUUID();
|
|
646
1192
|
});
|
|
647
1193
|
}
|
|
648
|
-
const
|
|
649
|
-
emit: async (event2, data) => {
|
|
650
|
-
if (!publish) {
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
try {
|
|
654
|
-
await publish({
|
|
655
|
-
channel: `workflow:${this.id}:${runId}`,
|
|
656
|
-
topic: event2,
|
|
657
|
-
data
|
|
658
|
-
});
|
|
659
|
-
} catch (err) {
|
|
660
|
-
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
661
|
-
}
|
|
662
|
-
},
|
|
663
|
-
on: (_event, _callback) => {
|
|
664
|
-
},
|
|
665
|
-
off: (_event, _callback) => {
|
|
666
|
-
},
|
|
667
|
-
once: (_event, _callback) => {
|
|
668
|
-
}
|
|
669
|
-
};
|
|
1194
|
+
const pubsub = new InngestPubSub(this.inngest, this.id, publish);
|
|
670
1195
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
|
|
671
1196
|
const result = await engine.execute({
|
|
672
1197
|
workflowId: this.id,
|
|
@@ -676,24 +1201,29 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
676
1201
|
serializedStepGraph: this.serializedStepGraph,
|
|
677
1202
|
input: inputData,
|
|
678
1203
|
initialState,
|
|
679
|
-
|
|
1204
|
+
pubsub,
|
|
680
1205
|
retryConfig: this.retryConfig,
|
|
681
|
-
requestContext: new RequestContext(),
|
|
682
|
-
// TODO
|
|
1206
|
+
requestContext: new RequestContext(Object.entries(event.data.requestContext ?? {})),
|
|
683
1207
|
resume,
|
|
684
1208
|
timeTravel,
|
|
685
1209
|
format,
|
|
686
1210
|
abortController: new AbortController(),
|
|
687
1211
|
// currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
|
|
688
1212
|
outputOptions,
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
1213
|
+
outputWriter: async (chunk) => {
|
|
1214
|
+
try {
|
|
1215
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1216
|
+
type: "watch",
|
|
1217
|
+
runId,
|
|
1218
|
+
data: chunk
|
|
692
1219
|
});
|
|
1220
|
+
} catch (err) {
|
|
1221
|
+
this.logger.debug?.("Failed to publish watch event:", err);
|
|
693
1222
|
}
|
|
694
|
-
}
|
|
1223
|
+
}
|
|
695
1224
|
});
|
|
696
1225
|
await step.run(`workflow.${this.id}.finalize`, async () => {
|
|
1226
|
+
await engine.invokeLifecycleCallbacksInternal(result);
|
|
697
1227
|
if (result.status === "failed") {
|
|
698
1228
|
throw new NonRetriableError(`Workflow failed`, {
|
|
699
1229
|
cause: result
|
|
@@ -723,14 +1253,50 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
|
|
|
723
1253
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
724
1254
|
}
|
|
725
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
|
|
726
1285
|
function isAgent(params) {
|
|
727
1286
|
return params?.component === "AGENT";
|
|
728
1287
|
}
|
|
729
1288
|
function isTool(params) {
|
|
730
1289
|
return params instanceof Tool;
|
|
731
1290
|
}
|
|
1291
|
+
function isInngestWorkflow(params) {
|
|
1292
|
+
return params instanceof InngestWorkflow;
|
|
1293
|
+
}
|
|
732
1294
|
function createStep(params, agentOptions) {
|
|
1295
|
+
if (isInngestWorkflow(params)) {
|
|
1296
|
+
return params;
|
|
1297
|
+
}
|
|
733
1298
|
if (isAgent(params)) {
|
|
1299
|
+
const outputSchema = agentOptions?.structuredOutput?.schema ?? z.object({ text: z.string() });
|
|
734
1300
|
return {
|
|
735
1301
|
id: params.name,
|
|
736
1302
|
description: params.getDescription(),
|
|
@@ -739,12 +1305,11 @@ function createStep(params, agentOptions) {
|
|
|
739
1305
|
// resourceId: z.string().optional(),
|
|
740
1306
|
// threadId: z.string().optional(),
|
|
741
1307
|
}),
|
|
742
|
-
outputSchema
|
|
743
|
-
text: z.string()
|
|
744
|
-
}),
|
|
1308
|
+
outputSchema,
|
|
745
1309
|
execute: async ({
|
|
746
1310
|
inputData,
|
|
747
|
-
|
|
1311
|
+
runId,
|
|
1312
|
+
[PUBSUB_SYMBOL]: pubsub,
|
|
748
1313
|
[STREAM_FORMAT_SYMBOL]: streamFormat,
|
|
749
1314
|
requestContext,
|
|
750
1315
|
tracingContext,
|
|
@@ -757,6 +1322,7 @@ function createStep(params, agentOptions) {
|
|
|
757
1322
|
streamPromise.resolve = resolve;
|
|
758
1323
|
streamPromise.reject = reject;
|
|
759
1324
|
});
|
|
1325
|
+
let structuredResult = null;
|
|
760
1326
|
const toolData = {
|
|
761
1327
|
name: params.name,
|
|
762
1328
|
args: inputData
|
|
@@ -770,6 +1336,10 @@ function createStep(params, agentOptions) {
|
|
|
770
1336
|
requestContext,
|
|
771
1337
|
tracingContext,
|
|
772
1338
|
onFinish: (result) => {
|
|
1339
|
+
const resultWithObject = result;
|
|
1340
|
+
if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
|
|
1341
|
+
structuredResult = resultWithObject.object;
|
|
1342
|
+
}
|
|
773
1343
|
streamPromise.resolve(result.text);
|
|
774
1344
|
void agentOptions?.onFinish?.(result);
|
|
775
1345
|
},
|
|
@@ -782,6 +1352,10 @@ function createStep(params, agentOptions) {
|
|
|
782
1352
|
requestContext,
|
|
783
1353
|
tracingContext,
|
|
784
1354
|
onFinish: (result) => {
|
|
1355
|
+
const resultWithObject = result;
|
|
1356
|
+
if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
|
|
1357
|
+
structuredResult = resultWithObject.object;
|
|
1358
|
+
}
|
|
785
1359
|
streamPromise.resolve(result.text);
|
|
786
1360
|
void agentOptions?.onFinish?.(result);
|
|
787
1361
|
},
|
|
@@ -790,22 +1364,24 @@ function createStep(params, agentOptions) {
|
|
|
790
1364
|
stream = modelOutput.fullStream;
|
|
791
1365
|
}
|
|
792
1366
|
if (streamFormat === "legacy") {
|
|
793
|
-
await
|
|
794
|
-
type: "
|
|
795
|
-
|
|
1367
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1368
|
+
type: "watch",
|
|
1369
|
+
runId,
|
|
1370
|
+
data: { type: "tool-call-streaming-start", ...toolData ?? {} }
|
|
796
1371
|
});
|
|
797
1372
|
for await (const chunk of stream) {
|
|
798
1373
|
if (chunk.type === "text-delta") {
|
|
799
|
-
await
|
|
800
|
-
type: "
|
|
801
|
-
|
|
802
|
-
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 }
|
|
803
1378
|
});
|
|
804
1379
|
}
|
|
805
1380
|
}
|
|
806
|
-
await
|
|
807
|
-
type: "
|
|
808
|
-
|
|
1381
|
+
await pubsub.publish(`workflow.events.v2.${runId}`, {
|
|
1382
|
+
type: "watch",
|
|
1383
|
+
runId,
|
|
1384
|
+
data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
|
|
809
1385
|
});
|
|
810
1386
|
} else {
|
|
811
1387
|
for await (const chunk of stream) {
|
|
@@ -815,6 +1391,9 @@ function createStep(params, agentOptions) {
|
|
|
815
1391
|
if (abortSignal.aborted) {
|
|
816
1392
|
return abort();
|
|
817
1393
|
}
|
|
1394
|
+
if (structuredResult !== null) {
|
|
1395
|
+
return structuredResult;
|
|
1396
|
+
}
|
|
818
1397
|
return {
|
|
819
1398
|
text: await streamPromise.promise
|
|
820
1399
|
};
|
|
@@ -913,867 +1492,7 @@ function init(inngest) {
|
|
|
913
1492
|
}
|
|
914
1493
|
};
|
|
915
1494
|
}
|
|
916
|
-
var InngestExecutionEngine = class extends DefaultExecutionEngine {
|
|
917
|
-
inngestStep;
|
|
918
|
-
inngestAttempts;
|
|
919
|
-
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
920
|
-
super({ mastra, options });
|
|
921
|
-
this.inngestStep = inngestStep;
|
|
922
|
-
this.inngestAttempts = inngestAttempts;
|
|
923
|
-
}
|
|
924
|
-
async fmtReturnValue(emitter, stepResults, lastOutput, error) {
|
|
925
|
-
const base = {
|
|
926
|
-
status: lastOutput.status,
|
|
927
|
-
steps: stepResults
|
|
928
|
-
};
|
|
929
|
-
if (lastOutput.status === "success") {
|
|
930
|
-
base.result = lastOutput.output;
|
|
931
|
-
} else if (lastOutput.status === "failed") {
|
|
932
|
-
base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
|
|
933
|
-
} else if (lastOutput.status === "suspended") {
|
|
934
|
-
const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
|
|
935
|
-
if (stepResult?.status === "suspended") {
|
|
936
|
-
const nestedPath = stepResult?.suspendPayload?.__workflow_meta?.path;
|
|
937
|
-
return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
|
|
938
|
-
}
|
|
939
|
-
return [];
|
|
940
|
-
});
|
|
941
|
-
base.suspended = suspendedStepIds;
|
|
942
|
-
}
|
|
943
|
-
return base;
|
|
944
|
-
}
|
|
945
|
-
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
946
|
-
// await this.inngestStep.sleep(id, duration);
|
|
947
|
-
// }
|
|
948
|
-
async executeSleep({
|
|
949
|
-
workflowId,
|
|
950
|
-
runId,
|
|
951
|
-
entry,
|
|
952
|
-
prevOutput,
|
|
953
|
-
stepResults,
|
|
954
|
-
emitter,
|
|
955
|
-
abortController,
|
|
956
|
-
requestContext,
|
|
957
|
-
executionContext,
|
|
958
|
-
writableStream,
|
|
959
|
-
tracingContext
|
|
960
|
-
}) {
|
|
961
|
-
let { duration, fn } = entry;
|
|
962
|
-
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
963
|
-
type: SpanType.WORKFLOW_SLEEP,
|
|
964
|
-
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
965
|
-
attributes: {
|
|
966
|
-
durationMs: duration,
|
|
967
|
-
sleepType: fn ? "dynamic" : "fixed"
|
|
968
|
-
},
|
|
969
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
970
|
-
});
|
|
971
|
-
if (fn) {
|
|
972
|
-
const stepCallId = randomUUID();
|
|
973
|
-
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
974
|
-
return await fn(
|
|
975
|
-
createDeprecationProxy(
|
|
976
|
-
{
|
|
977
|
-
runId,
|
|
978
|
-
workflowId,
|
|
979
|
-
mastra: this.mastra,
|
|
980
|
-
requestContext,
|
|
981
|
-
inputData: prevOutput,
|
|
982
|
-
state: executionContext.state,
|
|
983
|
-
setState: (state) => {
|
|
984
|
-
executionContext.state = state;
|
|
985
|
-
},
|
|
986
|
-
retryCount: -1,
|
|
987
|
-
tracingContext: {
|
|
988
|
-
currentSpan: sleepSpan
|
|
989
|
-
},
|
|
990
|
-
getInitData: () => stepResults?.input,
|
|
991
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
992
|
-
// TODO: this function shouldn't have suspend probably?
|
|
993
|
-
suspend: async (_suspendPayload) => {
|
|
994
|
-
},
|
|
995
|
-
bail: () => {
|
|
996
|
-
},
|
|
997
|
-
abort: () => {
|
|
998
|
-
abortController?.abort();
|
|
999
|
-
},
|
|
1000
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1001
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1002
|
-
engine: { step: this.inngestStep },
|
|
1003
|
-
abortSignal: abortController?.signal,
|
|
1004
|
-
writer: new ToolStream(
|
|
1005
|
-
{
|
|
1006
|
-
prefix: "workflow-step",
|
|
1007
|
-
callId: stepCallId,
|
|
1008
|
-
name: "sleep",
|
|
1009
|
-
runId
|
|
1010
|
-
},
|
|
1011
|
-
writableStream
|
|
1012
|
-
)
|
|
1013
|
-
},
|
|
1014
|
-
{
|
|
1015
|
-
paramName: "runCount",
|
|
1016
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
1017
|
-
logger: this.logger
|
|
1018
|
-
}
|
|
1019
|
-
)
|
|
1020
|
-
);
|
|
1021
|
-
});
|
|
1022
|
-
sleepSpan?.update({
|
|
1023
|
-
attributes: {
|
|
1024
|
-
durationMs: duration
|
|
1025
|
-
}
|
|
1026
|
-
});
|
|
1027
|
-
}
|
|
1028
|
-
try {
|
|
1029
|
-
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
1030
|
-
sleepSpan?.end();
|
|
1031
|
-
} catch (e) {
|
|
1032
|
-
sleepSpan?.error({ error: e });
|
|
1033
|
-
throw e;
|
|
1034
|
-
}
|
|
1035
|
-
}
|
|
1036
|
-
async executeSleepUntil({
|
|
1037
|
-
workflowId,
|
|
1038
|
-
runId,
|
|
1039
|
-
entry,
|
|
1040
|
-
prevOutput,
|
|
1041
|
-
stepResults,
|
|
1042
|
-
emitter,
|
|
1043
|
-
abortController,
|
|
1044
|
-
requestContext,
|
|
1045
|
-
executionContext,
|
|
1046
|
-
writableStream,
|
|
1047
|
-
tracingContext
|
|
1048
|
-
}) {
|
|
1049
|
-
let { date, fn } = entry;
|
|
1050
|
-
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1051
|
-
type: SpanType.WORKFLOW_SLEEP,
|
|
1052
|
-
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
1053
|
-
attributes: {
|
|
1054
|
-
untilDate: date,
|
|
1055
|
-
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
1056
|
-
sleepType: fn ? "dynamic" : "fixed"
|
|
1057
|
-
},
|
|
1058
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1059
|
-
});
|
|
1060
|
-
if (fn) {
|
|
1061
|
-
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
1062
|
-
const stepCallId = randomUUID();
|
|
1063
|
-
return await fn(
|
|
1064
|
-
createDeprecationProxy(
|
|
1065
|
-
{
|
|
1066
|
-
runId,
|
|
1067
|
-
workflowId,
|
|
1068
|
-
mastra: this.mastra,
|
|
1069
|
-
requestContext,
|
|
1070
|
-
inputData: prevOutput,
|
|
1071
|
-
state: executionContext.state,
|
|
1072
|
-
setState: (state) => {
|
|
1073
|
-
executionContext.state = state;
|
|
1074
|
-
},
|
|
1075
|
-
retryCount: -1,
|
|
1076
|
-
tracingContext: {
|
|
1077
|
-
currentSpan: sleepUntilSpan
|
|
1078
|
-
},
|
|
1079
|
-
getInitData: () => stepResults?.input,
|
|
1080
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
1081
|
-
// TODO: this function shouldn't have suspend probably?
|
|
1082
|
-
suspend: async (_suspendPayload) => {
|
|
1083
|
-
},
|
|
1084
|
-
bail: () => {
|
|
1085
|
-
},
|
|
1086
|
-
abort: () => {
|
|
1087
|
-
abortController?.abort();
|
|
1088
|
-
},
|
|
1089
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1090
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1091
|
-
engine: { step: this.inngestStep },
|
|
1092
|
-
abortSignal: abortController?.signal,
|
|
1093
|
-
writer: new ToolStream(
|
|
1094
|
-
{
|
|
1095
|
-
prefix: "workflow-step",
|
|
1096
|
-
callId: stepCallId,
|
|
1097
|
-
name: "sleep",
|
|
1098
|
-
runId
|
|
1099
|
-
},
|
|
1100
|
-
writableStream
|
|
1101
|
-
)
|
|
1102
|
-
},
|
|
1103
|
-
{
|
|
1104
|
-
paramName: "runCount",
|
|
1105
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
1106
|
-
logger: this.logger
|
|
1107
|
-
}
|
|
1108
|
-
)
|
|
1109
|
-
);
|
|
1110
|
-
});
|
|
1111
|
-
if (date && !(date instanceof Date)) {
|
|
1112
|
-
date = new Date(date);
|
|
1113
|
-
}
|
|
1114
|
-
const time = !date ? 0 : date.getTime() - Date.now();
|
|
1115
|
-
sleepUntilSpan?.update({
|
|
1116
|
-
attributes: {
|
|
1117
|
-
durationMs: Math.max(0, time)
|
|
1118
|
-
}
|
|
1119
|
-
});
|
|
1120
|
-
}
|
|
1121
|
-
if (!(date instanceof Date)) {
|
|
1122
|
-
sleepUntilSpan?.end();
|
|
1123
|
-
return;
|
|
1124
|
-
}
|
|
1125
|
-
try {
|
|
1126
|
-
await this.inngestStep.sleepUntil(entry.id, date);
|
|
1127
|
-
sleepUntilSpan?.end();
|
|
1128
|
-
} catch (e) {
|
|
1129
|
-
sleepUntilSpan?.error({ error: e });
|
|
1130
|
-
throw e;
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
async executeStep({
|
|
1134
|
-
step,
|
|
1135
|
-
stepResults,
|
|
1136
|
-
executionContext,
|
|
1137
|
-
resume,
|
|
1138
|
-
timeTravel,
|
|
1139
|
-
prevOutput,
|
|
1140
|
-
emitter,
|
|
1141
|
-
abortController,
|
|
1142
|
-
requestContext,
|
|
1143
|
-
tracingContext,
|
|
1144
|
-
writableStream,
|
|
1145
|
-
disableScorers
|
|
1146
|
-
}) {
|
|
1147
|
-
const stepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1148
|
-
name: `workflow step: '${step.id}'`,
|
|
1149
|
-
type: SpanType.WORKFLOW_STEP,
|
|
1150
|
-
input: prevOutput,
|
|
1151
|
-
attributes: {
|
|
1152
|
-
stepId: step.id
|
|
1153
|
-
},
|
|
1154
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1155
|
-
});
|
|
1156
|
-
const { inputData, validationError } = await validateStepInput({
|
|
1157
|
-
prevOutput,
|
|
1158
|
-
step,
|
|
1159
|
-
validateInputs: this.options?.validateInputs ?? true
|
|
1160
|
-
});
|
|
1161
|
-
const startedAt = await this.inngestStep.run(
|
|
1162
|
-
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
1163
|
-
async () => {
|
|
1164
|
-
const startedAt2 = Date.now();
|
|
1165
|
-
await emitter.emit("watch", {
|
|
1166
|
-
type: "workflow-step-start",
|
|
1167
|
-
payload: {
|
|
1168
|
-
id: step.id,
|
|
1169
|
-
status: "running",
|
|
1170
|
-
payload: inputData,
|
|
1171
|
-
startedAt: startedAt2
|
|
1172
|
-
}
|
|
1173
|
-
});
|
|
1174
|
-
return startedAt2;
|
|
1175
|
-
}
|
|
1176
|
-
);
|
|
1177
|
-
if (step instanceof InngestWorkflow) {
|
|
1178
|
-
const isResume = !!resume?.steps?.length;
|
|
1179
|
-
let result;
|
|
1180
|
-
let runId;
|
|
1181
|
-
const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
|
|
1182
|
-
try {
|
|
1183
|
-
if (isResume) {
|
|
1184
|
-
runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
|
|
1185
|
-
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1186
|
-
workflowName: step.id,
|
|
1187
|
-
runId
|
|
1188
|
-
});
|
|
1189
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1190
|
-
function: step.getFunction(),
|
|
1191
|
-
data: {
|
|
1192
|
-
inputData,
|
|
1193
|
-
initialState: executionContext.state ?? snapshot?.value ?? {},
|
|
1194
|
-
runId,
|
|
1195
|
-
resume: {
|
|
1196
|
-
runId,
|
|
1197
|
-
steps: resume.steps.slice(1),
|
|
1198
|
-
stepResults: snapshot?.context,
|
|
1199
|
-
resumePayload: resume.resumePayload,
|
|
1200
|
-
resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
|
|
1201
|
-
},
|
|
1202
|
-
outputOptions: { includeState: true }
|
|
1203
|
-
}
|
|
1204
|
-
});
|
|
1205
|
-
result = invokeResp.result;
|
|
1206
|
-
runId = invokeResp.runId;
|
|
1207
|
-
executionContext.state = invokeResp.result.state;
|
|
1208
|
-
} else if (isTimeTravel) {
|
|
1209
|
-
const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
|
|
1210
|
-
workflowName: step.id,
|
|
1211
|
-
runId: executionContext.runId
|
|
1212
|
-
}) ?? { context: {} };
|
|
1213
|
-
const timeTravelParams = createTimeTravelExecutionParams({
|
|
1214
|
-
steps: timeTravel.steps.slice(1),
|
|
1215
|
-
inputData: timeTravel.inputData,
|
|
1216
|
-
resumeData: timeTravel.resumeData,
|
|
1217
|
-
context: timeTravel.nestedStepResults?.[step.id] ?? {},
|
|
1218
|
-
nestedStepsContext: timeTravel.nestedStepResults ?? {},
|
|
1219
|
-
snapshot,
|
|
1220
|
-
graph: step.buildExecutionGraph()
|
|
1221
|
-
});
|
|
1222
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1223
|
-
function: step.getFunction(),
|
|
1224
|
-
data: {
|
|
1225
|
-
timeTravel: timeTravelParams,
|
|
1226
|
-
initialState: executionContext.state ?? {},
|
|
1227
|
-
runId: executionContext.runId,
|
|
1228
|
-
outputOptions: { includeState: true }
|
|
1229
|
-
}
|
|
1230
|
-
});
|
|
1231
|
-
result = invokeResp.result;
|
|
1232
|
-
runId = invokeResp.runId;
|
|
1233
|
-
executionContext.state = invokeResp.result.state;
|
|
1234
|
-
} else {
|
|
1235
|
-
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
1236
|
-
function: step.getFunction(),
|
|
1237
|
-
data: {
|
|
1238
|
-
inputData,
|
|
1239
|
-
initialState: executionContext.state ?? {},
|
|
1240
|
-
outputOptions: { includeState: true }
|
|
1241
|
-
}
|
|
1242
|
-
});
|
|
1243
|
-
result = invokeResp.result;
|
|
1244
|
-
runId = invokeResp.runId;
|
|
1245
|
-
executionContext.state = invokeResp.result.state;
|
|
1246
|
-
}
|
|
1247
|
-
} catch (e) {
|
|
1248
|
-
const errorCause = e?.cause;
|
|
1249
|
-
if (errorCause && typeof errorCause === "object") {
|
|
1250
|
-
result = errorCause;
|
|
1251
|
-
runId = errorCause.runId || randomUUID();
|
|
1252
|
-
} else {
|
|
1253
|
-
runId = randomUUID();
|
|
1254
|
-
result = {
|
|
1255
|
-
status: "failed",
|
|
1256
|
-
error: e instanceof Error ? e : new Error(String(e)),
|
|
1257
|
-
steps: {},
|
|
1258
|
-
input: inputData
|
|
1259
|
-
};
|
|
1260
|
-
}
|
|
1261
|
-
}
|
|
1262
|
-
const res = await this.inngestStep.run(
|
|
1263
|
-
`workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
|
|
1264
|
-
async () => {
|
|
1265
|
-
if (result.status === "failed") {
|
|
1266
|
-
await emitter.emit("watch", {
|
|
1267
|
-
type: "workflow-step-result",
|
|
1268
|
-
payload: {
|
|
1269
|
-
id: step.id,
|
|
1270
|
-
status: "failed",
|
|
1271
|
-
error: result?.error,
|
|
1272
|
-
payload: prevOutput
|
|
1273
|
-
}
|
|
1274
|
-
});
|
|
1275
|
-
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
1276
|
-
} else if (result.status === "suspended") {
|
|
1277
|
-
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
1278
|
-
const stepRes2 = stepResult;
|
|
1279
|
-
return stepRes2?.status === "suspended";
|
|
1280
|
-
});
|
|
1281
|
-
for (const [stepName, stepResult] of suspendedSteps) {
|
|
1282
|
-
const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
|
|
1283
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1284
|
-
await emitter.emit("watch", {
|
|
1285
|
-
type: "workflow-step-suspended",
|
|
1286
|
-
payload: {
|
|
1287
|
-
id: step.id,
|
|
1288
|
-
status: "suspended"
|
|
1289
|
-
}
|
|
1290
|
-
});
|
|
1291
|
-
return {
|
|
1292
|
-
executionContext,
|
|
1293
|
-
result: {
|
|
1294
|
-
status: "suspended",
|
|
1295
|
-
payload: stepResult.payload,
|
|
1296
|
-
suspendPayload: {
|
|
1297
|
-
...stepResult?.suspendPayload,
|
|
1298
|
-
__workflow_meta: { runId, path: suspendPath }
|
|
1299
|
-
}
|
|
1300
|
-
}
|
|
1301
|
-
};
|
|
1302
|
-
}
|
|
1303
|
-
return {
|
|
1304
|
-
executionContext,
|
|
1305
|
-
result: {
|
|
1306
|
-
status: "suspended",
|
|
1307
|
-
payload: {}
|
|
1308
|
-
}
|
|
1309
|
-
};
|
|
1310
|
-
}
|
|
1311
|
-
await emitter.emit("watch", {
|
|
1312
|
-
type: "workflow-step-result",
|
|
1313
|
-
payload: {
|
|
1314
|
-
id: step.id,
|
|
1315
|
-
status: "success",
|
|
1316
|
-
output: result?.result
|
|
1317
|
-
}
|
|
1318
|
-
});
|
|
1319
|
-
await emitter.emit("watch", {
|
|
1320
|
-
type: "workflow-step-finish",
|
|
1321
|
-
payload: {
|
|
1322
|
-
id: step.id,
|
|
1323
|
-
metadata: {}
|
|
1324
|
-
}
|
|
1325
|
-
});
|
|
1326
|
-
return { executionContext, result: { status: "success", output: result?.result } };
|
|
1327
|
-
}
|
|
1328
|
-
);
|
|
1329
|
-
Object.assign(executionContext, res.executionContext);
|
|
1330
|
-
return {
|
|
1331
|
-
...res.result,
|
|
1332
|
-
startedAt,
|
|
1333
|
-
endedAt: Date.now(),
|
|
1334
|
-
payload: inputData,
|
|
1335
|
-
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1336
|
-
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1337
|
-
};
|
|
1338
|
-
}
|
|
1339
|
-
const stepCallId = randomUUID();
|
|
1340
|
-
let stepRes;
|
|
1341
|
-
try {
|
|
1342
|
-
stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
1343
|
-
let execResults;
|
|
1344
|
-
let suspended;
|
|
1345
|
-
let bailed;
|
|
1346
|
-
const { resumeData: timeTravelResumeData, validationError: timeTravelResumeValidationError } = await validateStepResumeData({
|
|
1347
|
-
resumeData: timeTravel?.stepResults[step.id]?.status === "suspended" ? timeTravel?.resumeData : void 0,
|
|
1348
|
-
step
|
|
1349
|
-
});
|
|
1350
|
-
let resumeDataToUse;
|
|
1351
|
-
if (timeTravelResumeData && !timeTravelResumeValidationError) {
|
|
1352
|
-
resumeDataToUse = timeTravelResumeData;
|
|
1353
|
-
} else if (timeTravelResumeData && timeTravelResumeValidationError) {
|
|
1354
|
-
this.logger.warn("Time travel resume data validation failed", {
|
|
1355
|
-
stepId: step.id,
|
|
1356
|
-
error: timeTravelResumeValidationError.message
|
|
1357
|
-
});
|
|
1358
|
-
} else if (resume?.steps[0] === step.id) {
|
|
1359
|
-
resumeDataToUse = resume?.resumePayload;
|
|
1360
|
-
}
|
|
1361
|
-
try {
|
|
1362
|
-
if (validationError) {
|
|
1363
|
-
throw validationError;
|
|
1364
|
-
}
|
|
1365
|
-
const retryCount = this.getOrGenerateRetryCount(step.id);
|
|
1366
|
-
const result = await step.execute({
|
|
1367
|
-
runId: executionContext.runId,
|
|
1368
|
-
workflowId: executionContext.workflowId,
|
|
1369
|
-
mastra: this.mastra,
|
|
1370
|
-
requestContext,
|
|
1371
|
-
retryCount,
|
|
1372
|
-
writer: new ToolStream(
|
|
1373
|
-
{
|
|
1374
|
-
prefix: "workflow-step",
|
|
1375
|
-
callId: stepCallId,
|
|
1376
|
-
name: step.id,
|
|
1377
|
-
runId: executionContext.runId
|
|
1378
|
-
},
|
|
1379
|
-
writableStream
|
|
1380
|
-
),
|
|
1381
|
-
state: executionContext?.state ?? {},
|
|
1382
|
-
setState: (state) => {
|
|
1383
|
-
executionContext.state = state;
|
|
1384
|
-
},
|
|
1385
|
-
inputData,
|
|
1386
|
-
resumeData: resumeDataToUse,
|
|
1387
|
-
tracingContext: {
|
|
1388
|
-
currentSpan: stepSpan
|
|
1389
|
-
},
|
|
1390
|
-
getInitData: () => stepResults?.input,
|
|
1391
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
1392
|
-
suspend: async (suspendPayload, suspendOptions) => {
|
|
1393
|
-
const { suspendData, validationError: validationError2 } = await validateStepSuspendData({
|
|
1394
|
-
suspendData: suspendPayload,
|
|
1395
|
-
step
|
|
1396
|
-
});
|
|
1397
|
-
if (validationError2) {
|
|
1398
|
-
throw validationError2;
|
|
1399
|
-
}
|
|
1400
|
-
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
1401
|
-
if (suspendOptions?.resumeLabel) {
|
|
1402
|
-
const resumeLabel = Array.isArray(suspendOptions.resumeLabel) ? suspendOptions.resumeLabel : [suspendOptions.resumeLabel];
|
|
1403
|
-
for (const label of resumeLabel) {
|
|
1404
|
-
executionContext.resumeLabels[label] = {
|
|
1405
|
-
stepId: step.id,
|
|
1406
|
-
foreachIndex: executionContext.foreachIndex
|
|
1407
|
-
};
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
suspended = { payload: suspendData };
|
|
1411
|
-
},
|
|
1412
|
-
bail: (result2) => {
|
|
1413
|
-
bailed = { payload: result2 };
|
|
1414
|
-
},
|
|
1415
|
-
abort: () => {
|
|
1416
|
-
abortController?.abort();
|
|
1417
|
-
},
|
|
1418
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1419
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1420
|
-
engine: {
|
|
1421
|
-
step: this.inngestStep
|
|
1422
|
-
},
|
|
1423
|
-
abortSignal: abortController.signal
|
|
1424
|
-
});
|
|
1425
|
-
const endedAt = Date.now();
|
|
1426
|
-
execResults = {
|
|
1427
|
-
status: "success",
|
|
1428
|
-
output: result,
|
|
1429
|
-
startedAt,
|
|
1430
|
-
endedAt,
|
|
1431
|
-
payload: inputData,
|
|
1432
|
-
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1433
|
-
resumePayload: resumeDataToUse
|
|
1434
|
-
};
|
|
1435
|
-
} catch (e) {
|
|
1436
|
-
const stepFailure = {
|
|
1437
|
-
status: "failed",
|
|
1438
|
-
payload: inputData,
|
|
1439
|
-
error: e instanceof Error ? e.message : String(e),
|
|
1440
|
-
endedAt: Date.now(),
|
|
1441
|
-
startedAt,
|
|
1442
|
-
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1443
|
-
resumePayload: resumeDataToUse
|
|
1444
|
-
};
|
|
1445
|
-
execResults = stepFailure;
|
|
1446
|
-
const fallbackErrorMessage = `Step ${step.id} failed`;
|
|
1447
|
-
stepSpan?.error({ error: new Error(execResults.error ?? fallbackErrorMessage) });
|
|
1448
|
-
throw new RetryAfterError(execResults.error ?? fallbackErrorMessage, executionContext.retryConfig.delay, {
|
|
1449
|
-
cause: execResults
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
if (suspended) {
|
|
1453
|
-
execResults = {
|
|
1454
|
-
status: "suspended",
|
|
1455
|
-
suspendPayload: suspended.payload,
|
|
1456
|
-
...execResults.output ? { suspendOutput: execResults.output } : {},
|
|
1457
|
-
payload: inputData,
|
|
1458
|
-
suspendedAt: Date.now(),
|
|
1459
|
-
startedAt,
|
|
1460
|
-
resumedAt: resumeDataToUse ? startedAt : void 0,
|
|
1461
|
-
resumePayload: resumeDataToUse
|
|
1462
|
-
};
|
|
1463
|
-
} else if (bailed) {
|
|
1464
|
-
execResults = {
|
|
1465
|
-
status: "bailed",
|
|
1466
|
-
output: bailed.payload,
|
|
1467
|
-
payload: inputData,
|
|
1468
|
-
endedAt: Date.now(),
|
|
1469
|
-
startedAt
|
|
1470
|
-
};
|
|
1471
|
-
}
|
|
1472
|
-
if (execResults.status === "suspended") {
|
|
1473
|
-
await emitter.emit("watch", {
|
|
1474
|
-
type: "workflow-step-suspended",
|
|
1475
|
-
payload: {
|
|
1476
|
-
id: step.id,
|
|
1477
|
-
...execResults
|
|
1478
|
-
}
|
|
1479
|
-
});
|
|
1480
|
-
} else {
|
|
1481
|
-
await emitter.emit("watch", {
|
|
1482
|
-
type: "workflow-step-result",
|
|
1483
|
-
payload: {
|
|
1484
|
-
id: step.id,
|
|
1485
|
-
...execResults
|
|
1486
|
-
}
|
|
1487
|
-
});
|
|
1488
|
-
await emitter.emit("watch", {
|
|
1489
|
-
type: "workflow-step-finish",
|
|
1490
|
-
payload: {
|
|
1491
|
-
id: step.id,
|
|
1492
|
-
metadata: {}
|
|
1493
|
-
}
|
|
1494
|
-
});
|
|
1495
|
-
}
|
|
1496
|
-
stepSpan?.end({ output: execResults });
|
|
1497
|
-
return { result: execResults, executionContext, stepResults };
|
|
1498
|
-
});
|
|
1499
|
-
} catch (e) {
|
|
1500
|
-
const stepFailure = e instanceof Error ? e?.cause : {
|
|
1501
|
-
status: "failed",
|
|
1502
|
-
error: e instanceof Error ? e.message : String(e),
|
|
1503
|
-
payload: inputData,
|
|
1504
|
-
startedAt,
|
|
1505
|
-
endedAt: Date.now()
|
|
1506
|
-
};
|
|
1507
|
-
await emitter.emit("watch", {
|
|
1508
|
-
type: "workflow-step-result",
|
|
1509
|
-
payload: {
|
|
1510
|
-
id: step.id,
|
|
1511
|
-
...stepFailure
|
|
1512
|
-
}
|
|
1513
|
-
});
|
|
1514
|
-
await emitter.emit("watch", {
|
|
1515
|
-
type: "workflow-step-finish",
|
|
1516
|
-
payload: {
|
|
1517
|
-
id: step.id,
|
|
1518
|
-
metadata: {}
|
|
1519
|
-
}
|
|
1520
|
-
});
|
|
1521
|
-
stepRes = {
|
|
1522
|
-
result: stepFailure,
|
|
1523
|
-
executionContext,
|
|
1524
|
-
stepResults: {
|
|
1525
|
-
...stepResults,
|
|
1526
|
-
[step.id]: stepFailure
|
|
1527
|
-
}
|
|
1528
|
-
};
|
|
1529
|
-
}
|
|
1530
|
-
if (disableScorers !== false && stepRes.result.status === "success") {
|
|
1531
|
-
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1532
|
-
if (step.scorers) {
|
|
1533
|
-
await this.runScorers({
|
|
1534
|
-
scorers: step.scorers,
|
|
1535
|
-
runId: executionContext.runId,
|
|
1536
|
-
input: inputData,
|
|
1537
|
-
output: stepRes.result,
|
|
1538
|
-
workflowId: executionContext.workflowId,
|
|
1539
|
-
stepId: step.id,
|
|
1540
|
-
requestContext,
|
|
1541
|
-
disableScorers,
|
|
1542
|
-
tracingContext: { currentSpan: stepSpan }
|
|
1543
|
-
});
|
|
1544
|
-
}
|
|
1545
|
-
});
|
|
1546
|
-
}
|
|
1547
|
-
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
1548
|
-
executionContext.state = stepRes.executionContext.state;
|
|
1549
|
-
return stepRes.result;
|
|
1550
|
-
}
|
|
1551
|
-
async persistStepUpdate({
|
|
1552
|
-
workflowId,
|
|
1553
|
-
runId,
|
|
1554
|
-
stepResults,
|
|
1555
|
-
resourceId,
|
|
1556
|
-
executionContext,
|
|
1557
|
-
serializedStepGraph,
|
|
1558
|
-
workflowStatus,
|
|
1559
|
-
result,
|
|
1560
|
-
error
|
|
1561
|
-
}) {
|
|
1562
|
-
await this.inngestStep.run(
|
|
1563
|
-
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
1564
|
-
async () => {
|
|
1565
|
-
const shouldPersistSnapshot = this.options.shouldPersistSnapshot({ stepResults, workflowStatus });
|
|
1566
|
-
if (!shouldPersistSnapshot) {
|
|
1567
|
-
return;
|
|
1568
|
-
}
|
|
1569
|
-
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
1570
|
-
workflowName: workflowId,
|
|
1571
|
-
runId,
|
|
1572
|
-
resourceId,
|
|
1573
|
-
snapshot: {
|
|
1574
|
-
runId,
|
|
1575
|
-
status: workflowStatus,
|
|
1576
|
-
value: executionContext.state,
|
|
1577
|
-
context: stepResults,
|
|
1578
|
-
activePaths: executionContext.executionPath,
|
|
1579
|
-
activeStepsPath: executionContext.activeStepsPath,
|
|
1580
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1581
|
-
resumeLabels: executionContext.resumeLabels,
|
|
1582
|
-
waitingPaths: {},
|
|
1583
|
-
serializedStepGraph,
|
|
1584
|
-
result,
|
|
1585
|
-
error,
|
|
1586
|
-
timestamp: Date.now()
|
|
1587
|
-
}
|
|
1588
|
-
});
|
|
1589
|
-
}
|
|
1590
|
-
);
|
|
1591
|
-
}
|
|
1592
|
-
async executeConditional({
|
|
1593
|
-
workflowId,
|
|
1594
|
-
runId,
|
|
1595
|
-
entry,
|
|
1596
|
-
prevOutput,
|
|
1597
|
-
stepResults,
|
|
1598
|
-
timeTravel,
|
|
1599
|
-
resume,
|
|
1600
|
-
executionContext,
|
|
1601
|
-
emitter,
|
|
1602
|
-
abortController,
|
|
1603
|
-
requestContext,
|
|
1604
|
-
writableStream,
|
|
1605
|
-
disableScorers,
|
|
1606
|
-
tracingContext
|
|
1607
|
-
}) {
|
|
1608
|
-
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1609
|
-
type: SpanType.WORKFLOW_CONDITIONAL,
|
|
1610
|
-
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1611
|
-
input: prevOutput,
|
|
1612
|
-
attributes: {
|
|
1613
|
-
conditionCount: entry.conditions.length
|
|
1614
|
-
},
|
|
1615
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1616
|
-
});
|
|
1617
|
-
let execResults;
|
|
1618
|
-
const truthyIndexes = (await Promise.all(
|
|
1619
|
-
entry.conditions.map(
|
|
1620
|
-
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1621
|
-
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1622
|
-
type: SpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1623
|
-
name: `condition: '${index}'`,
|
|
1624
|
-
input: prevOutput,
|
|
1625
|
-
attributes: {
|
|
1626
|
-
conditionIndex: index
|
|
1627
|
-
},
|
|
1628
|
-
tracingPolicy: this.options?.tracingPolicy
|
|
1629
|
-
});
|
|
1630
|
-
try {
|
|
1631
|
-
const result = await cond(
|
|
1632
|
-
createDeprecationProxy(
|
|
1633
|
-
{
|
|
1634
|
-
runId,
|
|
1635
|
-
workflowId,
|
|
1636
|
-
mastra: this.mastra,
|
|
1637
|
-
requestContext,
|
|
1638
|
-
retryCount: -1,
|
|
1639
|
-
inputData: prevOutput,
|
|
1640
|
-
state: executionContext.state,
|
|
1641
|
-
setState: (state) => {
|
|
1642
|
-
executionContext.state = state;
|
|
1643
|
-
},
|
|
1644
|
-
tracingContext: {
|
|
1645
|
-
currentSpan: evalSpan
|
|
1646
|
-
},
|
|
1647
|
-
getInitData: () => stepResults?.input,
|
|
1648
|
-
getStepResult: getStepResult.bind(this, stepResults),
|
|
1649
|
-
// TODO: this function shouldn't have suspend probably?
|
|
1650
|
-
suspend: async (_suspendPayload) => {
|
|
1651
|
-
},
|
|
1652
|
-
bail: () => {
|
|
1653
|
-
},
|
|
1654
|
-
abort: () => {
|
|
1655
|
-
abortController.abort();
|
|
1656
|
-
},
|
|
1657
|
-
[EMITTER_SYMBOL]: emitter,
|
|
1658
|
-
[STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1659
|
-
engine: {
|
|
1660
|
-
step: this.inngestStep
|
|
1661
|
-
},
|
|
1662
|
-
abortSignal: abortController.signal,
|
|
1663
|
-
writer: new ToolStream(
|
|
1664
|
-
{
|
|
1665
|
-
prefix: "workflow-step",
|
|
1666
|
-
callId: randomUUID(),
|
|
1667
|
-
name: "conditional",
|
|
1668
|
-
runId
|
|
1669
|
-
},
|
|
1670
|
-
writableStream
|
|
1671
|
-
)
|
|
1672
|
-
},
|
|
1673
|
-
{
|
|
1674
|
-
paramName: "runCount",
|
|
1675
|
-
deprecationMessage: runCountDeprecationMessage,
|
|
1676
|
-
logger: this.logger
|
|
1677
|
-
}
|
|
1678
|
-
)
|
|
1679
|
-
);
|
|
1680
|
-
evalSpan?.end({
|
|
1681
|
-
output: result,
|
|
1682
|
-
attributes: {
|
|
1683
|
-
result: !!result
|
|
1684
|
-
}
|
|
1685
|
-
});
|
|
1686
|
-
return result ? index : null;
|
|
1687
|
-
} catch (e) {
|
|
1688
|
-
evalSpan?.error({
|
|
1689
|
-
error: e instanceof Error ? e : new Error(String(e)),
|
|
1690
|
-
attributes: {
|
|
1691
|
-
result: false
|
|
1692
|
-
}
|
|
1693
|
-
});
|
|
1694
|
-
return null;
|
|
1695
|
-
}
|
|
1696
|
-
})
|
|
1697
|
-
)
|
|
1698
|
-
)).filter((index) => index !== null);
|
|
1699
|
-
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1700
|
-
conditionalSpan?.update({
|
|
1701
|
-
attributes: {
|
|
1702
|
-
truthyIndexes,
|
|
1703
|
-
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1704
|
-
}
|
|
1705
|
-
});
|
|
1706
|
-
const results = await Promise.all(
|
|
1707
|
-
stepsToRun.map(async (step, index) => {
|
|
1708
|
-
const currStepResult = stepResults[step.step.id];
|
|
1709
|
-
if (currStepResult && currStepResult.status === "success") {
|
|
1710
|
-
return currStepResult;
|
|
1711
|
-
}
|
|
1712
|
-
const result = await this.executeStep({
|
|
1713
|
-
step: step.step,
|
|
1714
|
-
prevOutput,
|
|
1715
|
-
stepResults,
|
|
1716
|
-
resume,
|
|
1717
|
-
timeTravel,
|
|
1718
|
-
executionContext: {
|
|
1719
|
-
workflowId,
|
|
1720
|
-
runId,
|
|
1721
|
-
executionPath: [...executionContext.executionPath, index],
|
|
1722
|
-
activeStepsPath: executionContext.activeStepsPath,
|
|
1723
|
-
suspendedPaths: executionContext.suspendedPaths,
|
|
1724
|
-
resumeLabels: executionContext.resumeLabels,
|
|
1725
|
-
retryConfig: executionContext.retryConfig,
|
|
1726
|
-
state: executionContext.state
|
|
1727
|
-
},
|
|
1728
|
-
emitter,
|
|
1729
|
-
abortController,
|
|
1730
|
-
requestContext,
|
|
1731
|
-
writableStream,
|
|
1732
|
-
disableScorers,
|
|
1733
|
-
tracingContext: {
|
|
1734
|
-
currentSpan: conditionalSpan
|
|
1735
|
-
}
|
|
1736
|
-
});
|
|
1737
|
-
stepResults[step.step.id] = result;
|
|
1738
|
-
return result;
|
|
1739
|
-
})
|
|
1740
|
-
);
|
|
1741
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
1742
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1743
|
-
if (hasFailed) {
|
|
1744
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1745
|
-
} else if (hasSuspended) {
|
|
1746
|
-
execResults = {
|
|
1747
|
-
status: "suspended",
|
|
1748
|
-
suspendPayload: hasSuspended.suspendPayload,
|
|
1749
|
-
...hasSuspended.suspendOutput ? { suspendOutput: hasSuspended.suspendOutput } : {}
|
|
1750
|
-
};
|
|
1751
|
-
} else {
|
|
1752
|
-
execResults = {
|
|
1753
|
-
status: "success",
|
|
1754
|
-
output: results.reduce((acc, result, index) => {
|
|
1755
|
-
if (result.status === "success") {
|
|
1756
|
-
if ("step" in stepsToRun[index]) {
|
|
1757
|
-
acc[stepsToRun[index].step.id] = result.output;
|
|
1758
|
-
}
|
|
1759
|
-
}
|
|
1760
|
-
return acc;
|
|
1761
|
-
}, {})
|
|
1762
|
-
};
|
|
1763
|
-
}
|
|
1764
|
-
if (execResults.status === "failed") {
|
|
1765
|
-
conditionalSpan?.error({
|
|
1766
|
-
error: new Error(execResults.error)
|
|
1767
|
-
});
|
|
1768
|
-
} else {
|
|
1769
|
-
conditionalSpan?.end({
|
|
1770
|
-
output: execResults.output || execResults
|
|
1771
|
-
});
|
|
1772
|
-
}
|
|
1773
|
-
return execResults;
|
|
1774
|
-
}
|
|
1775
|
-
};
|
|
1776
1495
|
|
|
1777
|
-
export { InngestExecutionEngine, InngestRun, InngestWorkflow, createStep, init, serve };
|
|
1496
|
+
export { InngestExecutionEngine, InngestPubSub, InngestRun, InngestWorkflow, _compatibilityCheck, createStep, init, serve };
|
|
1778
1497
|
//# sourceMappingURL=index.js.map
|
|
1779
1498
|
//# sourceMappingURL=index.js.map
|