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