@mastra/inngest 0.0.0-vnext-inngest-20250508131921 → 0.0.0-vnext-20251119160359

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