@mastra/inngest 0.0.0-redis-cloud-transporter-20250508203756 → 0.0.0-roamin-openaivoice-speak-options-passing-20250926163614
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 +1154 -2
- package/LICENSE.md +11 -42
- package/dist/index.cjs +772 -109
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +295 -5
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +769 -107
- package/dist/index.js.map +1 -0
- package/package.json +39 -20
- package/dist/_tsup-dts-rollup.d.cts +0 -194
- package/dist/_tsup-dts-rollup.d.ts +0 -194
- package/dist/index.d.cts +0 -5
- package/docker-compose.yaml +0 -10
- package/eslint.config.js +0 -6
- package/src/index.test.ts +0 -5437
- package/src/index.ts +0 -956
- package/tsconfig.json +0 -5
- package/vitest.config.ts +0 -8
package/dist/index.cjs
CHANGED
|
@@ -2,35 +2,51 @@
|
|
|
2
2
|
|
|
3
3
|
var crypto = require('crypto');
|
|
4
4
|
var realtime = require('@inngest/realtime');
|
|
5
|
+
var aiTracing = require('@mastra/core/ai-tracing');
|
|
5
6
|
var di = require('@mastra/core/di');
|
|
6
|
-
var
|
|
7
|
+
var tools = require('@mastra/core/tools');
|
|
8
|
+
var workflows = require('@mastra/core/workflows');
|
|
9
|
+
var _constants = require('@mastra/core/workflows/_constants');
|
|
7
10
|
var hono = require('inngest/hono');
|
|
11
|
+
var zod = require('zod');
|
|
8
12
|
|
|
9
13
|
// src/index.ts
|
|
10
|
-
function serve({
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
function serve({
|
|
15
|
+
mastra,
|
|
16
|
+
inngest,
|
|
17
|
+
functions: userFunctions = [],
|
|
18
|
+
registerOptions
|
|
19
|
+
}) {
|
|
20
|
+
const wfs = mastra.getWorkflows();
|
|
21
|
+
const workflowFunctions = Array.from(
|
|
22
|
+
new Set(
|
|
23
|
+
Object.values(wfs).flatMap((wf) => {
|
|
24
|
+
if (wf instanceof InngestWorkflow) {
|
|
25
|
+
wf.__registerMastra(mastra);
|
|
26
|
+
return wf.getFunctions();
|
|
27
|
+
}
|
|
28
|
+
return [];
|
|
29
|
+
})
|
|
30
|
+
)
|
|
31
|
+
);
|
|
19
32
|
return hono.serve({
|
|
33
|
+
...registerOptions,
|
|
20
34
|
client: inngest,
|
|
21
|
-
functions
|
|
35
|
+
functions: [...workflowFunctions, ...userFunctions]
|
|
22
36
|
});
|
|
23
37
|
}
|
|
24
|
-
var InngestRun = class extends
|
|
38
|
+
var InngestRun = class extends workflows.Run {
|
|
25
39
|
inngest;
|
|
40
|
+
serializedStepGraph;
|
|
26
41
|
#mastra;
|
|
27
42
|
constructor(params, inngest) {
|
|
28
43
|
super(params);
|
|
29
44
|
this.inngest = inngest;
|
|
45
|
+
this.serializedStepGraph = params.serializedStepGraph;
|
|
30
46
|
this.#mastra = params.mastra;
|
|
31
47
|
}
|
|
32
48
|
async getRuns(eventId) {
|
|
33
|
-
const response = await fetch(`${this.inngest.apiBaseUrl}/v1/events/${eventId}/runs`, {
|
|
49
|
+
const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
|
|
34
50
|
headers: {
|
|
35
51
|
Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
|
|
36
52
|
}
|
|
@@ -40,35 +56,76 @@ var InngestRun = class extends vNext.Run {
|
|
|
40
56
|
}
|
|
41
57
|
async getRunOutput(eventId) {
|
|
42
58
|
let runs = await this.getRuns(eventId);
|
|
43
|
-
while (runs?.[0]?.status !== "Completed") {
|
|
59
|
+
while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
|
|
44
60
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
45
61
|
runs = await this.getRuns(eventId);
|
|
46
|
-
if (runs?.[0]?.status === "Failed"
|
|
62
|
+
if (runs?.[0]?.status === "Failed") {
|
|
47
63
|
throw new Error(`Function run ${runs?.[0]?.status}`);
|
|
64
|
+
} else if (runs?.[0]?.status === "Cancelled") {
|
|
65
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
66
|
+
workflowName: this.workflowId,
|
|
67
|
+
runId: this.runId
|
|
68
|
+
});
|
|
69
|
+
return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
|
|
48
70
|
}
|
|
49
71
|
}
|
|
50
72
|
return runs?.[0];
|
|
51
73
|
}
|
|
74
|
+
async sendEvent(event, data) {
|
|
75
|
+
await this.inngest.send({
|
|
76
|
+
name: `user-event-${event}`,
|
|
77
|
+
data
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async cancel() {
|
|
81
|
+
await this.inngest.send({
|
|
82
|
+
name: `cancel.workflow.${this.workflowId}`,
|
|
83
|
+
data: {
|
|
84
|
+
runId: this.runId
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
|
|
88
|
+
workflowName: this.workflowId,
|
|
89
|
+
runId: this.runId
|
|
90
|
+
});
|
|
91
|
+
if (snapshot) {
|
|
92
|
+
await this.#mastra?.storage?.persistWorkflowSnapshot({
|
|
93
|
+
workflowName: this.workflowId,
|
|
94
|
+
runId: this.runId,
|
|
95
|
+
resourceId: this.resourceId,
|
|
96
|
+
snapshot: {
|
|
97
|
+
...snapshot,
|
|
98
|
+
status: "canceled"
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
52
103
|
async start({
|
|
53
104
|
inputData
|
|
54
105
|
}) {
|
|
55
106
|
await this.#mastra.getStorage()?.persistWorkflowSnapshot({
|
|
56
107
|
workflowName: this.workflowId,
|
|
57
108
|
runId: this.runId,
|
|
109
|
+
resourceId: this.resourceId,
|
|
58
110
|
snapshot: {
|
|
59
111
|
runId: this.runId,
|
|
112
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
60
113
|
value: {},
|
|
61
114
|
context: {},
|
|
62
115
|
activePaths: [],
|
|
63
116
|
suspendedPaths: {},
|
|
64
|
-
|
|
117
|
+
waitingPaths: {},
|
|
118
|
+
timestamp: Date.now(),
|
|
119
|
+
status: "running"
|
|
65
120
|
}
|
|
66
121
|
});
|
|
122
|
+
const inputDataToUse = await this._validateInput(inputData);
|
|
67
123
|
const eventOutput = await this.inngest.send({
|
|
68
124
|
name: `workflow.${this.workflowId}`,
|
|
69
125
|
data: {
|
|
70
|
-
inputData,
|
|
71
|
-
runId: this.runId
|
|
126
|
+
inputData: inputDataToUse,
|
|
127
|
+
runId: this.runId,
|
|
128
|
+
resourceId: this.resourceId
|
|
72
129
|
}
|
|
73
130
|
});
|
|
74
131
|
const eventId = eventOutput.ids[0];
|
|
@@ -80,10 +137,23 @@ var InngestRun = class extends vNext.Run {
|
|
|
80
137
|
if (result.status === "failed") {
|
|
81
138
|
result.error = new Error(result.error);
|
|
82
139
|
}
|
|
83
|
-
|
|
140
|
+
if (result.status !== "suspended") {
|
|
141
|
+
this.cleanup?.();
|
|
142
|
+
}
|
|
84
143
|
return result;
|
|
85
144
|
}
|
|
86
145
|
async resume(params) {
|
|
146
|
+
const p = this._resume(params).then((result) => {
|
|
147
|
+
if (result.status !== "suspended") {
|
|
148
|
+
this.closeStreamAction?.().catch(() => {
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
});
|
|
153
|
+
this.executionResults = p;
|
|
154
|
+
return p;
|
|
155
|
+
}
|
|
156
|
+
async _resume(params) {
|
|
87
157
|
const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
|
|
88
158
|
(step) => typeof step === "string" ? step : step?.id
|
|
89
159
|
);
|
|
@@ -91,16 +161,19 @@ var InngestRun = class extends vNext.Run {
|
|
|
91
161
|
workflowName: this.workflowId,
|
|
92
162
|
runId: this.runId
|
|
93
163
|
});
|
|
164
|
+
const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
|
|
165
|
+
const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
|
|
94
166
|
const eventOutput = await this.inngest.send({
|
|
95
167
|
name: `workflow.${this.workflowId}`,
|
|
96
168
|
data: {
|
|
97
|
-
inputData:
|
|
169
|
+
inputData: resumeDataToUse,
|
|
98
170
|
runId: this.runId,
|
|
171
|
+
workflowId: this.workflowId,
|
|
99
172
|
stepResults: snapshot?.context,
|
|
100
173
|
resume: {
|
|
101
174
|
steps,
|
|
102
175
|
stepResults: snapshot?.context,
|
|
103
|
-
resumePayload:
|
|
176
|
+
resumePayload: resumeDataToUse,
|
|
104
177
|
// @ts-ignore
|
|
105
178
|
resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
|
|
106
179
|
}
|
|
@@ -117,32 +190,77 @@ var InngestRun = class extends vNext.Run {
|
|
|
117
190
|
}
|
|
118
191
|
return result;
|
|
119
192
|
}
|
|
120
|
-
watch(cb) {
|
|
193
|
+
watch(cb, type = "watch") {
|
|
194
|
+
let active = true;
|
|
121
195
|
const streamPromise = realtime.subscribe(
|
|
122
196
|
{
|
|
123
197
|
channel: `workflow:${this.workflowId}:${this.runId}`,
|
|
124
|
-
topics: [
|
|
198
|
+
topics: [type],
|
|
125
199
|
app: this.inngest
|
|
126
200
|
},
|
|
127
201
|
(message) => {
|
|
128
|
-
|
|
202
|
+
if (active) {
|
|
203
|
+
cb(message.data);
|
|
204
|
+
}
|
|
129
205
|
}
|
|
130
206
|
);
|
|
131
207
|
return () => {
|
|
132
|
-
|
|
133
|
-
|
|
208
|
+
active = false;
|
|
209
|
+
streamPromise.then(async (stream) => {
|
|
210
|
+
return stream.cancel();
|
|
134
211
|
}).catch((err) => {
|
|
135
212
|
console.error(err);
|
|
136
213
|
});
|
|
137
214
|
};
|
|
138
215
|
}
|
|
216
|
+
stream({ inputData, runtimeContext } = {}) {
|
|
217
|
+
const { readable, writable } = new TransformStream();
|
|
218
|
+
const writer = writable.getWriter();
|
|
219
|
+
const unwatch = this.watch(async (event) => {
|
|
220
|
+
try {
|
|
221
|
+
const e = {
|
|
222
|
+
...event,
|
|
223
|
+
type: event.type.replace("workflow-", "")
|
|
224
|
+
};
|
|
225
|
+
await writer.write(e);
|
|
226
|
+
} catch {
|
|
227
|
+
}
|
|
228
|
+
}, "watch-v2");
|
|
229
|
+
this.closeStreamAction = async () => {
|
|
230
|
+
unwatch();
|
|
231
|
+
try {
|
|
232
|
+
await writer.close();
|
|
233
|
+
} catch (err) {
|
|
234
|
+
console.error("Error closing stream:", err);
|
|
235
|
+
} finally {
|
|
236
|
+
writer.releaseLock();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
this.executionResults = this.start({ inputData, runtimeContext }).then((result) => {
|
|
240
|
+
if (result.status !== "suspended") {
|
|
241
|
+
this.closeStreamAction?.().catch(() => {
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
return result;
|
|
245
|
+
});
|
|
246
|
+
return {
|
|
247
|
+
stream: readable,
|
|
248
|
+
getWorkflowState: () => this.executionResults
|
|
249
|
+
};
|
|
250
|
+
}
|
|
139
251
|
};
|
|
140
|
-
var InngestWorkflow = class _InngestWorkflow extends
|
|
252
|
+
var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
|
|
141
253
|
#mastra;
|
|
142
254
|
inngest;
|
|
143
255
|
function;
|
|
256
|
+
flowControlConfig;
|
|
144
257
|
constructor(params, inngest) {
|
|
145
|
-
|
|
258
|
+
const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
|
|
259
|
+
super(workflowParams);
|
|
260
|
+
const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
|
|
261
|
+
([_, value]) => value !== void 0
|
|
262
|
+
);
|
|
263
|
+
this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
|
|
146
264
|
this.#mastra = params.mastra;
|
|
147
265
|
this.inngest = inngest;
|
|
148
266
|
}
|
|
@@ -158,7 +276,7 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
158
276
|
const storage = this.#mastra?.getStorage();
|
|
159
277
|
if (!storage) {
|
|
160
278
|
this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
|
|
161
|
-
return null;
|
|
279
|
+
return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
|
|
162
280
|
}
|
|
163
281
|
const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
|
|
164
282
|
return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
|
|
@@ -181,21 +299,55 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
181
299
|
}
|
|
182
300
|
}
|
|
183
301
|
}
|
|
184
|
-
|
|
302
|
+
/**
|
|
303
|
+
* @deprecated Use createRunAsync() instead.
|
|
304
|
+
* @throws {Error} Always throws an error directing users to use createRunAsync()
|
|
305
|
+
*/
|
|
306
|
+
createRun(_options) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
"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."
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
async createRunAsync(options) {
|
|
185
312
|
const runIdToUse = options?.runId || crypto.randomUUID();
|
|
186
313
|
const run = this.runs.get(runIdToUse) ?? new InngestRun(
|
|
187
314
|
{
|
|
188
315
|
workflowId: this.id,
|
|
189
316
|
runId: runIdToUse,
|
|
317
|
+
resourceId: options?.resourceId,
|
|
190
318
|
executionEngine: this.executionEngine,
|
|
191
319
|
executionGraph: this.executionGraph,
|
|
320
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
192
321
|
mastra: this.#mastra,
|
|
193
322
|
retryConfig: this.retryConfig,
|
|
194
|
-
cleanup: () => this.runs.delete(runIdToUse)
|
|
323
|
+
cleanup: () => this.runs.delete(runIdToUse),
|
|
324
|
+
workflowSteps: this.steps
|
|
195
325
|
},
|
|
196
326
|
this.inngest
|
|
197
327
|
);
|
|
198
328
|
this.runs.set(runIdToUse, run);
|
|
329
|
+
const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
|
|
330
|
+
if (!workflowSnapshotInStorage) {
|
|
331
|
+
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
332
|
+
workflowName: this.id,
|
|
333
|
+
runId: runIdToUse,
|
|
334
|
+
resourceId: options?.resourceId,
|
|
335
|
+
snapshot: {
|
|
336
|
+
runId: runIdToUse,
|
|
337
|
+
status: "pending",
|
|
338
|
+
value: {},
|
|
339
|
+
context: {},
|
|
340
|
+
activePaths: [],
|
|
341
|
+
waitingPaths: {},
|
|
342
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
343
|
+
suspendedPaths: {},
|
|
344
|
+
result: void 0,
|
|
345
|
+
error: void 0,
|
|
346
|
+
// @ts-ignore
|
|
347
|
+
timestamp: Date.now()
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
199
351
|
return run;
|
|
200
352
|
}
|
|
201
353
|
getFunction() {
|
|
@@ -203,11 +355,17 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
203
355
|
return this.function;
|
|
204
356
|
}
|
|
205
357
|
this.function = this.inngest.createFunction(
|
|
206
|
-
|
|
207
|
-
|
|
358
|
+
{
|
|
359
|
+
id: `workflow.${this.id}`,
|
|
360
|
+
// @ts-ignore
|
|
361
|
+
retries: this.retryConfig?.attempts ?? 0,
|
|
362
|
+
cancelOn: [{ event: `cancel.workflow.${this.id}` }],
|
|
363
|
+
// Spread flow control configuration
|
|
364
|
+
...this.flowControlConfig
|
|
365
|
+
},
|
|
208
366
|
{ event: `workflow.${this.id}` },
|
|
209
367
|
async ({ event, step, attempt, publish }) => {
|
|
210
|
-
let { inputData, runId, resume } = event.data;
|
|
368
|
+
let { inputData, runId, resourceId, resume } = event.data;
|
|
211
369
|
if (!runId) {
|
|
212
370
|
runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
|
|
213
371
|
return crypto.randomUUID();
|
|
@@ -221,25 +379,36 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
221
379
|
try {
|
|
222
380
|
await publish({
|
|
223
381
|
channel: `workflow:${this.id}:${runId}`,
|
|
224
|
-
topic:
|
|
382
|
+
topic: event2,
|
|
225
383
|
data
|
|
226
384
|
});
|
|
227
385
|
} catch (err) {
|
|
228
386
|
this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
|
|
229
387
|
}
|
|
388
|
+
},
|
|
389
|
+
on: (_event, _callback) => {
|
|
390
|
+
},
|
|
391
|
+
off: (_event, _callback) => {
|
|
392
|
+
},
|
|
393
|
+
once: (_event, _callback) => {
|
|
230
394
|
}
|
|
231
395
|
};
|
|
232
396
|
const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
|
|
233
397
|
const result = await engine.execute({
|
|
234
398
|
workflowId: this.id,
|
|
235
399
|
runId,
|
|
400
|
+
resourceId,
|
|
236
401
|
graph: this.executionGraph,
|
|
402
|
+
serializedStepGraph: this.serializedStepGraph,
|
|
237
403
|
input: inputData,
|
|
238
404
|
emitter,
|
|
239
405
|
retryConfig: this.retryConfig,
|
|
240
406
|
runtimeContext: new di.RuntimeContext(),
|
|
241
407
|
// TODO
|
|
242
|
-
resume
|
|
408
|
+
resume,
|
|
409
|
+
abortController: new AbortController(),
|
|
410
|
+
currentSpan: void 0
|
|
411
|
+
// TODO: Pass actual parent AI span from workflow execution context
|
|
243
412
|
});
|
|
244
413
|
return { result, runId };
|
|
245
414
|
}
|
|
@@ -263,39 +432,154 @@ var InngestWorkflow = class _InngestWorkflow extends vNext.NewWorkflow {
|
|
|
263
432
|
return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
|
|
264
433
|
}
|
|
265
434
|
};
|
|
266
|
-
function
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
435
|
+
function isAgent(params) {
|
|
436
|
+
return params?.component === "AGENT";
|
|
437
|
+
}
|
|
438
|
+
function isTool(params) {
|
|
439
|
+
return params instanceof tools.Tool;
|
|
440
|
+
}
|
|
441
|
+
function createStep(params) {
|
|
442
|
+
if (isAgent(params)) {
|
|
443
|
+
return {
|
|
444
|
+
id: params.name,
|
|
445
|
+
description: params.getDescription(),
|
|
446
|
+
// @ts-ignore
|
|
447
|
+
inputSchema: zod.z.object({
|
|
448
|
+
prompt: zod.z.string()
|
|
449
|
+
}),
|
|
450
|
+
// @ts-ignore
|
|
451
|
+
outputSchema: zod.z.object({
|
|
452
|
+
text: zod.z.string()
|
|
453
|
+
}),
|
|
454
|
+
execute: async ({ inputData, [_constants.EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort, tracingContext }) => {
|
|
455
|
+
let streamPromise = {};
|
|
456
|
+
streamPromise.promise = new Promise((resolve, reject) => {
|
|
457
|
+
streamPromise.resolve = resolve;
|
|
458
|
+
streamPromise.reject = reject;
|
|
459
|
+
});
|
|
460
|
+
const toolData = {
|
|
461
|
+
name: params.name,
|
|
462
|
+
args: inputData
|
|
463
|
+
};
|
|
464
|
+
const { fullStream } = await params.stream(inputData.prompt, {
|
|
465
|
+
runtimeContext,
|
|
466
|
+
tracingContext,
|
|
467
|
+
onFinish: (result) => {
|
|
468
|
+
streamPromise.resolve(result.text);
|
|
469
|
+
},
|
|
470
|
+
abortSignal
|
|
471
|
+
});
|
|
472
|
+
if (abortSignal.aborted) {
|
|
473
|
+
return abort();
|
|
474
|
+
}
|
|
475
|
+
await emitter.emit("watch-v2", {
|
|
476
|
+
type: "tool-call-streaming-start",
|
|
477
|
+
...toolData ?? {}
|
|
478
|
+
});
|
|
479
|
+
for await (const chunk of fullStream) {
|
|
480
|
+
if (chunk.type === "text-delta") {
|
|
481
|
+
await emitter.emit("watch-v2", {
|
|
482
|
+
type: "tool-call-delta",
|
|
483
|
+
...toolData ?? {},
|
|
484
|
+
argsTextDelta: chunk.textDelta
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
await emitter.emit("watch-v2", {
|
|
489
|
+
type: "tool-call-streaming-finish",
|
|
490
|
+
...toolData ?? {}
|
|
491
|
+
});
|
|
492
|
+
return {
|
|
493
|
+
text: await streamPromise.promise
|
|
494
|
+
};
|
|
495
|
+
},
|
|
496
|
+
component: params.component
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
if (isTool(params)) {
|
|
500
|
+
if (!params.inputSchema || !params.outputSchema) {
|
|
501
|
+
throw new Error("Tool must have input and output schemas defined");
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
// TODO: tool probably should have strong id type
|
|
505
|
+
// @ts-ignore
|
|
506
|
+
id: params.id,
|
|
507
|
+
description: params.description,
|
|
508
|
+
inputSchema: params.inputSchema,
|
|
509
|
+
outputSchema: params.outputSchema,
|
|
510
|
+
execute: async ({ inputData, mastra, runtimeContext, tracingContext, suspend, resumeData }) => {
|
|
511
|
+
return params.execute({
|
|
512
|
+
context: inputData,
|
|
513
|
+
mastra: aiTracing.wrapMastra(mastra, tracingContext),
|
|
514
|
+
runtimeContext,
|
|
515
|
+
tracingContext,
|
|
516
|
+
suspend,
|
|
517
|
+
resumeData
|
|
518
|
+
});
|
|
519
|
+
},
|
|
520
|
+
component: "TOOL"
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
return {
|
|
524
|
+
id: params.id,
|
|
525
|
+
description: params.description,
|
|
526
|
+
inputSchema: params.inputSchema,
|
|
527
|
+
outputSchema: params.outputSchema,
|
|
528
|
+
resumeSchema: params.resumeSchema,
|
|
529
|
+
suspendSchema: params.suspendSchema,
|
|
530
|
+
execute: params.execute
|
|
531
|
+
};
|
|
280
532
|
}
|
|
281
533
|
function init(inngest) {
|
|
282
534
|
return {
|
|
283
535
|
createWorkflow(params) {
|
|
284
536
|
return new InngestWorkflow(params, inngest);
|
|
285
537
|
},
|
|
286
|
-
createStep
|
|
287
|
-
cloneStep
|
|
288
|
-
|
|
538
|
+
createStep,
|
|
539
|
+
cloneStep(step, opts) {
|
|
540
|
+
return {
|
|
541
|
+
id: opts.id,
|
|
542
|
+
description: step.description,
|
|
543
|
+
inputSchema: step.inputSchema,
|
|
544
|
+
outputSchema: step.outputSchema,
|
|
545
|
+
execute: step.execute,
|
|
546
|
+
component: step.component
|
|
547
|
+
};
|
|
548
|
+
},
|
|
549
|
+
cloneWorkflow(workflow, opts) {
|
|
550
|
+
const wf = new workflows.Workflow({
|
|
551
|
+
id: opts.id,
|
|
552
|
+
inputSchema: workflow.inputSchema,
|
|
553
|
+
outputSchema: workflow.outputSchema,
|
|
554
|
+
steps: workflow.stepDefs,
|
|
555
|
+
mastra: workflow.mastra
|
|
556
|
+
});
|
|
557
|
+
wf.setStepFlow(workflow.stepGraph);
|
|
558
|
+
wf.commit();
|
|
559
|
+
return wf;
|
|
560
|
+
}
|
|
289
561
|
};
|
|
290
562
|
}
|
|
291
|
-
var InngestExecutionEngine = class extends
|
|
563
|
+
var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
|
|
292
564
|
inngestStep;
|
|
293
565
|
inngestAttempts;
|
|
294
|
-
constructor(mastra, inngestStep, inngestAttempts = 0) {
|
|
295
|
-
super({ mastra });
|
|
566
|
+
constructor(mastra, inngestStep, inngestAttempts = 0, options) {
|
|
567
|
+
super({ mastra, options });
|
|
296
568
|
this.inngestStep = inngestStep;
|
|
297
569
|
this.inngestAttempts = inngestAttempts;
|
|
298
570
|
}
|
|
571
|
+
async execute(params) {
|
|
572
|
+
await params.emitter.emit("watch-v2", {
|
|
573
|
+
type: "workflow-start",
|
|
574
|
+
payload: { runId: params.runId }
|
|
575
|
+
});
|
|
576
|
+
const result = await super.execute(params);
|
|
577
|
+
await params.emitter.emit("watch-v2", {
|
|
578
|
+
type: "workflow-finish",
|
|
579
|
+
payload: { runId: params.runId }
|
|
580
|
+
});
|
|
581
|
+
return result;
|
|
582
|
+
}
|
|
299
583
|
async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
|
|
300
584
|
const base = {
|
|
301
585
|
status: lastOutput.status,
|
|
@@ -353,28 +637,179 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
353
637
|
executionSpan?.end();
|
|
354
638
|
return base;
|
|
355
639
|
}
|
|
356
|
-
async
|
|
640
|
+
// async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
|
|
641
|
+
// await this.inngestStep.sleep(id, duration);
|
|
642
|
+
// }
|
|
643
|
+
async executeSleep({
|
|
357
644
|
workflowId,
|
|
358
645
|
runId,
|
|
359
|
-
|
|
646
|
+
entry,
|
|
647
|
+
prevOutput,
|
|
360
648
|
stepResults,
|
|
649
|
+
emitter,
|
|
650
|
+
abortController,
|
|
651
|
+
runtimeContext,
|
|
361
652
|
executionContext,
|
|
362
|
-
|
|
653
|
+
writableStream,
|
|
654
|
+
tracingContext
|
|
655
|
+
}) {
|
|
656
|
+
let { duration, fn } = entry;
|
|
657
|
+
const sleepSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
658
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
659
|
+
name: `sleep: ${duration ? `${duration}ms` : "dynamic"}`,
|
|
660
|
+
attributes: {
|
|
661
|
+
durationMs: duration,
|
|
662
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
663
|
+
},
|
|
664
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
665
|
+
});
|
|
666
|
+
if (fn) {
|
|
667
|
+
const stepCallId = crypto.randomUUID();
|
|
668
|
+
duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
|
|
669
|
+
return await fn({
|
|
670
|
+
runId,
|
|
671
|
+
workflowId,
|
|
672
|
+
mastra: this.mastra,
|
|
673
|
+
runtimeContext,
|
|
674
|
+
inputData: prevOutput,
|
|
675
|
+
runCount: -1,
|
|
676
|
+
tracingContext: {
|
|
677
|
+
currentSpan: sleepSpan
|
|
678
|
+
},
|
|
679
|
+
getInitData: () => stepResults?.input,
|
|
680
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
681
|
+
// TODO: this function shouldn't have suspend probably?
|
|
682
|
+
suspend: async (_suspendPayload) => {
|
|
683
|
+
},
|
|
684
|
+
bail: () => {
|
|
685
|
+
},
|
|
686
|
+
abort: () => {
|
|
687
|
+
abortController?.abort();
|
|
688
|
+
},
|
|
689
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
690
|
+
// TODO: add streamVNext support
|
|
691
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
692
|
+
engine: { step: this.inngestStep },
|
|
693
|
+
abortSignal: abortController?.signal,
|
|
694
|
+
writer: new tools.ToolStream(
|
|
695
|
+
{
|
|
696
|
+
prefix: "workflow-step",
|
|
697
|
+
callId: stepCallId,
|
|
698
|
+
name: "sleep",
|
|
699
|
+
runId
|
|
700
|
+
},
|
|
701
|
+
writableStream
|
|
702
|
+
)
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
sleepSpan?.update({
|
|
706
|
+
attributes: {
|
|
707
|
+
durationMs: duration
|
|
708
|
+
}
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
try {
|
|
712
|
+
await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
|
|
713
|
+
sleepSpan?.end();
|
|
714
|
+
} catch (e) {
|
|
715
|
+
sleepSpan?.error({ error: e });
|
|
716
|
+
throw e;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
async executeSleepUntil({
|
|
720
|
+
workflowId,
|
|
721
|
+
runId,
|
|
722
|
+
entry,
|
|
363
723
|
prevOutput,
|
|
724
|
+
stepResults,
|
|
364
725
|
emitter,
|
|
365
|
-
|
|
726
|
+
abortController,
|
|
727
|
+
runtimeContext,
|
|
728
|
+
executionContext,
|
|
729
|
+
writableStream,
|
|
730
|
+
tracingContext
|
|
366
731
|
}) {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
732
|
+
let { date, fn } = entry;
|
|
733
|
+
const sleepUntilSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
734
|
+
type: aiTracing.AISpanType.WORKFLOW_SLEEP,
|
|
735
|
+
name: `sleepUntil: ${date ? date.toISOString() : "dynamic"}`,
|
|
736
|
+
attributes: {
|
|
737
|
+
untilDate: date,
|
|
738
|
+
durationMs: date ? Math.max(0, date.getTime() - Date.now()) : void 0,
|
|
739
|
+
sleepType: fn ? "dynamic" : "fixed"
|
|
740
|
+
},
|
|
741
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
742
|
+
});
|
|
743
|
+
if (fn) {
|
|
744
|
+
date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
|
|
745
|
+
const stepCallId = crypto.randomUUID();
|
|
746
|
+
return await fn({
|
|
747
|
+
runId,
|
|
748
|
+
workflowId,
|
|
749
|
+
mastra: this.mastra,
|
|
750
|
+
runtimeContext,
|
|
751
|
+
inputData: prevOutput,
|
|
752
|
+
runCount: -1,
|
|
753
|
+
tracingContext: {
|
|
754
|
+
currentSpan: sleepUntilSpan
|
|
755
|
+
},
|
|
756
|
+
getInitData: () => stepResults?.input,
|
|
757
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
758
|
+
// TODO: this function shouldn't have suspend probably?
|
|
759
|
+
suspend: async (_suspendPayload) => {
|
|
760
|
+
},
|
|
761
|
+
bail: () => {
|
|
762
|
+
},
|
|
763
|
+
abort: () => {
|
|
764
|
+
abortController?.abort();
|
|
765
|
+
},
|
|
766
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
767
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
768
|
+
// TODO: add streamVNext support
|
|
769
|
+
engine: { step: this.inngestStep },
|
|
770
|
+
abortSignal: abortController?.signal,
|
|
771
|
+
writer: new tools.ToolStream(
|
|
772
|
+
{
|
|
773
|
+
prefix: "workflow-step",
|
|
774
|
+
callId: stepCallId,
|
|
775
|
+
name: "sleep",
|
|
776
|
+
runId
|
|
777
|
+
},
|
|
778
|
+
writableStream
|
|
779
|
+
)
|
|
780
|
+
});
|
|
781
|
+
});
|
|
782
|
+
if (date && !(date instanceof Date)) {
|
|
783
|
+
date = new Date(date);
|
|
784
|
+
}
|
|
785
|
+
const time = !date ? 0 : date.getTime() - Date.now();
|
|
786
|
+
sleepUntilSpan?.update({
|
|
787
|
+
attributes: {
|
|
788
|
+
durationMs: Math.max(0, time)
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
}
|
|
792
|
+
if (!(date instanceof Date)) {
|
|
793
|
+
sleepUntilSpan?.end();
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
try {
|
|
797
|
+
await this.inngestStep.sleepUntil(entry.id, date);
|
|
798
|
+
sleepUntilSpan?.end();
|
|
799
|
+
} catch (e) {
|
|
800
|
+
sleepUntilSpan?.error({ error: e });
|
|
801
|
+
throw e;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
async executeWaitForEvent({ event, timeout }) {
|
|
805
|
+
const eventData = await this.inngestStep.waitForEvent(`user-event-${event}`, {
|
|
806
|
+
event: `user-event-${event}`,
|
|
807
|
+
timeout: timeout ?? 5e3
|
|
377
808
|
});
|
|
809
|
+
if (eventData === null) {
|
|
810
|
+
throw "Timeout waiting for event";
|
|
811
|
+
}
|
|
812
|
+
return eventData?.data;
|
|
378
813
|
}
|
|
379
814
|
async executeStep({
|
|
380
815
|
step,
|
|
@@ -383,11 +818,30 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
383
818
|
resume,
|
|
384
819
|
prevOutput,
|
|
385
820
|
emitter,
|
|
386
|
-
|
|
821
|
+
abortController,
|
|
822
|
+
runtimeContext,
|
|
823
|
+
tracingContext,
|
|
824
|
+
writableStream,
|
|
825
|
+
disableScorers
|
|
387
826
|
}) {
|
|
388
|
-
|
|
827
|
+
const stepAISpan = tracingContext?.currentSpan?.createChildSpan({
|
|
828
|
+
name: `workflow step: '${step.id}'`,
|
|
829
|
+
type: aiTracing.AISpanType.WORKFLOW_STEP,
|
|
830
|
+
input: prevOutput,
|
|
831
|
+
attributes: {
|
|
832
|
+
stepId: step.id
|
|
833
|
+
},
|
|
834
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
835
|
+
});
|
|
836
|
+
const { inputData, validationError } = await workflows.validateStepInput({
|
|
837
|
+
prevOutput,
|
|
838
|
+
step,
|
|
839
|
+
validateInputs: this.options?.validateInputs ?? false
|
|
840
|
+
});
|
|
841
|
+
const startedAt = await this.inngestStep.run(
|
|
389
842
|
`workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
|
|
390
843
|
async () => {
|
|
844
|
+
const startedAt2 = Date.now();
|
|
391
845
|
await emitter.emit("watch", {
|
|
392
846
|
type: "watch",
|
|
393
847
|
payload: {
|
|
@@ -409,6 +863,16 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
409
863
|
},
|
|
410
864
|
eventTimestamp: Date.now()
|
|
411
865
|
});
|
|
866
|
+
await emitter.emit("watch-v2", {
|
|
867
|
+
type: "workflow-step-start",
|
|
868
|
+
payload: {
|
|
869
|
+
id: step.id,
|
|
870
|
+
status: "running",
|
|
871
|
+
payload: inputData,
|
|
872
|
+
startedAt: startedAt2
|
|
873
|
+
}
|
|
874
|
+
});
|
|
875
|
+
return startedAt2;
|
|
412
876
|
}
|
|
413
877
|
);
|
|
414
878
|
if (step instanceof InngestWorkflow) {
|
|
@@ -424,7 +888,7 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
424
888
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
425
889
|
function: step.getFunction(),
|
|
426
890
|
data: {
|
|
427
|
-
inputData
|
|
891
|
+
inputData,
|
|
428
892
|
runId,
|
|
429
893
|
resume: {
|
|
430
894
|
runId,
|
|
@@ -442,7 +906,7 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
442
906
|
const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
|
|
443
907
|
function: step.getFunction(),
|
|
444
908
|
data: {
|
|
445
|
-
inputData
|
|
909
|
+
inputData
|
|
446
910
|
}
|
|
447
911
|
});
|
|
448
912
|
result = invokeResp.result;
|
|
@@ -469,6 +933,15 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
469
933
|
},
|
|
470
934
|
eventTimestamp: Date.now()
|
|
471
935
|
});
|
|
936
|
+
await emitter.emit("watch-v2", {
|
|
937
|
+
type: "workflow-step-result",
|
|
938
|
+
payload: {
|
|
939
|
+
id: step.id,
|
|
940
|
+
status: "failed",
|
|
941
|
+
error: result?.error,
|
|
942
|
+
payload: prevOutput
|
|
943
|
+
}
|
|
944
|
+
});
|
|
472
945
|
return { executionContext, result: { status: "failed", error: result?.error } };
|
|
473
946
|
} else if (result.status === "suspended") {
|
|
474
947
|
const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
|
|
@@ -495,6 +968,13 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
495
968
|
},
|
|
496
969
|
eventTimestamp: Date.now()
|
|
497
970
|
});
|
|
971
|
+
await emitter.emit("watch-v2", {
|
|
972
|
+
type: "workflow-step-suspended",
|
|
973
|
+
payload: {
|
|
974
|
+
id: step.id,
|
|
975
|
+
status: "suspended"
|
|
976
|
+
}
|
|
977
|
+
});
|
|
498
978
|
return {
|
|
499
979
|
executionContext,
|
|
500
980
|
result: {
|
|
@@ -545,6 +1025,21 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
545
1025
|
},
|
|
546
1026
|
eventTimestamp: Date.now()
|
|
547
1027
|
});
|
|
1028
|
+
await emitter.emit("watch-v2", {
|
|
1029
|
+
type: "workflow-step-result",
|
|
1030
|
+
payload: {
|
|
1031
|
+
id: step.id,
|
|
1032
|
+
status: "success",
|
|
1033
|
+
output: result?.result
|
|
1034
|
+
}
|
|
1035
|
+
});
|
|
1036
|
+
await emitter.emit("watch-v2", {
|
|
1037
|
+
type: "workflow-step-finish",
|
|
1038
|
+
payload: {
|
|
1039
|
+
id: step.id,
|
|
1040
|
+
metadata: {}
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
548
1043
|
return { executionContext, result: { status: "success", output: result?.result } };
|
|
549
1044
|
}
|
|
550
1045
|
);
|
|
@@ -554,42 +1049,81 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
554
1049
|
const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
|
|
555
1050
|
let execResults;
|
|
556
1051
|
let suspended;
|
|
1052
|
+
let bailed;
|
|
557
1053
|
try {
|
|
1054
|
+
if (validationError) {
|
|
1055
|
+
throw validationError;
|
|
1056
|
+
}
|
|
558
1057
|
const result = await step.execute({
|
|
1058
|
+
runId: executionContext.runId,
|
|
559
1059
|
mastra: this.mastra,
|
|
560
1060
|
runtimeContext,
|
|
561
|
-
|
|
1061
|
+
writableStream,
|
|
1062
|
+
inputData,
|
|
562
1063
|
resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
const result2 = stepResults[step2.id];
|
|
566
|
-
if (result2?.status === "success") {
|
|
567
|
-
return result2.output;
|
|
568
|
-
}
|
|
569
|
-
return null;
|
|
1064
|
+
tracingContext: {
|
|
1065
|
+
currentSpan: stepAISpan
|
|
570
1066
|
},
|
|
1067
|
+
getInitData: () => stepResults?.input,
|
|
1068
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
571
1069
|
suspend: async (suspendPayload) => {
|
|
572
1070
|
executionContext.suspendedPaths[step.id] = executionContext.executionPath;
|
|
573
1071
|
suspended = { payload: suspendPayload };
|
|
574
1072
|
},
|
|
1073
|
+
bail: (result2) => {
|
|
1074
|
+
bailed = { payload: result2 };
|
|
1075
|
+
},
|
|
575
1076
|
resume: {
|
|
576
1077
|
steps: resume?.steps?.slice(1) || [],
|
|
577
1078
|
resumePayload: resume?.resumePayload,
|
|
578
1079
|
// @ts-ignore
|
|
579
1080
|
runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
|
|
580
1081
|
},
|
|
581
|
-
emitter
|
|
1082
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1083
|
+
engine: {
|
|
1084
|
+
step: this.inngestStep
|
|
1085
|
+
},
|
|
1086
|
+
abortSignal: abortController.signal
|
|
582
1087
|
});
|
|
583
|
-
|
|
1088
|
+
const endedAt = Date.now();
|
|
1089
|
+
execResults = {
|
|
1090
|
+
status: "success",
|
|
1091
|
+
output: result,
|
|
1092
|
+
startedAt,
|
|
1093
|
+
endedAt,
|
|
1094
|
+
payload: inputData,
|
|
1095
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1096
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1097
|
+
};
|
|
584
1098
|
} catch (e) {
|
|
585
|
-
execResults = {
|
|
1099
|
+
execResults = {
|
|
1100
|
+
status: "failed",
|
|
1101
|
+
payload: inputData,
|
|
1102
|
+
error: e instanceof Error ? e.message : String(e),
|
|
1103
|
+
endedAt: Date.now(),
|
|
1104
|
+
startedAt,
|
|
1105
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1106
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1107
|
+
};
|
|
586
1108
|
}
|
|
587
1109
|
if (suspended) {
|
|
588
|
-
execResults = {
|
|
1110
|
+
execResults = {
|
|
1111
|
+
status: "suspended",
|
|
1112
|
+
suspendedPayload: suspended.payload,
|
|
1113
|
+
payload: inputData,
|
|
1114
|
+
suspendedAt: Date.now(),
|
|
1115
|
+
startedAt,
|
|
1116
|
+
resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
|
|
1117
|
+
resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
|
|
1118
|
+
};
|
|
1119
|
+
} else if (bailed) {
|
|
1120
|
+
execResults = { status: "bailed", output: bailed.payload, payload: inputData, endedAt: Date.now(), startedAt };
|
|
589
1121
|
}
|
|
590
1122
|
if (execResults.status === "failed") {
|
|
591
1123
|
if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
|
|
592
|
-
|
|
1124
|
+
const error = new Error(execResults.error);
|
|
1125
|
+
stepAISpan?.error({ error });
|
|
1126
|
+
throw error;
|
|
593
1127
|
}
|
|
594
1128
|
}
|
|
595
1129
|
await emitter.emit("watch", {
|
|
@@ -597,20 +1131,61 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
597
1131
|
payload: {
|
|
598
1132
|
currentStep: {
|
|
599
1133
|
id: step.id,
|
|
600
|
-
|
|
601
|
-
output: execResults.output
|
|
1134
|
+
...execResults
|
|
602
1135
|
},
|
|
603
1136
|
workflowState: {
|
|
604
1137
|
status: "running",
|
|
605
|
-
steps: stepResults,
|
|
1138
|
+
steps: { ...stepResults, [step.id]: execResults },
|
|
606
1139
|
result: null,
|
|
607
1140
|
error: null
|
|
608
1141
|
}
|
|
609
1142
|
},
|
|
610
1143
|
eventTimestamp: Date.now()
|
|
611
1144
|
});
|
|
1145
|
+
if (execResults.status === "suspended") {
|
|
1146
|
+
await emitter.emit("watch-v2", {
|
|
1147
|
+
type: "workflow-step-suspended",
|
|
1148
|
+
payload: {
|
|
1149
|
+
id: step.id,
|
|
1150
|
+
...execResults
|
|
1151
|
+
}
|
|
1152
|
+
});
|
|
1153
|
+
} else {
|
|
1154
|
+
await emitter.emit("watch-v2", {
|
|
1155
|
+
type: "workflow-step-result",
|
|
1156
|
+
payload: {
|
|
1157
|
+
id: step.id,
|
|
1158
|
+
...execResults
|
|
1159
|
+
}
|
|
1160
|
+
});
|
|
1161
|
+
await emitter.emit("watch-v2", {
|
|
1162
|
+
type: "workflow-step-finish",
|
|
1163
|
+
payload: {
|
|
1164
|
+
id: step.id,
|
|
1165
|
+
metadata: {}
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
stepAISpan?.end({ output: execResults });
|
|
612
1170
|
return { result: execResults, executionContext, stepResults };
|
|
613
1171
|
});
|
|
1172
|
+
if (disableScorers !== false) {
|
|
1173
|
+
await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}.score`, async () => {
|
|
1174
|
+
if (step.scorers) {
|
|
1175
|
+
await this.runScorers({
|
|
1176
|
+
scorers: step.scorers,
|
|
1177
|
+
runId: executionContext.runId,
|
|
1178
|
+
input: inputData,
|
|
1179
|
+
output: stepRes.result,
|
|
1180
|
+
workflowId: executionContext.workflowId,
|
|
1181
|
+
stepId: step.id,
|
|
1182
|
+
runtimeContext,
|
|
1183
|
+
disableScorers,
|
|
1184
|
+
tracingContext: { currentSpan: stepAISpan }
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
614
1189
|
Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
|
|
615
1190
|
Object.assign(stepResults, stepRes.stepResults);
|
|
616
1191
|
return stepRes.result;
|
|
@@ -619,7 +1194,12 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
619
1194
|
workflowId,
|
|
620
1195
|
runId,
|
|
621
1196
|
stepResults,
|
|
622
|
-
|
|
1197
|
+
resourceId,
|
|
1198
|
+
executionContext,
|
|
1199
|
+
serializedStepGraph,
|
|
1200
|
+
workflowStatus,
|
|
1201
|
+
result,
|
|
1202
|
+
error
|
|
623
1203
|
}) {
|
|
624
1204
|
await this.inngestStep.run(
|
|
625
1205
|
`workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
|
|
@@ -627,12 +1207,18 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
627
1207
|
await this.mastra?.getStorage()?.persistWorkflowSnapshot({
|
|
628
1208
|
workflowName: workflowId,
|
|
629
1209
|
runId,
|
|
1210
|
+
resourceId,
|
|
630
1211
|
snapshot: {
|
|
631
1212
|
runId,
|
|
632
1213
|
value: {},
|
|
633
1214
|
context: stepResults,
|
|
634
1215
|
activePaths: [],
|
|
635
1216
|
suspendedPaths: executionContext.suspendedPaths,
|
|
1217
|
+
waitingPaths: {},
|
|
1218
|
+
serializedStepGraph,
|
|
1219
|
+
status: workflowStatus,
|
|
1220
|
+
result,
|
|
1221
|
+
error,
|
|
636
1222
|
// @ts-ignore
|
|
637
1223
|
timestamp: Date.now()
|
|
638
1224
|
}
|
|
@@ -647,50 +1233,109 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
647
1233
|
prevOutput,
|
|
648
1234
|
prevStep,
|
|
649
1235
|
stepResults,
|
|
1236
|
+
serializedStepGraph,
|
|
650
1237
|
resume,
|
|
651
1238
|
executionContext,
|
|
652
1239
|
emitter,
|
|
653
|
-
|
|
1240
|
+
abortController,
|
|
1241
|
+
runtimeContext,
|
|
1242
|
+
writableStream,
|
|
1243
|
+
disableScorers,
|
|
1244
|
+
tracingContext
|
|
654
1245
|
}) {
|
|
1246
|
+
const conditionalSpan = tracingContext?.currentSpan?.createChildSpan({
|
|
1247
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL,
|
|
1248
|
+
name: `conditional: '${entry.conditions.length} conditions'`,
|
|
1249
|
+
input: prevOutput,
|
|
1250
|
+
attributes: {
|
|
1251
|
+
conditionCount: entry.conditions.length
|
|
1252
|
+
},
|
|
1253
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1254
|
+
});
|
|
655
1255
|
let execResults;
|
|
656
1256
|
const truthyIndexes = (await Promise.all(
|
|
657
1257
|
entry.conditions.map(
|
|
658
1258
|
(cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
|
|
1259
|
+
const evalSpan = conditionalSpan?.createChildSpan({
|
|
1260
|
+
type: aiTracing.AISpanType.WORKFLOW_CONDITIONAL_EVAL,
|
|
1261
|
+
name: `condition: '${index}'`,
|
|
1262
|
+
input: prevOutput,
|
|
1263
|
+
attributes: {
|
|
1264
|
+
conditionIndex: index
|
|
1265
|
+
},
|
|
1266
|
+
tracingPolicy: this.options?.tracingPolicy
|
|
1267
|
+
});
|
|
659
1268
|
try {
|
|
660
1269
|
const result = await cond({
|
|
1270
|
+
runId,
|
|
1271
|
+
workflowId,
|
|
661
1272
|
mastra: this.mastra,
|
|
662
1273
|
runtimeContext,
|
|
1274
|
+
runCount: -1,
|
|
663
1275
|
inputData: prevOutput,
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
if (!step?.id) {
|
|
667
|
-
return null;
|
|
668
|
-
}
|
|
669
|
-
const result2 = stepResults[step.id];
|
|
670
|
-
if (result2?.status === "success") {
|
|
671
|
-
return result2.output;
|
|
672
|
-
}
|
|
673
|
-
return null;
|
|
1276
|
+
tracingContext: {
|
|
1277
|
+
currentSpan: evalSpan
|
|
674
1278
|
},
|
|
1279
|
+
getInitData: () => stepResults?.input,
|
|
1280
|
+
getStepResult: workflows.getStepResult.bind(this, stepResults),
|
|
675
1281
|
// TODO: this function shouldn't have suspend probably?
|
|
676
1282
|
suspend: async (_suspendPayload) => {
|
|
677
1283
|
},
|
|
678
|
-
|
|
1284
|
+
bail: () => {
|
|
1285
|
+
},
|
|
1286
|
+
abort: () => {
|
|
1287
|
+
abortController.abort();
|
|
1288
|
+
},
|
|
1289
|
+
[_constants.EMITTER_SYMBOL]: emitter,
|
|
1290
|
+
[_constants.STREAM_FORMAT_SYMBOL]: executionContext.format,
|
|
1291
|
+
// TODO: add streamVNext support
|
|
1292
|
+
engine: {
|
|
1293
|
+
step: this.inngestStep
|
|
1294
|
+
},
|
|
1295
|
+
abortSignal: abortController.signal,
|
|
1296
|
+
writer: new tools.ToolStream(
|
|
1297
|
+
{
|
|
1298
|
+
prefix: "workflow-step",
|
|
1299
|
+
callId: crypto.randomUUID(),
|
|
1300
|
+
name: "conditional",
|
|
1301
|
+
runId
|
|
1302
|
+
},
|
|
1303
|
+
writableStream
|
|
1304
|
+
)
|
|
1305
|
+
});
|
|
1306
|
+
evalSpan?.end({
|
|
1307
|
+
output: result,
|
|
1308
|
+
attributes: {
|
|
1309
|
+
result: !!result
|
|
1310
|
+
}
|
|
679
1311
|
});
|
|
680
1312
|
return result ? index : null;
|
|
681
1313
|
} catch (e) {
|
|
1314
|
+
evalSpan?.error({
|
|
1315
|
+
error: e instanceof Error ? e : new Error(String(e)),
|
|
1316
|
+
attributes: {
|
|
1317
|
+
result: false
|
|
1318
|
+
}
|
|
1319
|
+
});
|
|
682
1320
|
return null;
|
|
683
1321
|
}
|
|
684
1322
|
})
|
|
685
1323
|
)
|
|
686
1324
|
)).filter((index) => index !== null);
|
|
687
1325
|
const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
|
|
1326
|
+
conditionalSpan?.update({
|
|
1327
|
+
attributes: {
|
|
1328
|
+
truthyIndexes,
|
|
1329
|
+
selectedSteps: stepsToRun.map((s) => s.type === "step" ? s.step.id : `control-${s.type}`)
|
|
1330
|
+
}
|
|
1331
|
+
});
|
|
688
1332
|
const results = await Promise.all(
|
|
689
1333
|
stepsToRun.map(
|
|
690
1334
|
(step, index) => this.executeEntry({
|
|
691
1335
|
workflowId,
|
|
692
1336
|
runId,
|
|
693
1337
|
entry: step,
|
|
1338
|
+
serializedStepGraph,
|
|
694
1339
|
prevStep,
|
|
695
1340
|
stepResults,
|
|
696
1341
|
resume,
|
|
@@ -703,27 +1348,42 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
703
1348
|
executionSpan: executionContext.executionSpan
|
|
704
1349
|
},
|
|
705
1350
|
emitter,
|
|
706
|
-
|
|
1351
|
+
abortController,
|
|
1352
|
+
runtimeContext,
|
|
1353
|
+
writableStream,
|
|
1354
|
+
disableScorers,
|
|
1355
|
+
tracingContext: {
|
|
1356
|
+
currentSpan: conditionalSpan
|
|
1357
|
+
}
|
|
707
1358
|
})
|
|
708
1359
|
)
|
|
709
1360
|
);
|
|
710
|
-
const hasFailed = results.find((result) => result.status === "failed");
|
|
711
|
-
const hasSuspended = results.find((result) => result.status === "suspended");
|
|
1361
|
+
const hasFailed = results.find((result) => result.result.status === "failed");
|
|
1362
|
+
const hasSuspended = results.find((result) => result.result.status === "suspended");
|
|
712
1363
|
if (hasFailed) {
|
|
713
|
-
execResults = { status: "failed", error: hasFailed.error };
|
|
1364
|
+
execResults = { status: "failed", error: hasFailed.result.error };
|
|
714
1365
|
} else if (hasSuspended) {
|
|
715
|
-
execResults = { status: "suspended", payload: hasSuspended.
|
|
1366
|
+
execResults = { status: "suspended", payload: hasSuspended.result.suspendPayload };
|
|
716
1367
|
} else {
|
|
717
1368
|
execResults = {
|
|
718
1369
|
status: "success",
|
|
719
1370
|
output: results.reduce((acc, result, index) => {
|
|
720
|
-
if (result.status === "success") {
|
|
1371
|
+
if (result.result.status === "success") {
|
|
721
1372
|
acc[stepsToRun[index].step.id] = result.output;
|
|
722
1373
|
}
|
|
723
1374
|
return acc;
|
|
724
1375
|
}, {})
|
|
725
1376
|
};
|
|
726
1377
|
}
|
|
1378
|
+
if (execResults.status === "failed") {
|
|
1379
|
+
conditionalSpan?.error({
|
|
1380
|
+
error: new Error(execResults.error)
|
|
1381
|
+
});
|
|
1382
|
+
} else {
|
|
1383
|
+
conditionalSpan?.end({
|
|
1384
|
+
output: execResults.output || execResults
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
727
1387
|
return execResults;
|
|
728
1388
|
}
|
|
729
1389
|
};
|
|
@@ -731,5 +1391,8 @@ var InngestExecutionEngine = class extends vNext.DefaultExecutionEngine {
|
|
|
731
1391
|
exports.InngestExecutionEngine = InngestExecutionEngine;
|
|
732
1392
|
exports.InngestRun = InngestRun;
|
|
733
1393
|
exports.InngestWorkflow = InngestWorkflow;
|
|
1394
|
+
exports.createStep = createStep;
|
|
734
1395
|
exports.init = init;
|
|
735
1396
|
exports.serve = serve;
|
|
1397
|
+
//# sourceMappingURL=index.cjs.map
|
|
1398
|
+
//# sourceMappingURL=index.cjs.map
|