@mastra/inngest 0.0.0-tool-call-parts-20250630193309 → 0.0.0-transpile-packages-20250730132657

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
  }: {
@@ -196,6 +232,7 @@ export class InngestRun<
196
232
  data: {
197
233
  inputData: params.resumeData,
198
234
  runId: this.runId,
235
+ workflowId: this.workflowId,
199
236
  stepResults: snapshot?.context as any,
200
237
  resume: {
201
238
  steps,
@@ -464,8 +501,12 @@ export class InngestWorkflow<
464
501
  return this.function;
465
502
  }
466
503
  this.function = this.inngest.createFunction(
467
- // @ts-ignore
468
- { 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
+ },
469
510
  { event: `workflow.${this.id}` },
470
511
  async ({ event, step, attempt, publish }) => {
471
512
  let { inputData, runId, resume } = event.data;
@@ -514,6 +555,7 @@ export class InngestWorkflow<
514
555
  retryConfig: this.retryConfig,
515
556
  runtimeContext: new RuntimeContext(), // TODO
516
557
  resume,
558
+ abortController: new AbortController(),
517
559
  });
518
560
 
519
561
  return { result, runId };
@@ -636,7 +678,7 @@ export function createStep<
636
678
  outputSchema: z.object({
637
679
  text: z.string(),
638
680
  }),
639
- execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext }) => {
681
+ execute: async ({ inputData, [EMITTER_SYMBOL]: emitter, runtimeContext, abortSignal, abort }) => {
640
682
  let streamPromise = {} as {
641
683
  promise: Promise<string>;
642
684
  resolve: (value: string) => void;
@@ -662,8 +704,13 @@ export function createStep<
662
704
  onFinish: result => {
663
705
  streamPromise.resolve(result.text);
664
706
  },
707
+ abortSignal,
665
708
  });
666
709
 
710
+ if (abortSignal.aborted) {
711
+ return abort();
712
+ }
713
+
667
714
  for await (const chunk of fullStream) {
668
715
  switch (chunk.type) {
669
716
  case 'text-delta':
@@ -821,6 +868,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
821
868
  delay?: number;
822
869
  };
823
870
  runtimeContext: RuntimeContext;
871
+ abortController: AbortController;
824
872
  }): Promise<TOutput> {
825
873
  await params.emitter.emit('watch-v2', {
826
874
  type: 'start',
@@ -920,7 +968,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
920
968
  resume,
921
969
  prevOutput,
922
970
  emitter,
971
+ abortController,
923
972
  runtimeContext,
973
+ writableStream,
924
974
  }: {
925
975
  workflowId: string;
926
976
  runId: string;
@@ -933,7 +983,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
933
983
  };
934
984
  prevOutput: any;
935
985
  emitter: Emitter;
986
+ abortController: AbortController;
936
987
  runtimeContext: RuntimeContext;
988
+ writableStream?: WritableStream<ChunkType>;
937
989
  }): Promise<StepResult<any, any, any, any>> {
938
990
  return super.executeStep({
939
991
  workflowId,
@@ -944,12 +996,190 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
944
996
  resume,
945
997
  prevOutput,
946
998
  emitter,
999
+ abortController,
947
1000
  runtimeContext,
1001
+ writableStream,
948
1002
  });
949
1003
  }
950
1004
 
951
- async executeSleep({ id, duration }: { id: string; duration: number }): Promise<void> {
952
- 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);
953
1183
  }
954
1184
 
