@mastra/inngest 0.0.0-feat-improve-processors-20251205191721 → 0.0.0-feat-mcp-embedded-docs-tools-clean-20260102135536

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,12 +1,15 @@
1
+ import { Agent } from '@mastra/core/agent';
1
2
  import { Tool } from '@mastra/core/tools';
2
- import { DefaultExecutionEngine, createTimeTravelExecutionParams, Run, Workflow } from '@mastra/core/workflows';
3
- import { EMITTER_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
3
+ import { DefaultExecutionEngine, createTimeTravelExecutionParams, Run, hydrateSerializedStepErrors, Workflow } from '@mastra/core/workflows';
4
+ import { PUBSUB_SYMBOL, STREAM_FORMAT_SYMBOL } from '@mastra/core/workflows/_constants';
4
5
  import { z } from 'zod';
5
6
  import { randomUUID } from 'crypto';
6
- import { ReadableStream, WritableStream } from 'stream/web';
7
7
  import { RequestContext } from '@mastra/core/di';
8
- import { RetryAfterError, NonRetriableError } from 'inngest';
8
+ import { NonRetriableError } from 'inngest';
9
+ import { getErrorFromUnknown } from '@mastra/core/error';
9
10
  import { subscribe } from '@inngest/realtime';
11
+ import { PubSub } from '@mastra/core/events';
12
+ import { ReadableStream } from 'stream/web';
10
13
  import { ChunkFrom, WorkflowRunOutput } from '@mastra/core/stream';
11
14
  import { serve as serve$1 } from 'inngest/hono';
12
15
 
@@ -23,17 +26,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
23
26
  // Hook Overrides
24
27
  // =============================================================================
25
28
  /**
26
- * Format errors with stack traces for better debugging in Inngest
29
+ * Format errors while preserving Error instances and their custom properties.
30
+ * Uses getErrorFromUnknown to ensure all error properties are preserved.
27
31
  */
28
32
  formatResultError(error, lastOutput) {
29
- if (error instanceof Error) {
30
- return error.stack ?? error.message;
31
- }
32
33
  const outputError = lastOutput?.error;
33
- if (outputError instanceof Error) {
34
- return outputError.message;
35
- }
36
- return outputError ?? error ?? "Unknown error";
34
+ const errorSource = error || outputError;
35
+ const errorInstance = getErrorFromUnknown(errorSource, {
36
+ serializeStack: true,
37
+ // Include stack in JSON for better debugging in Inngest
38
+ fallbackMessage: "Unknown workflow error"
39
+ });
40
+ return errorInstance.toJSON();
37
41
  }
38
42
  /**
39
43
  * Detect InngestWorkflow instances for special nested workflow handling
@@ -55,32 +59,46 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
55
59
  * After retries exhausted, error propagates here and we return a failed result.
56
60
  */
57
61
  async executeStepWithRetry(stepId, runStep, params) {
58
- try {
59
- const result = await this.wrapDurableOperation(stepId, runStep, { delay: params.delay });
60
- return { ok: true, result };
61
- } catch (e) {
62
- const cause = e?.cause;
63
- if (cause?.status === "failed") {
64
- params.stepSpan?.error({
65
- error: e,
66
- attributes: { status: "failed" }
67
- });
68
- return { ok: false, error: cause };
62
+ for (let i = 0; i < params.retries + 1; i++) {
63
+ if (i > 0 && params.delay) {
64
+ await new Promise((resolve) => setTimeout(resolve, params.delay));
69
65
  }
70
- const errorMessage = e instanceof Error ? e.message : String(e);
71
- params.stepSpan?.error({
72
- error: e,
73
- attributes: { status: "failed" }
74
- });
75
- return {
76
- ok: false,
77
- error: {
78
- status: "failed",
79
- error: `Error: ${errorMessage}`,
80
- endedAt: Date.now()
66
+ try {
67
+ const result = await this.wrapDurableOperation(stepId, runStep);
68
+ return { ok: true, result };
69
+ } catch (e) {
70
+ if (i === params.retries) {
71
+ const cause = e?.cause;
72
+ if (cause?.status === "failed") {
73
+ params.stepSpan?.error({
74
+ error: e,
75
+ attributes: { status: "failed" }
76
+ });
77
+ if (cause.error && !(cause.error instanceof Error)) {
78
+ cause.error = getErrorFromUnknown(cause.error, { serializeStack: false });
79
+ }
80
+ return { ok: false, error: cause };
81
+ }
82
+ const errorInstance = getErrorFromUnknown(e, {
83
+ serializeStack: false,
84
+ fallbackMessage: "Unknown step execution error"
85
+ });
86
+ params.stepSpan?.error({
87
+ error: errorInstance,
88
+ attributes: { status: "failed" }
89
+ });
90
+ return {
91
+ ok: false,
92
+ error: {
93
+ status: "failed",
94
+ error: errorInstance,
95
+ endedAt: Date.now()
96
+ }
97
+ };
81
98
  }
82
- };
99
+ }
83
100
  }
101
+ return { ok: false, error: { status: "failed", error: new Error("Unknown error"), endedAt: Date.now() } };
84
102
  }
85
103
  /**
86
104
  * Use Inngest's sleep primitive for durability
@@ -99,21 +117,11 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
99
117
  * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
100
118
  * Inngest's step-level retry mechanism (not function-level retry).
101
119
  */
102
- async wrapDurableOperation(operationId, operationFn, retryConfig) {
120
+ async wrapDurableOperation(operationId, operationFn) {
103
121
  return this.inngestStep.run(operationId, async () => {
104
122
  try {
105
123
  return await operationFn();
106
124
  } catch (e) {
107
- if (retryConfig) {
108
- const errorMessage = e instanceof Error ? e.message : String(e);
109
- throw new RetryAfterError(errorMessage, retryConfig.delay, {
110
- cause: {
111
- status: "failed",
112
- error: `Error: ${errorMessage}`,
113
- endedAt: Date.now()
114
- }
115
- });
116
- }
117
125
  throw e;
118
126
  }
119
127
  });
@@ -124,6 +132,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
124
132
  getEngineContext() {
125
133
  return { step: this.inngestStep };
126
134
  }
135
+ /**
136
+ * For Inngest, lifecycle callbacks are invoked in the workflow's finalize step
137
+ * (wrapped in step.run for durability), not in execute(). Override to skip.
138
+ */
139
+ async invokeLifecycleCallbacks(_result) {
140
+ }
141
+ /**
142
+ * Actually invoke the lifecycle callbacks. Called from workflow.ts finalize step.
143
+ */
144
+ async invokeLifecycleCallbacksInternal(result) {
145
+ return super.invokeLifecycleCallbacks(result);
146
+ }
127
147
  /**
128
148
  * Execute nested InngestWorkflow using inngestStep.invoke() for durability.
129
149
  * This MUST be called directly (not inside step.run()) due to Inngest constraints.
@@ -132,7 +152,18 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
132
152
  if (!(params.step instanceof InngestWorkflow)) {
133
153
  return null;
134
154
  }
135
- const { step, stepResults, executionContext, resume, timeTravel, prevOutput, inputData, emitter, startedAt } = params;
155
+ const {
156
+ step,
157
+ stepResults,
158
+ executionContext,
159
+ resume,
160
+ timeTravel,
161
+ prevOutput,
162
+ inputData,
163
+ pubsub,
164
+ startedAt,
165
+ perStep
166
+ } = params;
136
167
  const isResume = !!resume?.steps?.length;
137
168
  let result;
138
169
  let runId;
@@ -140,7 +171,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
140
171
  try {
141
172
  if (isResume) {
142
173
  runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? randomUUID();
143
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
174
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
175
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
144
176
  workflowName: step.id,
145
177
  runId
146
178
  });
@@ -157,14 +189,16 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
157
189
  resumePayload: resume.resumePayload,
158
190
  resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
159
191
  },
160
- outputOptions: { includeState: true }
192
+ outputOptions: { includeState: true },
193
+ perStep
161
194
  }
162
195
  });
163
196
  result = invokeResp.result;
164
197
  runId = invokeResp.runId;
165
198
  executionContext.state = invokeResp.result.state;
166
199
  } else if (isTimeTravel) {
167
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
200
+ const workflowsStoreForTimeTravel = await this.mastra?.getStorage()?.getStore("workflows");
201
+ const snapshot = await workflowsStoreForTimeTravel?.loadWorkflowSnapshot({
168
202
  workflowName: step.id,
169
203
  runId: executionContext.runId
170
204
  }) ?? { context: {} };
@@ -183,7 +217,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
183
217
  timeTravel: timeTravelParams,
184
218
  initialState: executionContext.state ?? {},
185
219
  runId: executionContext.runId,
186
- outputOptions: { includeState: true }
220
+ outputOptions: { includeState: true },
221
+ perStep
187
222
  }
188
223
  });
189
224
  result = invokeResp.result;
@@ -195,7 +230,8 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
195
230
  data: {
196
231
  inputData,
197
232
  initialState: executionContext.state ?? {},
198
- outputOptions: { includeState: true }
233
+ outputOptions: { includeState: true },
234
+ perStep
199
235
  }
200
236
  });
201
237
  result = invokeResp.result;
@@ -221,16 +257,20 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
221
257
  `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
222
258
  async () => {
223
259
  if (result.status === "failed") {
224
- await emitter.emit("watch", {
225
- type: "workflow-step-result",
226
- payload: {
227
- id: step.id,
228
- status: "failed",
229
- error: result?.error,
230
- payload: prevOutput
260
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
261
+ type: "watch",
262
+ runId: executionContext.runId,
263
+ data: {
264
+ type: "workflow-step-result",
265
+ payload: {
266
+ id: step.id,
267
+ status: "failed",
268
+ error: result?.error,
269
+ payload: prevOutput
270
+ }
231
271
  }
232
272
  });
233
- return { executionContext, result: { status: "failed", error: result?.error } };
273
+ return { executionContext, result: { status: "failed", error: result?.error, endedAt: Date.now() } };
234
274
  } else if (result.status === "suspended") {
235
275
  const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
236
276
  const stepRes = stepResult;
@@ -239,17 +279,22 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
239
279
  for (const [stepName, stepResult] of suspendedSteps) {
240
280
  const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
241
281
  executionContext.suspendedPaths[step.id] = executionContext.executionPath;
242
- await emitter.emit("watch", {
243
- type: "workflow-step-suspended",
244
- payload: {
245
- id: step.id,
246
- status: "suspended"
282
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
283
+ type: "watch",
284
+ runId: executionContext.runId,
285
+ data: {
286
+ type: "workflow-step-suspended",
287
+ payload: {
288
+ id: step.id,
289
+ status: "suspended"
290
+ }
247
291
  }
248
292
  });
249
293
  return {
250
294
  executionContext,
251
295
  result: {
252
296
  status: "suspended",
297
+ suspendedAt: Date.now(),
253
298
  payload: stepResult.payload,
254
299
  suspendPayload: {
255
300
  ...stepResult?.suspendPayload,
@@ -262,59 +307,205 @@ var InngestExecutionEngine = class extends DefaultExecutionEngine {
262
307
  executionContext,
263
308
  result: {
264
309
  status: "suspended",
310
+ suspendedAt: Date.now(),
265
311
  payload: {}
266
312
  }
267
313
  };
268
314
  } else if (result.status === "tripwire") {
269
- await emitter.emit("watch", {
270
- type: "workflow-step-result",
271
- payload: {
272
- id: step.id,
273
- status: "tripwire",
274
- error: result?.reason,
275
- payload: prevOutput
315
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
316
+ type: "watch",
317
+ runId: executionContext.runId,
318
+ data: {
319
+ type: "workflow-step-result",
320
+ payload: {
321
+ id: step.id,
322
+ status: "tripwire",
323
+ error: result?.tripwire?.reason,
324
+ payload: prevOutput
325
+ }
276
326
  }
277
327
  });
278
328
  return {
279
329
  executionContext,
280
330
  result: {
281
331
  status: "tripwire",
282
- reason: result?.reason,
283
- retry: result?.retry,
284
- metadata: result?.metadata,
285
- processorId: result?.processorId
332
+ tripwire: result?.tripwire,
333
+ endedAt: Date.now()
286
334
  }
287
335
  };
336
+ } else if (perStep || result.status === "paused") {
337
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
338
+ type: "watch",
339
+ runId: executionContext.runId,
340
+ data: {
341
+ type: "workflow-step-result",
342
+ payload: {
343
+ id: step.id,
344
+ status: "paused"
345
+ }
346
+ }
347
+ });
348
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
349
+ type: "watch",
350
+ runId: executionContext.runId,
351
+ data: {
352
+ type: "workflow-step-finish",
353
+ payload: {
354
+ id: step.id,
355
+ metadata: {}
356
+ }
357
+ }
358
+ });
359
+ return { executionContext, result: { status: "paused" } };
288
360
  }
289
- await emitter.emit("watch", {
290
- type: "workflow-step-result",
291
- payload: {
292
- id: step.id,
293
- status: "success",
294
- output: result?.result
361
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
362
+ type: "watch",
363
+ runId: executionContext.runId,
364
+ data: {
365
+ type: "workflow-step-result",
366
+ payload: {
367
+ id: step.id,
368
+ status: "success",
369
+ output: result?.result
370
+ }
295
371
  }
296
372
  });
297
- await emitter.emit("watch", {
298
- type: "workflow-step-finish",
299
- payload: {
300
- id: step.id,
301
- metadata: {}
373
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
374
+ type: "watch",
375
+ runId: executionContext.runId,
376
+ data: {
377
+ type: "workflow-step-finish",
378
+ payload: {
379
+ id: step.id,
380
+ metadata: {}
381
+ }
302
382
  }
303
383
  });
304
- return { executionContext, result: { status: "success", output: result?.result } };
384
+ return { executionContext, result: { status: "success", output: result?.result, endedAt: Date.now() } };
305
385
  }
306
386
  );
307
387
  Object.assign(executionContext, res.executionContext);
308
388
  return {
309
389
  ...res.result,
310
390
  startedAt,
311
- endedAt: Date.now(),
312
391
  payload: inputData,
313
392
  resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
314
393
  resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
315
394
  };
316
395
  }
317
396
  };
397
+ var InngestPubSub = class extends PubSub {
398
+ inngest;
399
+ workflowId;
400
+ publishFn;
401
+ subscriptions = /* @__PURE__ */ new Map();
402
+ constructor(inngest, workflowId, publishFn) {
403
+ super();
404
+ this.inngest = inngest;
405
+ this.workflowId = workflowId;
406
+ this.publishFn = publishFn;
407
+ }
408
+ /**
409
+ * Publish an event to Inngest's realtime system.
410
+ *
411
+ * Topic format: "workflow.events.v2.{runId}"
412
+ * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
413
+ */
414
+ async publish(topic, event) {
415
+ if (!this.publishFn) {
416
+ return;
417
+ }
418
+ const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
419
+ if (!match) {
420
+ return;
421
+ }
422
+ const runId = match[1];
423
+ try {
424
+ await this.publishFn({
425
+ channel: `workflow:${this.workflowId}:${runId}`,
426
+ topic: "watch",
427
+ data: event.data
428
+ });
429
+ } catch (err) {
430
+ console.error("InngestPubSub publish error:", err?.message ?? err);
431
+ }
432
+ }
433
+ /**
434
+ * Subscribe to events from Inngest's realtime system.
435
+ *
436
+ * Topic format: "workflow.events.v2.{runId}"
437
+ * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
438
+ */
439
+ async subscribe(topic, cb) {
440
+ const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
441
+ if (!match || !match[1]) {
442
+ return;
443
+ }
444
+ const runId = match[1];
445
+ if (this.subscriptions.has(topic)) {
446
+ this.subscriptions.get(topic).callbacks.add(cb);
447
+ return;
448
+ }
449
+ const callbacks = /* @__PURE__ */ new Set([cb]);
450
+ const channel = `workflow:${this.workflowId}:${runId}`;
451
+ const streamPromise = subscribe(
452
+ {
453
+ channel,
454
+ topics: ["watch"],
455
+ app: this.inngest
456
+ },
457
+ (message) => {
458
+ const event = {
459
+ id: crypto.randomUUID(),
460
+ type: "watch",
461
+ runId,
462
+ data: message.data,
463
+ createdAt: /* @__PURE__ */ new Date()
464
+ };
465
+ for (const callback of callbacks) {
466
+ callback(event);
467
+ }
468
+ }
469
+ );
470
+ this.subscriptions.set(topic, {
471
+ unsubscribe: () => {
472
+ streamPromise.then((stream) => stream.cancel()).catch((err) => {
473
+ console.error("InngestPubSub unsubscribe error:", err);
474
+ });
475
+ },
476
+ callbacks
477
+ });
478
+ }
479
+ /**
480
+ * Unsubscribe a callback from a topic.
481
+ * If no callbacks remain, the underlying Inngest subscription is cancelled.
482
+ */
483
+ async unsubscribe(topic, cb) {
484
+ const sub = this.subscriptions.get(topic);
485
+ if (!sub) {
486
+ return;
487
+ }
488
+ sub.callbacks.delete(cb);
489
+ if (sub.callbacks.size === 0) {
490
+ sub.unsubscribe();
491
+ this.subscriptions.delete(topic);
492
+ }
493
+ }
494
+ /**
495
+ * Flush any pending operations. No-op for Inngest.
496
+ */
497
+ async flush() {
498
+ }
499
+ /**
500
+ * Clean up all subscriptions during graceful shutdown.
501
+ */
502
+ async close() {
503
+ for (const [, sub] of this.subscriptions) {
504
+ sub.unsubscribe();
505
+ }
506
+ this.subscriptions.clear();
507
+ }
508
+ };
318
509
  var InngestRun = class extends Run {
319
510
  inngest;
320
511
  serializedStepGraph;
@@ -326,38 +517,90 @@ var InngestRun = class extends Run {
326
517
  this.#mastra = params.mastra;
327
518
  }
328
519
  async getRuns(eventId) {
329
- const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
330
- headers: {
331
- Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
520
+ const maxRetries = 3;
521
+ let lastError = null;
522
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
523
+ try {
524
+ const response = await fetch(
525
+ `${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`,
526
+ {
527
+ headers: {
528
+ Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
529
+ }
530
+ }
531
+ );
532
+ if (response.status === 429) {
533
+ const retryAfter = parseInt(response.headers.get("retry-after") || "2", 10);
534
+ await new Promise((resolve) => setTimeout(resolve, retryAfter * 1e3));
535
+ continue;
536
+ }
537
+ if (!response.ok) {
538
+ throw new Error(`Inngest API error: ${response.status} ${response.statusText}`);
539
+ }
540
+ const text = await response.text();
541
+ if (!text) {
542
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
543
+ continue;
544
+ }
545
+ const json = JSON.parse(text);
546
+ return json.data;
547
+ } catch (error) {
548
+ lastError = error;
549
+ if (attempt < maxRetries - 1) {
550
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * Math.pow(2, attempt)));
551
+ }
332
552
  }
333
- });
334
- const json = await response.json();
335
- return json.data;
553
+ }
554
+ throw new NonRetriableError(`Failed to get runs after ${maxRetries} attempts: ${lastError?.message}`);
336
555
  }
337
- async getRunOutput(eventId) {
338
- let runs = await this.getRuns(eventId);
556
+ async getRunOutput(eventId, maxWaitMs = 3e5) {
557
+ const startTime = Date.now();
339
558
  const storage = this.#mastra?.getStorage();
340
- while (runs?.[0]?.status !== "Completed" || runs?.[0]?.event_id !== eventId) {
341
- await new Promise((resolve) => setTimeout(resolve, 1e3));
342
- runs = await this.getRuns(eventId);
559
+ const workflowsStore = await storage?.getStore("workflows");
560
+ while (Date.now() - startTime < maxWaitMs) {
561
+ let runs;
562
+ try {
563
+ runs = await this.getRuns(eventId);
564
+ } catch (error) {
565
+ if (error instanceof NonRetriableError) {
566
+ throw error;
567
+ }
568
+ throw new NonRetriableError(
569
+ `Failed to poll workflow status: ${error instanceof Error ? error.message : String(error)}`
570
+ );
571
+ }
572
+ if (runs?.[0]?.status === "Completed" && runs?.[0]?.event_id === eventId) {
573
+ return runs[0];
574
+ }
343
575
  if (runs?.[0]?.status === "Failed") {
344
- const snapshot = await storage?.loadWorkflowSnapshot({
576
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
345
577
  workflowName: this.workflowId,
346
578
  runId: this.runId
347
579
  });
580
+ if (snapshot?.context) {
581
+ snapshot.context = hydrateSerializedStepErrors(snapshot.context);
582
+ }
348
583
  return {
349
- output: { result: { steps: snapshot?.context, status: "failed", error: runs?.[0]?.output?.message } }
584
+ output: {
585
+ result: {
586
+ steps: snapshot?.context,
587
+ status: "failed",
588
+ // Get the original error from NonRetriableError's cause (which contains the workflow result)
589
+ error: getErrorFromUnknown(runs?.[0]?.output?.cause?.error, { serializeStack: false })
590
+ }
591
+ }
350
592
  };
351
593
  }
352
594
  if (runs?.[0]?.status === "Cancelled") {
353
- const snapshot = await storage?.loadWorkflowSnapshot({
595
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
354
596
  workflowName: this.workflowId,
355
597
  runId: this.runId
356
598
  });
357
599
  return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
358
600
  }
601
+ await new Promise((resolve) => setTimeout(resolve, 1e3 + Math.random() * 1e3));
359
602
  }
360
- return runs?.[0];
603
+ throw new NonRetriableError(`Workflow did not complete within ${maxWaitMs}ms`);
361
604
  }
362
605
  async cancel() {
363
606
  const storage = this.#mastra?.getStorage();
@@ -367,12 +610,13 @@ var InngestRun = class extends Run {
367
610
  runId: this.runId
368
611
  }
369
612
  });
370
- const snapshot = await storage?.loadWorkflowSnapshot({
613
+ const workflowsStore = await storage?.getStore("workflows");
614
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
371
615
  workflowName: this.workflowId,
372
616
  runId: this.runId
373
617
  });
374
618
  if (snapshot) {
375
- await storage?.persistWorkflowSnapshot({
619
+ await workflowsStore?.persistWorkflowSnapshot({
376
620
  workflowName: this.workflowId,
377
621
  runId: this.runId,
378
622
  resourceId: this.resourceId,
@@ -387,15 +631,64 @@ var InngestRun = class extends Run {
387
631
  async start(params) {
388
632
  return this._start(params);
389
633
  }
634
+ /**
635
+ * Starts the workflow execution without waiting for completion (fire-and-forget).
636
+ * Returns immediately with the runId after sending the event to Inngest.
637
+ * The workflow executes independently in Inngest.
638
+ * Use this when you don't need to wait for the result or want to avoid polling failures.
639
+ */
640
+ async startAsync(params) {
641
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
642
+ await workflowsStore?.persistWorkflowSnapshot({
643
+ workflowName: this.workflowId,
644
+ runId: this.runId,
645
+ resourceId: this.resourceId,
646
+ snapshot: {
647
+ runId: this.runId,
648
+ serializedStepGraph: this.serializedStepGraph,
649
+ status: "running",
650
+ value: {},
651
+ context: {},
652
+ activePaths: [],
653
+ suspendedPaths: {},
654
+ activeStepsPath: {},
655
+ resumeLabels: {},
656
+ waitingPaths: {},
657
+ timestamp: Date.now()
658
+ }
659
+ });
660
+ const inputDataToUse = await this._validateInput(params.inputData);
661
+ const initialStateToUse = await this._validateInitialState(params.initialState ?? {});
662
+ const eventOutput = await this.inngest.send({
663
+ name: `workflow.${this.workflowId}`,
664
+ data: {
665
+ inputData: inputDataToUse,
666
+ initialState: initialStateToUse,
667
+ runId: this.runId,
668
+ resourceId: this.resourceId,
669
+ outputOptions: params.outputOptions,
670
+ tracingOptions: params.tracingOptions,
671
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {},
672
+ perStep: params.perStep
673
+ }
674
+ });
675
+ const eventId = eventOutput.ids[0];
676
+ if (!eventId) {
677
+ throw new Error("Event ID is not set");
678
+ }
679
+ return { runId: this.runId };
680
+ }
390
681
  async _start({
391
682
  inputData,
392
683
  initialState,
393
684
  outputOptions,
394
685
  tracingOptions,
395
686
  format,
396
- requestContext
687
+ requestContext,
688
+ perStep
397
689
  }) {
398
- await this.#mastra.getStorage()?.persistWorkflowSnapshot({
690
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
691
+ await workflowsStore?.persistWorkflowSnapshot({
399
692
  workflowName: this.workflowId,
400
693
  runId: this.runId,
401
694
  resourceId: this.resourceId,
@@ -425,7 +718,8 @@ var InngestRun = class extends Run {
425
718
  outputOptions,
426
719
  tracingOptions,
427
720
  format,
428
- requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {}
721
+ requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {},
722
+ perStep
429
723
  }
430
724
  });
431
725
  const eventId = eventOutput.ids[0];
@@ -434,9 +728,7 @@ var InngestRun = class extends Run {
434
728
  }
435
729
  const runOutput = await this.getRunOutput(eventId);
436
730
  const result = runOutput?.output?.result;
437
- if (result.status === "failed") {
438
- result.error = new Error(result.error);
439
- }
731
+ this.hydrateFailedResult(result);
440
732
  if (result.status !== "suspended") {
441
733
  this.cleanup?.();
442
734
  }
@@ -463,7 +755,8 @@ var InngestRun = class extends Run {
463
755
  (step) => typeof step === "string" ? step : step?.id
464
756
  );
465
757
  }
466
- const snapshot = await storage?.loadWorkflowSnapshot({
758
+ const workflowsStore = await storage?.getStore("workflows");
759
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
467
760
  workflowName: this.workflowId,
468
761
  runId: this.runId
469
762
  });
@@ -486,7 +779,8 @@ var InngestRun = class extends Run {
486
779
  resumePayload: resumeDataToUse,
487
780
  resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
488
781
  },
489
- requestContext: mergedRequestContext
782
+ requestContext: mergedRequestContext,
783
+ perStep: params.perStep
490
784
  }
491
785
  });
492
786
  const eventId = eventOutput.ids[0];
@@ -495,9 +789,7 @@ var InngestRun = class extends Run {
495
789
  }
496
790
  const runOutput = await this.getRunOutput(eventId);
497
791
  const result = runOutput?.output?.result;
498
- if (result.status === "failed") {
499
- result.error = new Error(result.error);
500
- }
792
+ this.hydrateFailedResult(result);
501
793
  return result;
502
794
  }
503
795
  async timeTravel(params) {
@@ -527,12 +819,13 @@ var InngestRun = class extends Run {
527
819
  throw new Error("No steps provided to timeTravel");
528
820
  }
529
821
  const storage = this.#mastra?.getStorage();
530
- const snapshot = await storage?.loadWorkflowSnapshot({
822
+ const workflowsStore = await storage?.getStore("workflows");
823
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
531
824
  workflowName: this.workflowId,
532
825
  runId: this.runId
533
826
  });
534
827
  if (!snapshot) {
535
- await storage?.persistWorkflowSnapshot({
828
+ await workflowsStore?.persistWorkflowSnapshot({
536
829
  workflowName: this.workflowId,
537
830
  runId: this.runId,
538
831
  resourceId: this.resourceId,
@@ -566,7 +859,8 @@ var InngestRun = class extends Run {
566
859
  nestedStepsContext: params.nestedStepsContext,
567
860
  snapshot: snapshot ?? { context: {} },
568
861
  graph: this.executionGraph,
569
- initialState: params.initialState
862
+ initialState: params.initialState,
863
+ perStep: params.perStep
570
864
  });
571
865
  const eventOutput = await this.inngest.send({
572
866
  name: `workflow.${this.workflowId}`,
@@ -578,7 +872,8 @@ var InngestRun = class extends Run {
578
872
  timeTravel: timeTravelData,
579
873
  tracingOptions: params.tracingOptions,
580
874
  outputOptions: params.outputOptions,
581
- requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {}
875
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {},
876
+ perStep: params.perStep
582
877
  }
583
878
  });
584
879
  const eventId = eventOutput.ids[0];
@@ -587,9 +882,7 @@ var InngestRun = class extends Run {
587
882
  }
588
883
  const runOutput = await this.getRunOutput(eventId);
589
884
  const result = runOutput?.output?.result;
590
- if (result.status === "failed") {
591
- result.error = new Error(result.error);
592
- }
885
+ this.hydrateFailedResult(result);
593
886
  return result;
594
887
  }
595
888
  watch(cb) {
@@ -671,7 +964,8 @@ var InngestRun = class extends Run {
671
964
  tracingOptions,
672
965
  closeOnSuspend = true,
673
966
  initialState,
674
- outputOptions
967
+ outputOptions,
968
+ perStep
675
969
  } = {}) {
676
970
  if (this.closeStreamAction && this.streamOutput) {
677
971
  return this.streamOutput;
@@ -707,7 +1001,8 @@ var InngestRun = class extends Run {
707
1001
  initialState,
708
1002
  tracingOptions,
709
1003
  outputOptions,
710
- format: "vnext"
1004
+ format: "vnext",
1005
+ perStep
711
1006
  });
712
1007
  let executionResults;
713
1008
  try {
@@ -738,9 +1033,6 @@ var InngestRun = class extends Run {
738
1033
  });
739
1034
  return this.streamOutput;
740
1035
  }
741
- streamVNext(args = {}) {
742
- return this.stream(args);
743
- }
744
1036
  timeTravelStream({
745
1037
  inputData,
746
1038
  resumeData,
@@ -750,7 +1042,8 @@ var InngestRun = class extends Run {
750
1042
  nestedStepsContext,
751
1043
  requestContext,
752
1044
  tracingOptions,
753
- outputOptions
1045
+ outputOptions,
1046
+ perStep
754
1047
  }) {
755
1048
  this.closeStreamAction = async () => {
756
1049
  };
@@ -785,7 +1078,8 @@ var InngestRun = class extends Run {
785
1078
  initialState,
786
1079
  requestContext,
787
1080
  tracingOptions,
788
- outputOptions
1081
+ outputOptions,
1082
+ perStep
789
1083
  });
790
1084
  self.executionResults = executionResultsPromise;
791
1085
  let executionResults;
@@ -810,6 +1104,18 @@ var InngestRun = class extends Run {
810
1104
  });
811
1105
  return this.streamOutput;
812
1106
  }
1107
+ /**
1108
+ * Hydrates errors in a failed workflow result back to proper Error instances.
1109
+ * This ensures error.cause chains and custom properties are preserved.
1110
+ */
1111
+ hydrateFailedResult(result) {
1112
+ if (result.status === "failed") {
1113
+ result.error = getErrorFromUnknown(result.error, { serializeStack: false });
1114
+ if (result.steps) {
1115
+ hydrateSerializedStepErrors(result.steps);
1116
+ }
1117
+ }
1118
+ }
813
1119
  };
814
1120
 
815
1121
  // src/workflow.ts
@@ -817,9 +1123,11 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
817
1123
  #mastra;
818
1124
  inngest;
819
1125
  function;
1126
+ cronFunction;
820
1127
  flowControlConfig;
1128
+ cronConfig;
821
1129
  constructor(params, inngest) {
822
- const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
1130
+ const { concurrency, rateLimit, throttle, debounce, priority, cron, inputData, initialState, ...workflowParams } = params;
823
1131
  super(workflowParams);
824
1132
  this.engineType = "inngest";
825
1133
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
@@ -828,6 +1136,9 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
828
1136
  this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
829
1137
  this.#mastra = params.mastra;
830
1138
  this.inngest = inngest;
1139
+ if (cron) {
1140
+ this.cronConfig = { cron, inputData, initialState };
1141
+ }
831
1142
  }
832
1143
  async listWorkflowRuns(args) {
833
1144
  const storage = this.#mastra?.getStorage();
@@ -835,7 +1146,11 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
835
1146
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
836
1147
  return { runs: [], total: 0 };
837
1148
  }
838
- return storage.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
1149
+ const workflowsStore = await storage.getStore("workflows");
1150
+ if (!workflowsStore) {
1151
+ return { runs: [], total: 0 };
1152
+ }
1153
+ return workflowsStore.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
839
1154
  }
840
1155
  async getWorkflowRunById(runId) {
841
1156
  const storage = this.#mastra?.getStorage();
@@ -843,10 +1158,15 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
843
1158
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
844
1159
  return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
845
1160
  }
846
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
1161
+ const workflowsStore = await storage.getStore("workflows");
1162
+ if (!workflowsStore) {
1163
+ return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
1164
+ }
1165
+ const run = await workflowsStore.getWorkflowRunById({ runId, workflowName: this.id });
847
1166
  return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
848
1167
  }
849
1168
  __registerMastra(mastra) {
1169
+ super.__registerMastra(mastra);
850
1170
  this.#mastra = mastra;
851
1171
  this.executionEngine.__registerMastra(mastra);
852
1172
  const updateNested = (step) => {
@@ -888,9 +1208,12 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
888
1208
  workflowStatus: run.workflowRunStatus,
889
1209
  stepResults: {}
890
1210
  });
891
- const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, false);
1211
+ const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, {
1212
+ withNestedWorkflows: false
1213
+ });
892
1214
  if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
893
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
1215
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
1216
+ await workflowsStore?.persistWorkflowSnapshot({
894
1217
  workflowName: this.id,
895
1218
  runId: runIdToUse,
896
1219
  resourceId: options?.resourceId,
@@ -913,6 +1236,30 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
913
1236
  }
914
1237
  return run;
915
1238
  }
1239
+ //createCronFunction is only called if cronConfig.cron is defined.
1240
+ createCronFunction() {
1241
+ if (this.cronFunction) {
1242
+ return this.cronFunction;
1243
+ }
1244
+ this.cronFunction = this.inngest.createFunction(
1245
+ {
1246
+ id: `workflow.${this.id}.cron`,
1247
+ retries: 0,
1248
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1249
+ ...this.flowControlConfig
1250
+ },
1251
+ { cron: this.cronConfig?.cron ?? "" },
1252
+ async () => {
1253
+ const run = await this.createRun();
1254
+ const result = await run.start({
1255
+ inputData: this.cronConfig?.inputData,
1256
+ initialState: this.cronConfig?.initialState
1257
+ });
1258
+ return { result, runId: run.runId };
1259
+ }
1260
+ );
1261
+ return this.cronFunction;
1262
+ }
916
1263
  getFunction() {
917
1264
  if (this.function) {
918
1265
  return this.function;
@@ -920,41 +1267,20 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
920
1267
  this.function = this.inngest.createFunction(
921
1268
  {
922
1269
  id: `workflow.${this.id}`,
923
- retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
1270
+ retries: 0,
924
1271
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
925
1272
  // Spread flow control configuration
926
1273
  ...this.flowControlConfig
927
1274
  },
928
1275
  { event: `workflow.${this.id}` },
929
1276
  async ({ event, step, attempt, publish }) => {
930
- let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel } = event.data;
1277
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel, perStep } = event.data;
931
1278
  if (!runId) {
932
1279
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
933
1280
  return randomUUID();
934
1281
  });
935
1282
  }
936
- const emitter = {
937
- emit: async (event2, data) => {
938
- if (!publish) {
939
- return;
940
- }
941
- try {
942
- await publish({
943
- channel: `workflow:${this.id}:${runId}`,
944
- topic: event2,
945
- data
946
- });
947
- } catch (err) {
948
- this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
949
- }
950
- },
951
- on: (_event, _callback) => {
952
- },
953
- off: (_event, _callback) => {
954
- },
955
- once: (_event, _callback) => {
956
- }
957
- };
1283
+ const pubsub = new InngestPubSub(this.inngest, this.id, publish);
958
1284
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
959
1285
  const result = await engine.execute({
960
1286
  workflowId: this.id,
@@ -964,23 +1290,32 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
964
1290
  serializedStepGraph: this.serializedStepGraph,
965
1291
  input: inputData,
966
1292
  initialState,
967
- emitter,
1293
+ pubsub,
968
1294
  retryConfig: this.retryConfig,
969
1295
  requestContext: new RequestContext(Object.entries(event.data.requestContext ?? {})),
970
1296
  resume,
971
1297
  timeTravel,
1298
+ perStep,
972
1299
  format,
973
1300
  abortController: new AbortController(),
974
1301
  // currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
975
1302
  outputOptions,
976
- writableStream: new WritableStream({
977
- write(chunk) {
978
- void emitter.emit("watch", chunk).catch(() => {
1303
+ outputWriter: async (chunk) => {
1304
+ try {
1305
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1306
+ type: "watch",
1307
+ runId,
1308
+ data: chunk
979
1309
  });
1310
+ } catch (err) {
1311
+ this.logger.debug?.("Failed to publish watch event:", err);
980
1312
  }
981
- })
1313
+ }
982
1314
  });
983
1315
  await step.run(`workflow.${this.id}.finalize`, async () => {
1316
+ if (result.status !== "paused") {
1317
+ await engine.invokeLifecycleCallbacksInternal(result);
1318
+ }
984
1319
  if (result.status === "failed") {
985
1320
  throw new NonRetriableError(`Workflow failed`, {
986
1321
  cause: result
@@ -1007,7 +1342,11 @@ var InngestWorkflow = class _InngestWorkflow extends Workflow {
1007
1342
  });
1008
1343
  }
1009
1344
  getFunctions() {
1010
- return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
1345
+ return [
1346
+ this.getFunction(),
1347
+ ...this.cronConfig?.cron ? [this.createCronFunction()] : [],
1348
+ ...this.getNestedFunctions(this.executionGraph.steps)
1349
+ ];
1011
1350
  }
1012
1351
  };
1013
1352
  function serve({
@@ -1039,20 +1378,14 @@ function serve({
1039
1378
  var _compatibilityCheck = true;
1040
1379
 
1041
1380
  // src/index.ts
1042
- function isAgent(params) {
1043
- return params?.component === "AGENT";
1044
- }
1045
- function isTool(params) {
1046
- return params instanceof Tool;
1047
- }
1048
- function isInngestWorkflow(params) {
1049
- return params instanceof InngestWorkflow;
1050
- }
1051
- function createStep(params, agentOptions) {
1052
- if (isInngestWorkflow(params)) {
1381
+ function createStep(params, agentOrToolOptions) {
1382
+ if (params instanceof InngestWorkflow) {
1053
1383
  return params;
1054
1384
  }
1055
- if (isAgent(params)) {
1385
+ if (params instanceof Agent) {
1386
+ const options = agentOrToolOptions;
1387
+ const outputSchema = options?.structuredOutput?.schema ?? z.object({ text: z.string() });
1388
+ const { retries, scorers, ...agentOptions } = options ?? {};
1056
1389
  return {
1057
1390
  id: params.name,
1058
1391
  description: params.getDescription(),
@@ -1061,12 +1394,13 @@ function createStep(params, agentOptions) {
1061
1394
  // resourceId: z.string().optional(),
1062
1395
  // threadId: z.string().optional(),
1063
1396
  }),
1064
- outputSchema: z.object({
1065
- text: z.string()
1066
- }),
1397
+ outputSchema,
1398
+ retries,
1399
+ scorers,
1067
1400
  execute: async ({
1068
1401
  inputData,
1069
- [EMITTER_SYMBOL]: emitter,
1402
+ runId,
1403
+ [PUBSUB_SYMBOL]: pubsub,
1070
1404
  [STREAM_FORMAT_SYMBOL]: streamFormat,
1071
1405
  requestContext,
1072
1406
  tracingContext,
@@ -1079,6 +1413,7 @@ function createStep(params, agentOptions) {
1079
1413
  streamPromise.resolve = resolve;
1080
1414
  streamPromise.reject = reject;
1081
1415
  });
1416
+ let structuredResult = null;
1082
1417
  const toolData = {
1083
1418
  name: params.name,
1084
1419
  args: inputData
@@ -1092,6 +1427,10 @@ function createStep(params, agentOptions) {
1092
1427
  requestContext,
1093
1428
  tracingContext,
1094
1429
  onFinish: (result) => {
1430
+ const resultWithObject = result;
1431
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1432
+ structuredResult = resultWithObject.object;
1433
+ }
1095
1434
  streamPromise.resolve(result.text);
1096
1435
  void agentOptions?.onFinish?.(result);
1097
1436
  },
@@ -1104,6 +1443,10 @@ function createStep(params, agentOptions) {
1104
1443
  requestContext,
1105
1444
  tracingContext,
1106
1445
  onFinish: (result) => {
1446
+ const resultWithObject = result;
1447
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1448
+ structuredResult = resultWithObject.object;
1449
+ }
1107
1450
  streamPromise.resolve(result.text);
1108
1451
  void agentOptions?.onFinish?.(result);
1109
1452
  },
@@ -1112,22 +1455,24 @@ function createStep(params, agentOptions) {
1112
1455
  stream = modelOutput.fullStream;
1113
1456
  }
1114
1457
  if (streamFormat === "legacy") {
1115
- await emitter.emit("watch", {
1116
- type: "tool-call-streaming-start",
1117
- ...toolData ?? {}
1458
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1459
+ type: "watch",
1460
+ runId,
1461
+ data: { type: "tool-call-streaming-start", ...toolData ?? {} }
1118
1462
  });
1119
1463
  for await (const chunk of stream) {
1120
1464
  if (chunk.type === "text-delta") {
1121
- await emitter.emit("watch", {
1122
- type: "tool-call-delta",
1123
- ...toolData ?? {},
1124
- argsTextDelta: chunk.textDelta
1465
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1466
+ type: "watch",
1467
+ runId,
1468
+ data: { type: "tool-call-delta", ...toolData ?? {}, argsTextDelta: chunk.textDelta }
1125
1469
  });
1126
1470
  }
1127
1471
  }
1128
- await emitter.emit("watch", {
1129
- type: "tool-call-streaming-finish",
1130
- ...toolData ?? {}
1472
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1473
+ type: "watch",
1474
+ runId,
1475
+ data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
1131
1476
  });
1132
1477
  } else {
1133
1478
  for await (const chunk of stream) {
@@ -1137,6 +1482,9 @@ function createStep(params, agentOptions) {
1137
1482
  if (abortSignal.aborted) {
1138
1483
  return abort();
1139
1484
  }
1485
+ if (structuredResult !== null) {
1486
+ return structuredResult;
1487
+ }
1140
1488
  return {
1141
1489
  text: await streamPromise.promise
1142
1490
  };
@@ -1144,7 +1492,8 @@ function createStep(params, agentOptions) {
1144
1492
  component: params.component
1145
1493
  };
1146
1494
  }
1147
- if (isTool(params)) {
1495
+ if (params instanceof Tool) {
1496
+ const toolOpts = agentOrToolOptions;
1148
1497
  if (!params.inputSchema || !params.outputSchema) {
1149
1498
  throw new Error("Tool must have input and output schemas defined");
1150
1499
  }
@@ -1156,6 +1505,8 @@ function createStep(params, agentOptions) {
1156
1505
  outputSchema: params.outputSchema,
1157
1506
  suspendSchema: params.suspendSchema,
1158
1507
  resumeSchema: params.resumeSchema,
1508
+ retries: toolOpts?.retries,
1509
+ scorers: toolOpts?.scorers,
1159
1510
  execute: async ({
1160
1511
  inputData,
1161
1512
  mastra,
@@ -1193,6 +1544,8 @@ function createStep(params, agentOptions) {
1193
1544
  outputSchema: params.outputSchema,
1194
1545
  resumeSchema: params.resumeSchema,
1195
1546
  suspendSchema: params.suspendSchema,
1547
+ retries: params.retries,
1548
+ scorers: params.scorers,
1196
1549
  execute: params.execute
1197
1550
  };
1198
1551
  }
@@ -1236,6 +1589,6 @@ function init(inngest) {
1236
1589
  };
1237
1590
  }
1238
1591
 
1239
- export { InngestExecutionEngine, InngestRun, InngestWorkflow, _compatibilityCheck, createStep, init, serve };
1592
+ export { InngestExecutionEngine, InngestPubSub, InngestRun, InngestWorkflow, _compatibilityCheck, createStep, init, serve };
1240
1593
  //# sourceMappingURL=index.js.map
1241
1594
  //# sourceMappingURL=index.js.map