@mastra/inngest 0.0.0-custom-instrumentation-20250626084921 → 0.0.0-declaration-maps-20250729202623

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/src/index.ts CHANGED
@@ -3,7 +3,7 @@ import type { ReadableStream } from 'node:stream/web';
3
3
  import { subscribe } from '@inngest/realtime';
4
4
  import type { Agent, Mastra, ToolExecutionContext, WorkflowRun, WorkflowRuns } from '@mastra/core';
5
5
  import { RuntimeContext } from '@mastra/core/di';
6
- import { Tool } from '@mastra/core/tools';
6
+ import { Tool, ToolStream } from '@mastra/core/tools';
7
7
  import { Workflow, Run, DefaultExecutionEngine } from '@mastra/core/workflows';
8
8
  import type {
9
9
  ExecuteFunction,
@@ -20,6 +20,7 @@ import type {
20
20
  Emitter,
21
21
  WatchEvent,
22
22
  StreamEvent,
23
+ ChunkType,
23
24
  } from '@mastra/core/workflows';
24
25
  import { EMITTER_SYMBOL } from '@mastra/core/workflows/_constants';
25
26
  import type { Span } from '@opentelemetry/api';
@@ -33,13 +34,17 @@ export type InngestEngineType = {
33
34
 
34
35
  export function serve({ mastra, inngest }: { mastra: Mastra; inngest: Inngest }): ReturnType<typeof inngestServe> {
35
36
  const wfs = mastra.getWorkflows();
36
- const functions = Object.values(wfs).flatMap(wf => {
37
- if (wf instanceof InngestWorkflow) {
38
- wf.__registerMastra(mastra);
39
- return wf.getFunctions();
40
- }
41
- return [];
42
- });
37
+ const functions = Array.from(
38
+ new Set(
39
+ Object.values(wfs).flatMap(wf => {
40
+ if (wf instanceof InngestWorkflow) {
41
+ wf.__registerMastra(mastra);
42
+ return wf.getFunctions();
43
+ }
44
+ return [];
45
+ }),
46
+ ),
47
+ );
43
48
  return inngestServe({
44
49
  client: inngest,
45
50
  functions,
@@ -94,8 +99,15 @@ export class InngestRun<
94
99
  while (runs?.[0]?.status !== 'Completed' || runs?.[0]?.event_id !== eventId) {
95
100
  await new Promise(resolve => setTimeout(resolve, 1000));
96
101
  runs = await this.getRuns(eventId);
97
- if (runs?.[0]?.status === 'Failed' || runs?.[0]?.status === 'Cancelled') {
102
+ if (runs?.[0]?.status === 'Failed') {
103
+ console.log('run', runs?.[0]);
98
104
  throw new Error(`Function run ${runs?.[0]?.status}`);
105
+ } else if (runs?.[0]?.status === 'Cancelled') {
106
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
107
+ workflowName: this.workflowId,
108
+ runId: this.runId,
109
+ });
110
+ return { output: { result: { steps: snapshot?.context, status: 'canceled' } } };
99
111
  }
100
112
  }
101
113
  return runs?.[0];
@@ -108,6 +120,30 @@ export class InngestRun<
108
120
  });
109
121
  }
110
122
 
123
+ async cancel() {
124
+ await this.inngest.send({
125
+ name: `cancel.workflow.${this.workflowId}`,
126
+ data: {
127
+ runId: this.runId,
128
+ },
129
+ });
130
+
131
+ const snapshot = await this.#mastra?.storage?.loadWorkflowSnapshot({
132
+ workflowName: this.workflowId,
133
+ runId: this.runId,
134
+ });
135
+ if (snapshot) {
136
+ await this.#mastra?.storage?.persistWorkflowSnapshot({
137
+ workflowName: this.workflowId,
138
+ runId: this.runId,
139
+ snapshot: {
140
+ ...snapshot,
141
+ status: 'canceled' as any,
142
+ },
143
+ });
144
+ }
145
+ }
146
+
111
147
  async start({
112
148
  inputData,
113
149
  }: {
@@ -147,7 +183,9 @@ export class InngestRun<
147
183
  result.error = new Error(result.error);
148
184
  }
149
185
 
150
- this.cleanup?.();
186
+ if (result.status !== 'suspended') {
187
+ this.cleanup?.();
188
+ }
151
189
  return result;
152
190
  }
153
191
 