955
1185
  async executeWaitForEvent({ event, timeout }: { event: string; timeout?: number }): Promise<any> {
@@ -972,17 +1202,13 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
972
1202
  resume,
973
1203
  prevOutput,
974
1204
  emitter,
1205
+ abortController,
975
1206
  runtimeContext,
1207
+ writableStream,
976
1208
  }: {
977
1209
  step: Step<string, any, any>;
978
1210
  stepResults: Record<string, StepResult<any, any, any, any>>;
979
- executionContext: {
980
- workflowId: string;
981
- runId: string;
982
- executionPath: number[];
983
- suspendedPaths: Record<string, number[]>;
984
- retryConfig: { attempts: number; delay: number };
985
- };
1211
+ executionContext: ExecutionContext;
986
1212
  resume?: {
987
1213
  steps: string[];
988
1214
  resumePayload: any;
@@ -990,7 +1216,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
990
1216
  };
991
1217
  prevOutput: any;
992
1218
  emitter: Emitter;
1219
+ abortController: AbortController;
993
1220
  runtimeContext: RuntimeContext;
1221
+ writableStream?: WritableStream<ChunkType>;
994
1222
  }): Promise<StepResult<any, any, any, any>> {
995
1223
  const startedAt = await this.inngestStep.run(
996
1224
  `workflow.${executionContext.workflowId}.run.${executionContext.runId}.step.${step.id}.running_ev`,
@@ -1023,6 +1251,8 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1023
1251
  payload: {
1024
1252
  id: step.id,
1025
1253
  status: 'running',
1254
+ payload: prevOutput,
1255
+ startedAt,
1026
1256
  },
1027
1257
  });
1028
1258
 
@@ -1232,6 +1462,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1232
1462
  runId: executionContext.runId,
1233
1463
  mastra: this.mastra!,
1234
1464
  runtimeContext,
1465
+ writableStream,
1235
1466
  inputData: prevOutput,
1236
1467
  resumeData: resume?.steps[0] === step.id ? resume?.resumePayload : undefined,
1237
1468
  getInitData: () => stepResults?.input as any,
@@ -1260,6 +1491,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1260
1491
  engine: {
1261
1492
  step: this.inngestStep,
1262
1493
  },
1494
+ abortSignal: abortController.signal,
1263
1495
  });
1264
1496
  const endedAt = Date.now();
1265
1497
 
@@ -1377,6 +1609,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1377
1609
  workflowStatus: 'success' | 'failed' | 'suspended' | 'running';
1378
1610
  result?: Record<string, any>;
1379
1611
  error?: string | Error;
1612
+ runtimeContext: RuntimeContext;
1380
1613
  }) {
1381
1614
  await this.inngestStep.run(
1382
1615
  `workflow.${workflowId}.run.${runId}.path.${JSON.stringify(executionContext.executionPath)}.stepUpdate`,
@@ -1413,7 +1646,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1413
1646
  resume,
1414
1647
  executionContext,
1415
1648
  emitter,
1649
+ abortController,
1416
1650
  runtimeContext,
1651
+ writableStream,
1417
1652
  }: {
1418
1653
  workflowId: string;
1419
1654
  runId: string;
@@ -1434,7 +1669,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1434
1669
  };
1435
1670
  executionContext: ExecutionContext;
1436
1671
  emitter: Emitter;
1672
+ abortController: AbortController;
1437
1673
  runtimeContext: RuntimeContext;
1674
+ writableStream?: WritableStream<ChunkType>;
1438
1675
  }): Promise<StepResult<any, any, any, any>> {
1439
1676
  let execResults: any;
1440
1677
  const truthyIndexes = (
@@ -1444,6 +1681,7 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1444
1681
  try {
1445
1682
  const result = await cond({
1446
1683
  runId,
1684
+ workflowId,
1447
1685
  mastra: this.mastra!,
1448
1686
  runtimeContext,
1449
1687
  runCount: -1,
@@ -1465,10 +1703,23 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1465
1703
  // TODO: this function shouldn't have suspend probably?
1466
1704
  suspend: async (_suspendPayload: any) => {},
1467
1705
  bail: () => {},
1706
+ abort: () => {
1707
+ abortController.abort();
1708
+ },
1468
1709
  [EMITTER_SYMBOL]: emitter,
1469
1710
  engine: {
1470
1711
  step: this.inngestStep,
1471
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
+ ),
1472
1723
  });
1473
1724
  return result ? index : null;
1474
1725
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1500,7 +1751,9 @@ export class InngestExecutionEngine extends DefaultExecutionEngine {
1500
1751
  executionSpan: executionContext.executionSpan,
1501
1752
  },
1502
1753
  emitter,
1754
+ abortController,
1503
1755
  runtimeContext,
1756
+ writableStream,
1504
1757
  }),
1505
1758
  ),
1506
1759
  );
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
  });