@mastra/inngest 0.0.0-vector-query-sources-20250516172905 → 0.0.0-vector-query-tool-provider-options-20250828222356

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