@@ -194,6 +232,7 @@ export class InngestRun<
194
232
  data: {
195
233
  inputData: params.resumeData,
196
234
  runId: this.runId,
235
+ workflowId: this.workflowId,
197
236
  stepResults: snapshot?.context as any,
198
237
  resume: {
199
238
  steps,
@@ -432,23 +471,27 @@ export class InngestWorkflow<
432
471
 
433
472
  this.runs.set(runIdToUse, run);
434
473
 
435
- await this.mastra?.getStorage()?.persistWorkflowSnapshot({
436
- workflowName: this.id,
437
- runId: runIdToUse,
438
- snapshot: {
474
+ const workflowSnapshotInStorage = await this.getWorkflowRunExecutionResult(runIdToUse);
475
+
476
+ if (!workflowSnapshotInStorage) {
477
+ await this.mastra?.getStorage()?.persistWorkflowSnapshot({
478
+ workflowName: this.id,
439
479
  runId: runIdToUse,
440
- status: 'pending',
441
- value: {},
442
- context: {},
443
- activePaths: [],
444
- serializedStepGraph: this.serializedStepGraph,
445
- suspendedPaths: {},
446
- result: undefined,
447
- error: undefined,
448
- // @ts-ignore
449
- timestamp: Date.now(),
450
- },
451
- });
480
+ snapshot: {
481
+ runId: runIdToUse,
482
+ status: 'pending',
483
+ value: {},
484
+ context: {},
485
+ activePaths: [],
486
+ serializedStepGraph: this.serializedStepGraph,
487
+ suspendedPaths: {},
488
+ result: undefined,
489
+ error: undefined,
490
+ // @ts-ignore
491
+ timestamp: Date.now(),
492
+ },
493
+ });
494
+ }
452
495
 
453
496
  return run;
454
497
  }
@@ -458,8 +501,12 @@ export class InngestWorkflow<
458
501
  return this.function;
459
502
  }
460
503
  this.function = this.inngest.createFunction(
461
- // @ts-ignore
462
- { id: `workflow.${this.id}`, retries: this.retryConfig?.attempts ?? 0 },
504
+ {
505
+ id: `workflow.${this.id}`,
506
+ // @ts-ignore
507
+ retries: this.retryConfig?.attempts ?? 0,
508
+ cancelOn: [{ event: `cancel.workflow.${this.id}` }],
509
+ },
463
510
  { event: `workflow.${this.id}` },
464
511
  async ({ event, step, attempt, publish }) => {
465
512
  let { inputData, runId, resume } = event.data;
@@ -508,6 +555,7 @@ export class InngestWorkflow<
508
555
  retryConfig: this.retryConfig,
509
556
  runtimeContext: new RuntimeContext(), // TODO
510
557
  resume,
558
+ abortController: new AbortController(),
511
559
  });
512
560
 
513
561
  return { result, runId };
@@ -630,7 +678,7 @@ export function createStep<
630
678
  outputSchema: z.object({
631
679
  text: z.string(),
632
680
  }),
633
- execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
681
+ execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
634
682
  let streamPromise = {} as {
635
683
  promise: Promise<string>;
636
684
  resolve: (value: string) => void;
@@ -656,8 +704,13 @@ export function createStep<
656
704
  onFinish: result => {
657
705
  streamPromise.resolve(result.text);
658
706
  },
707
+ abortSignal,
659
708
  });
660
709
 
710
+ if (abortSignal.aborted) {
711
+ return abort();
712
+ }
713
+
661
714
  for await (const chunk of fullStream) {
662
715
  switch (chunk.type) {
663
716
  case 'text-delta':
@@ -815,6 +868,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
815
868
  delay?: number;
816
869
  };
817
870
  runtimeContext: RuntimeContext;
871
+ abortController: AbortController;
818
872
  }): Promise<TOutput> {
819
873
  await params.emitter.emit('watch-v2', {
820
874
  type: 'start',
@@ -914,7 +968,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
914
968
  resume,
915
969
  prevOutput,
916
970
  emitter,
971
+ abortController,
917
972
  runtimeContext,
973
+ writableStream,
918
974
  }: {
919
975
  workflowId: string;
920
976
  runId: string;
@@ -927,7 +983,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
927
983
  };
928
984
  prevOutput: any;
929
985
  emitter: Emitter;
986
+ abortController: AbortController;
930
987
  runtimeContext: RuntimeContext;
988
+ writableStream?: WritableStream<ChunkType>;
931
989
  }): Promise<StepResult<any, any, any, any>> {
932
990
  return super.executeStep({
933
991
  workflowId,
@@ -938,12 +996,190 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
938
996
  resume,
939
997
  prevOutput,
940
998
  emitter,
999
+ abortController,
941
1000
  runtimeContext,
1001
+ writableStream,
942
1002
  });
943
1003
  }
