@mastra/inngest 0.0.0-new-button-export-20251219130424 → 0.0.0-om-20260129001517

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