@mastra/inngest 1.0.0-beta.10 → 1.0.0-beta.12

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/CHANGELOG.md CHANGED
@@ -1,5 +1,192 @@
1
1
  # @mastra/inngest
2
2
 
3
+ ## 1.0.0-beta.12
4
+
5
+ ### Minor Changes
6
+
7
+ - Added `createServe` factory function to support multiple web framework adapters for Inngest workflows. ([#11667](https://github.com/mastra-ai/mastra/pull/11667))
8
+
9
+ Previously, the `serve` function only supported Hono. Now you can use any framework adapter provided by the Inngest package (Express, Fastify, Koa, Next.js, and more).
10
+
11
+ **Before (Hono only)**
12
+
13
+ ```typescript
14
+ import { serve } from '@mastra/inngest';
15
+
16
+ // Only worked with Hono
17
+ app.all('/api/inngest', c => serve({ mastra, inngest })(c));
18
+ ```
19
+
20
+ **After (any framework)**
21
+
22
+ ```typescript
23
+ import { createServe } from '@mastra/inngest';
24
+ import { serve as expressAdapter } from 'inngest/express';
25
+ import { serve as fastifyAdapter } from 'inngest/fastify';
26
+
27
+ // Express
28
+ app.use('/api/inngest', createServe(expressAdapter)({ mastra, inngest }));
29
+
30
+ // Fastify
31
+ fastify.route({
32
+ method: ['GET', 'POST', 'PUT'],
33
+ url: '/api/inngest',
34
+ handler: createServe(fastifyAdapter)({ mastra, inngest }),
35
+ });
36
+ ```
37
+
38
+ The existing `serve` export remains available for backward compatibility with Hono.
39
+
40
+ Fixes #10053
41
+
42
+ ### Patch Changes
43
+
44
+ - Add additional context to workflow `onFinish` and `onError` callbacks ([#11705](https://github.com/mastra-ai/mastra/pull/11705))
45
+
46
+ The `onFinish` and `onError` lifecycle callbacks now receive additional properties:
47
+ - `runId` - The unique identifier for the workflow run
48
+ - `workflowId` - The workflow's identifier
49
+ - `resourceId` - Optional resource identifier (if provided when creating the run)
50
+ - `getInitData()` - Function that returns the initial input data passed to the workflow
51
+ - `mastra` - The Mastra instance (if workflow is registered with Mastra)
52
+ - `requestContext` - Request-scoped context data
53
+ - `logger` - The workflow's logger instance
54
+ - `state` - The workflow's current state object
55
+
56
+ ```typescript
57
+ const workflow = createWorkflow({
58
+ id: 'order-processing',
59
+ inputSchema: z.object({ orderId: z.string() }),
60
+ outputSchema: z.object({ status: z.string() }),
61
+ options: {
62
+ onFinish: async ({ runId, workflowId, getInitData, logger, state, mastra }) => {
63
+ const inputData = getInitData();
64
+ logger.info(`Workflow ${workflowId} run ${runId} completed`, {
65
+ orderId: inputData.orderId,
66
+ finalState: state,
67
+ });
68
+
69
+ // Access other Mastra components if needed
70
+ const agent = mastra?.getAgent('notification-agent');
71
+ },
72
+ onError: async ({ runId, workflowId, error, logger, requestContext }) => {
73
+ logger.error(`Workflow ${workflowId} run ${runId} failed: ${error?.message}`);
74
+ // Access request context for additional debugging
75
+ const userId = requestContext.get('userId');
76
+ },
77
+ },
78
+ });
79
+ ```
80
+
81
+ - Updated dependencies [[`08766f1`](https://github.com/mastra-ai/mastra/commit/08766f15e13ac0692fde2a8bd366c2e16e4321df), [`ae8baf7`](https://github.com/mastra-ai/mastra/commit/ae8baf7d8adcb0ff9dac11880400452bc49b33ff), [`cfabdd4`](https://github.com/mastra-ai/mastra/commit/cfabdd4aae7a726b706942d6836eeca110fb6267), [`a0e437f`](https://github.com/mastra-ai/mastra/commit/a0e437fac561b28ee719e0302d72b2f9b4c138f0), [`bec5efd`](https://github.com/mastra-ai/mastra/commit/bec5efde96653ccae6604e68c696d1bc6c1a0bf5), [`9eedf7d`](https://github.com/mastra-ai/mastra/commit/9eedf7de1d6e0022a2f4e5e9e6fe1ec468f9b43c)]:
82
+ - @mastra/core@1.0.0-beta.21
83
+
84
+ ## 1.0.0-beta.11
85
+
86
+ ### Patch Changes
87
+
88
+ - Add support for `retries` and `scorers` parameters across all `createStep` overloads.
89
+ ([#11495](https://github.com/mastra-ai/mastra/pull/11495))
90
+
91
+ The `createStep` function now includes support for the `retries` and `scorers` fields across all step creation patterns, enabling step-level retry configuration and AI evaluation support for regular steps, agent-based steps, and tool-based steps.
92
+
93
+ ```typescript
94
+ import { init } from '@mastra/inngest';
95
+ import { z } from 'zod';
96
+
97
+ const { createStep } = init(inngest);
98
+
99
+ // 1. Regular step with retries
100
+ const regularStep = createStep({
101
+ id: 'api-call',
102
+ inputSchema: z.object({ url: z.string() }),
103
+ outputSchema: z.object({ data: z.any() }),
104
+ retries: 3, // ← Will retry up to 3 times on failure
105
+ execute: async ({ inputData }) => {
106
+ const response = await fetch(inputData.url);
107
+ return { data: await response.json() };
108
+ },
109
+ });
110
+
111
+ // 2. Agent step with retries and scorers
112
+ const agentStep = createStep(myAgent, {
113
+ retries: 3,
114
+ scorers: [{ id: 'accuracy-scorer', scorer: myAccuracyScorer }],
115
+ });
116
+
117
+ // 3. Tool step with retries and scorers
118
+ const toolStep = createStep(myTool, {
119
+ retries: 2,
120
+ scorers: [{ id: 'quality-scorer', scorer: myQualityScorer }],
121
+ });
122
+ ```
123
+
124
+ This change ensures API consistency across all `createStep` overloads. All step types now support retry and evaluation configurations.
125
+
126
+ This is a non-breaking change - steps without these parameters continue to work exactly as before.
127
+
128
+ Fixes #9351
129
+
130
+ - Remove `streamVNext`, `resumeStreamVNext`, and `observeStreamVNext` methods, call `stream`, `resumeStream` and `observeStream` directly ([#11499](https://github.com/mastra-ai/mastra/pull/11499))
131
+
132
+ ```diff
133
+ + const run = await workflow.createRun({ runId: '123' });
134
+ - const stream = await run.streamVNext({ inputData: { ... } });
135
+ + const stream = await run.stream({ inputData: { ... } });
136
+ ```
137
+
138
+ - Unified `getWorkflowRunById` and `getWorkflowRunExecutionResult` into a single API that returns `WorkflowState` with both metadata and execution state. ([#11429](https://github.com/mastra-ai/mastra/pull/11429))
139
+
140
+ **What changed:**
141
+ - `getWorkflowRunById` now returns a unified `WorkflowState` object containing metadata (runId, workflowName, resourceId, createdAt, updatedAt) along with processed execution state (status, result, error, payload, steps)
142
+ - Added optional `fields` parameter to request only specific fields for better performance
143
+ - Added optional `withNestedWorkflows` parameter to control nested workflow step inclusion
144
+ - Removed `getWorkflowRunExecutionResult` - use `getWorkflowRunById` instead (breaking change)
145
+ - Removed `/execution-result` API endpoints from server (breaking change)
146
+ - Removed `runExecutionResult()` method from client SDK (breaking change)
147
+ - Removed `GetWorkflowRunExecutionResultResponse` type from client SDK (breaking change)
148
+
149
+ **Before:**
150
+
151
+ ```typescript
152
+ // Had to call two different methods for different data
153
+ const run = await workflow.getWorkflowRunById(runId); // Returns raw WorkflowRun with snapshot
154
+ const result = await workflow.getWorkflowRunExecutionResult(runId); // Returns processed execution state
155
+ ```
156
+
157
+ **After:**
158
+
159
+ ```typescript
160
+ // Single method returns everything
161
+ const run = await workflow.getWorkflowRunById(runId);
162
+ // Returns: { runId, workflowName, resourceId, createdAt, updatedAt, status, result, error, payload, steps }
163
+
164
+ // Request only specific fields for better performance (avoids expensive step fetching)
165
+ const status = await workflow.getWorkflowRunById(runId, { fields: ['status'] });
166
+
167
+ // Skip nested workflow steps for faster response
168
+ const run = await workflow.getWorkflowRunById(runId, { withNestedWorkflows: false });
169
+ ```
170
+
171
+ **Why:** The previous API required calling two separate methods to get complete workflow run information. This unification simplifies the API surface and gives users control over performance - fetching all steps (especially nested workflows) can be expensive, so the `fields` and `withNestedWorkflows` options let users request only what they need.
172
+
173
+ - Add cron scheduling support to Inngest workflows. Workflows can now be automatically triggered on a schedule by adding a `cron` property along with optional `inputData` and `initialState`: ([#11518](https://github.com/mastra-ai/mastra/pull/11518))
174
+
175
+ ```typescript
176
+ const workflow = createWorkflow({
177
+ id: 'scheduled-workflow',
178
+ inputSchema: z.object({ value: z.string() }),
179
+ outputSchema: z.object({ result: z.string() }),
180
+ steps: [step1],
181
+ cron: '0 0 * * *', // Run daily at midnight
182
+ inputData: { value: 'scheduled-run' }, // Optional inputData for the scheduled workflow run
183
+ initialState: { count: 0 }, // Optional initialState for the scheduled workflow run
184
+ });
185
+ ```
186
+
187
+ - Updated dependencies [[`d2d3e22`](https://github.com/mastra-ai/mastra/commit/d2d3e22a419ee243f8812a84e3453dd44365ecb0), [`bc72b52`](https://github.com/mastra-ai/mastra/commit/bc72b529ee4478fe89ecd85a8be47ce0127b82a0), [`05b8bee`](https://github.com/mastra-ai/mastra/commit/05b8bee9e50e6c2a4a2bf210eca25ee212ca24fa), [`c042bd0`](https://github.com/mastra-ai/mastra/commit/c042bd0b743e0e86199d0cb83344ca7690e34a9c), [`940a2b2`](https://github.com/mastra-ai/mastra/commit/940a2b27480626ed7e74f55806dcd2181c1dd0c2), [`e0941c3`](https://github.com/mastra-ai/mastra/commit/e0941c3d7fc75695d5d258e7008fd5d6e650800c), [`0c0580a`](https://github.com/mastra-ai/mastra/commit/0c0580a42f697cd2a7d5973f25bfe7da9055038a), [`28f5f89`](https://github.com/mastra-ai/mastra/commit/28f5f89705f2409921e3c45178796c0e0d0bbb64), [`e601b27`](https://github.com/mastra-ai/mastra/commit/e601b272c70f3a5ecca610373aa6223012704892), [`3d3366f`](https://github.com/mastra-ai/mastra/commit/3d3366f31683e7137d126a3a57174a222c5801fb), [`5a4953f`](https://github.com/mastra-ai/mastra/commit/5a4953f7d25bb15ca31ed16038092a39cb3f98b3), [`eb9e522`](https://github.com/mastra-ai/mastra/commit/eb9e522ce3070a405e5b949b7bf5609ca51d7fe2), [`20e6f19`](https://github.com/mastra-ai/mastra/commit/20e6f1971d51d3ff6dd7accad8aaaae826d540ed), [`4f0b3c6`](https://github.com/mastra-ai/mastra/commit/4f0b3c66f196c06448487f680ccbb614d281e2f7), [`74c4f22`](https://github.com/mastra-ai/mastra/commit/74c4f22ed4c71e72598eacc346ba95cdbc00294f), [`81b6a8f`](https://github.com/mastra-ai/mastra/commit/81b6a8ff79f49a7549d15d66624ac1a0b8f5f971), [`e4d366a`](https://github.com/mastra-ai/mastra/commit/e4d366aeb500371dd4210d6aa8361a4c21d87034), [`a4f010b`](https://github.com/mastra-ai/mastra/commit/a4f010b22e4355a5fdee70a1fe0f6e4a692cc29e), [`73b0bb3`](https://github.com/mastra-ai/mastra/commit/73b0bb394dba7c9482eb467a97ab283dbc0ef4db), [`5627a8c`](https://github.com/mastra-ai/mastra/commit/5627a8c6dc11fe3711b3fa7a6ffd6eb34100a306), [`3ff45d1`](https://github.com/mastra-ai/mastra/commit/3ff45d10e0c80c5335a957ab563da72feb623520), [`251df45`](https://github.com/mastra-ai/mastra/commit/251df4531407dfa46d805feb40ff3fb49769f455), [`f894d14`](https://github.com/mastra-ai/mastra/commit/f894d148946629af7b1f452d65a9cf864cec3765), [`c2b9547`](https://github.com/mastra-ai/mastra/commit/c2b9547bf435f56339f23625a743b2147ab1c7a6), [`580b592`](https://github.com/mastra-ai/mastra/commit/580b5927afc82fe460dfdf9a38a902511b6b7e7f), [`58e3931`](https://github.com/mastra-ai/mastra/commit/58e3931af9baa5921688566210f00fb0c10479fa), [`08bb631`](https://github.com/mastra-ai/mastra/commit/08bb631ae2b14684b2678e3549d0b399a6f0561e), [`4fba91b`](https://github.com/mastra-ai/mastra/commit/4fba91bec7c95911dc28e369437596b152b04cd0), [`12b0cc4`](https://github.com/mastra-ai/mastra/commit/12b0cc4077d886b1a552637dedb70a7ade93528c)]:
188
+ - @mastra/core@1.0.0-beta.20
189
+
3
190
  ## 1.0.0-beta.10
4
191
 
5
192
  ### Minor Changes
@@ -0,0 +1,18 @@
1
+ import { Mastra } from '@mastra/core/mastra';
2
+ import { Inngest } from 'inngest';
3
+ import type { InngestWorkflow } from '../../workflow.js';
4
+ export declare const INNGEST_PORT = 4000;
5
+ export declare const HANDLER_PORT = 4001;
6
+ export declare function createTestInngest(id: string): Inngest<{
7
+ id: string;
8
+ baseUrl: string;
9
+ }>;
10
+ export declare function resetInngest(): Promise<void>;
11
+ export declare function waitForInngestSync(ms?: number): Promise<void>;
12
+ export interface TestWorkflowResult {
13
+ workflow: InngestWorkflow<any, any, any>;
14
+ mastra: Mastra;
15
+ inngest: Inngest;
16
+ }
17
+ export declare function createTestWorkflow(adapterId: string): TestWorkflowResult;
18
+ //# sourceMappingURL=_utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_utils.d.ts","sourceRoot":"","sources":["../../../src/__tests__/adapters/_utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIlC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD,eAAO,MAAM,YAAY,OAAO,CAAC;AACjC,eAAO,MAAM,YAAY,OAAO,CAAC;AAEjC,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM;;;GAK3C;AAED,wBAAsB,YAAY,kBAIjC;AAED,wBAAsB,kBAAkB,CAAC,EAAE,SAAO,iBAEjD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,kBAAkB,CA0CxE"}
@@ -1,3 +1,4 @@
1
+ import type { RequestContext } from '@mastra/core/di';
1
2
  import type { SerializedError } from '@mastra/core/error';
2
3
  import type { PubSub } from '@mastra/core/events';
3
4
  import type { Mastra } from '@mastra/core/mastra';
@@ -58,9 +59,7 @@ export declare class InngestExecutionEngine extends DefaultExecutionEngine {
58
59
  * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
59
60
  * Inngest's step-level retry mechanism (not function-level retry).
60
61
  */
61
- wrapDurableOperation<T>(operationId: string, operationFn: () => Promise<T>, retryConfig?: {
62
- delay: number;
63
- }): Promise<T>;
62
+ wrapDurableOperation<T>(operationId: string, operationFn: () => Promise<T>): Promise<T>;
64
63
  /**
65
64
  * Provide Inngest step primitive in engine context
66
65
  */
@@ -75,6 +74,12 @@ export declare class InngestExecutionEngine extends DefaultExecutionEngine {
75
74
  error?: any;
76
75
  steps: Record<string, any>;
77
76
  tripwire?: any;
77
+ runId: string;
78
+ workflowId: string;
79
+ resourceId?: string;
80
+ input?: any;
81
+ requestContext: RequestContext;
82
+ state: Record<string, any>;
78
83
  }): Promise<void>;
79
84
  /**
80
85
  * Actually invoke the lifecycle callbacks. Called from workflow.ts finalize step.
@@ -85,6 +90,12 @@ export declare class InngestExecutionEngine extends DefaultExecutionEngine {
85
90
  error?: any;
86
91
  steps: Record<string, any>;
87
92
  tripwire?: any;
93
+ runId: string;
94
+ workflowId: string;
95
+ resourceId?: string;
96
+ input?: any;
97
+ requestContext: RequestContext;
98
+ state: Record<string, any>;
88
99
  }): Promise<void>;
89
100
  /**
90
101
  * Execute nested InngestWorkflow using inngestStep.invoke() for durability.
@@ -1 +1 @@
1
- {"version":3,"file":"execution-engine.d.ts","sourceRoot":"","sources":["../src/execution-engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execution-engine.d.ts","sourceRoot":"","sources":["../src/execution-engine.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ var agent = require('@mastra/core/agent');
3
4
  var tools = require('@mastra/core/tools');
4
5
  var workflows = require('@mastra/core/workflows');
5
6
  var _constants = require('@mastra/core/workflows/_constants');
@@ -60,38 +61,46 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
60
61
  * After retries exhausted, error propagates here and we return a failed result.
61
62
  */
62
63
  async executeStepWithRetry(stepId, runStep, params) {
63
- try {
64
- const result = await this.wrapDurableOperation(stepId, runStep, { delay: params.delay });
65
- return { ok: true, result };
66
- } catch (e) {
67
- const cause = e?.cause;
68
- if (cause?.status === "failed") {
69
- params.stepSpan?.error({
70
- error: e,
71
- attributes: { status: "failed" }
72
- });
73
- if (cause.error && !(cause.error instanceof Error)) {
74
- cause.error = error.getErrorFromUnknown(cause.error, { serializeStack: false });
75
- }
76
- return { ok: false, error: cause };
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));
77
67
  }
78
- const errorInstance = error.getErrorFromUnknown(e, {
79
- serializeStack: false,
80
- fallbackMessage: "Unknown step execution error"
81
- });
82
- params.stepSpan?.error({
83
- error: errorInstance,
84
- attributes: { status: "failed" }
85
- });
86
- return {
87
- ok: false,
88
- error: {
89
- status: "failed",
90
- error: errorInstance,
91
- endedAt: Date.now()
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 = error.getErrorFromUnknown(cause.error, { serializeStack: false });
81
+ }
82
+ return { ok: false, error: cause };
83
+ }
84
+ const errorInstance = error.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
+ };
92
100
  }
93
- };
101
+ }
94
102
  }
103
+ return { ok: false, error: { status: "failed", error: new Error("Unknown error"), endedAt: Date.now() } };
95
104
  }
96
105
  /**
97
106
  * Use Inngest's sleep primitive for durability
@@ -110,24 +119,11 @@ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
110
119
  * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
111
120
  * Inngest's step-level retry mechanism (not function-level retry).
112
121
  */
113
- async wrapDurableOperation(operationId, operationFn, retryConfig) {
122
+ async wrapDurableOperation(operationId, operationFn) {
114
123
  return this.inngestStep.run(operationId, async () => {
115
124
  try {
116
125
  return await operationFn();
117
126
  } catch (e) {
118
- if (retryConfig) {
119
- const errorInstance = error.getErrorFromUnknown(e, {
120
- serializeStack: false,
121
- fallbackMessage: "Unknown step execution error"
122
- });
123
- throw new inngest.RetryAfterError(errorInstance.message, retryConfig.delay, {
124
- cause: {
125
- status: "failed",
126
- error: errorInstance,
127
- endedAt: Date.now()
128
- }
129
- });
130
- }
131
127
  throw e;
132
128
  }
133
129
  });
@@ -1039,9 +1035,6 @@ var InngestRun = class extends workflows.Run {
1039
1035
  });
1040
1036
  return this.streamOutput;
1041
1037
  }
1042
- streamVNext(args = {}) {
1043
- return this.stream(args);
1044
- }
1045
1038
  timeTravelStream({
1046
1039
  inputData,
1047
1040
  resumeData,
@@ -1132,9 +1125,11 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1132
1125
  #mastra;
1133
1126
  inngest;
1134
1127
  function;
1128
+ cronFunction;
1135
1129
  flowControlConfig;
1130
+ cronConfig;
1136
1131
  constructor(params, inngest) {
1137
- const { concurrency, rateLimit, throttle, debounce, priority, ...workflowParams } = params;
1132
+ const { concurrency, rateLimit, throttle, debounce, priority, cron, inputData, initialState, ...workflowParams } = params;
1138
1133
  super(workflowParams);
1139
1134
  this.engineType = "inngest";
1140
1135
  const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
@@ -1143,6 +1138,9 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1143
1138
  this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
1144
1139
  this.#mastra = params.mastra;
1145
1140
  this.inngest = inngest;
1141
+ if (cron) {
1142
+ this.cronConfig = { cron, inputData, initialState };
1143
+ }
1146
1144
  }
1147
1145
  async listWorkflowRuns(args) {
1148
1146
  const storage = this.#mastra?.getStorage();
@@ -1156,19 +1154,6 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1156
1154
  }
1157
1155
  return workflowsStore.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
1158
1156
  }
1159
- async getWorkflowRunById(runId) {
1160
- const storage = this.#mastra?.getStorage();
1161
- if (!storage) {
1162
- this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
1163
- return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
1164
- }
1165
- const workflowsStore = await storage.getStore("workflows");
1166
- if (!workflowsStore) {
1167
- return this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null;
1168
- }
1169
- const run = await workflowsStore.getWorkflowRunById({ runId, workflowName: this.id });
1170
- return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
1171
- }
1172
1157
  __registerMastra(mastra) {
1173
1158
  super.__registerMastra(mastra);
1174
1159
  this.#mastra = mastra;
@@ -1212,10 +1197,11 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1212
1197
  workflowStatus: run.workflowRunStatus,
1213
1198
  stepResults: {}
1214
1199
  });
1215
- const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse, {
1200
+ const existingRun = await this.getWorkflowRunById(runIdToUse, {
1216
1201
  withNestedWorkflows: false
1217
1202
  });
1218
- if (!workflowSnapshotInStorage && shouldPersistSnapshot) {
1203
+ const existsInStorage = existingRun && !existingRun.isFromInMemory;
1204
+ if (!existsInStorage && shouldPersistSnapshot) {
1219
1205
  const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
1220
1206
  await workflowsStore?.persistWorkflowSnapshot({
1221
1207
  workflowName: this.id,
@@ -1240,6 +1226,30 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1240
1226
  }
1241
1227
  return run;
1242
1228
  }
1229
+ //createCronFunction is only called if cronConfig.cron is defined.
1230
+ createCronFunction() {
1231
+ if (this.cronFunction) {
1232
+ return this.cronFunction;
1233
+ }
1234
+ this.cronFunction = this.inngest.createFunction(
1235
+ {
1236
+ id: `workflow.${this.id}.cron`,
1237
+ retries: 0,
1238
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1239
+ ...this.flowControlConfig
1240
+ },
1241
+ { cron: this.cronConfig?.cron ?? "" },
1242
+ async () => {
1243
+ const run = await this.createRun();
1244
+ const result = await run.start({
1245
+ inputData: this.cronConfig?.inputData,
1246
+ initialState: this.cronConfig?.initialState
1247
+ });
1248
+ return { result, runId: run.runId };
1249
+ }
1250
+ );
1251
+ return this.cronFunction;
1252
+ }
1243
1253
  getFunction() {
1244
1254
  if (this.function) {
1245
1255
  return this.function;
@@ -1247,7 +1257,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1247
1257
  this.function = this.inngest.createFunction(
1248
1258
  {
1249
1259
  id: `workflow.${this.id}`,
1250
- retries: Math.min(this.retryConfig?.attempts ?? 0, 20),
1260
+ retries: 0,
1251
1261
  cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1252
1262
  // Spread flow control configuration
1253
1263
  ...this.flowControlConfig
@@ -1261,6 +1271,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1261
1271
  });
1262
1272
  }
1263
1273
  const pubsub = new InngestPubSub(this.inngest, this.id, publish);
1274
+ const requestContext = new di.RequestContext(Object.entries(event.data.requestContext ?? {}));
1264
1275
  const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
1265
1276
  const result = await engine.execute({
1266
1277
  workflowId: this.id,
@@ -1272,7 +1283,7 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1272
1283
  initialState,
1273
1284
  pubsub,
1274
1285
  retryConfig: this.retryConfig,
1275
- requestContext: new di.RequestContext(Object.entries(event.data.requestContext ?? {})),
1286
+ requestContext,
1276
1287
  resume,
1277
1288
  timeTravel,
1278
1289
  perStep,
@@ -1294,7 +1305,19 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1294
1305
  });
1295
1306
  await step.run(`workflow.${this.id}.finalize`, async () => {
1296
1307
  if (result.status !== "paused") {
1297
- await engine.invokeLifecycleCallbacksInternal(result);
1308
+ await engine.invokeLifecycleCallbacksInternal({
1309
+ status: result.status,
1310
+ result: "result" in result ? result.result : void 0,
1311
+ error: "error" in result ? result.error : void 0,
1312
+ steps: result.steps,
1313
+ tripwire: "tripwire" in result ? result.tripwire : void 0,
1314
+ runId,
1315
+ workflowId: this.id,
1316
+ resourceId,
1317
+ input: inputData,
1318
+ requestContext,
1319
+ state: result.state ?? initialState ?? {}
1320
+ });
1298
1321
  }
1299
1322
  if (result.status === "failed") {
1300
1323
  throw new inngest.NonRetriableError(`Workflow failed`, {
@@ -1322,15 +1345,14 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
1322
1345
  });
1323
1346
  }
1324
1347
  getFunctions() {
1325
- return [this.getFunction(), ...this.getNestedFunctions(this.executionGraph.steps)];
1348
+ return [
1349
+ this.getFunction(),
1350
+ ...this.cronConfig?.cron ? [this.createCronFunction()] : [],
1351
+ ...this.getNestedFunctions(this.executionGraph.steps)
1352
+ ];
1326
1353
  }
1327
1354
  };
1328
- function serve({
1329
- mastra,
1330
- inngest,
1331
- functions: userFunctions = [],
1332
- registerOptions
1333
- }) {
1355
+ function prepareServeOptions({ mastra, inngest, functions: userFunctions = [], registerOptions }) {
1334
1356
  const wfs = mastra.listWorkflows();
1335
1357
  const workflowFunctions = Array.from(
1336
1358
  new Set(
@@ -1343,32 +1365,32 @@ function serve({
1343
1365
  })
1344
1366
  )
1345
1367
  );
1346
- return hono.serve({
1368
+ return {
1347
1369
  ...registerOptions,
1348
1370
  client: inngest,
1349
1371
  functions: [...workflowFunctions, ...userFunctions]
1350
- });
1372
+ };
1373
+ }
1374
+ function createServe(adapter) {
1375
+ return (options) => {
1376
+ const serveOptions = prepareServeOptions(options);
1377
+ return adapter(serveOptions);
1378
+ };
1351
1379
  }
1380
+ var serve = createServe(hono.serve);
1352
1381
 
1353
1382
  // src/types.ts
1354
1383
  var _compatibilityCheck = true;
1355
1384
 
1356
1385
  // src/index.ts
1357
- function isAgent(params) {
1358
- return params?.component === "AGENT";
1359
- }
1360
- function isTool(params) {
1361
- return params instanceof tools.Tool;
1362
- }
1363
- function isInngestWorkflow(params) {
1364
- return params instanceof InngestWorkflow;
1365
- }
1366
- function createStep(params, agentOptions) {
1367
- if (isInngestWorkflow(params)) {
1386
+ function createStep(params, agentOrToolOptions) {
1387
+ if (params instanceof InngestWorkflow) {
1368
1388
  return params;
1369
1389
  }
1370
- if (isAgent(params)) {
1371
- const outputSchema = agentOptions?.structuredOutput?.schema ?? zod.z.object({ text: zod.z.string() });
1390
+ if (params instanceof agent.Agent) {
1391
+ const options = agentOrToolOptions;
1392
+ const outputSchema = options?.structuredOutput?.schema ?? zod.z.object({ text: zod.z.string() });
1393
+ const { retries, scorers, ...agentOptions } = options ?? {};
1372
1394
  return {
1373
1395
  id: params.name,
1374
1396
  description: params.getDescription(),
@@ -1378,6 +1400,8 @@ function createStep(params, agentOptions) {
1378
1400
  // threadId: z.string().optional(),
1379
1401
  }),
1380
1402
  outputSchema,
1403
+ retries,
1404
+ scorers,
1381
1405
  execute: async ({
1382
1406
  inputData,
1383
1407
  runId,
@@ -1473,7 +1497,8 @@ function createStep(params, agentOptions) {
1473
1497
  component: params.component
1474
1498
  };
1475
1499
  }
1476
- if (isTool(params)) {
1500
+ if (params instanceof tools.Tool) {
1501
+ const toolOpts = agentOrToolOptions;
1477
1502
  if (!params.inputSchema || !params.outputSchema) {
1478
1503
  throw new Error("Tool must have input and output schemas defined");
1479
1504
  }
@@ -1485,6 +1510,8 @@ function createStep(params, agentOptions) {
1485
1510
  outputSchema: params.outputSchema,
1486
1511
  suspendSchema: params.suspendSchema,
1487
1512
  resumeSchema: params.resumeSchema,
1513
+ retries: toolOpts?.retries,
1514
+ scorers: toolOpts?.scorers,
1488
1515
  execute: async ({
1489
1516
  inputData,
1490
1517
  mastra,
@@ -1522,6 +1549,8 @@ function createStep(params, agentOptions) {
1522
1549
  outputSchema: params.outputSchema,
1523
1550
  resumeSchema: params.resumeSchema,
1524
1551
  suspendSchema: params.suspendSchema,
1552
+ retries: params.retries,
1553
+ scorers: params.scorers,
1525
1554
  execute: params.execute
1526
1555
  };
1527
1556
  }
@@ -1570,6 +1599,7 @@ exports.InngestPubSub = InngestPubSub;
1570
1599
  exports.InngestRun = InngestRun;
1571
1600
  exports.InngestWorkflow = InngestWorkflow;
1572
1601
  exports._compatibilityCheck = _compatibilityCheck;
1602
+ exports.createServe = createServe;
1573
1603
  exports.createStep = createStep;
1574
1604
  exports.init = init;
1575
1605
  exports.serve = serve;