944
1004
 
945
- async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
946
- await this.inngestStep.sleep(id, duration);
1005
+ // async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
1006
+ // await this.inngestStep.sleep(id, duration);
1007
+ // }
1008
+
1009
+ async executeSleep({
1010
+ workflowId,
1011
+ runId,
1012
+ entry,
1013
+ prevOutput,
1014
+ stepResults,
1015
+ emitter,
1016
+ abortController,
1017
+ runtimeContext,
1018
+ writableStream,
1019
+ }: {
1020
+ workflowId: string;
1021
+ runId: string;
1022
+ serializedStepGraph: SerializedStepFlowEntry[];
1023
+ entry: {
1024
+ type: 'sleep';
1025
+ id: string;
1026
+ duration?: number;
1027
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
1028
+ };
1029
+ prevStep: StepFlowEntry;
1030
+ prevOutput: any;
1031
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1032
+ resume?: {
1033
+ steps: string[];
1034
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1035
+ resumePayload: any;
1036
+ resumePath: number[];
1037
+ };
1038
+ executionContext: ExecutionContext;
1039
+ emitter: Emitter;
1040
+ abortController: AbortController;
1041
+ runtimeContext: RuntimeContext;
1042
+ writableStream?: WritableStream<ChunkType>;
1043
+ }): Promise<void> {
1044
+ let { duration, fn } = entry;
1045
+
1046
+ if (fn) {
1047
+ const stepCallId = randomUUID();
1048
+ duration = await this.inngestStep.run(`workflow.${workflowId}.sleep.${entry.id}`, async () => {
1049
+ return await fn({
1050
+ runId,
1051
+ workflowId,
1052
+ mastra: this.mastra!,
1053
+ runtimeContext,
1054
+ inputData: prevOutput,
1055
+ runCount: -1,
1056
+ getInitData: () => stepResults?.input as any,
1057
+ getStepResult: (step: any) => {
1058
+ if (!step?.id) {
1059
+ return null;
1060
+ }
1061
+
1062
+ const result = stepResults[step.id];
1063
+ if (result?.status === 'success') {
1064
+ return result.output;
1065
+ }
1066
+
1067
+ return null;
1068
+ },
1069
+
1070
+ // TODO: this function shouldn't have suspend probably?
1071
+ suspend: async (_suspendPayload: any): Promise<any> => {},
1072
+ bail: () => {},
1073
+ abort: () => {
1074
+ abortController?.abort();
1075
+ },
1076
+ [EMITTER_SYMBOL]: emitter,
1077
+ engine: { step: this.inngestStep },
1078
+ abortSignal: abortController?.signal,
1079
+ writer: new ToolStream(
1080
+ {
1081
+ prefix: 'step',
1082
+ callId: stepCallId,
1083
+ name: 'sleep',
1084
+ runId,
1085
+ },
1086
+ writableStream,
1087
+ ),
1088
+ });
1089
+ });
1090
+ }
1091
+
1092
+ await this.inngestStep.sleep(entry.id, !duration || duration < 0 ? 0 : duration);
1093
+ }
1094
+
1095
+ async executeSleepUntil({
1096
+ workflowId,
1097
+ runId,
1098
+ entry,
1099
+ prevOutput,
1100
+ stepResults,
1101
+ emitter,
1102
+ abortController,
1103
+ runtimeContext,
1104
+ writableStream,
1105
+ }: {
1106
+ workflowId: string;
1107
+ runId: string;
1108
+ serializedStepGraph: SerializedStepFlowEntry[];
1109
+ entry: {
1110
+ type: 'sleepUntil';
1111
+ id: string;
1112
+ date?: Date;
1113
+ fn?: ExecuteFunction<any, any, any, any, InngestEngineType>;
1114
+ };
1115
+ prevStep: StepFlowEntry;
1116
+ prevOutput: any;
1117
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1118
+ resume?: {
1119
+ steps: string[];
1120
+ stepResults: Record<string, StepResult<any, any, any, any>>;
1121
+ resumePayload: any;
1122
+ resumePath: number[];
1123
+ };
1124
+ executionContext: ExecutionContext;
1125
+ emitter: Emitter;
1126
+ abortController: AbortController;
1127
+ runtimeContext: RuntimeContext;
1128
+ writableStream?: WritableStream<ChunkType>;
1129
+ }): Promise<void> {
1130
+ let { date, fn } = entry;
1131
+
1132
+ if (fn) {
1133
+ date = await this.inngestStep.run(`workflow.${workflowId}.sleepUntil.${entry.id}`, async () => {
1134
+ const stepCallId = randomUUID();
1135
+ return await fn({
1136
+ runId,
1137
+ workflowId,
1138
+ mastra: this.mastra!,
1139
+ runtimeContext,
1140
+ inputData: prevOutput,
1141
+ runCount: -1,
1142
+ getInitData: () => stepResults?.input as any,
1143
+ getStepResult: (step: any) => {
1144
+ if (!step?.id) {
1145
+ return null;
1146
+ }
1147
+
1148
+ const result = stepResults[step.id];
1149
+ if (result?.status === 'success') {
1150
+ return result.output;
1151
+ }
1152
+
1153
+ return null;
1154
+ },
1155
+
1156
+ // TODO: this function shouldn't have suspend probably?
1157
+ suspend: async (_suspendPayload: any): Promise<any> => {},
1158
+ bail: () => {},
1159
+ abort: () => {
1160
+ abortController?.abort();
1161
+ },
1162
+ [EMITTER_SYMBOL]: emitter,
1163
+ engine: { step: this.inngestStep },
1164
+ abortSignal: abortController?.signal,
1165
+ writer: new ToolStream(
1166
+ {
1167
+ prefix: 'step',
1168
+ callId: stepCallId,
1169
+ name: 'sleep',
1170
+ runId,
1171
+ },
1172
+ writableStream,
1173
+ ),
1174
+ });
1175
+ });
1176
+ }
1177
+
1178
+ if (!(date instanceof Date)) {
1179
+ return;
1180
+ }
1181
+
1182
+ await this.inngestStep.sleepUntil(entry.id, date);
947
1183
  }
