@mastra/inngest 0.0.0-taofeeqInngest-20250603090617 → 0.0.0-testing-cloud-studios-20260114234039

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,27 +1,513 @@
1
1
  'use strict';
2
2
 
3
- var crypto = require('crypto');
4
- var realtime = require('@inngest/realtime');
5
- var di = require('@mastra/core/di');
3
+ var agent = require('@mastra/core/agent');
4
+ var tools = require('@mastra/core/tools');
6
5
  var workflows = require('@mastra/core/workflows');
7
6
  var _constants = require('@mastra/core/workflows/_constants');
7
+ var zod = require('zod');
8
+ var crypto$1 = require('crypto');
9
+ var di = require('@mastra/core/di');
10
+ var inngest = require('inngest');
11
+ var error = require('@mastra/core/error');
12
+ var realtime = require('@inngest/realtime');
13
+ var events = require('@mastra/core/events');
14
+ var web = require('stream/web');
15
+ var stream = require('@mastra/core/stream');
8
16
  var hono = require('inngest/hono');
9
17
 
10
18
  // src/index.ts
11
- function serve({ mastra, inngest }) {
12
- const wfs = mastra.getWorkflows();
13
- const functions = Object.values(wfs).flatMap((wf) => {
14
- if (wf instanceof InngestWorkflow) {
15
- wf.__registerMastra(mastra);
16
- return wf.getFunctions();
17
- }
18
- return [];
19
- });
20
- return hono.serve({
21
- client: inngest,
22
- functions
23
- });
24
- }
19
+ var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
20
+ inngestStep;
21
+ inngestAttempts;
22
+ constructor(mastra, inngestStep, inngestAttempts = 0, options) {
23
+ super({ mastra, options });
24
+ this.inngestStep = inngestStep;
25
+ this.inngestAttempts = inngestAttempts;
26
+ }
27
+ // =============================================================================
28
+ // Hook Overrides
29
+ // =============================================================================
30
+ /**
31
+ * Format errors while preserving Error instances and their custom properties.
32
+ * Uses getErrorFromUnknown to ensure all error properties are preserved.
33
+ */
34
+ formatResultError(error$1, lastOutput) {
35
+ const outputError = lastOutput?.error;
36
+ const errorSource = error$1 || outputError;
37
+ const errorInstance = error.getErrorFromUnknown(errorSource, {
38
+ serializeStack: true,
39
+ // Include stack in JSON for better debugging in Inngest
40
+ fallbackMessage: "Unknown workflow error"
41
+ });
42
+ return errorInstance.toJSON();
43
+ }
44
+ /**
45
+ * Detect InngestWorkflow instances for special nested workflow handling
46
+ */
47
+ isNestedWorkflowStep(step) {
48
+ return step instanceof InngestWorkflow;
49
+ }
50
+ /**
51
+ * Inngest requires requestContext serialization for memoization.
52
+ * When steps are replayed, the original function doesn't re-execute,
53
+ * so requestContext modifications must be captured and restored.
54
+ */
55
+ requiresDurableContextSerialization() {
56
+ return true;
57
+ }
58
+ /**
59
+ * Execute a step with retry logic for Inngest.
60
+ * Retries are handled via step-level retry (RetryAfterError thrown INSIDE step.run()).
61
+ * After retries exhausted, error propagates here and we return a failed result.
62
+ */
63
+ async executeStepWithRetry(stepId, runStep, params) {
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));
67
+ }
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
+ };
100
+ }
101
+ }
102
+ }
103
+ return { ok: false, error: { status: "failed", error: new Error("Unknown error"), endedAt: Date.now() } };
104
+ }
105
+ /**
106
+ * Use Inngest's sleep primitive for durability
107
+ */
108
+ async executeSleepDuration(duration, sleepId, workflowId) {
109
+ await this.inngestStep.sleep(`workflow.${workflowId}.sleep.${sleepId}`, duration < 0 ? 0 : duration);
110
+ }
111
+ /**
112
+ * Use Inngest's sleepUntil primitive for durability
113
+ */
114
+ async executeSleepUntilDate(date, sleepUntilId, workflowId) {
115
+ await this.inngestStep.sleepUntil(`workflow.${workflowId}.sleepUntil.${sleepUntilId}`, date);
116
+ }
117
+ /**
118
+ * Wrap durable operations in Inngest step.run() for durability.
119
+ * If retryConfig is provided, throws RetryAfterError INSIDE step.run() to trigger
120
+ * Inngest's step-level retry mechanism (not function-level retry).
121
+ */
122
+ async wrapDurableOperation(operationId, operationFn) {
123
+ return this.inngestStep.run(operationId, async () => {
124
+ try {
125
+ return await operationFn();
126
+ } catch (e) {
127
+ throw e;
128
+ }
129
+ });
130
+ }
131
+ /**
132
+ * Provide Inngest step primitive in engine context
133
+ */
134
+ getEngineContext() {
135
+ return { step: this.inngestStep };
136
+ }
137
+ /**
138
+ * For Inngest, lifecycle callbacks are invoked in the workflow's finalize step
139
+ * (wrapped in step.run for durability), not in execute(). Override to skip.
140
+ */
141
+ async invokeLifecycleCallbacks(_result) {
142
+ }
143
+ /**
144
+ * Actually invoke the lifecycle callbacks. Called from workflow.ts finalize step.
145
+ */
146
+ async invokeLifecycleCallbacksInternal(result) {
147
+ return super.invokeLifecycleCallbacks(result);
148
+ }
149
+ /**
150
+ * Execute nested InngestWorkflow using inngestStep.invoke() for durability.
151
+ * This MUST be called directly (not inside step.run()) due to Inngest constraints.
152
+ */
153
+ async executeWorkflowStep(params) {
154
+ if (!(params.step instanceof InngestWorkflow)) {
155
+ return null;
156
+ }
157
+ const {
158
+ step,
159
+ stepResults,
160
+ executionContext,
161
+ resume,
162
+ timeTravel,
163
+ prevOutput,
164
+ inputData,
165
+ pubsub,
166
+ startedAt,
167
+ perStep
168
+ } = params;
169
+ const isResume = !!resume?.steps?.length;
170
+ let result;
171
+ let runId;
172
+ const isTimeTravel = !!(timeTravel && timeTravel.steps?.length > 1 && timeTravel.steps[0] === step.id);
173
+ try {
174
+ if (isResume) {
175
+ runId = stepResults[resume?.steps?.[0] ?? ""]?.suspendPayload?.__workflow_meta?.runId ?? crypto$1.randomUUID();
176
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
177
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
178
+ workflowName: step.id,
179
+ runId
180
+ });
181
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
182
+ function: step.getFunction(),
183
+ data: {
184
+ inputData,
185
+ initialState: executionContext.state ?? snapshot?.value ?? {},
186
+ runId,
187
+ resume: {
188
+ runId,
189
+ steps: resume.steps.slice(1),
190
+ stepResults: snapshot?.context,
191
+ resumePayload: resume.resumePayload,
192
+ resumePath: resume.steps?.[1] ? snapshot?.suspendedPaths?.[resume.steps?.[1]] : void 0
193
+ },
194
+ outputOptions: { includeState: true },
195
+ perStep
196
+ }
197
+ });
198
+ result = invokeResp.result;
199
+ runId = invokeResp.runId;
200
+ executionContext.state = invokeResp.result.state;
201
+ } else if (isTimeTravel) {
202
+ const workflowsStoreForTimeTravel = await this.mastra?.getStorage()?.getStore("workflows");
203
+ const snapshot = await workflowsStoreForTimeTravel?.loadWorkflowSnapshot({
204
+ workflowName: step.id,
205
+ runId: executionContext.runId
206
+ }) ?? { context: {} };
207
+ const timeTravelParams = workflows.createTimeTravelExecutionParams({
208
+ steps: timeTravel.steps.slice(1),
209
+ inputData: timeTravel.inputData,
210
+ resumeData: timeTravel.resumeData,
211
+ context: timeTravel.nestedStepResults?.[step.id] ?? {},
212
+ nestedStepsContext: timeTravel.nestedStepResults ?? {},
213
+ snapshot,
214
+ graph: step.buildExecutionGraph()
215
+ });
216
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
217
+ function: step.getFunction(),
218
+ data: {
219
+ timeTravel: timeTravelParams,
220
+ initialState: executionContext.state ?? {},
221
+ runId: executionContext.runId,
222
+ outputOptions: { includeState: true },
223
+ perStep
224
+ }
225
+ });
226
+ result = invokeResp.result;
227
+ runId = invokeResp.runId;
228
+ executionContext.state = invokeResp.result.state;
229
+ } else {
230
+ const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
231
+ function: step.getFunction(),
232
+ data: {
233
+ inputData,
234
+ initialState: executionContext.state ?? {},
235
+ outputOptions: { includeState: true },
236
+ perStep
237
+ }
238
+ });
239
+ result = invokeResp.result;
240
+ runId = invokeResp.runId;
241
+ executionContext.state = invokeResp.result.state;
242
+ }
243
+ } catch (e) {
244
+ const errorCause = e?.cause;
245
+ if (errorCause && typeof errorCause === "object") {
246
+ result = errorCause;
247
+ runId = errorCause.runId || crypto$1.randomUUID();
248
+ } else {
249
+ runId = crypto$1.randomUUID();
250
+ result = {
251
+ status: "failed",
252
+ error: e instanceof Error ? e : new Error(String(e)),
253
+ steps: {},
254
+ input: inputData
255
+ };
256
+ }
257
+ }
258
+ const res = await this.inngestStep.run(
259
+ `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
260
+ async () => {
261
+ if (result.status === "failed") {
262
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
263
+ type: "watch",
264
+ runId: executionContext.runId,
265
+ data: {
266
+ type: "workflow-step-result",
267
+ payload: {
268
+ id: step.id,
269
+ status: "failed",
270
+ error: result?.error,
271
+ payload: prevOutput
272
+ }
273
+ }
274
+ });
275
+ return { executionContext, result: { status: "failed", error: result?.error, endedAt: Date.now() } };
276
+ } else if (result.status === "suspended") {
277
+ const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
278
+ const stepRes = stepResult;
279
+ return stepRes?.status === "suspended";
280
+ });
281
+ for (const [stepName, stepResult] of suspendedSteps) {
282
+ const suspendPath = [stepName, ...stepResult?.suspendPayload?.__workflow_meta?.path ?? []];
283
+ executionContext.suspendedPaths[step.id] = executionContext.executionPath;
284
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
285
+ type: "watch",
286
+ runId: executionContext.runId,
287
+ data: {
288
+ type: "workflow-step-suspended",
289
+ payload: {
290
+ id: step.id,
291
+ status: "suspended"
292
+ }
293
+ }
294
+ });
295
+ return {
296
+ executionContext,
297
+ result: {
298
+ status: "suspended",
299
+ suspendedAt: Date.now(),
300
+ payload: stepResult.payload,
301
+ suspendPayload: {
302
+ ...stepResult?.suspendPayload,
303
+ __workflow_meta: { runId, path: suspendPath }
304
+ }
305
+ }
306
+ };
307
+ }
308
+ return {
309
+ executionContext,
310
+ result: {
311
+ status: "suspended",
312
+ suspendedAt: Date.now(),
313
+ payload: {}
314
+ }
315
+ };
316
+ } else if (result.status === "tripwire") {
317
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
318
+ type: "watch",
319
+ runId: executionContext.runId,
320
+ data: {
321
+ type: "workflow-step-result",
322
+ payload: {
323
+ id: step.id,
324
+ status: "tripwire",
325
+ error: result?.tripwire?.reason,
326
+ payload: prevOutput
327
+ }
328
+ }
329
+ });
330
+ return {
331
+ executionContext,
332
+ result: {
333
+ status: "tripwire",
334
+ tripwire: result?.tripwire,
335
+ endedAt: Date.now()
336
+ }
337
+ };
338
+ } else if (perStep || result.status === "paused") {
339
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
340
+ type: "watch",
341
+ runId: executionContext.runId,
342
+ data: {
343
+ type: "workflow-step-result",
344
+ payload: {
345
+ id: step.id,
346
+ status: "paused"
347
+ }
348
+ }
349
+ });
350
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
351
+ type: "watch",
352
+ runId: executionContext.runId,
353
+ data: {
354
+ type: "workflow-step-finish",
355
+ payload: {
356
+ id: step.id,
357
+ metadata: {}
358
+ }
359
+ }
360
+ });
361
+ return { executionContext, result: { status: "paused" } };
362
+ }
363
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
364
+ type: "watch",
365
+ runId: executionContext.runId,
366
+ data: {
367
+ type: "workflow-step-result",
368
+ payload: {
369
+ id: step.id,
370
+ status: "success",
371
+ output: result?.result
372
+ }
373
+ }
374
+ });
375
+ await pubsub.publish(`workflow.events.v2.${executionContext.runId}`, {
376
+ type: "watch",
377
+ runId: executionContext.runId,
378
+ data: {
379
+ type: "workflow-step-finish",
380
+ payload: {
381
+ id: step.id,
382
+ metadata: {}
383
+ }
384
+ }
385
+ });
386
+ return { executionContext, result: { status: "success", output: result?.result, endedAt: Date.now() } };
387
+ }
388
+ );
389
+ Object.assign(executionContext, res.executionContext);
390
+ return {
391
+ ...res.result,
392
+ startedAt,
393
+ payload: inputData,
394
+ resumedAt: resume?.steps[0] === step.id ? startedAt : void 0,
395
+ resumePayload: resume?.steps[0] === step.id ? resume?.resumePayload : void 0
396
+ };
397
+ }
398
+ };
399
+ var InngestPubSub = class extends events.PubSub {
400
+ inngest;
401
+ workflowId;
402
+ publishFn;
403
+ subscriptions = /* @__PURE__ */ new Map();
404
+ constructor(inngest, workflowId, publishFn) {
405
+ super();
406
+ this.inngest = inngest;
407
+ this.workflowId = workflowId;
408
+ this.publishFn = publishFn;
409
+ }
410
+ /**
411
+ * Publish an event to Inngest's realtime system.
412
+ *
413
+ * Topic format: "workflow.events.v2.{runId}"
414
+ * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
415
+ */
416
+ async publish(topic, event) {
417
+ if (!this.publishFn) {
418
+ return;
419
+ }
420
+ const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
421
+ if (!match) {
422
+ return;
423
+ }
424
+ const runId = match[1];
425
+ try {
426
+ await this.publishFn({
427
+ channel: `workflow:${this.workflowId}:${runId}`,
428
+ topic: "watch",
429
+ data: event.data
430
+ });
431
+ } catch (err) {
432
+ console.error("InngestPubSub publish error:", err?.message ?? err);
433
+ }
434
+ }
435
+ /**
436
+ * Subscribe to events from Inngest's realtime system.
437
+ *
438
+ * Topic format: "workflow.events.v2.{runId}"
439
+ * Maps to Inngest channel: "workflow:{workflowId}:{runId}"
440
+ */
441
+ async subscribe(topic, cb) {
442
+ const match = topic.match(/^workflow\.events\.v2\.(.+)$/);
443
+ if (!match || !match[1]) {
444
+ return;
445
+ }
446
+ const runId = match[1];
447
+ if (this.subscriptions.has(topic)) {
448
+ this.subscriptions.get(topic).callbacks.add(cb);
449
+ return;
450
+ }
451
+ const callbacks = /* @__PURE__ */ new Set([cb]);
452
+ const channel = `workflow:${this.workflowId}:${runId}`;
453
+ const streamPromise = realtime.subscribe(
454
+ {
455
+ channel,
456
+ topics: ["watch"],
457
+ app: this.inngest
458
+ },
459
+ (message) => {
460
+ const event = {
461
+ id: crypto.randomUUID(),
462
+ type: "watch",
463
+ runId,
464
+ data: message.data,
465
+ createdAt: /* @__PURE__ */ new Date()
466
+ };
467
+ for (const callback of callbacks) {
468
+ callback(event);
469
+ }
470
+ }
471
+ );
472
+ this.subscriptions.set(topic, {
473
+ unsubscribe: () => {
474
+ streamPromise.then((stream) => stream.cancel()).catch((err) => {
475
+ console.error("InngestPubSub unsubscribe error:", err);
476
+ });
477
+ },
478
+ callbacks
479
+ });
480
+ }
481
+ /**
482
+ * Unsubscribe a callback from a topic.
483
+ * If no callbacks remain, the underlying Inngest subscription is cancelled.
484
+ */
485
+ async unsubscribe(topic, cb) {
486
+ const sub = this.subscriptions.get(topic);
487
+ if (!sub) {
488
+ return;
489
+ }
490
+ sub.callbacks.delete(cb);
491
+ if (sub.callbacks.size === 0) {
492
+ sub.unsubscribe();
493
+ this.subscriptions.delete(topic);
494
+ }
495
+ }
496
+ /**
497
+ * Flush any pending operations. No-op for Inngest.
498
+ */
499
+ async flush() {
500
+ }
501
+ /**
502
+ * Clean up all subscriptions during graceful shutdown.
503
+ */
504
+ async close() {
505
+ for (const [, sub] of this.subscriptions) {
506
+ sub.unsubscribe();
507
+ }
508
+ this.subscriptions.clear();
509
+ }
510
+ };
25
511
  var InngestRun = class extends workflows.Run {
26
512
  inngest;
27
513
  serializedStepGraph;
@@ -33,46 +519,209 @@ var InngestRun = class extends workflows.Run {
33
519
  this.#mastra = params.mastra;
34
520
  }
35
521
  async getRuns(eventId) {
36
- const response = await fetch(`${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`, {
37
- headers: {
38
- Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
522
+ const maxRetries = 3;
523
+ let lastError = null;
524
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
525
+ try {
526
+ const response = await fetch(
527
+ `${this.inngest.apiBaseUrl ?? "https://api.inngest.com"}/v1/events/${eventId}/runs`,
528
+ {
529
+ headers: {
530
+ Authorization: `Bearer ${process.env.INNGEST_SIGNING_KEY}`
531
+ }
532
+ }
533
+ );
534
+ if (response.status === 429) {
535
+ const retryAfter = parseInt(response.headers.get("retry-after") || "2", 10);
536
+ await new Promise((resolve) => setTimeout(resolve, retryAfter * 1e3));
537
+ continue;
538
+ }
539
+ if (!response.ok) {
540
+ throw new Error(`Inngest API error: ${response.status} ${response.statusText}`);
541
+ }
542
+ const text = await response.text();
543
+ if (!text) {
544
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * (attempt + 1)));
545
+ continue;
546
+ }
547
+ const json = JSON.parse(text);
548
+ return json.data;
549
+ } catch (error) {
550
+ lastError = error;
551
+ if (attempt < maxRetries - 1) {
552
+ await new Promise((resolve) => setTimeout(resolve, 1e3 * Math.pow(2, attempt)));
553
+ }
554
+ }
555
+ }
556
+ throw new inngest.NonRetriableError(`Failed to get runs after ${maxRetries} attempts: ${lastError?.message}`);
557
+ }
558
+ async getRunOutput(eventId, maxWaitMs = 3e5) {
559
+ const startTime = Date.now();
560
+ const storage = this.#mastra?.getStorage();
561
+ const workflowsStore = await storage?.getStore("workflows");
562
+ while (Date.now() - startTime < maxWaitMs) {
563
+ let runs;
564
+ try {
565
+ runs = await this.getRuns(eventId);
566
+ } catch (error) {
567
+ if (error instanceof inngest.NonRetriableError) {
568
+ throw error;
569
+ }
570
+ throw new inngest.NonRetriableError(
571
+ `Failed to poll workflow status: ${error instanceof Error ? error.message : String(error)}`
572
+ );
573
+ }
574
+ if (runs?.[0]?.status === "Completed" && runs?.[0]?.event_id === eventId) {
575
+ return runs[0];
576
+ }
577
+ if (runs?.[0]?.status === "Failed") {
578
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
579
+ workflowName: this.workflowId,
580
+ runId: this.runId
581
+ });
582
+ if (snapshot?.context) {
583
+ snapshot.context = workflows.hydrateSerializedStepErrors(snapshot.context);
584
+ }
585
+ return {
586
+ output: {
587
+ result: {
588
+ steps: snapshot?.context,
589
+ status: "failed",
590
+ // Get the original error from NonRetriableError's cause (which contains the workflow result)
591
+ error: error.getErrorFromUnknown(runs?.[0]?.output?.cause?.error, { serializeStack: false })
592
+ }
593
+ }
594
+ };
39
595
  }
596
+ if (runs?.[0]?.status === "Cancelled") {
597
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
598
+ workflowName: this.workflowId,
599
+ runId: this.runId
600
+ });
601
+ return { output: { result: { steps: snapshot?.context, status: "canceled" } } };
602
+ }
603
+ await new Promise((resolve) => setTimeout(resolve, 1e3 + Math.random() * 1e3));
604
+ }
605
+ throw new inngest.NonRetriableError(`Workflow did not complete within ${maxWaitMs}ms`);
606
+ }
607
+ async cancel() {
608
+ const storage = this.#mastra?.getStorage();
609
+ await this.inngest.send({
610
+ name: `cancel.workflow.${this.workflowId}`,
611
+ data: {
612
+ runId: this.runId
613
+ }
614
+ });
615
+ const workflowsStore = await storage?.getStore("workflows");
616
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
617
+ workflowName: this.workflowId,
618
+ runId: this.runId
40
619
  });
41
- const json = await response.json();
42
- return json.data;
620
+ if (snapshot) {
621
+ await workflowsStore?.persistWorkflowSnapshot({
622
+ workflowName: this.workflowId,
623
+ runId: this.runId,
624
+ resourceId: this.resourceId,
625
+ snapshot: {
626
+ ...snapshot,
627
+ status: "canceled",
628
+ value: snapshot.value
629
+ }
630
+ });
631
+ }
43
632
  }
44
- async getRunOutput(eventId) {
45
- let runs = await this.getRuns(eventId);
46
- while (runs?.[0]?.status !== "Completed") {
47
- await new Promise((resolve) => setTimeout(resolve, 1e3));
48
- runs = await this.getRuns(eventId);
49
- if (runs?.[0]?.status === "Failed" || runs?.[0]?.status === "Cancelled") {
50
- throw new Error(`Function run ${runs?.[0]?.status}`);
633
+ async start(params) {
634
+ return this._start(params);
635
+ }
636
+ /**
637
+ * Starts the workflow execution without waiting for completion (fire-and-forget).
638
+ * Returns immediately with the runId after sending the event to Inngest.
639
+ * The workflow executes independently in Inngest.
640
+ * Use this when you don't need to wait for the result or want to avoid polling failures.
641
+ */
642
+ async startAsync(params) {
643
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
644
+ await workflowsStore?.persistWorkflowSnapshot({
645
+ workflowName: this.workflowId,
646
+ runId: this.runId,
647
+ resourceId: this.resourceId,
648
+ snapshot: {
649
+ runId: this.runId,
650
+ serializedStepGraph: this.serializedStepGraph,
651
+ status: "running",
652
+ value: {},
653
+ context: {},
654
+ activePaths: [],
655
+ suspendedPaths: {},
656
+ activeStepsPath: {},
657
+ resumeLabels: {},
658
+ waitingPaths: {},
659
+ timestamp: Date.now()
660
+ }
661
+ });
662
+ const inputDataToUse = await this._validateInput(params.inputData);
663
+ const initialStateToUse = await this._validateInitialState(params.initialState ?? {});
664
+ const eventOutput = await this.inngest.send({
665
+ name: `workflow.${this.workflowId}`,
666
+ data: {
667
+ inputData: inputDataToUse,
668
+ initialState: initialStateToUse,
669
+ runId: this.runId,
670
+ resourceId: this.resourceId,
671
+ outputOptions: params.outputOptions,
672
+ tracingOptions: params.tracingOptions,
673
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {},
674
+ perStep: params.perStep
51
675
  }
676
+ });
677
+ const eventId = eventOutput.ids[0];
678
+ if (!eventId) {
679
+ throw new Error("Event ID is not set");
52
680
  }
53
- return runs?.[0];
681
+ return { runId: this.runId };
54
682
  }
55
- async start({
56
- inputData
683
+ async _start({
684
+ inputData,
685
+ initialState,
686
+ outputOptions,
687
+ tracingOptions,
688
+ format,
689
+ requestContext,
690
+ perStep
57
691
  }) {
58
- await this.#mastra.getStorage()?.persistWorkflowSnapshot({
692
+ const workflowsStore = await this.#mastra.getStorage()?.getStore("workflows");
693
+ await workflowsStore?.persistWorkflowSnapshot({
59
694
  workflowName: this.workflowId,
60
695
  runId: this.runId,
696
+ resourceId: this.resourceId,
61
697
  snapshot: {
62
698
  runId: this.runId,
63
699
  serializedStepGraph: this.serializedStepGraph,
700
+ status: "running",
64
701
  value: {},
65
702
  context: {},
66
703
  activePaths: [],
67
704
  suspendedPaths: {},
705
+ activeStepsPath: {},
706
+ resumeLabels: {},
707
+ waitingPaths: {},
68
708
  timestamp: Date.now()
69
709
  }
70
710
  });
711
+ const inputDataToUse = await this._validateInput(inputData);
712
+ const initialStateToUse = await this._validateInitialState(initialState ?? {});
71
713
  const eventOutput = await this.inngest.send({
72
714
  name: `workflow.${this.workflowId}`,
73
715
  data: {
74
- inputData,
75
- runId: this.runId
716
+ inputData: inputDataToUse,
717
+ initialState: initialStateToUse,
718
+ runId: this.runId,
719
+ resourceId: this.resourceId,
720
+ outputOptions,
721
+ tracingOptions,
722
+ format,
723
+ requestContext: requestContext ? Object.fromEntries(requestContext.entries()) : {},
724
+ perStep
76
725
  }
77
726
  });
78
727
  const eventId = eventOutput.ids[0];
@@ -81,93 +730,432 @@ var InngestRun = class extends workflows.Run {
81
730
  }
82
731
  const runOutput = await this.getRunOutput(eventId);
83
732
  const result = runOutput?.output?.result;
84
- if (result.status === "failed") {
85
- result.error = new Error(result.error);
733
+ this.hydrateFailedResult(result);
734
+ if (result.status !== "suspended") {
735
+ this.cleanup?.();
86
736
  }
87
- this.cleanup?.();
88
737
  return result;
89
738
  }
90
739
  async resume(params) {
91
- const steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
92
- (step) => typeof step === "string" ? step : step?.id
93
- );
94
- const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
740
+ const p = this._resume(params).then((result) => {
741
+ if (result.status !== "suspended") {
742
+ this.closeStreamAction?.().catch(() => {
743
+ });
744
+ }
745
+ return result;
746
+ });
747
+ this.executionResults = p;
748
+ return p;
749
+ }
750
+ async _resume(params) {
751
+ const storage = this.#mastra?.getStorage();
752
+ let steps = [];
753
+ if (typeof params.step === "string") {
754
+ steps = params.step.split(".");
755
+ } else {
756
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
757
+ (step) => typeof step === "string" ? step : step?.id
758
+ );
759
+ }
760
+ const workflowsStore = await storage?.getStore("workflows");
761
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
95
762
  workflowName: this.workflowId,
96
763
  runId: this.runId
97
764
  });
765
+ const suspendedStep = this.workflowSteps[steps?.[0] ?? ""];
766
+ const resumeDataToUse = await this._validateResumeData(params.resumeData, suspendedStep);
767
+ const persistedRequestContext = snapshot?.requestContext ?? {};
768
+ const newRequestContext = params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {};
769
+ const mergedRequestContext = { ...persistedRequestContext, ...newRequestContext };
98
770
  const eventOutput = await this.inngest.send({
99
771
  name: `workflow.${this.workflowId}`,
100
772
  data: {
101
- inputData: params.resumeData,
773
+ inputData: resumeDataToUse,
774
+ initialState: snapshot?.value ?? {},
102
775
  runId: this.runId,
776
+ workflowId: this.workflowId,
103
777
  stepResults: snapshot?.context,
104
778
  resume: {
105
779
  steps,
106
780
  stepResults: snapshot?.context,
107
- resumePayload: params.resumeData,
108
- // @ts-ignore
109
- resumePath: snapshot?.suspendedPaths?.[steps?.[0]]
781
+ resumePayload: resumeDataToUse,
782
+ resumePath: steps?.[0] ? snapshot?.suspendedPaths?.[steps?.[0]] : void 0
783
+ },
784
+ requestContext: mergedRequestContext,
785
+ perStep: params.perStep
786
+ }
787
+ });
788
+ const eventId = eventOutput.ids[0];
789
+ if (!eventId) {
790
+ throw new Error("Event ID is not set");
791
+ }
792
+ const runOutput = await this.getRunOutput(eventId);
793
+ const result = runOutput?.output?.result;
794
+ this.hydrateFailedResult(result);
795
+ return result;
796
+ }
797
+ async timeTravel(params) {
798
+ const p = this._timeTravel(params).then((result) => {
799
+ if (result.status !== "suspended") {
800
+ this.closeStreamAction?.().catch(() => {
801
+ });
802
+ }
803
+ return result;
804
+ });
805
+ this.executionResults = p;
806
+ return p;
807
+ }
808
+ async _timeTravel(params) {
809
+ if (!params.step || Array.isArray(params.step) && params.step?.length === 0) {
810
+ throw new Error("Step is required and must be a valid step or array of steps");
811
+ }
812
+ let steps = [];
813
+ if (typeof params.step === "string") {
814
+ steps = params.step.split(".");
815
+ } else {
816
+ steps = (Array.isArray(params.step) ? params.step : [params.step]).map(
817
+ (step) => typeof step === "string" ? step : step?.id
818
+ );
819
+ }
820
+ if (steps.length === 0) {
821
+ throw new Error("No steps provided to timeTravel");
822
+ }
823
+ const storage = this.#mastra?.getStorage();
824
+ const workflowsStore = await storage?.getStore("workflows");
825
+ const snapshot = await workflowsStore?.loadWorkflowSnapshot({
826
+ workflowName: this.workflowId,
827
+ runId: this.runId
828
+ });
829
+ if (!snapshot) {
830
+ await workflowsStore?.persistWorkflowSnapshot({
831
+ workflowName: this.workflowId,
832
+ runId: this.runId,
833
+ resourceId: this.resourceId,
834
+ snapshot: {
835
+ runId: this.runId,
836
+ serializedStepGraph: this.serializedStepGraph,
837
+ status: "pending",
838
+ value: {},
839
+ context: {},
840
+ activePaths: [],
841
+ suspendedPaths: {},
842
+ activeStepsPath: {},
843
+ resumeLabels: {},
844
+ waitingPaths: {},
845
+ timestamp: Date.now()
846
+ }
847
+ });
848
+ }
849
+ if (snapshot?.status === "running") {
850
+ throw new Error("This workflow run is still running, cannot time travel");
851
+ }
852
+ let inputDataToUse = params.inputData;
853
+ if (inputDataToUse && steps.length === 1) {
854
+ inputDataToUse = await this._validateTimetravelInputData(params.inputData, this.workflowSteps[steps[0]]);
855
+ }
856
+ const timeTravelData = workflows.createTimeTravelExecutionParams({
857
+ steps,
858
+ inputData: inputDataToUse,
859
+ resumeData: params.resumeData,
860
+ context: params.context,
861
+ nestedStepsContext: params.nestedStepsContext,
862
+ snapshot: snapshot ?? { context: {} },
863
+ graph: this.executionGraph,
864
+ initialState: params.initialState,
865
+ perStep: params.perStep
866
+ });
867
+ const eventOutput = await this.inngest.send({
868
+ name: `workflow.${this.workflowId}`,
869
+ data: {
870
+ initialState: timeTravelData.state,
871
+ runId: this.runId,
872
+ workflowId: this.workflowId,
873
+ stepResults: timeTravelData.stepResults,
874
+ timeTravel: timeTravelData,
875
+ tracingOptions: params.tracingOptions,
876
+ outputOptions: params.outputOptions,
877
+ requestContext: params.requestContext ? Object.fromEntries(params.requestContext.entries()) : {},
878
+ perStep: params.perStep
879
+ }
880
+ });
881
+ const eventId = eventOutput.ids[0];
882
+ if (!eventId) {
883
+ throw new Error("Event ID is not set");
884
+ }
885
+ const runOutput = await this.getRunOutput(eventId);
886
+ const result = runOutput?.output?.result;
887
+ this.hydrateFailedResult(result);
888
+ return result;
889
+ }
890
+ watch(cb) {
891
+ let active = true;
892
+ const streamPromise = realtime.subscribe(
893
+ {
894
+ channel: `workflow:${this.workflowId}:${this.runId}`,
895
+ topics: ["watch"],
896
+ app: this.inngest
897
+ },
898
+ (message) => {
899
+ if (active) {
900
+ cb(message.data);
901
+ }
902
+ }
903
+ );
904
+ return () => {
905
+ active = false;
906
+ streamPromise.then(async (stream) => {
907
+ return stream.cancel();
908
+ }).catch((err) => {
909
+ console.error(err);
910
+ });
911
+ };
912
+ }
913
+ streamLegacy({ inputData, requestContext } = {}) {
914
+ const { readable, writable } = new TransformStream();
915
+ const writer = writable.getWriter();
916
+ void writer.write({
917
+ // @ts-ignore
918
+ type: "start",
919
+ // @ts-ignore
920
+ payload: { runId: this.runId }
921
+ });
922
+ const unwatch = this.watch(async (event) => {
923
+ try {
924
+ const e = {
925
+ ...event,
926
+ type: event.type.replace("workflow-", "")
927
+ };
928
+ if (e.type === "step-output") {
929
+ e.type = e.payload.output.type;
930
+ e.payload = e.payload.output.payload;
931
+ }
932
+ await writer.write(e);
933
+ } catch {
934
+ }
935
+ });
936
+ this.closeStreamAction = async () => {
937
+ await writer.write({
938
+ type: "finish",
939
+ // @ts-ignore
940
+ payload: { runId: this.runId }
941
+ });
942
+ unwatch();
943
+ try {
944
+ await writer.close();
945
+ } catch (err) {
946
+ console.error("Error closing stream:", err);
947
+ } finally {
948
+ writer.releaseLock();
949
+ }
950
+ };
951
+ this.executionResults = this._start({ inputData, requestContext, format: "legacy" }).then((result) => {
952
+ if (result.status !== "suspended") {
953
+ this.closeStreamAction?.().catch(() => {
954
+ });
955
+ }
956
+ return result;
957
+ });
958
+ return {
959
+ stream: readable,
960
+ getWorkflowState: () => this.executionResults
961
+ };
962
+ }
963
+ stream({
964
+ inputData,
965
+ requestContext,
966
+ tracingOptions,
967
+ closeOnSuspend = true,
968
+ initialState,
969
+ outputOptions,
970
+ perStep
971
+ } = {}) {
972
+ if (this.closeStreamAction && this.streamOutput) {
973
+ return this.streamOutput;
974
+ }
975
+ this.closeStreamAction = async () => {
976
+ };
977
+ const self = this;
978
+ const stream$1 = new web.ReadableStream({
979
+ async start(controller) {
980
+ const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
981
+ controller.enqueue({
982
+ type,
983
+ runId: self.runId,
984
+ from,
985
+ payload: {
986
+ stepName: payload?.id,
987
+ ...payload
988
+ }
989
+ });
990
+ });
991
+ self.closeStreamAction = async () => {
992
+ unwatch();
993
+ try {
994
+ await controller.close();
995
+ } catch (err) {
996
+ console.error("Error closing stream:", err);
997
+ }
998
+ };
999
+ const executionResultsPromise = self._start({
1000
+ inputData,
1001
+ requestContext,
1002
+ // tracingContext, // We are not able to pass a reference to a span here, what to do?
1003
+ initialState,
1004
+ tracingOptions,
1005
+ outputOptions,
1006
+ format: "vnext",
1007
+ perStep
1008
+ });
1009
+ let executionResults;
1010
+ try {
1011
+ executionResults = await executionResultsPromise;
1012
+ if (closeOnSuspend) {
1013
+ self.closeStreamAction?.().catch(() => {
1014
+ });
1015
+ } else if (executionResults.status !== "suspended") {
1016
+ self.closeStreamAction?.().catch(() => {
1017
+ });
1018
+ }
1019
+ if (self.streamOutput) {
1020
+ self.streamOutput.updateResults(
1021
+ executionResults
1022
+ );
1023
+ }
1024
+ } catch (err) {
1025
+ self.streamOutput?.rejectResults(err);
1026
+ self.closeStreamAction?.().catch(() => {
1027
+ });
1028
+ }
1029
+ }
1030
+ });
1031
+ this.streamOutput = new stream.WorkflowRunOutput({
1032
+ runId: this.runId,
1033
+ workflowId: this.workflowId,
1034
+ stream: stream$1
1035
+ });
1036
+ return this.streamOutput;
1037
+ }
1038
+ timeTravelStream({
1039
+ inputData,
1040
+ resumeData,
1041
+ initialState,
1042
+ step,
1043
+ context,
1044
+ nestedStepsContext,
1045
+ requestContext,
1046
+ tracingOptions,
1047
+ outputOptions,
1048
+ perStep
1049
+ }) {
1050
+ this.closeStreamAction = async () => {
1051
+ };
1052
+ const self = this;
1053
+ const stream$1 = new web.ReadableStream({
1054
+ async start(controller) {
1055
+ const unwatch = self.watch(async ({ type, from = stream.ChunkFrom.WORKFLOW, payload }) => {
1056
+ controller.enqueue({
1057
+ type,
1058
+ runId: self.runId,
1059
+ from,
1060
+ payload: {
1061
+ stepName: payload?.id,
1062
+ ...payload
1063
+ }
1064
+ });
1065
+ });
1066
+ self.closeStreamAction = async () => {
1067
+ unwatch();
1068
+ try {
1069
+ controller.close();
1070
+ } catch (err) {
1071
+ console.error("Error closing stream:", err);
1072
+ }
1073
+ };
1074
+ const executionResultsPromise = self._timeTravel({
1075
+ inputData,
1076
+ step,
1077
+ context,
1078
+ nestedStepsContext,
1079
+ resumeData,
1080
+ initialState,
1081
+ requestContext,
1082
+ tracingOptions,
1083
+ outputOptions,
1084
+ perStep
1085
+ });
1086
+ self.executionResults = executionResultsPromise;
1087
+ let executionResults;
1088
+ try {
1089
+ executionResults = await executionResultsPromise;
1090
+ self.closeStreamAction?.().catch(() => {
1091
+ });
1092
+ if (self.streamOutput) {
1093
+ self.streamOutput.updateResults(executionResults);
1094
+ }
1095
+ } catch (err) {
1096
+ self.streamOutput?.rejectResults(err);
1097
+ self.closeStreamAction?.().catch(() => {
1098
+ });
110
1099
  }
111
1100
  }
112
1101
  });
113
- const eventId = eventOutput.ids[0];
114
- if (!eventId) {
115
- throw new Error("Event ID is not set");
116
- }
117
- const runOutput = await this.getRunOutput(eventId);
118
- const result = runOutput?.output?.result;
119
- if (result.status === "failed") {
120
- result.error = new Error(result.error);
121
- }
122
- return result;
1102
+ this.streamOutput = new stream.WorkflowRunOutput({
1103
+ runId: this.runId,
1104
+ workflowId: this.workflowId,
1105
+ stream: stream$1
1106
+ });
1107
+ return this.streamOutput;
123
1108
  }
124
- watch(cb) {
125
- const streamPromise = realtime.subscribe(
126
- {
127
- channel: `workflow:${this.workflowId}:${this.runId}`,
128
- topics: ["watch"],
129
- app: this.inngest
130
- },
131
- (message) => {
132
- cb(message.data);
1109
+ /**
1110
+ * Hydrates errors in a failed workflow result back to proper Error instances.
1111
+ * This ensures error.cause chains and custom properties are preserved.
1112
+ */
1113
+ hydrateFailedResult(result) {
1114
+ if (result.status === "failed") {
1115
+ result.error = error.getErrorFromUnknown(result.error, { serializeStack: false });
1116
+ if (result.steps) {
1117
+ workflows.hydrateSerializedStepErrors(result.steps);
133
1118
  }
134
- );
135
- return () => {
136
- streamPromise.then((stream) => {
137
- stream.cancel();
138
- }).catch((err) => {
139
- console.error(err);
140
- });
141
- };
1119
+ }
142
1120
  }
143
1121
  };
1122
+
1123
+ // src/workflow.ts
144
1124
  var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
145
1125
  #mastra;
146
1126
  inngest;
147
1127
  function;
1128
+ cronFunction;
1129
+ flowControlConfig;
1130
+ cronConfig;
148
1131
  constructor(params, inngest) {
149
- super(params);
1132
+ const { concurrency, rateLimit, throttle, debounce, priority, cron, inputData, initialState, ...workflowParams } = params;
1133
+ super(workflowParams);
1134
+ this.engineType = "inngest";
1135
+ const flowControlEntries = Object.entries({ concurrency, rateLimit, throttle, debounce, priority }).filter(
1136
+ ([_, value]) => value !== void 0
1137
+ );
1138
+ this.flowControlConfig = flowControlEntries.length > 0 ? Object.fromEntries(flowControlEntries) : void 0;
150
1139
  this.#mastra = params.mastra;
151
1140
  this.inngest = inngest;
1141
+ if (cron) {
1142
+ this.cronConfig = { cron, inputData, initialState };
1143
+ }
152
1144
  }
153
- async getWorkflowRuns(args) {
1145
+ async listWorkflowRuns(args) {
154
1146
  const storage = this.#mastra?.getStorage();
155
1147
  if (!storage) {
156
1148
  this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
157
1149
  return { runs: [], total: 0 };
158
1150
  }
159
- return storage.getWorkflowRuns({ workflowName: this.id, ...args ?? {} });
160
- }
161
- async getWorkflowRunById(runId) {
162
- const storage = this.#mastra?.getStorage();
163
- if (!storage) {
164
- this.logger.debug("Cannot get workflow runs. Mastra engine is not initialized");
165
- return null;
1151
+ const workflowsStore = await storage.getStore("workflows");
1152
+ if (!workflowsStore) {
1153
+ return { runs: [], total: 0 };
166
1154
  }
167
- const run = await storage.getWorkflowRunById({ runId, workflowName: this.id });
168
- return run ?? (this.runs.get(runId) ? { ...this.runs.get(runId), workflowName: this.id } : null);
1155
+ return workflowsStore.listWorkflowRuns({ workflowName: this.id, ...args ?? {} });
169
1156
  }
170
1157
  __registerMastra(mastra) {
1158
+ super.__registerMastra(mastra);
171
1159
  this.#mastra = mastra;
172
1160
  this.executionEngine.__registerMastra(mastra);
173
1161
  const updateNested = (step) => {
@@ -185,67 +1173,158 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
185
1173
  }
186
1174
  }
187
1175
  }
188
- createRun(options) {
189
- const runIdToUse = options?.runId || crypto.randomUUID();
1176
+ async createRun(options) {
1177
+ const runIdToUse = options?.runId || crypto$1.randomUUID();
190
1178
  const run = this.runs.get(runIdToUse) ?? new InngestRun(
191
1179
  {
192
1180
  workflowId: this.id,
193
1181
  runId: runIdToUse,
1182
+ resourceId: options?.resourceId,
194
1183
  executionEngine: this.executionEngine,
195
1184
  executionGraph: this.executionGraph,
196
1185
  serializedStepGraph: this.serializedStepGraph,
197
1186
  mastra: this.#mastra,
198
1187
  retryConfig: this.retryConfig,
199
- cleanup: () => this.runs.delete(runIdToUse)
1188
+ cleanup: () => this.runs.delete(runIdToUse),
1189
+ workflowSteps: this.steps,
1190
+ workflowEngineType: this.engineType,
1191
+ validateInputs: this.options.validateInputs
200
1192
  },
201
1193
  this.inngest
202
1194
  );
203
1195
  this.runs.set(runIdToUse, run);
1196
+ const shouldPersistSnapshot = this.options.shouldPersistSnapshot({
1197
+ workflowStatus: run.workflowRunStatus,
1198
+ stepResults: {}
1199
+ });
1200
+ const existingRun = await this.getWorkflowRunById(runIdToUse, {
1201
+ withNestedWorkflows: false
1202
+ });
1203
+ const existsInStorage = existingRun && !existingRun.isFromInMemory;
1204
+ if (!existsInStorage && shouldPersistSnapshot) {
1205
+ const workflowsStore = await this.mastra?.getStorage()?.getStore("workflows");
1206
+ await workflowsStore?.persistWorkflowSnapshot({
1207
+ workflowName: this.id,
1208
+ runId: runIdToUse,
1209
+ resourceId: options?.resourceId,
1210
+ snapshot: {
1211
+ runId: runIdToUse,
1212
+ status: "pending",
1213
+ value: {},
1214
+ context: {},
1215
+ activePaths: [],
1216
+ activeStepsPath: {},
1217
+ waitingPaths: {},
1218
+ serializedStepGraph: this.serializedStepGraph,
1219
+ suspendedPaths: {},
1220
+ resumeLabels: {},
1221
+ result: void 0,
1222
+ error: void 0,
1223
+ timestamp: Date.now()
1224
+ }
1225
+ });
1226
+ }
204
1227
  return run;
205
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
+ }
206
1253
  getFunction() {
207
1254
  if (this.function) {
208
1255
  return this.function;
209
1256
  }
210
1257
  this.function = this.inngest.createFunction(
211
- // @ts-ignore
212
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
1258
+ {
1259
+ id: `workflow.${this.id}`,
1260
+ retries: 0,
1261
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
1262
+ // Spread flow control configuration
1263
+ ...this.flowControlConfig
1264
+ },
213
1265
  { event: `workflow.${this.id}` },
214
1266
  async ({ event, step, attempt, publish }) => {
215
- let { inputData, runId, resume } = event.data;
1267
+ let { inputData, initialState, runId, resourceId, resume, outputOptions, format, timeTravel, perStep } = event.data;
216
1268
  if (!runId) {
217
1269
  runId = await step.run(`workflow.${this.id}.runIdGen`, async () => {
218
- return crypto.randomUUID();
1270
+ return crypto$1.randomUUID();
219
1271
  });
220
1272
  }
221
- const emitter = {
222
- emit: async (event2, data) => {
223
- if (!publish) {
224
- return;
225
- }
226
- try {
227
- await publish({
228
- channel: `workflow:${this.id}:${runId}`,
229
- topic: "watch",
230
- data
231
- });
232
- } catch (err) {
233
- this.logger.error("Error emitting event: " + (err?.stack ?? err?.message ?? err));
234
- }
235
- }
236
- };
237
- const engine = new InngestExecutionEngine(this.#mastra, step, attempt);
1273
+ const pubsub = new InngestPubSub(this.inngest, this.id, publish);
1274
+ const requestContext = new di.RequestContext(Object.entries(event.data.requestContext ?? {}));
1275
+ const engine = new InngestExecutionEngine(this.#mastra, step, attempt, this.options);
238
1276
  const result = await engine.execute({
239
1277
  workflowId: this.id,
240
1278
  runId,
1279
+ resourceId,
241
1280
  graph: this.executionGraph,
242
1281
  serializedStepGraph: this.serializedStepGraph,
243
1282
  input: inputData,
244
- emitter,
1283
+ initialState,
1284
+ pubsub,
245
1285
  retryConfig: this.retryConfig,
246
- runtimeContext: new di.RuntimeContext(),
247
- // TODO
248
- resume
1286
+ requestContext,
1287
+ resume,
1288
+ timeTravel,
1289
+ perStep,
1290
+ format,
1291
+ abortController: new AbortController(),
1292
+ // currentSpan: undefined, // TODO: Pass actual parent Span from workflow execution context
1293
+ outputOptions,
1294
+ outputWriter: async (chunk) => {
1295
+ try {
1296
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1297
+ type: "watch",
1298
+ runId,
1299
+ data: chunk
1300
+ });
1301
+ } catch (err) {
1302
+ this.logger.debug?.("Failed to publish watch event:", err);
1303
+ }
1304
+ }
1305
+ });
1306
+ await step.run(`workflow.${this.id}.finalize`, async () => {
1307
+ if (result.status !== "paused") {
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
+ });
1321
+ }
1322
+ if (result.status === "failed") {
1323
+ throw new inngest.NonRetriableError(`Workflow failed`, {
1324
+ cause: result
1325
+ });
1326
+ }
1327
+ return result;
249
1328
  });
250
1329
  return { result, runId };
251
1330
  }
@@ -266,482 +1345,260 @@ var InngestWorkflow = class _InngestWorkflow extends workflows.Workflow {
266
1345
  });
267
1346
  }
268
1347
  getFunctions() {
269
- 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
+ ];
270
1353
  }
271
1354
  };
272
- function cloneWorkflow(workflow, opts) {
273
- const wf = new InngestWorkflow(
274
- {
275
- id: opts.id,
276
- inputSchema: workflow.inputSchema,
277
- outputSchema: workflow.outputSchema,
278
- steps: workflow.stepDefs,
279
- mastra: workflow.mastra
280
- },
281
- workflow.inngest
282
- );
283
- wf.setStepFlow(workflow.stepGraph);
284
- wf.commit();
285
- return wf;
286
- }
287
- function init(inngest) {
288
- return {
289
- createWorkflow(params) {
290
- return new InngestWorkflow(params, inngest);
291
- },
292
- createStep: workflows.createStep,
293
- cloneStep: workflows.cloneStep,
294
- cloneWorkflow
295
- };
296
- }
297
- var InngestExecutionEngine = class extends workflows.DefaultExecutionEngine {
298
- inngestStep;
299
- inngestAttempts;
300
- constructor(mastra, inngestStep, inngestAttempts = 0) {
301
- super({ mastra });
302
- this.inngestStep = inngestStep;
303
- this.inngestAttempts = inngestAttempts;
304
- }
305
- async fmtReturnValue(executionSpan, emitter, stepResults, lastOutput, error) {
306
- const base = {
307
- status: lastOutput.status,
308
- steps: stepResults
309
- };
310
- if (lastOutput.status === "success") {
311
- await emitter.emit("watch", {
312
- type: "watch",
313
- payload: {
314
- workflowState: {
315
- status: lastOutput.status,
316
- steps: stepResults,
317
- result: lastOutput.output
318
- }
319
- },
320
- eventTimestamp: Date.now()
321
- });
322
- base.result = lastOutput.output;
323
- } else if (lastOutput.status === "failed") {
324
- base.error = error instanceof Error ? error?.stack ?? error.message : lastOutput?.error instanceof Error ? lastOutput.error.message : lastOutput.error ?? error ?? "Unknown error";
325
- await emitter.emit("watch", {
326
- type: "watch",
327
- payload: {
328
- workflowState: {
329
- status: lastOutput.status,
330
- steps: stepResults,
331
- result: null,
332
- error: base.error
333
- }
334
- },
335
- eventTimestamp: Date.now()
336
- });
337
- } else if (lastOutput.status === "suspended") {
338
- await emitter.emit("watch", {
339
- type: "watch",
340
- payload: {
341
- workflowState: {
342
- status: lastOutput.status,
343
- steps: stepResults,
344
- result: null,
345
- error: null
346
- }
347
- },
348
- eventTimestamp: Date.now()
349
- });
350
- const suspendedStepIds = Object.entries(stepResults).flatMap(([stepId, stepResult]) => {
351
- if (stepResult?.status === "suspended") {
352
- const nestedPath = stepResult?.payload?.__workflow_meta?.path;
353
- return nestedPath ? [[stepId, ...nestedPath]] : [[stepId]];
1355
+ function serve({
1356
+ mastra,
1357
+ inngest,
1358
+ functions: userFunctions = [],
1359
+ registerOptions
1360
+ }) {
1361
+ const wfs = mastra.listWorkflows();
1362
+ const workflowFunctions = Array.from(
1363
+ new Set(
1364
+ Object.values(wfs).flatMap((wf) => {
1365
+ if (wf instanceof InngestWorkflow) {
1366
+ wf.__registerMastra(mastra);
1367
+ return wf.getFunctions();
354
1368
  }
355
1369
  return [];
356
- });
357
- base.suspended = suspendedStepIds;
358
- }
359
- executionSpan?.end();
360
- return base;
361
- }
362
- async superExecuteStep({
363
- workflowId,
364
- runId,
365
- step,
366
- stepResults,
367
- executionContext,
368
- resume,
369
- prevOutput,
370
- emitter,
371
- runtimeContext
372
- }) {
373
- return super.executeStep({
374
- workflowId,
375
- runId,
376
- step,
377
- stepResults,
378
- executionContext,
379
- resume,
380
- prevOutput,
381
- emitter,
382
- runtimeContext
383
- });
1370
+ })
1371
+ )
1372
+ );
1373
+ return hono.serve({
1374
+ ...registerOptions,
1375
+ client: inngest,
1376
+ functions: [...workflowFunctions, ...userFunctions]
1377
+ });
1378
+ }
1379
+
1380
+ // src/types.ts
1381
+ var _compatibilityCheck = true;
1382
+
1383
+ // src/index.ts
1384
+ function createStep(params, agentOrToolOptions) {
1385
+ if (params instanceof InngestWorkflow) {
1386
+ return params;
384
1387
  }
385
- async executeStep({
386
- step,
387
- stepResults,
388
- executionContext,
389
- resume,
390
- prevOutput,
391
- emitter,
392
- runtimeContext
393
- }) {
394
- await this.inngestStep.run(
395
- `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
396
- async () => {
397
- await emitter.emit("watch", {
398
- type: "watch",
399
- payload: {
400
- currentStep: {
401
- id: step.id,
402
- status: "running"
403
- },
404
- workflowState: {
405
- status: "running",
406
- steps: {
407
- ...stepResults,
408
- [step.id]: {
409
- status: "running"
410
- }
411
- },
412
- result: null,
413
- error: null
414
- }
415
- },
416
- eventTimestamp: Date.now()
417
- });
418
- }
419
- );
420
- if (step instanceof InngestWorkflow) {
421
- const isResume = !!resume?.steps?.length;
422
- let result;
423
- let runId;
424
- if (isResume) {
425
- runId = stepResults[resume?.steps?.[0]]?.payload?.__workflow_meta?.runId ?? crypto.randomUUID();
426
- const snapshot = await this.mastra?.getStorage()?.loadWorkflowSnapshot({
427
- workflowName: step.id,
428
- runId
429
- });
430
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
431
- function: step.getFunction(),
432
- data: {
433
- inputData: prevOutput,
434
- runId,
435
- resume: {
436
- runId,
437
- steps: resume.steps.slice(1),
438
- stepResults: snapshot?.context,
439
- resumePayload: resume.resumePayload,
440
- // @ts-ignore
441
- resumePath: snapshot?.suspendedPaths?.[resume.steps?.[1]]
442
- }
443
- }
444
- });
445
- result = invokeResp.result;
446
- runId = invokeResp.runId;
447
- } else {
448
- const invokeResp = await this.inngestStep.invoke(`workflow.${executionContext.workflowId}.step.${step.id}`, {
449
- function: step.getFunction(),
450
- data: {
451
- inputData: prevOutput
452
- }
1388
+ if (params instanceof agent.Agent) {
1389
+ const options = agentOrToolOptions;
1390
+ const outputSchema = options?.structuredOutput?.schema ?? zod.z.object({ text: zod.z.string() });
1391
+ const { retries, scorers, ...agentOptions } = options ?? {};
1392
+ return {
1393
+ id: params.name,
1394
+ description: params.getDescription(),
1395
+ inputSchema: zod.z.object({
1396
+ prompt: zod.z.string()
1397
+ // resourceId: z.string().optional(),
1398
+ // threadId: z.string().optional(),
1399
+ }),
1400
+ outputSchema,
1401
+ retries,
1402
+ scorers,
1403
+ execute: async ({
1404
+ inputData,
1405
+ runId,
1406
+ [_constants.PUBSUB_SYMBOL]: pubsub,
1407
+ [_constants.STREAM_FORMAT_SYMBOL]: streamFormat,
1408
+ requestContext,
1409
+ tracingContext,
1410
+ abortSignal,
1411
+ abort,
1412
+ writer
1413
+ }) => {
1414
+ let streamPromise = {};
1415
+ streamPromise.promise = new Promise((resolve, reject) => {
1416
+ streamPromise.resolve = resolve;
1417
+ streamPromise.reject = reject;
453
1418
  });
454
- result = invokeResp.result;
455
- runId = invokeResp.runId;
456
- }
457
- const res = await this.inngestStep.run(
458
- `workflow.${executionContext.workflowId}.step.${step.id}.nestedwf-results`,
459
- async () => {
460
- if (result.status === "failed") {
461
- await emitter.emit("watch", {
462
- type: "watch",
463
- payload: {
464
- currentStep: {
465
- id: step.id,
466
- status: "failed",
467
- error: result?.error
468
- },
469
- workflowState: {
470
- status: "running",
471
- steps: stepResults,
472
- result: null,
473
- error: null
474
- }
475
- },
476
- eventTimestamp: Date.now()
477
- });
478
- return { executionContext, result: { status: "failed", error: result?.error } };
479
- } else if (result.status === "suspended") {
480
- const suspendedSteps = Object.entries(result.steps).filter(([_stepName, stepResult]) => {
481
- const stepRes2 = stepResult;
482
- return stepRes2?.status === "suspended";
483
- });
484
- for (const [stepName, stepResult] of suspendedSteps) {
485
- const suspendPath = [stepName, ...stepResult?.payload?.__workflow_meta?.path ?? []];
486
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
487
- await emitter.emit("watch", {
488
- type: "watch",
489
- payload: {
490
- currentStep: {
491
- id: step.id,
492
- status: "suspended",
493
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
494
- },
495
- workflowState: {
496
- status: "running",
497
- steps: stepResults,
498
- result: null,
499
- error: null
500
- }
501
- },
502
- eventTimestamp: Date.now()
503
- });
504
- return {
505
- executionContext,
506
- result: {
507
- status: "suspended",
508
- payload: { ...stepResult?.payload, __workflow_meta: { runId, path: suspendPath } }
509
- }
510
- };
511
- }
512
- await emitter.emit("watch", {
513
- type: "watch",
514
- payload: {
515
- currentStep: {
516
- id: step.id,
517
- status: "suspended",
518
- payload: {}
519
- },
520
- workflowState: {
521
- status: "running",
522
- steps: stepResults,
523
- result: null,
524
- error: null
525
- }
526
- },
527
- eventTimestamp: Date.now()
528
- });
529
- return {
530
- executionContext,
531
- result: {
532
- status: "suspended",
533
- payload: {}
1419
+ let structuredResult = null;
1420
+ const toolData = {
1421
+ name: params.name,
1422
+ args: inputData
1423
+ };
1424
+ let stream;
1425
+ if ((await params.getModel()).specificationVersion === "v1") {
1426
+ const { fullStream } = await params.streamLegacy(inputData.prompt, {
1427
+ ...agentOptions ?? {},
1428
+ // resourceId: inputData.resourceId,
1429
+ // threadId: inputData.threadId,
1430
+ requestContext,
1431
+ tracingContext,
1432
+ onFinish: (result) => {
1433
+ const resultWithObject = result;
1434
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1435
+ structuredResult = resultWithObject.object;
534
1436
  }
535
- };
536
- }
537
- await emitter.emit("watch", {
538
- type: "watch",
539
- payload: {
540
- currentStep: {
541
- id: step.id,
542
- status: "success",
543
- output: result?.result
544
- },
545
- workflowState: {
546
- status: "running",
547
- steps: stepResults,
548
- result: null,
549
- error: null
1437
+ streamPromise.resolve(result.text);
1438
+ void agentOptions?.onFinish?.(result);
1439
+ },
1440
+ abortSignal
1441
+ });
1442
+ stream = fullStream;
1443
+ } else {
1444
+ const modelOutput = await params.stream(inputData.prompt, {
1445
+ ...agentOptions ?? {},
1446
+ requestContext,
1447
+ tracingContext,
1448
+ onFinish: (result) => {
1449
+ const resultWithObject = result;
1450
+ if (agentOptions?.structuredOutput?.schema && resultWithObject.object) {
1451
+ structuredResult = resultWithObject.object;
550
1452
  }
1453
+ streamPromise.resolve(result.text);
1454
+ void agentOptions?.onFinish?.(result);
551
1455
  },
552
- eventTimestamp: Date.now()
1456
+ abortSignal
553
1457
  });
554
- return { executionContext, result: { status: "success", output: result?.result } };
1458
+ stream = modelOutput.fullStream;
555
1459
  }
556
- );
557
- Object.assign(executionContext, res.executionContext);
558
- return res.result;
559
- }
560
- const stepRes = await this.inngestStep.run(`workflow.${executionContext.workflowId}.step.${step.id}`, async () => {
561
- let execResults;
562
- let suspended;
563
- try {
564
- const result = await step.execute({
565
- runId: executionContext.runId,
566
- mastra: this.mastra,
567
- runtimeContext,
568
- inputData: prevOutput,
569
- resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : void 0,
570
- getInitData: () => stepResults?.input,
571
- getStepResult: (step2) => {
572
- const result2 = stepResults[step2.id];
573
- if (result2?.status === "success") {
574
- return result2.output;
1460
+ if (streamFormat === "legacy") {
1461
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1462
+ type: "watch",
1463
+ runId,
1464
+ data: { type: "tool-call-streaming-start", ...toolData ?? {} }
1465
+ });
1466
+ for await (const chunk of stream) {
1467
+ if (chunk.type === "text-delta") {
1468
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1469
+ type: "watch",
1470
+ runId,
1471
+ data: { type: "tool-call-delta", ...toolData ?? {}, argsTextDelta: chunk.textDelta }
1472
+ });
575
1473
  }
576
- return null;
577
- },
578
- suspend: async (suspendPayload) => {
579
- executionContext.suspendedPaths[step.id] = executionContext.executionPath;
580
- suspended = { payload: suspendPayload };
581
- },
582
- resume: {
583
- steps: resume?.steps?.slice(1) || [],
584
- resumePayload: resume?.resumePayload,
585
- // @ts-ignore
586
- runId: stepResults[step.id]?.payload?.__workflow_meta?.runId
587
- },
588
- emitter
589
- });
590
- execResults = { status: "success", output: result };
591
- } catch (e) {
592
- execResults = { status: "failed", error: e instanceof Error ? e.message : String(e) };
593
- }
594
- if (suspended) {
595
- execResults = { status: "suspended", payload: suspended.payload };
596
- }
597
- if (execResults.status === "failed") {
598
- if (executionContext.retryConfig.attempts > 0 && this.inngestAttempts < executionContext.retryConfig.attempts) {
599
- throw execResults.error;
600
- }
601
- }
602
- await emitter.emit("watch", {
603
- type: "watch",
604
- payload: {
605
- currentStep: {
606
- id: step.id,
607
- status: execResults.status,
608
- output: execResults.output
609
- },
610
- workflowState: {
611
- status: "running",
612
- steps: stepResults,
613
- result: null,
614
- error: null
615
1474
  }
616
- },
617
- eventTimestamp: Date.now()
618
- });
619
- return { result: execResults, executionContext, stepResults };
620
- });
621
- Object.assign(executionContext.suspendedPaths, stepRes.executionContext.suspendedPaths);
622
- Object.assign(stepResults, stepRes.stepResults);
623
- return stepRes.result;
624
- }
625
- async persistStepUpdate({
626
- workflowId,
627
- runId,
628
- stepResults,
629
- executionContext,
630
- serializedStepGraph
631
- }) {
632
- await this.inngestStep.run(
633
- `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
634
- async () => {
635
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
636
- workflowName: workflowId,
637
- runId,
638
- snapshot: {
1475
+ await pubsub.publish(`workflow.events.v2.${runId}`, {
1476
+ type: "watch",
639
1477
  runId,
640
- value: {},
641
- context: stepResults,
642
- activePaths: [],
643
- suspendedPaths: executionContext.suspendedPaths,
644
- serializedStepGraph,
645
- // @ts-ignore
646
- timestamp: Date.now()
1478
+ data: { type: "tool-call-streaming-finish", ...toolData ?? {} }
1479
+ });
1480
+ } else {
1481
+ for await (const chunk of stream) {
1482
+ await writer.write(chunk);
647
1483
  }
648
- });
649
- }
650
- );
1484
+ }
1485
+ if (abortSignal.aborted) {
1486
+ return abort();
1487
+ }
1488
+ if (structuredResult !== null) {
1489
+ return structuredResult;
1490
+ }
1491
+ return {
1492
+ text: await streamPromise.promise
1493
+ };
1494
+ },
1495
+ component: params.component
1496
+ };
651
1497
  }
652
- async executeConditional({
653
- workflowId,
654
- runId,
655
- entry,
656
- prevOutput,
657
- prevStep,
658
- stepResults,
659
- serializedStepGraph,
660
- resume,
661
- executionContext,
662
- emitter,
663
- runtimeContext
664
- }) {
665
- let execResults;
666
- const truthyIndexes = (await Promise.all(
667
- entry.conditions.map(
668
- (cond, index) => this.inngestStep.run(`workflow.${workflowId}.conditional.${index}`, async () => {
669
- try {
670
- const result = await cond({
671
- runId,
672
- mastra: this.mastra,
673
- runtimeContext,
674
- inputData: prevOutput,
675
- getInitData: () => stepResults?.input,
676
- getStepResult: (step) => {
677
- if (!step?.id) {
678
- return null;
679
- }
680
- const result2 = stepResults[step.id];
681
- if (result2?.status === "success") {
682
- return result2.output;
683
- }
684
- return null;
685
- },
686
- // TODO: this function shouldn't have suspend probably?
687
- suspend: async (_suspendPayload) => {
688
- },
689
- [_constants.EMITTER_SYMBOL]: emitter
690
- });
691
- return result ? index : null;
692
- } catch (e) {
693
- return null;
694
- }
695
- })
696
- )
697
- )).filter((index) => index !== null);
698
- const stepsToRun = entry.steps.filter((_, index) => truthyIndexes.includes(index));
699
- const results = await Promise.all(
700
- stepsToRun.map(
701
- (step, index) => this.executeEntry({
702
- workflowId,
703
- runId,
704
- entry: step,
705
- prevStep,
706
- stepResults,
707
- resume,
708
- serializedStepGraph,
709
- executionContext: {
710
- workflowId,
1498
+ if (params instanceof tools.Tool) {
1499
+ const toolOpts = agentOrToolOptions;
1500
+ if (!params.inputSchema || !params.outputSchema) {
1501
+ throw new Error("Tool must have input and output schemas defined");
1502
+ }
1503
+ return {
1504
+ // TODO: tool probably should have strong id type
1505
+ id: params.id,
1506
+ description: params.description,
1507
+ inputSchema: params.inputSchema,
1508
+ outputSchema: params.outputSchema,
1509
+ suspendSchema: params.suspendSchema,
1510
+ resumeSchema: params.resumeSchema,
1511
+ retries: toolOpts?.retries,
1512
+ scorers: toolOpts?.scorers,
1513
+ execute: async ({
1514
+ inputData,
1515
+ mastra,
1516
+ requestContext,
1517
+ tracingContext,
1518
+ suspend,
1519
+ resumeData,
1520
+ runId,
1521
+ workflowId,
1522
+ state,
1523
+ setState
1524
+ }) => {
1525
+ const toolContext = {
1526
+ mastra,
1527
+ requestContext,
1528
+ tracingContext,
1529
+ workflow: {
711
1530
  runId,
712
- executionPath: [...executionContext.executionPath, index],
713
- suspendedPaths: executionContext.suspendedPaths,
714
- retryConfig: executionContext.retryConfig,
715
- executionSpan: executionContext.executionSpan
716
- },
717
- emitter,
718
- runtimeContext
719
- })
720
- )
721
- );
722
- const hasFailed = results.find((result) => result.status === "failed");
723
- const hasSuspended = results.find((result) => result.status === "suspended");
724
- if (hasFailed) {
725
- execResults = { status: "failed", error: hasFailed.error };
726
- } else if (hasSuspended) {
727
- execResults = { status: "suspended", payload: hasSuspended.payload };
728
- } else {
729
- execResults = {
730
- status: "success",
731
- output: results.reduce((acc, result, index) => {
732
- if (result.status === "success") {
733
- acc[stepsToRun[index].step.id] = result.output;
1531
+ resumeData,
1532
+ suspend,
1533
+ workflowId,
1534
+ state,
1535
+ setState
734
1536
  }
735
- return acc;
736
- }, {})
1537
+ };
1538
+ return params.execute(inputData, toolContext);
1539
+ },
1540
+ component: "TOOL"
1541
+ };
1542
+ }
1543
+ return {
1544
+ id: params.id,
1545
+ description: params.description,
1546
+ inputSchema: params.inputSchema,
1547
+ outputSchema: params.outputSchema,
1548
+ resumeSchema: params.resumeSchema,
1549
+ suspendSchema: params.suspendSchema,
1550
+ retries: params.retries,
1551
+ scorers: params.scorers,
1552
+ execute: params.execute
1553
+ };
1554
+ }
1555
+ function init(inngest) {
1556
+ return {
1557
+ createWorkflow(params) {
1558
+ return new InngestWorkflow(
1559
+ params,
1560
+ inngest
1561
+ );
1562
+ },
1563
+ createStep,
1564
+ cloneStep(step, opts) {
1565
+ return {
1566
+ id: opts.id,
1567
+ description: step.description,
1568
+ inputSchema: step.inputSchema,
1569
+ outputSchema: step.outputSchema,
1570
+ resumeSchema: step.resumeSchema,
1571
+ suspendSchema: step.suspendSchema,
1572
+ stateSchema: step.stateSchema,
1573
+ execute: step.execute,
1574
+ retries: step.retries,
1575
+ scorers: step.scorers,
1576
+ component: step.component
737
1577
  };
1578
+ },
1579
+ cloneWorkflow(workflow, opts) {
1580
+ const wf = new workflows.Workflow({
1581
+ id: opts.id,
1582
+ inputSchema: workflow.inputSchema,
1583
+ outputSchema: workflow.outputSchema,
1584
+ steps: workflow.stepDefs,
1585
+ mastra: workflow.mastra,
1586
+ options: workflow.options
1587
+ });
1588
+ wf.setStepFlow(workflow.stepGraph);
1589
+ wf.commit();
1590
+ return wf;
738
1591
  }
739
- return execResults;
740
- }
741
- };
1592
+ };
1593
+ }
742
1594
 
743
1595
  exports.InngestExecutionEngine = InngestExecutionEngine;
1596
+ exports.InngestPubSub = InngestPubSub;
744
1597
  exports.InngestRun = InngestRun;
745
1598
  exports.InngestWorkflow = InngestWorkflow;
1599
+ exports._compatibilityCheck = _compatibilityCheck;
1600
+ exports.createStep = createStep;
746
1601
  exports.init = init;
747
1602
  exports.serve = serve;
1603
+ //# sourceMappingURL=index.cjs.map
1604
+ //# sourceMappingURL=index.cjs.map