@mastra/inngest 0.0.0-cloud-604-map-nested-flow-details-to-side-panel-20251212192149 → 0.0.0-cloudflare-file-url-lazy-20260130204903

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,5 +1,9 @@
1
1
  'use strict';
2
2
 
3
+ var agent = require('@mastra/core/agent');
4
+ var error = require('@mastra/core/error');
5
+ var observability = require('@mastra/core/observability');
6
+ var processors = require('@mastra/core/processors');
3
7
  var tools = require('@mastra/core/tools');
4
8
  var workflows = require('@mastra/core/workflows');
5
9
  var _constants = require('@mastra/core/workflows/_constants');
@@ -7,7 +11,6 @@ var zod = require('zod');
7
11
  var crypto$1 = require('crypto');
8
12
  var di = require('@mastra/core/di');
9
13
  var inngest = require('inngest');
10
- var error = require('@mastra/core/error');
11
14
  var realtime = require('@inngest/realtime');
12
15
  var events = require('@mastra/core/events');
13
16
  var web = require('stream/web');
@@ -60,38 +63,46 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
60
63
  * After retries exhausted, error propagates here and we return a failed result.
61
64
  */
62
65
  async executeStepWithRetry(stepId, runStep, params) {
63
- try {
64
- const result = await this.wrapDurableOperation(stepId, runStep, { delay: params.delay });
65
- return { ok: true, result };
66
- } catch (e) {
67
- const cause = e?.cause;
68
- if (cause?.status === "failed") {
69
- params.stepSpan?.error({
70
- error: e,
71
- attributes: { status: "failed" }
72
- });
73
- if (cause.error && !(cause.error instanceof Error)) {
74
- cause.error = error.getErrorFromUnknown(cause.error, { serializeStack: false });
75
- }
76
- return { ok: false, error: cause };
66
+ for (let i = 0; i < params.retries + 1; i++) {
67
+ if (i > 0 && params.delay) {
68
+ await new Promise((resolve) => setTimeout(resolve, params.delay));
77
69
  }
78
- const errorInstance = error.getErrorFromUnknown(e, {
79
- serializeStack: false,
80
- fallbackMessage: "Unknown step execution error"
81
- });
82
- params.stepSpan?.error({
83
- error: errorInstance,
84
- attributes: { status: "failed" }
85
- });
86
- return {
87
- ok: false,
88
- error: {
89
- status: "failed",
90
- error: errorInstance,
91
- endedAt: Date.now()
70
+ try {
71
+ const result = await this.wrapDurableOperation(stepId, runStep);
72
+ return { ok: true, result };
73
+ } catch (e) {
74
+ if (i === params.retries) {
75
+ const cause = e?.cause;
76
+ if (cause?.status === "failed") {
77
+ params.stepSpan?.error({
78
+ error: e,
79
+ attributes: { status: "failed" }
80
+ });
81
+ if (cause.error && !(cause.error instanceof Error)) {
82
+ cause.error = error.getErrorFromUnknown(cause.error, { serializeStack: false });
83
+ }
84
+ return { ok: false, error: cause };
85
+ }
86
+ const errorInstance = error.getErrorFromUnknown(e, {
87
+ serializeStack: false,
88
+ fallbackMessage: "Unknown step execution error"
89
+ });
90
+ params.stepSpan?.error({
91
+ error: errorInstance,
92
+ attributes: { status: "failed" }
93
+ });
94
+ return {
95
+ ok: false,
96
+ error: {
97
+ status: "failed",
98
+ error: errorInstance,
99
+ endedAt: Date.now()
100
+ }
101
+ };
92
102
  }
93
- };
103
+ }
94
104
  }
105
+ return { ok: false, error: { status: "failed", error: new Error("Unknown error"), endedAt: Date.now() } };
95
106
  }
96
107
  /**
97
108
  * Use Inngest's sleep primitive for durability
@@ -107,28 +118,32 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
107
118
  }
108
119
  /**
109
120
  * Wrap durable operations in Inngest step.run() for durability.
110
- * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
111
- * Inngest's step-level retry mechanism (not function-level retry).
121
+ *
122
+ * IMPORTANT: Errors are wrapped with a cause structure before throwing.
123
+ * This is necessary because Inngest's error serialization (serialize-error-cjs)
124
+ * only captures standard Error properties (message, name, stack, code, cause).
125
+ * Custom properties like statusCode, responseHeaders from AI SDK errors would
126
+ * be lost. By putting our serialized error (via getErrorFromUnknown with toJSON())
127
+ * in the cause property, we ensure custom properties survive serialization.
128
+ * The cause property is in serialize-error-cjs's allowlist, and when the cause
129
+ * object is finally JSON.stringify'd, our error's toJSON() is called.
112
130
  */
113
- async wrapDurableOperation(operationId, operationFn, retryConfig) {
131
+ async wrapDurableOperation(operationId, operationFn) {
114
132
  return this.inngestStep.run(operationId, async () => {
115
133
  try {
116
134
  return await operationFn();
117
135
  } catch (e) {
118
- if (retryConfig) {
119
- const errorInstance = error.getErrorFromUnknown(e, {
120
- serializeStack: false,
121
- fallbackMessage: "Unknown step execution error"
122
- });
123
- throw new inngest.RetryAfterError(errorInstance.message, retryConfig.delay, {
124
- cause: {
125
- status: "failed",
126
- error: errorInstance,
127
- endedAt: Date.now()
128
- }
129
- });
130
- }
131
- throw e;
136
+ const errorInstance = error.getErrorFromUnknown(e, {
137
+ serializeStack: false,
138
+ fallbackMessage: "Unknown step execution error"
139
+ });
140
+ throw new Error(errorInstance.message, {
141
+ cause: {
142
+ status: "failed",
143
+ error: errorInstance,
144
+ endedAt: Date.now()
145
+ }
146
+ });
132
147
  }
133
148
  });
134
149
  }
@@ -138,6 +153,108 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
138
153
  getEngineContext() {
139
154
  return { step: this.inngestStep };
140
155
  }
156
+ /**
157
+ * For Inngest, lifecycle callbacks are invoked in the workflow's finalize step
158
+ * (wrapped in step.run for durability), not in execute(). Override to skip.
159
+ */
160
+ async invokeLifecycleCallbacks(_result) {
161
+ }
162
+ /**
163
+ * Actually invoke the lifecycle callbacks. Called from workflow.ts finalize step.
164
+ */
165
+ async invokeLifecycleCallbacksInternal(result) {
166
+ return super.invokeLifecycleCallbacks(result);
167
+ }
168
+ // =============================================================================
169
+ // Durable Span Lifecycle Hooks
170
+ // =============================================================================
171
+ /**
172
+ * Create a step span durably - on first execution, creates and exports span.
173
+ * On replay, returns cached span data without re-creating.
174
+ */
175
+ async createStepSpan(params) {
176
+ const { executionContext, operationId, options, parentSpan } = params;
177
+ const parentSpanId = parentSpan?.id ?? executionContext.tracingIds?.workflowSpanId;
178
+ const exportedSpan = await this.wrapDurableOperation(operationId, async () => {
179
+ const observability = this.mastra?.observability?.getSelectedInstance({});
180
+ if (!observability) return void 0;
181
+ const span = observability.startSpan({
182
+ ...options,
183
+ entityType: options.entityType,
184
+ traceId: executionContext.tracingIds?.traceId,
185
+ parentSpanId
186
+ });
187
+ return span?.exportSpan();
188
+ });
189
+ if (exportedSpan) {
190
+ const observability = this.mastra?.observability?.getSelectedInstance({});
191
+ return observability?.rebuildSpan(exportedSpan);
192
+ }
193
+ return void 0;
194
+ }
195
+ /**
196
+ * End a step span durably.
197
+ */
198
+ async endStepSpan(params) {
199
+ const { span, operationId, endOptions } = params;
200
+ if (!span) return;
201
+ await this.wrapDurableOperation(operationId, async () => {
202
+ span.end(endOptions);
203
+ });
204
+ }
205
+ /**
206
+ * Record error on step span durably.
207
+ */
208
+ async errorStepSpan(params) {
209
+ const { span, operationId, errorOptions } = params;
210
+ if (!span) return;
211
+ await this.wrapDurableOperation(operationId, async () => {
212
+ span.error(errorOptions);
213
+ });
214
+ }
215
+ /**
216
+ * Create a generic child span durably (for control-flow operations).
217
+ * On first execution, creates and exports span. On replay, returns cached span data.
218
+ */
219
+ async createChildSpan(params) {
220
+ const { executionContext, operationId, options, parentSpan } = params;
221
+ const parentSpanId = parentSpan?.id ?? executionContext.tracingIds?.workflowSpanId;
222
+ const exportedSpan = await this.wrapDurableOperation(operationId, async () => {
223
+ const observability = this.mastra?.observability?.getSelectedInstance({});
224
+ if (!observability) return void 0;
225
+ const span = observability.startSpan({
226
+ ...options,
227
+ traceId: executionContext.tracingIds?.traceId,
228
+ parentSpanId
229
+ });
230
+ return span?.exportSpan();
231
+ });
232
+ if (exportedSpan) {
233
+ const observability = this.mastra?.observability?.getSelectedInstance({});
234
+ return observability?.rebuildSpan(exportedSpan);
235
+ }
236
+ return void 0;
237
+ }
238
+ /**
239
+ * End a generic child span durably (for control-flow operations).
240
+ */
241
+ async endChildSpan(params) {
242
+ const { span, operationId, endOptions } = params;
243
+ if (!span) return;
244
+ await this.wrapDurableOperation(operationId, async () => {
245
+ span.end(endOptions);
246
+ });
247
+ }
248
+ /**
249
+ * Record error on a generic child span durably (for control-flow operations).
250
+ */
251
+ async errorChildSpan(params) {
252
+ const { span, operationId, errorOptions } = params;
253
+ if (!span) return;
254
+ await this.wrapDurableOperation(operationId, async () => {
255
+ span.error(errorOptions);
256
+ });
257
+ }
141
258
  /**
142
259
  * Execute nested InngestWorkflow using inngestStep.invoke() for durability.
143
260
  * This MUST be called directly (not inside step.run()) due to Inngest constraints.
@@ -146,7 +263,23 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
146
263
  if (!(params.step instanceof InngestWorkflow)) {
147
264
  return null;
148
265
  }
149
- const { step, stepResults, executionContext, resume, timeTravel, prevOutput, inputData, pubsub, startedAt } = params;
266
+ const {
267
+ step,
268
+ stepResults,
269
+ executionContext,
270
+ resume,
271
+ timeTravel,
272
+ prevOutput,
273
+ inputData,
274
+ pubsub,
275
+ startedAt,
276
+ perStep,
277
+ stepSpan
278
+ } = params;
279
+ const nestedTracingContext = executionContext.tracingIds?.traceId ? {
280
+ traceId: executionContext.tracingIds.traceId,
281
+ parentSpanId: stepSpan?.id
282
+ } : void 0;
150
283
  const isResume = !!resume?.steps?.length;
151
284
  let result;
152
285
  let runId;
@@ -154,7 +287,8 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
154
287
  try {
155
288
  if (isResume) {
156
289
  runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto$1.randomUUID();
157
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
290
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
291
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
158
292
  workflowName: step.id,
159
293
  runId
160
294
  });
@@ -171,14 +305,17 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
171
305
  resumePayload: resume.resumePayload,
172
306
  resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
173
307
  },
174
- outputOptions: { includeState: true }
308
+ outputOptions: { includeState: true },
309
+ perStep,
310
+ tracingOptions: nestedTracingContext
175
311
  }
176
312
  });
177
313
  result = invokeResp.result;
178
314
  runId = invokeResp.runId;
179
315
  executionContext.state = invokeResp.result.state;
180
316
  } else if (isTimeTravel) {
181
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
317
+ const workflowsStoreForTimeTravel = await this.mastra?.getStorage()?.getStore("workflows");
318
+ const snapshot = await workflowsStoreForTimeTravel?.loadWorkflowSnapshot({
182
319
  workflowName: step.id,
183
320
  runId: executionContext.runId
184
321
  }) ?? { context: {} };
@@ -197,7 +334,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
197
334
  timeTravel: timeTravelParams,
198
335
  initialState: executionContext.state ?? {},
199
336
  runId: executionContext.runId,
200
- outputOptions: { includeState: true }
337
+ outputOptions: { includeState: true },
338
+ perStep,
339
+ tracingOptions: nestedTracingContext
201
340
  }
202
341
  });
203
342
  result = invokeResp.result;
@@ -209,7 +348,9 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
209
348
  data: {
210
349
  inputData,
211
350
  initialState: executionContext.state ?? {},
212
- outputOptions: { includeState: true }
351
+ outputOptions: { includeState: true },
352
+ perStep,
353
+ tracingOptions: nestedTracingContext
213
354
  }
214
355
  });
215
356
  result = invokeResp.result;
@@ -248,7 +389,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
248
389
  }
249
390
  }
250
391
  });
251
- return { executionContext, result: { status: "failed", error: result?.error } };
392
+ return { executionContext, result: { status: "failed", error: result?.error, endedAt: Date.now() } };
252
393
  } else if (result.status === "suspended") {
253
394
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
254
395
  const stepRes = stepResult;
@@ -272,6 +413,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
272
413
  executionContext,
273
414
  result: {
274
415
  status: "suspended",
416
+ suspendedAt: Date.now(),
275
417
  payload: stepResult.payload,
276
418
  suspendPayload: {
277
419
  ...stepResult?.suspendPayload,
@@ -284,6 +426,7 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
284
426
  executionContext,
285
427
  result: {
286
428
  status: "suspended",
429
+ suspendedAt: Date.now(),
287
430
  payload: {}
288
431
  }
289
432
  };
@@ -305,9 +448,34 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
305
448
  executionContext,
306
449
  result: {
307
450
  status: "tripwire",
308
- tripwire: result?.tripwire
451
+ tripwire: result?.tripwire,
452
+ endedAt: Date.now()
309
453
  }
310
454
  };
455
+ } else if (perStep || result.status === "paused") {
456
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
457
+ type: "watch",
458
+ runId: executionContext.runId,
459
+ data: {
460
+ type: "workflow-step-result",
461
+ payload: {
462
+ id: step.id,
463
+ status: "paused"
464
+ }
465
+ }
466
+ });
467
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
468
+ type: "watch",
469
+ runId: executionContext.runId,
470
+ data: {
471
+ type: "workflow-step-finish",
472
+ payload: {
473
+ id: step.id,
474
+ metadata: {}
475
+ }
476
+ }
477
+ });
478
+ return { executionContext, result: { status: "paused" } };
311
479
  }
312
480
  await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
313
481
  type: "watch",
@@ -332,14 +500,13 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
332
500
  }
333
501
  }
334
502
  });
335
- return { executionContext, result: { status: "success", output: result?.result } };
503
+ return { executionContext, result: { status: "success", output: result?.result, endedAt: Date.now() } };
336
504
  }
337
505
  );
338
506
  Object.assign(executionContext, res.executionContext);
339
507
  return {
340
508
  ...res.result,
341
509
  startedAt,
342
- endedAt: Date.now(),
343
510
  payload: inputData,
344
511
  resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
345
512
  resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
@@ -508,6 +675,7 @@ var InngestRun = class extends workflows.Run {
508
675
  async getRunOutput(eventId, maxWaitMs = 3e5) {
509
676
  const startTime = Date.now();
510
677
  const storage = this.#mastra?.getStorage();
678
+ const workflowsStore = await storage?.getStore("workflows");
511
679
  while (Date.now() - startTime < maxWaitMs) {
512
680
  let runs;
513
681
  try {
@@ -524,7 +692,7 @@ var InngestRun = class extends workflows.Run {
524
692
  return runs[0];
525
693
  }
526
694
  if (runs?.[0]?.status === "Failed") {
527
- const snapshot = await storage?.loadWorkflowSnapshot({
695
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
528
696
  workflowName: this.workflowId,
529
697
  runId: this.runId
530
698
  });
@@ -543,7 +711,7 @@ var InngestRun = class extends workflows.Run {
543
711
  };
544
712
  }
545
713
  if (runs?.[0]?.status === "Cancelled") {
546
- const snapshot = await storage?.loadWorkflowSnapshot({
714
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
547
715
  workflowName: this.workflowId,
548
716
  runId: this.runId
549
717
  });
@@ -561,12 +729,13 @@ var InngestRun = class extends workflows.Run {
561
729
  runId: this.runId
562
730
  }
563
731
  });
564
- const snapshot = await storage?.loadWorkflowSnapshot({
732
+ const workflowsStore = await storage?.getStore("workflows");
733
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
565
734
  workflowName: this.workflowId,
566
735
  runId: this.runId
567
736
  });
568
737
  if (snapshot) {
569
- await storage?.persistWorkflowSnapshot({
738
+ await workflowsStore?.persistWorkflowSnapshot({
570
739
  workflowName: this.workflowId,
571
740
  runId: this.runId,
572
741
  resourceId: this.resourceId,
@@ -578,8 +747,8 @@ var InngestRun = class extends workflows.Run {
578
747
  });
579
748
  }
580
749
  }
581
- async start(params) {
582
- return this._start(params);
750
+ async start(args) {
751
+ return this._start(args);
583
752
  }
584
753
  /**
585
754
  * Starts the workflow execution without waiting for completion (fire-and-forget).
@@ -587,8 +756,9 @@ var InngestRun = class extends workflows.Run {
587
756
  * The workflow executes independently in Inngest.
588
757
  * Use this when you don't need to wait for the result or want to avoid polling failures.
589
758
  */
590
- async startAsync(params) {
591
- await this.#mastra.getStorage()?.persistWorkflowSnapshot({
759
+ async startAsync(args) {
760
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
761
+ await workflowsStore?.persistWorkflowSnapshot({
592
762
  workflowName: this.workflowId,
593
763
  runId: this.runId,
594
764
  resourceId: this.resourceId,
@@ -606,8 +776,8 @@ var InngestRun = class extends workflows.Run {
606
776
  timestamp: Date.now()
607
777
  }
608
778
  });
609
- const inputDataToUse = await this._validateInput(params.inputData);
610
- const initialStateToUse = await this._validateInitialState(params.initialState ?? {});
779
+ const inputDataToUse = await this._validateInput(args.inputData);
780
+ const initialStateToUse = await this._validateInitialState(args.initialState ?? {});
611
781
  const eventOutput = await this.inngest.send({
612
782
  name: `workflow.${this.workflowId}`,
613
783
  data: {
@@ -615,9 +785,10 @@ var InngestRun = class extends workflows.Run {
615
785
  initialState: initialStateToUse,
616
786
  runId: this.runId,
617
787
  resourceId: this.resourceId,
618
- outputOptions: params.outputOptions,
619
- tracingOptions: params.tracingOptions,
620
- requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
788
+ outputOptions: args.outputOptions,
789
+ tracingOptions: args.tracingOptions,
790
+ requestContext: args.requestContext ? Object.fromEntries(args.requestContext.entries()) : {},
791
+ perStep: args.perStep
621
792
  }
622
793
  });
623
794
  const eventId = eventOutput.ids[0];
@@ -632,9 +803,11 @@ var InngestRun = class extends workflows.Run {
632
803
  outputOptions,
633
804
  tracingOptions,
634
805
  format,
635
- requestContext
806
+ requestContext,
807
+ perStep
636
808
  }) {
637
- await this.#mastra.getStorage()?.persistWorkflowSnapshot({
809
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
810
+ await workflowsStore?.persistWorkflowSnapshot({
638
811
  workflowName: this.workflowId,
639
812
  runId: this.runId,
640
813
  resourceId: this.resourceId,
@@ -664,7 +837,8 @@ var InngestRun = class extends workflows.Run {
664
837
  outputOptions,
665
838
  tracingOptions,
666
839
  format,
667
- requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
840
+ requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {},
841
+ perStep
668
842
  }
669
843
  });
670
844
  const eventId = eventOutput.ids[0];
@@ -700,7 +874,8 @@ var InngestRun = class extends workflows.Run {
700
874
  (step) => typeof step === "string" ? step : step?.id
701
875
  );
702
876
  }
703
- const snapshot = await storage?.loadWorkflowSnapshot({
877
+ const workflowsStore = await storage?.getStore("workflows");
878
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
704
879
  workflowName: this.workflowId,
705
880
  runId: this.runId
706
881
  });
@@ -723,7 +898,8 @@ var InngestRun = class extends workflows.Run {
723
898
  resumePayload: resumeDataToUse,
724
899
  resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
725
900
  },
726
- requestContext: mergedRequestContext
901
+ requestContext: mergedRequestContext,
902
+ perStep: params.perStep
727
903
  }
728
904
  });
729
905
  const eventId = eventOutput.ids[0];
@@ -762,12 +938,13 @@ var InngestRun = class extends workflows.Run {
762
938
  throw new Error("No steps provided to timeTravel");
763
939
  }
764
940
  const storage = this.#mastra?.getStorage();
765
- const snapshot = await storage?.loadWorkflowSnapshot({
941
+ const workflowsStore = await storage?.getStore("workflows");
942
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
766
943
  workflowName: this.workflowId,
767
944
  runId: this.runId
768
945
  });
769
946
  if (!snapshot) {
770
- await storage?.persistWorkflowSnapshot({
947
+ await workflowsStore?.persistWorkflowSnapshot({
771
948
  workflowName: this.workflowId,
772
949
  runId: this.runId,
773
950
  resourceId: this.resourceId,
@@ -801,7 +978,8 @@ var InngestRun = class extends workflows.Run {
801
978
  nestedStepsContext: params.nestedStepsContext,
802
979
  snapshot: snapshot ?? { context: {} },
803
980
  graph: this.executionGraph,
804
- initialState: params.initialState
981
+ initialState: params.initialState,
982
+ perStep: params.perStep
805
983
  });
806
984
  const eventOutput = await this.inngest.send({
807
985
  name: `workflow.${this.workflowId}`,
@@ -813,7 +991,8 @@ var InngestRun = class extends workflows.Run {
813
991
  timeTravel: timeTravelData,
814
992
  tracingOptions: params.tracingOptions,
815
993
  outputOptions: params.outputOptions,
816
- requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
994
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {},
995
+ perStep: params.perStep
817
996
  }
818
997
  });
819
998
  const eventId = eventOutput.ids[0];
@@ -852,9 +1031,8 @@ var InngestRun = class extends workflows.Run {
852
1031
  const { readable, writable } = new TransformStream();
853
1032
  const writer = writable.getWriter();
854
1033
  void writer.write({
855
- // @ts-ignore
1034
+ // @ts-expect-error - stream event type mismatch
856
1035
  type: "start",
857
- // @ts-ignore
858
1036
  payload: { runId: this.runId }
859
1037
  });
860
1038
  const unwatch = this.watch(async (event) => {
@@ -874,7 +1052,7 @@ var InngestRun = class extends workflows.Run {
874
1052
  this.closeStreamAction = async () => {
875
1053
  await writer.write({
876
1054
  type: "finish",
877
- // @ts-ignore
1055
+ // @ts-expect-error - stream event type mismatch
878
1056
  payload: { runId: this.runId }
879
1057
  });
880
1058
  unwatch();
@@ -904,7 +1082,8 @@ var InngestRun = class extends workflows.Run {
904
1082
  tracingOptions,
905
1083
  closeOnSuspend = true,
906
1084
  initialState,
907
- outputOptions
1085
+ outputOptions,
1086
+ perStep
908
1087
  } = {}) {
909
1088
  if (this.closeStreamAction && this.streamOutput) {
910
1089
  return this.streamOutput;
@@ -940,7 +1119,8 @@ var InngestRun = class extends workflows.Run {
940
1119
  initialState,
941
1120
  tracingOptions,
942
1121
  outputOptions,
943
- format: "vnext"
1122
+ format: "vnext",
1123
+ perStep
944
1124
  });
945
1125
  let executionResults;
946
1126
  try {
@@ -971,9 +1151,6 @@ var InngestRun = class extends workflows.Run {
971
1151
  });
972
1152
  return this.streamOutput;
973
1153
  }
974
- streamVNext(args = {}) {
975
- return this.stream(args);
976
- }
977
1154
  timeTravelStream({
978
1155
  inputData,
979
1156
  resumeData,
@@ -982,8 +1159,10 @@ var InngestRun = class extends workflows.Run {
982
1159
  context,
983
1160
  nestedStepsContext,
984
1161
  requestContext,
1162
+ // tracingContext,
985
1163
  tracingOptions,
986
- outputOptions
1164
+ outputOptions,
1165
+ perStep
987
1166
  }) {
988
1167
  this.closeStreamAction = async () => {
989
1168
  };
@@ -1018,7 +1197,8 @@ var InngestRun = class extends workflows.Run {
1018
1197
  initialState,
1019
1198
  requestContext,
1020
1199
  tracingOptions,
1021
- outputOptions
1200
+ outputOptions,
1201
+ perStep
1022
1202
  });
1023
1203
  self.executionResults = executionResultsPromise;
1024
1204
  let executionResults;
@@ -1062,9 +1242,11 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1062
1242
  #mastra;
1063
1243
  inngest;
1064
1244
  function;
1245
+ cronFunction;
1065
1246
  flowControlConfig;
1247
+ cronConfig;
1066
1248
  constructor(params, inngest) {
1067
- const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
1249
+ const { concurrency, rateLimit, throttle, debounce, priority, cron, inputData, initialState, ...workflowParams } = params;
1068
1250
  super(workflowParams);
1069
1251
  this.engineType = "inngest";
1070
1252
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
@@ -1073,6 +1255,9 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1073
1255
  this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
1074
1256
  this.#mastra = params.mastra;
1075
1257
  this.inngest = inngest;
1258
+ if (cron) {
1259
+ this.cronConfig = { cron, inputData, initialState };
1260
+ }
1076
1261
  }
1077
1262
  async listWorkflowRuns(args) {
1078
1263
  const storage = this.#mastra?.getStorage();
@@ -1080,16 +1265,11 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1080
1265
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
1081
1266
  return { runs: [], total: 0 };
1082
1267
  }
1083
- return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
1084
- }
1085
- async getWorkflowRunById(runId) {
1086
- const storage = this.#mastra?.getStorage();
1087
- if (!storage) {
1088
- this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
1089
- return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
1268
+ const workflowsStore = await storage.getStore("workflows");
1269
+ if (!workflowsStore) {
1270
+ return { runs: [], total: 0 };
1090
1271
  }
1091
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
1092
- return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
1272
+ return workflowsStore.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
1093
1273
  }
1094
1274
  __registerMastra(mastra) {
1095
1275
  super.__registerMastra(mastra);
@@ -1112,7 +1292,8 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1112
1292
  }
1113
1293
  async createRun(options) {
1114
1294
  const runIdToUse = options?.runId || crypto$1.randomUUID();
1115
- const run = this.runs.get(runIdToUse) ?? new InngestRun(
1295
+ const existingInMemoryRun = this.runs.get(runIdToUse);
1296
+ const newRun = new InngestRun(
1116
1297
  {
1117
1298
  workflowId: this.id,
1118
1299
  runId: runIdToUse,
@@ -1129,14 +1310,19 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1129
1310
  },
1130
1311
  this.inngest
1131
1312
  );
1313
+ const run = existingInMemoryRun ?? newRun;
1132
1314
  this.runs.set(runIdToUse, run);
1133
1315
  const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
1134
1316
  workflowStatus: run.workflowRunStatus,
1135
1317
  stepResults: {}
1136
1318
  });
1137
- const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
1138
- if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
1139
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1319
+ const existingStoredRun = await this.getWorkflowRunById(runIdToUse, {
1320
+ withNestedWorkflows: false
1321
+ });
1322
+ const existsInStorage = existingStoredRun && !existingStoredRun.isFromInMemory;
1323
+ if (!existsInStorage && shouldPersistSnapshot) {
1324
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
1325
+ await workflowsStore?.persistWorkflowSnapshot({
1140
1326
  workflowName: this.id,
1141
1327
  runId: runIdToUse,
1142
1328
  resourceId: options?.resourceId,
@@ -1159,6 +1345,30 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1159
1345
  }
1160
1346
  return run;
1161
1347
  }
1348
+ //createCronFunction is only called if cronConfig.cron is defined.
1349
+ createCronFunction() {
1350
+ if (this.cronFunction) {
1351
+ return this.cronFunction;
1352
+ }
1353
+ this.cronFunction = this.inngest.createFunction(
1354
+ {
1355
+ id: `workflow.${this.id}.cron`,
1356
+ retries: 0,
1357
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1358
+ ...this.flowControlConfig
1359
+ },
1360
+ { cron: this.cronConfig?.cron ?? "" },
1361
+ async () => {
1362
+ const run = await this.createRun();
1363
+ const result = await run.start({
1364
+ inputData: this.cronConfig?.inputData,
1365
+ initialState: this.cronConfig?.initialState
1366
+ });
1367
+ return { result, runId: run.runId };
1368
+ }
1369
+ );
1370
+ return this.cronFunction;
1371
+ }
1162
1372
  getFunction() {
1163
1373
  if (this.function) {
1164
1374
  return this.function;
@@ -1166,51 +1376,128 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1166
1376
  this.function = this.inngest.createFunction(
1167
1377
  {
1168
1378
  id: `workflow.${this.id}`,
1169
- retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
1379
+ retries: 0,
1170
1380
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1171
1381
  // Spread flow control configuration
1172
1382
  ...this.flowControlConfig
1173
1383
  },
1174
1384
  { event: `workflow.${this.id}` },
1175
1385
  async ({ event, step, attempt, publish }) => {
1176
- let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
1386
+ let {
1387
+ inputData,
1388
+ initialState,
1389
+ runId,
1390
+ resourceId,
1391
+ resume,
1392
+ outputOptions,
1393
+ format,
1394
+ timeTravel,
1395
+ perStep,
1396
+ tracingOptions
1397
+ } = event.data;
1177
1398
  if (!runId) {
1178
1399
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
1179
1400
  return crypto$1.randomUUID();
1180
1401
  });
1181
1402
  }
1182
1403
  const pubsub = new InngestPubSub(this.inngest, this.id, publish);
1404
+ const requestContext = new di.RequestContext(Object.entries(event.data.requestContext ?? {}));
1405
+ const mastra = this.#mastra;
1406
+ const tracingPolicy = this.options.tracingPolicy;
1407
+ const workflowSpanData = await step.run(`workflow.${this.id}.span.start`, async () => {
1408
+ const observability$1 = mastra?.observability?.getSelectedInstance({ requestContext });
1409
+ if (!observability$1) return void 0;
1410
+ const span = observability$1.startSpan({
1411
+ type: observability.SpanType.WORKFLOW_RUN,
1412
+ name: `workflow run: '${this.id}'`,
1413
+ entityType: observability.EntityType.WORKFLOW_RUN,
1414
+ entityId: this.id,
1415
+ input: inputData,
1416
+ metadata: {
1417
+ resourceId,
1418
+ runId
1419
+ },
1420
+ tracingPolicy,
1421
+ tracingOptions,
1422
+ requestContext
1423
+ });
1424
+ return span?.exportSpan();
1425
+ });
1183
1426
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
1184
- const result = await engine.execute({
1185
- workflowId: this.id,
1186
- runId,
1187
- resourceId,
1188
- graph: this.executionGraph,
1189
- serializedStepGraph: this.serializedStepGraph,
1190
- input: inputData,
1191
- initialState,
1192
- pubsub,
1193
- retryConfig: this.retryConfig,
1194
- requestContext: new di.RequestContext(Object.entries(event.data.requestContext ?? {})),
1195
- resume,
1196
- timeTravel,
1197
- format,
1198
- abortController: new AbortController(),
1199
- // currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
1200
- outputOptions,
1201
- outputWriter: async (chunk) => {
1202
- try {
1203
- await pubsub.publish(`workflow.events.v2.${runId}`, {
1204
- type: "watch",
1205
- runId,
1206
- data: chunk
1207
- });
1208
- } catch (err) {
1209
- this.logger.debug?.("Failed to publish watch event:", err);
1427
+ let result;
1428
+ try {
1429
+ result = await engine.execute({
1430
+ workflowId: this.id,
1431
+ runId,
1432
+ resourceId,
1433
+ graph: this.executionGraph,
1434
+ serializedStepGraph: this.serializedStepGraph,
1435
+ input: inputData,
1436
+ initialState,
1437
+ pubsub,
1438
+ retryConfig: this.retryConfig,
1439
+ requestContext,
1440
+ resume,
1441
+ timeTravel,
1442
+ perStep,
1443
+ format,
1444
+ abortController: new AbortController(),
1445
+ // For Inngest, we don't pass workflowSpan - step spans use tracingIds instead
1446
+ workflowSpan: void 0,
1447
+ // Pass tracing IDs for durable span operations
1448
+ tracingIds: workflowSpanData ? {
1449
+ traceId: workflowSpanData.traceId,
1450
+ workflowSpanId: workflowSpanData.id
1451
+ } : void 0,
1452
+ outputOptions,
1453
+ outputWriter: async (chunk) => {
1454
+ try {
1455
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1456
+ type: "watch",
1457
+ runId,
1458
+ data: chunk
1459
+ });
1460
+ } catch (err) {
1461
+ this.logger.debug?.("Failed to publish watch event:", err);
1462
+ }
1210
1463
  }
1211
- }
1212
- });
1464
+ });
1465
+ } catch (error) {
1466
+ throw error;
1467
+ }
1213
1468
  await step.run(`workflow.${this.id}.finalize`, async () => {
1469
+ if (result.status !== "paused") {
1470
+ await engine.invokeLifecycleCallbacksInternal({
1471
+ status: result.status,
1472
+ result: "result" in result ? result.result : void 0,
1473
+ error: "error" in result ? result.error : void 0,
1474
+ steps: result.steps,
1475
+ tripwire: "tripwire" in result ? result.tripwire : void 0,
1476
+ runId,
1477
+ workflowId: this.id,
1478
+ resourceId,
1479
+ input: inputData,
1480
+ requestContext,
1481
+ state: result.state ?? initialState ?? {}
1482
+ });
1483
+ }
1484
+ if (workflowSpanData) {
1485
+ const observability = mastra?.observability?.getSelectedInstance({ requestContext });
1486
+ if (observability) {
1487
+ const workflowSpan = observability.rebuildSpan(workflowSpanData);
1488
+ if (result.status === "failed") {
1489
+ workflowSpan.error({
1490
+ error: result.error instanceof Error ? result.error : new Error(String(result.error)),
1491
+ attributes: { status: "failed" }
1492
+ });
1493
+ } else {
1494
+ workflowSpan.end({
1495
+ output: result.status === "success" ? result.result : void 0,
1496
+ attributes: { status: result.status }
1497
+ });
1498
+ }
1499
+ }
1500
+ }
1214
1501
  if (result.status === "failed") {
1215
1502
  throw new inngest.NonRetriableError(`Workflow failed`, {
1216
1503
  cause: result
@@ -1237,15 +1524,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1237
1524
  });
1238
1525
  }
1239
1526
  getFunctions() {
1240
- return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
1527
+ return [
1528
+ this.getFunction(),
1529
+ ...this.cronConfig?.cron ? [this.createCronFunction()] : [],
1530
+ ...this.getNestedFunctions(this.executionGraph.steps)
1531
+ ];
1241
1532
  }
1242
1533
  };
1243
- function serve({
1244
- mastra,
1245
- inngest,
1246
- functions: userFunctions = [],
1247
- registerOptions
1248
- }) {
1534
+ function prepareServeOptions({ mastra, inngest, functions: userFunctions = [], registerOptions }) {
1249
1535
  const wfs = mastra.listWorkflows();
1250
1536
  const workflowFunctions = Array.from(
1251
1537
  new Set(
@@ -1258,177 +1544,181 @@ function serve({
1258
1544
  })
1259
1545
  )
1260
1546
  );
1261
- return hono.serve({
1547
+ return {
1262
1548
  ...registerOptions,
1263
1549
  client: inngest,
1264
1550
  functions: [...workflowFunctions, ...userFunctions]
1265
- });
1551
+ };
1266
1552
  }
1553
+ function createServe(adapter) {
1554
+ return (options) => {
1555
+ const serveOptions = prepareServeOptions(options);
1556
+ return adapter(serveOptions);
1557
+ };
1558
+ }
1559
+ var serve = createServe(hono.serve);
1267
1560
 
1268
1561
  // src/types.ts
1269
1562
  var _compatibilityCheck = true;
1270
1563
 
1271
1564
  // src/index.ts
1272
- function isAgent(params) {
1273
- return params?.component === "AGENT";
1565
+ function isInngestWorkflow(input) {
1566
+ return input instanceof InngestWorkflow;
1567
+ }
1568
+ function isAgent(input) {
1569
+ return input instanceof agent.Agent;
1274
1570
  }
1275
- function isTool(params) {
1276
- return params instanceof tools.Tool;
1571
+ function isToolStep(input) {
1572
+ return input instanceof tools.Tool;
1277
1573
  }
1278
- function isInngestWorkflow(params) {
1279
- return params instanceof InngestWorkflow;
1574
+ function isStepParams(input) {
1575
+ return input !== null && typeof input === "object" && "id" in input && "execute" in input && !(input instanceof agent.Agent) && !(input instanceof tools.Tool) && !(input instanceof InngestWorkflow);
1280
1576
  }
1281
- function createStep(params, agentOptions) {
1577
+ function isProcessor(obj) {
1578
+ return obj !== null && typeof obj === "object" && "id" in obj && typeof obj.id === "string" && !(obj instanceof agent.Agent) && !(obj instanceof tools.Tool) && !(obj instanceof InngestWorkflow) && (typeof obj.processInput === "function" || typeof obj.processInputStep === "function" || typeof obj.processOutputStream === "function" || typeof obj.processOutputResult === "function" || typeof obj.processOutputStep === "function");
1579
+ }
1580
+ function createStep(params, agentOrToolOptions) {
1282
1581
  if (isInngestWorkflow(params)) {
1283
1582
  return params;
1284
1583
  }
1285
1584
  if (isAgent(params)) {
1286
- const outputSchema = agentOptions?.structuredOutput?.schema ?? zod.z.object({ text: zod.z.string() });
1287
- return {
1288
- id: params.name,
1289
- description: params.getDescription(),
1290
- inputSchema: zod.z.object({
1291
- prompt: zod.z.string()
1292
- // resourceId: z.string().optional(),
1293
- // threadId: z.string().optional(),
1294
- }),
1295
- outputSchema,
1296
- execute: async ({
1297
- inputData,
1298
- runId,
1299
- [_constants.PUBSUB_SYMBOL]: pubsub,
1300
- [_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
1301
- requestContext,
1302
- tracingContext,
1303
- abortSignal,
1304
- abort,
1305
- writer
1306
- }) => {
1307
- let streamPromise = {};
1308
- streamPromise.promise = new Promise((resolve, reject) => {
1309
- streamPromise.resolve = resolve;
1310
- streamPromise.reject = reject;
1585
+ return createStepFromAgent(params, agentOrToolOptions);
1586
+ }
1587
+ if (isToolStep(params)) {
1588
+ return createStepFromTool(params, agentOrToolOptions);
1589
+ }
1590
+ if (isStepParams(params)) {
1591
+ return createStepFromParams(params);
1592
+ }
1593
+ if (isProcessor(params)) {
1594
+ return createStepFromProcessor(params);
1595
+ }
1596
+ throw new Error("Invalid input: expected StepParams, Agent, ToolStep, Processor, or InngestWorkflow");
1597
+ }
1598
+ function createStepFromParams(params) {
1599
+ return {
1600
+ id: params.id,
1601
+ description: params.description,
1602
+ inputSchema: params.inputSchema,
1603
+ stateSchema: params.stateSchema,
1604
+ outputSchema: params.outputSchema,
1605
+ resumeSchema: params.resumeSchema,
1606
+ suspendSchema: params.suspendSchema,
1607
+ scorers: params.scorers,
1608
+ retries: params.retries,
1609
+ execute: params.execute.bind(params)
1610
+ };
1611
+ }
1612
+ function createStepFromAgent(params, agentOrToolOptions) {
1613
+ const options = agentOrToolOptions ?? {};
1614
+ const outputSchema = options?.structuredOutput?.schema ?? zod.z.object({ text: zod.z.string() });
1615
+ const { retries, scorers, ...agentOptions } = options ?? {};
1616
+ return {
1617
+ id: params.name,
1618
+ description: params.getDescription(),
1619
+ inputSchema: zod.z.object({
1620
+ prompt: zod.z.string()
1621
+ }),
1622
+ outputSchema,
1623
+ retries,
1624
+ scorers,
1625
+ execute: async ({
1626
+ inputData,
1627
+ runId,
1628
+ [_constants.PUBSUB_SYMBOL]: pubsub,
1629
+ [_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
1630
+ requestContext,
1631
+ tracingContext,
1632
+ abortSignal,
1633
+ abort,
1634
+ writer
1635
+ }) => {
1636
+ let streamPromise = {};
1637
+ streamPromise.promise = new Promise((resolve, reject) => {
1638
+ streamPromise.resolve = resolve;
1639
+ streamPromise.reject = reject;
1640
+ });
1641
+ let structuredResult = null;
1642
+ const toolData = {
1643
+ name: params.name,
1644
+ args: inputData
1645
+ };
1646
+ let stream;
1647
+ if ((await params.getModel()).specificationVersion === "v1") {
1648
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
1649
+ ...agentOptions ?? {},
1650
+ requestContext,
1651
+ tracingContext,
1652
+ onFinish: (result) => {
1653
+ const resultWithObject = result;
1654
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1655
+ structuredResult = resultWithObject.object;
1656
+ }
1657
+ streamPromise.resolve(result.text);
1658
+ void agentOptions?.onFinish?.(result);
1659
+ },
1660
+ abortSignal
1311
1661
  });
1312
- let structuredResult = null;
1313
- const toolData = {
1314
- name: params.name,
1315
- args: inputData
1316
- };
1317
- let stream;
1318
- if ((await params.getModel()).specificationVersion === "v1") {
1319
- const { fullStream } = await params.streamLegacy(inputData.prompt, {
1320
- ...agentOptions ?? {},
1321
- // resourceId: inputData.resourceId,
1322
- // threadId: inputData.threadId,
1323
- requestContext,
1324
- tracingContext,
1325
- onFinish: (result) => {
1326
- const resultWithObject = result;
1327
- if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1328
- structuredResult = resultWithObject.object;
1329
- }
1330
- streamPromise.resolve(result.text);
1331
- void agentOptions?.onFinish?.(result);
1332
- },
1333
- abortSignal
1334
- });
1335
- stream = fullStream;
1336
- } else {
1337
- const modelOutput = await params.stream(inputData.prompt, {
1338
- ...agentOptions ?? {},
1339
- requestContext,
1340
- tracingContext,
1341
- onFinish: (result) => {
1342
- const resultWithObject = result;
1343
- if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1344
- structuredResult = resultWithObject.object;
1345
- }
1346
- streamPromise.resolve(result.text);
1347
- void agentOptions?.onFinish?.(result);
1348
- },
1349
- abortSignal
1350
- });
1351
- stream = modelOutput.fullStream;
1352
- }
1353
- if (streamFormat === "legacy") {
1354
- await pubsub.publish(`workflow.events.v2.${runId}`, {
1355
- type: "watch",
1356
- runId,
1357
- data: { type: "tool-call-streaming-start", ...toolData ?? {} }
1358
- });
1359
- for await (const chunk of stream) {
1360
- if (chunk.type === "text-delta") {
1361
- await pubsub.publish(`workflow.events.v2.${runId}`, {
1362
- type: "watch",
1363
- runId,
1364
- data: { type: "tool-call-delta", ...toolData ?? {}, argsTextDelta: chunk.textDelta }
1365
- });
1662
+ stream = fullStream;
1663
+ } else {
1664
+ const modelOutput = await params.stream(inputData.prompt, {
1665
+ ...agentOptions ?? {},
1666
+ requestContext,
1667
+ tracingContext,
1668
+ onFinish: (result) => {
1669
+ const resultWithObject = result;
1670
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1671
+ structuredResult = resultWithObject.object;
1366
1672
  }
1673
+ streamPromise.resolve(result.text);
1674
+ void agentOptions?.onFinish?.(result);
1675
+ },
1676
+ abortSignal
1677
+ });
1678
+ stream = modelOutput.fullStream;
1679
+ }
1680
+ if (streamFormat === "legacy") {
1681
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1682
+ type: "watch",
1683
+ runId,
1684
+ data: { type: "tool-call-streaming-start", ...toolData ?? {} }
1685
+ });
1686
+ for await (const chunk of stream) {
1687
+ if (chunk.type === "text-delta") {
1688
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1689
+ type: "watch",
1690
+ runId,
1691
+ data: { type: "tool-call-delta", ...toolData ?? {}, argsTextDelta: chunk.textDelta }
1692
+ });
1367
1693
  }
1368
- await pubsub.publish(`workflow.events.v2.${runId}`, {
1369
- type: "watch",
1370
- runId,
1371
- data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
1372
- });
1373
- } else {
1374
- for await (const chunk of stream) {
1375
- await writer.write(chunk);
1376
- }
1377
- }
1378
- if (abortSignal.aborted) {
1379
- return abort();
1380
1694
  }
1381
- if (structuredResult !== null) {
1382
- return structuredResult;
1695
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1696
+ type: "watch",
1697
+ runId,
1698
+ data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
1699
+ });
1700
+ } else {
1701
+ for await (const chunk of stream) {
1702
+ await writer.write(chunk);
1383
1703
  }
1384
- return {
1385
- text: await streamPromise.promise
1386
- };
1387
- },
1388
- component: params.component
1389
- };
1390
- }
1391
- if (isTool(params)) {
1392
- if (!params.inputSchema || !params.outputSchema) {
1393
- throw new Error("Tool must have input and output schemas defined");
1394
- }
1395
- return {
1396
- // TODO: tool probably should have strong id type
1397
- id: params.id,
1398
- description: params.description,
1399
- inputSchema: params.inputSchema,
1400
- outputSchema: params.outputSchema,
1401
- suspendSchema: params.suspendSchema,
1402
- resumeSchema: params.resumeSchema,
1403
- execute: async ({
1404
- inputData,
1405
- mastra,
1406
- requestContext,
1407
- tracingContext,
1408
- suspend,
1409
- resumeData,
1410
- runId,
1411
- workflowId,
1412
- state,
1413
- setState
1414
- }) => {
1415
- const toolContext = {
1416
- mastra,
1417
- requestContext,
1418
- tracingContext,
1419
- workflow: {
1420
- runId,
1421
- resumeData,
1422
- suspend,
1423
- workflowId,
1424
- state,
1425
- setState
1426
- }
1427
- };
1428
- return params.execute(inputData, toolContext);
1429
- },
1430
- component: "TOOL"
1431
- };
1704
+ }
1705
+ if (abortSignal.aborted) {
1706
+ return abort();
1707
+ }
1708
+ if (structuredResult !== null) {
1709
+ return structuredResult;
1710
+ }
1711
+ return {
1712
+ text: await streamPromise.promise
1713
+ };
1714
+ },
1715
+ component: params.component
1716
+ };
1717
+ }
1718
+ function createStepFromTool(params, agentOrToolOptions) {
1719
+ const toolOpts = agentOrToolOptions;
1720
+ if (!params.inputSchema || !params.outputSchema) {
1721
+ throw new Error("Tool must have input and output schemas defined");
1432
1722
  }
1433
1723
  return {
1434
1724
  id: params.id,
@@ -1437,7 +1727,480 @@ function createStep(params, agentOptions) {
1437
1727
  outputSchema: params.outputSchema,
1438
1728
  resumeSchema: params.resumeSchema,
1439
1729
  suspendSchema: params.suspendSchema,
1440
- execute: params.execute
1730
+ retries: toolOpts?.retries,
1731
+ scorers: toolOpts?.scorers,
1732
+ execute: async ({
1733
+ inputData,
1734
+ mastra,
1735
+ requestContext,
1736
+ tracingContext,
1737
+ suspend,
1738
+ resumeData,
1739
+ runId,
1740
+ workflowId,
1741
+ state,
1742
+ setState
1743
+ }) => {
1744
+ const toolContext = {
1745
+ mastra,
1746
+ requestContext,
1747
+ tracingContext,
1748
+ workflow: {
1749
+ runId,
1750
+ resumeData,
1751
+ suspend,
1752
+ workflowId,
1753
+ state,
1754
+ setState
1755
+ }
1756
+ };
1757
+ return params.execute(inputData, toolContext);
1758
+ },
1759
+ component: "TOOL"
1760
+ };
1761
+ }
1762
+ function createStepFromProcessor(processor) {
1763
+ const getProcessorEntityType = (phase) => {
1764
+ switch (phase) {
1765
+ case "input":
1766
+ return observability.EntityType.INPUT_PROCESSOR;
1767
+ case "inputStep":
1768
+ return observability.EntityType.INPUT_STEP_PROCESSOR;
1769
+ case "outputStream":
1770
+ case "outputResult":
1771
+ return observability.EntityType.OUTPUT_PROCESSOR;
1772
+ case "outputStep":
1773
+ return observability.EntityType.OUTPUT_STEP_PROCESSOR;
1774
+ default:
1775
+ return observability.EntityType.OUTPUT_PROCESSOR;
1776
+ }
1777
+ };
1778
+ const getSpanNamePrefix = (phase) => {
1779
+ switch (phase) {
1780
+ case "input":
1781
+ return "input processor";
1782
+ case "inputStep":
1783
+ return "input step processor";
1784
+ case "outputStream":
1785
+ return "output stream processor";
1786
+ case "outputResult":
1787
+ return "output processor";
1788
+ case "outputStep":
1789
+ return "output step processor";
1790
+ default:
1791
+ return "processor";
1792
+ }
1793
+ };
1794
+ const hasPhaseMethod = (phase) => {
1795
+ switch (phase) {
1796
+ case "input":
1797
+ return !!processor.processInput;
1798
+ case "inputStep":
1799
+ return !!processor.processInputStep;
1800
+ case "outputStream":
1801
+ return !!processor.processOutputStream;
1802
+ case "outputResult":
1803
+ return !!processor.processOutputResult;
1804
+ case "outputStep":
1805
+ return !!processor.processOutputStep;
1806
+ default:
1807
+ return false;
1808
+ }
1809
+ };
1810
+ return {
1811
+ id: `processor:${processor.id}`,
1812
+ description: processor.name ?? `Processor ${processor.id}`,
1813
+ inputSchema: processors.ProcessorStepSchema,
1814
+ outputSchema: processors.ProcessorStepOutputSchema,
1815
+ execute: async ({ inputData, requestContext, tracingContext }) => {
1816
+ const input = inputData;
1817
+ const {
1818
+ phase,
1819
+ messages,
1820
+ messageList,
1821
+ stepNumber,
1822
+ systemMessages,
1823
+ part,
1824
+ streamParts,
1825
+ state,
1826
+ finishReason,
1827
+ toolCalls,
1828
+ text,
1829
+ retryCount,
1830
+ // inputStep phase fields for model/tools configuration
1831
+ model,
1832
+ tools,
1833
+ toolChoice,
1834
+ activeTools,
1835
+ providerOptions,
1836
+ modelSettings,
1837
+ structuredOutput,
1838
+ steps
1839
+ } = input;
1840
+ const abort = (reason, options) => {
1841
+ throw new agent.TripWire(reason || `Tripwire triggered by ${processor.id}`, options, processor.id);
1842
+ };
1843
+ if (!hasPhaseMethod(phase)) {
1844
+ return input;
1845
+ }
1846
+ const currentSpan = tracingContext?.currentSpan;
1847
+ const parentSpan = phase === "inputStep" || phase === "outputStep" ? currentSpan?.findParent(observability.SpanType.MODEL_STEP) || currentSpan : currentSpan?.findParent(observability.SpanType.AGENT_RUN) || currentSpan;
1848
+ const processorSpan = phase !== "outputStream" ? parentSpan?.createChildSpan({
1849
+ type: observability.SpanType.PROCESSOR_RUN,
1850
+ name: `${getSpanNamePrefix(phase)}: ${processor.id}`,
1851
+ entityType: getProcessorEntityType(phase),
1852
+ entityId: processor.id,
1853
+ entityName: processor.name ?? processor.id,
1854
+ input: { phase, messageCount: messages?.length },
1855
+ attributes: {
1856
+ processorExecutor: "workflow",
1857
+ // Read processorIndex from processor (set in combineProcessorsIntoWorkflow)
1858
+ processorIndex: processor.processorIndex
1859
+ }
1860
+ }) : void 0;
1861
+ const processorTracingContext = processorSpan ? { currentSpan: processorSpan } : tracingContext;
1862
+ const baseContext = {
1863
+ abort,
1864
+ retryCount: retryCount ?? 0,
1865
+ requestContext,
1866
+ tracingContext: processorTracingContext
1867
+ };
1868
+ const passThrough = {
1869
+ phase,
1870
+ // Auto-create MessageList from messages if not provided
1871
+ // This enables running processor workflows from the UI where messageList can't be serialized
1872
+ messageList: messageList ?? (Array.isArray(messages) ? new agent.MessageList().add(messages, "input").addSystem(systemMessages ?? []) : void 0),
1873
+ stepNumber,
1874
+ systemMessages,
1875
+ streamParts,
1876
+ state,
1877
+ finishReason,
1878
+ toolCalls,
1879
+ text,
1880
+ retryCount,
1881
+ // inputStep phase fields for model/tools configuration
1882
+ model,
1883
+ tools,
1884
+ toolChoice,
1885
+ activeTools,
1886
+ providerOptions,
1887
+ modelSettings,
1888
+ structuredOutput,
1889
+ steps
1890
+ };
1891
+ const executePhaseWithSpan = async (fn) => {
1892
+ try {
1893
+ const result = await fn();
1894
+ processorSpan?.end({ output: result });
1895
+ return result;
1896
+ } catch (error) {
1897
+ if (error instanceof agent.TripWire) {
1898
+ processorSpan?.end({ output: { tripwire: error.message } });
1899
+ } else {
1900
+ processorSpan?.error({ error, endSpan: true });
1901
+ }
1902
+ throw error;
1903
+ }
1904
+ };
1905
+ return executePhaseWithSpan(async () => {
1906
+ switch (phase) {
1907
+ case "input": {
1908
+ if (processor.processInput) {
1909
+ if (!passThrough.messageList) {
1910
+ throw new error.MastraError({
1911
+ category: error.ErrorCategory.USER,
1912
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
1913
+ id: "PROCESSOR_MISSING_MESSAGE_LIST",
1914
+ text: `Processor ${processor.id} requires messageList or messages for processInput phase`
1915
+ });
1916
+ }
1917
+ const idsBeforeProcessing = messages.map((m) => m.id);
1918
+ const check = passThrough.messageList.makeMessageSourceChecker();
1919
+ const result = await processor.processInput({
1920
+ ...baseContext,
1921
+ messages,
1922
+ messageList: passThrough.messageList,
1923
+ systemMessages: systemMessages ?? []
1924
+ });
1925
+ if (result instanceof agent.MessageList) {
1926
+ if (result !== passThrough.messageList) {
1927
+ throw new error.MastraError({
1928
+ category: error.ErrorCategory.USER,
1929
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
1930
+ id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST",
1931
+ text: `Processor ${processor.id} returned a MessageList instance other than the one passed in. Use the messageList argument instead.`
1932
+ });
1933
+ }
1934
+ return {
1935
+ ...passThrough,
1936
+ messages: result.get.all.db(),
1937
+ systemMessages: result.getAllSystemMessages()
1938
+ };
1939
+ } else if (Array.isArray(result)) {
1940
+ processors.ProcessorRunner.applyMessagesToMessageList(
1941
+ result,
1942
+ passThrough.messageList,
1943
+ idsBeforeProcessing,
1944
+ check,
1945
+ "input"
1946
+ );
1947
+ return { ...passThrough, messages: result };
1948
+ } else if (result && "messages" in result && "systemMessages" in result) {
1949
+ const typedResult = result;
1950
+ processors.ProcessorRunner.applyMessagesToMessageList(
1951
+ typedResult.messages,
1952
+ passThrough.messageList,
1953
+ idsBeforeProcessing,
1954
+ check,
1955
+ "input"
1956
+ );
1957
+ passThrough.messageList.replaceAllSystemMessages(typedResult.systemMessages);
1958
+ return {
1959
+ ...passThrough,
1960
+ messages: typedResult.messages,
1961
+ systemMessages: typedResult.systemMessages
1962
+ };
1963
+ }
1964
+ return { ...passThrough, messages };
1965
+ }
1966
+ return { ...passThrough, messages };
1967
+ }
1968
+ case "inputStep": {
1969
+ if (processor.processInputStep) {
1970
+ if (!passThrough.messageList) {
1971
+ throw new error.MastraError({
1972
+ category: error.ErrorCategory.USER,
1973
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
1974
+ id: "PROCESSOR_MISSING_MESSAGE_LIST",
1975
+ text: `Processor ${processor.id} requires messageList or messages for processInputStep phase`
1976
+ });
1977
+ }
1978
+ const idsBeforeProcessing = messages.map((m) => m.id);
1979
+ const check = passThrough.messageList.makeMessageSourceChecker();
1980
+ const result = await processor.processInputStep({
1981
+ ...baseContext,
1982
+ messages,
1983
+ messageList: passThrough.messageList,
1984
+ stepNumber: stepNumber ?? 0,
1985
+ systemMessages: systemMessages ?? [],
1986
+ // Pass model/tools configuration fields - types match ProcessInputStepArgs
1987
+ model,
1988
+ tools,
1989
+ toolChoice,
1990
+ activeTools,
1991
+ providerOptions,
1992
+ modelSettings,
1993
+ structuredOutput,
1994
+ steps: steps ?? []
1995
+ });
1996
+ const validatedResult = await processors.ProcessorRunner.validateAndFormatProcessInputStepResult(result, {
1997
+ messageList: passThrough.messageList,
1998
+ processor,
1999
+ stepNumber: stepNumber ?? 0
2000
+ });
2001
+ if (validatedResult.messages) {
2002
+ processors.ProcessorRunner.applyMessagesToMessageList(
2003
+ validatedResult.messages,
2004
+ passThrough.messageList,
2005
+ idsBeforeProcessing,
2006
+ check
2007
+ );
2008
+ }
2009
+ if (validatedResult.systemMessages) {
2010
+ passThrough.messageList.replaceAllSystemMessages(validatedResult.systemMessages);
2011
+ }
2012
+ return { ...passThrough, messages, ...validatedResult };
2013
+ }
2014
+ return { ...passThrough, messages };
2015
+ }
2016
+ case "outputStream": {
2017
+ if (processor.processOutputStream) {
2018
+ const spanKey = `__outputStreamSpan_${processor.id}`;
2019
+ const mutableState = state ?? {};
2020
+ let processorSpan2 = mutableState[spanKey];
2021
+ if (!processorSpan2 && parentSpan) {
2022
+ processorSpan2 = parentSpan.createChildSpan({
2023
+ type: observability.SpanType.PROCESSOR_RUN,
2024
+ name: `output stream processor: ${processor.id}`,
2025
+ entityType: observability.EntityType.OUTPUT_PROCESSOR,
2026
+ entityId: processor.id,
2027
+ entityName: processor.name ?? processor.id,
2028
+ input: { phase, streamParts: [] },
2029
+ attributes: {
2030
+ processorExecutor: "workflow",
2031
+ processorIndex: processor.processorIndex
2032
+ }
2033
+ });
2034
+ mutableState[spanKey] = processorSpan2;
2035
+ }
2036
+ if (processorSpan2) {
2037
+ processorSpan2.input = {
2038
+ phase,
2039
+ streamParts: streamParts ?? [],
2040
+ totalChunks: (streamParts ?? []).length
2041
+ };
2042
+ }
2043
+ const processorTracingContext2 = processorSpan2 ? { currentSpan: processorSpan2 } : baseContext.tracingContext;
2044
+ let result;
2045
+ try {
2046
+ result = await processor.processOutputStream({
2047
+ ...baseContext,
2048
+ tracingContext: processorTracingContext2,
2049
+ part,
2050
+ streamParts: streamParts ?? [],
2051
+ state: mutableState,
2052
+ messageList: passThrough.messageList
2053
+ // Optional for stream processing
2054
+ });
2055
+ if (part && part.type === "finish") {
2056
+ processorSpan2?.end({ output: result });
2057
+ delete mutableState[spanKey];
2058
+ }
2059
+ } catch (error) {
2060
+ if (error instanceof agent.TripWire) {
2061
+ processorSpan2?.end({ output: { tripwire: error.message } });
2062
+ } else {
2063
+ processorSpan2?.error({ error, endSpan: true });
2064
+ }
2065
+ delete mutableState[spanKey];
2066
+ throw error;
2067
+ }
2068
+ return { ...passThrough, state: mutableState, part: result };
2069
+ }
2070
+ return { ...passThrough, part };
2071
+ }
2072
+ case "outputResult": {
2073
+ if (processor.processOutputResult) {
2074
+ if (!passThrough.messageList) {
2075
+ throw new error.MastraError({
2076
+ category: error.ErrorCategory.USER,
2077
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
2078
+ id: "PROCESSOR_MISSING_MESSAGE_LIST",
2079
+ text: `Processor ${processor.id} requires messageList or messages for processOutputResult phase`
2080
+ });
2081
+ }
2082
+ const idsBeforeProcessing = messages.map((m) => m.id);
2083
+ const check = passThrough.messageList.makeMessageSourceChecker();
2084
+ const result = await processor.processOutputResult({
2085
+ ...baseContext,
2086
+ messages,
2087
+ messageList: passThrough.messageList
2088
+ });
2089
+ if (result instanceof agent.MessageList) {
2090
+ if (result !== passThrough.messageList) {
2091
+ throw new error.MastraError({
2092
+ category: error.ErrorCategory.USER,
2093
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
2094
+ id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST",
2095
+ text: `Processor ${processor.id} returned a MessageList instance other than the one passed in. Use the messageList argument instead.`
2096
+ });
2097
+ }
2098
+ return {
2099
+ ...passThrough,
2100
+ messages: result.get.all.db(),
2101
+ systemMessages: result.getAllSystemMessages()
2102
+ };
2103
+ } else if (Array.isArray(result)) {
2104
+ processors.ProcessorRunner.applyMessagesToMessageList(
2105
+ result,
2106
+ passThrough.messageList,
2107
+ idsBeforeProcessing,
2108
+ check,
2109
+ "response"
2110
+ );
2111
+ return { ...passThrough, messages: result };
2112
+ } else if (result && "messages" in result && "systemMessages" in result) {
2113
+ const typedResult = result;
2114
+ processors.ProcessorRunner.applyMessagesToMessageList(
2115
+ typedResult.messages,
2116
+ passThrough.messageList,
2117
+ idsBeforeProcessing,
2118
+ check,
2119
+ "response"
2120
+ );
2121
+ passThrough.messageList.replaceAllSystemMessages(typedResult.systemMessages);
2122
+ return {
2123
+ ...passThrough,
2124
+ messages: typedResult.messages,
2125
+ systemMessages: typedResult.systemMessages
2126
+ };
2127
+ }
2128
+ return { ...passThrough, messages };
2129
+ }
2130
+ return { ...passThrough, messages };
2131
+ }
2132
+ case "outputStep": {
2133
+ if (processor.processOutputStep) {
2134
+ if (!passThrough.messageList) {
2135
+ throw new error.MastraError({
2136
+ category: error.ErrorCategory.USER,
2137
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
2138
+ id: "PROCESSOR_MISSING_MESSAGE_LIST",
2139
+ text: `Processor ${processor.id} requires messageList or messages for processOutputStep phase`
2140
+ });
2141
+ }
2142
+ const idsBeforeProcessing = messages.map((m) => m.id);
2143
+ const check = passThrough.messageList.makeMessageSourceChecker();
2144
+ const result = await processor.processOutputStep({
2145
+ ...baseContext,
2146
+ messages,
2147
+ messageList: passThrough.messageList,
2148
+ stepNumber: stepNumber ?? 0,
2149
+ finishReason,
2150
+ toolCalls,
2151
+ text,
2152
+ systemMessages: systemMessages ?? [],
2153
+ steps: steps ?? []
2154
+ });
2155
+ if (result instanceof agent.MessageList) {
2156
+ if (result !== passThrough.messageList) {
2157
+ throw new error.MastraError({
2158
+ category: error.ErrorCategory.USER,
2159
+ domain: error.ErrorDomain.MASTRA_WORKFLOW,
2160
+ id: "PROCESSOR_RETURNED_EXTERNAL_MESSAGE_LIST",
2161
+ text: `Processor ${processor.id} returned a MessageList instance other than the one passed in. Use the messageList argument instead.`
2162
+ });
2163
+ }
2164
+ return {
2165
+ ...passThrough,
2166
+ messages: result.get.all.db(),
2167
+ systemMessages: result.getAllSystemMessages()
2168
+ };
2169
+ } else if (Array.isArray(result)) {
2170
+ processors.ProcessorRunner.applyMessagesToMessageList(
2171
+ result,
2172
+ passThrough.messageList,
2173
+ idsBeforeProcessing,
2174
+ check,
2175
+ "response"
2176
+ );
2177
+ return { ...passThrough, messages: result };
2178
+ } else if (result && "messages" in result && "systemMessages" in result) {
2179
+ const typedResult = result;
2180
+ processors.ProcessorRunner.applyMessagesToMessageList(
2181
+ typedResult.messages,
2182
+ passThrough.messageList,
2183
+ idsBeforeProcessing,
2184
+ check,
2185
+ "response"
2186
+ );
2187
+ passThrough.messageList.replaceAllSystemMessages(typedResult.systemMessages);
2188
+ return {
2189
+ ...passThrough,
2190
+ messages: typedResult.messages,
2191
+ systemMessages: typedResult.systemMessages
2192
+ };
2193
+ }
2194
+ return { ...passThrough, messages };
2195
+ }
2196
+ return { ...passThrough, messages };
2197
+ }
2198
+ default:
2199
+ return { ...passThrough, messages };
2200
+ }
2201
+ });
2202
+ },
2203
+ component: "PROCESSOR"
1441
2204
  };
1442
2205
  }
1443
2206
  function init(inngest) {
@@ -1485,6 +2248,7 @@ exports.InngestPubSub = InngestPubSub;
1485
2248
  exports.InngestRun = InngestRun;
1486
2249
  exports.InngestWorkflow = InngestWorkflow;
1487
2250
  exports._compatibilityCheck = _compatibilityCheck;
2251
+ exports.createServe = createServe;
1488
2252
  exports.createStep = createStep;
1489
2253
  exports.init = init;
1490
2254
  exports.serve = serve;