948
1184
 
949
1185
  async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
@@ -966,17 +1202,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
966
1202
  resume,
967
1203
  prevOutput,
968
1204
  emitter,
1205
+ abortController,
969
1206
  runtimeContext,
1207
+ writableStream,
970
1208
  }: {
971
1209
  step: Step<string, any, any>;
972
1210
  stepResults: Record<string, StepResult<any, any, any, any>>;
973
- executionContext: {
974
- workflowId: string;
975
- runId: string;
976
- executionPath: number[];
977
- suspendedPaths: Record<string, number[]>;
978
- retryConfig: { attempts: number; delay: number };
979
- };
1211
+ executionContext: ExecutionContext;
980
1212
  resume?: {
981
1213
  steps: string[];
982
1214
  resumePayload: any;
@@ -984,7 +1216,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
984
1216
  };
985
1217
  prevOutput: any;
986
1218
  emitter: Emitter;
1219
+ abortController: AbortController;
987
1220
  runtimeContext: RuntimeContext;
1221
+ writableStream?: WritableStream<ChunkType>;
988
1222
  }): Promise<StepResult<any, any, any, any>> {
989
1223
  const startedAt = await this.inngestStep.run(
990
1224
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
@@ -1016,6 +1250,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1016
1250
  type: 'step-start',
1017
1251
  payload: {
1018
1252
  id: step.id,
1253
+ status: 'running',
1254
+ payload: prevOutput,
1255
+ startedAt,
1019
1256
  },
1020
1257
  });
1021
1258
 
@@ -1091,6 +1328,8 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1091
1328
  payload: {
1092
1329
  id: step.id,
1093
1330
  status: 'failed',
1331
+ error: result?.error,
1332
+ payload: prevOutput,
1094
1333
  },
1095
1334
  });
1096
1335
 
@@ -1128,6 +1367,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1128
1367
  type: 'step-suspended',
1129
1368
  payload: {
1130
1369
  id: step.id,
1370
+ status: 'suspended',
1131
1371
  },
1132
1372
  });
1133
1373
 
@@ -1187,6 +1427,15 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1187
1427
  eventTimestamp: Date.now(),
1188
1428
  });
1189
1429
 
1430
+ await emitter.emit('watch-v2', {
1431
+ type: 'step-result',
1432
+ payload: {
1433
+ id: step.id,
1434
+ status: 'success',
1435
+ output: result?.result,
1436
+ },
1437
+ });
1438
+
1190
1439
  await emitter.emit('watch-v2', {
1191
1440
  type: 'step-finish',
1192
1441
  payload: {
@@ -1213,6 +1462,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1213
1462
  runId: executionContext.runId,
1214
1463
  mastra: this.mastra!,
1215
1464
  runtimeContext,
1465
+ writableStream,
1216
1466
  inputData: prevOutput,
1217
1467
  resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
1218
1468
  getInitData: () => stepResults?.input as any,
@@ -1241,6 +1491,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1241
1491
  engine: {
1242
1492
  step: this.inngestStep,
1243
1493
  },
1494
+ abortSignal: abortController.signal,
1244
1495
  });
1245
1496
  const endedAt = Date.now();
1246
1497
 
@@ -1307,8 +1558,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1307
1558
  type: 'step-suspended',
1308
1559
  payload: {
1309
1560
  id: step.id,
1310
- status: execResults.status,
1311
- output: execResults.status === 'success' ? execResults?.output : undefined,
1561
+ ...execResults,
1312
1562
  },
1313
1563
  });
1314
1564
  } else {
@@ -1316,8 +1566,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1316
1566
  type: 'step-result',
1317
1567
  payload: {
1318
1568
  id: step.id,
1319
- status: execResults.status,
1320
- output: execResults.status === 'success' ? execResults?.output : undefined,
1569
+ ...execResults,
1321
1570
  },
1322
1571
  });
1323
1572
 
@@ -1360,6 +1609,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1360
1609
  workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
1361
1610
  result?: Record<string, any>;
1362
1611
  error?: string | Error;
1612
+ runtimeContext: RuntimeContext;
1363
1613
  }) {
1364
1614
  await this.inngestStep.run(
1365
1615
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -1396,7 +1646,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1396
1646
  resume,
1397
1647
  executionContext,
1398
1648
  emitter,
1649
+ abortController,
1399
1650
  runtimeContext,
1651
+ writableStream,
1400
1652
  }: {
1401
1653
  workflowId: string;
1402
1654
  runId: string;
@@ -1417,7 +1669,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1417
1669
  };
1418
1670
  executionContext: ExecutionContext;
1419
1671
  emitter: Emitter;
1672
+ abortController: AbortController;
1420
1673
  runtimeContext: RuntimeContext;
1674
+ writableStream?: WritableStream<ChunkType>;
1421
1675
  }): Promise<StepResult<any, any, any, any>> {
1422
1676
  let execResults: any;
1423
1677
  const truthyIndexes = (
@@ -1427,8 +1681,10 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1427
1681
  try {
1428
1682
  const result = await cond({
1429
1683
  runId,
1684
+ workflowId,
1430
1685
  mastra: this.mastra!,
1431
1686
  runtimeContext,
1687
+ runCount: -1,
1432
1688
  inputData: prevOutput,
1433
1689
  getInitData: () => stepResults?.input as any,
1434
1690
  getStepResult: (step: any) => {
@@ -1447,10 +1703,23 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1447
1703
  // TODO: this function shouldn't have suspend probably?
1448
1704
  suspend: async (_suspendPayload: any) => {},
1449
1705
  bail: () => {},
1706
+ abort: () => {
1707
+ abortController.abort();
1708
+ },
1450
1709
  [EMITTER_SYMBOL]: emitter,
1451
1710
  engine: {
1452
1711
  step: this.inngestStep,
1453
1712
  },
1713
+ abortSignal: abortController.signal,
1714
+ writer: new ToolStream(
1715
+ {
1716
+ prefix: 'step',
1717
+ callId: randomUUID(),
1718
+ name: 'conditional',
1719
+ runId,
1720
+ },
1721
+ writableStream,
1722
+ ),
1454
1723
  });
1455
1724
  return result ? index : null;
1456
1725
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1482,7 +1751,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1482
1751
  executionSpan: executionContext.executionSpan,
1483
1752
  },
1484
1753
  emitter,
1754
+ abortController,
1485
1755
  runtimeContext,
1756
+ writableStream,
1486
1757
  }),
1487
1758
  ),
1488
1759
  );
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": ["./tsconfig.json", "../../tsconfig.build.json"],
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["node_modules", "**/*.test.ts", "src/**/*.mock.ts"]
9
+ }
package/vitest.config.ts CHANGED
@@ -4,5 +4,11 @@ export default defineConfig({
4
4
  test: {
5
5
  globals: true,
6
6
  include: ['src/**/*.test.ts'],
7
+ pool: 'threads',
8
+ poolOptions: {
9
+ threads: {
10
+ singleThread: true,
11
+ },
12
+ },
7
13
  },
8
14
  });