@mastra/dynamodb 0.0.0-remove-unused-model-providers-api-20251030210744 → 0.0.0-remove-ai-peer-dep-from-evals-20260105220639

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { DynamoDBClient, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
2
2
  import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
3
3
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
4
- import { MastraStorage, StoreOperations, WorkflowsStorage, MemoryStorage, resolveMessageLimit, ScoresStorage, TABLE_AI_SPANS, TABLE_RESOURCES, TABLE_TRACES, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
4
+ import { MemoryStorage, createStorageErrorId, normalizePerPage, calculatePagination, filterByDateRange, ScoresStorage, SCORERS_SCHEMA, WorkflowsStorage, MastraStorage, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_RESOURCES, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
5
5
  import { Entity, Service } from 'electrodb';
6
6
  import { MessageList } from '@mastra/core/agent';
7
- import { saveScorePayloadSchema } from '@mastra/core/scores';
7
+ import { saveScorePayloadSchema } from '@mastra/core/evals';
8
8
 
9
9
  // src/storage/index.ts
10
10
 
@@ -423,6 +423,10 @@ var scoreEntity = new Entity({
423
423
  return value;
424
424
  }
425
425
  },
426
+ preprocessPrompt: {
427
+ type: "string",
428
+ required: false
429
+ },
426
430
  preprocessStepResult: {
427
431
  type: "string",
428
432
  required: false,
@@ -933,11 +937,113 @@ function getElectroDbService(client, tableName) {
933
937
  }
934
938
  );
935
939
  }
940
+ function resolveDynamoDBConfig(config) {
941
+ if ("service" in config) {
942
+ return config.service;
943
+ }
944
+ const dynamoClient = new DynamoDBClient({
945
+ region: config.region || "us-east-1",
946
+ endpoint: config.endpoint,
947
+ credentials: config.credentials
948
+ });
949
+ const client = DynamoDBDocumentClient.from(dynamoClient);
950
+ return getElectroDbService(client, config.tableName);
951
+ }
952
+ var ENTITY_MAP = {
953
+ [TABLE_THREADS]: "thread",
954
+ [TABLE_MESSAGES]: "message",
955
+ [TABLE_RESOURCES]: "resource",
956
+ [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
957
+ [TABLE_SCORERS]: "score"
958
+ };
959
+ function getDeleteKey(entityName, item) {
960
+ const key = { entity: entityName };
961
+ switch (entityName) {
962
+ case "thread":
963
+ case "message":
964
+ case "resource":
965
+ case "score":
966
+ key.id = item.id;
967
+ break;
968
+ case "workflow_snapshot":
969
+ key.workflow_name = item.workflow_name;
970
+ key.run_id = item.run_id;
971
+ break;
972
+ default:
973
+ key.id = item.id;
974
+ }
975
+ return key;
976
+ }
977
+ async function deleteTableData(service, tableName) {
978
+ const entityName = ENTITY_MAP[tableName];
979
+ if (!entityName || !service.entities[entityName]) {
980
+ throw new Error(`No entity mapping found for table: ${tableName}`);
981
+ }
982
+ const entity = service.entities[entityName];
983
+ const result = await entity.scan.go({ pages: "all" });
984
+ if (!result.data.length) {
985
+ return;
986
+ }
987
+ const batchSize = 25;
988
+ for (let i = 0; i < result.data.length; i += batchSize) {
989
+ const batch = result.data.slice(i, i + batchSize);
990
+ const keysToDelete = batch.map((item) => getDeleteKey(entityName, item));
991
+ await entity.delete(keysToDelete).go();
992
+ }
993
+ }
994
+
995
+ // src/storage/domains/memory/index.ts
936
996
  var MemoryStorageDynamoDB = class extends MemoryStorage {
937
997
  service;
938
- constructor({ service }) {
998
+ constructor(config) {
939
999
  super();
940
- this.service = service;
1000
+ this.service = resolveDynamoDBConfig(config);
1001
+ }
1002
+ async dangerouslyClearAll() {
1003
+ await deleteTableData(this.service, TABLE_THREADS);
1004
+ await deleteTableData(this.service, TABLE_MESSAGES);
1005
+ await deleteTableData(this.service, TABLE_RESOURCES);
1006
+ }
1007
+ async deleteMessages(messageIds) {
1008
+ if (!messageIds || messageIds.length === 0) {
1009
+ return;
1010
+ }
1011
+ this.logger.debug("Deleting messages", { count: messageIds.length });
1012
+ try {
1013
+ const threadIds = /* @__PURE__ */ new Set();
1014
+ const batchSize = 25;
1015
+ for (let i = 0; i < messageIds.length; i += batchSize) {
1016
+ const batch = messageIds.slice(i, i + batchSize);
1017
+ const messagesToDelete = await Promise.all(
1018
+ batch.map(async (id) => {
1019
+ const result = await this.service.entities.message.get({ entity: "message", id }).go();
1020
+ return result.data;
1021
+ })
1022
+ );
1023
+ for (const message of messagesToDelete) {
1024
+ if (message) {
1025
+ if (message.threadId) {
1026
+ threadIds.add(message.threadId);
1027
+ }
1028
+ await this.service.entities.message.delete({ entity: "message", id: message.id }).go();
1029
+ }
1030
+ }
1031
+ }
1032
+ const now = (/* @__PURE__ */ new Date()).toISOString();
1033
+ for (const threadId of threadIds) {
1034
+ await this.service.entities.thread.update({ entity: "thread", id: threadId }).set({ updatedAt: now }).go();
1035
+ }
1036
+ } catch (error) {
1037
+ throw new MastraError(
1038
+ {
1039
+ id: createStorageErrorId("DYNAMODB", "DELETE_MESSAGES", "FAILED"),
1040
+ domain: ErrorDomain.STORAGE,
1041
+ category: ErrorCategory.THIRD_PARTY,
1042
+ details: { count: messageIds.length }
1043
+ },
1044
+ error
1045
+ );
1046
+ }
941
1047
  }
942
1048
  // Helper function to parse message data (handle JSON fields)
943
1049
  parseMessageData(data) {
@@ -951,17 +1057,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
951
1057
  };
952
1058
  }
953
1059
  // Helper function to transform and sort threads
954
- transformAndSortThreads(rawThreads, orderBy, sortDirection) {
1060
+ transformAndSortThreads(rawThreads, field, direction) {
955
1061
  return rawThreads.map((data) => ({
956
1062
  ...data,
957
1063
  // Convert date strings back to Date objects for consistency
958
1064
  createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
959
1065
  updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
960
1066
  })).sort((a, b) => {
961
- const fieldA = orderBy === "createdAt" ? a.createdAt : a.updatedAt;
962
- const fieldB = orderBy === "createdAt" ? b.createdAt : b.updatedAt;
1067
+ const fieldA = field === "createdAt" ? a.createdAt : a.updatedAt;
1068
+ const fieldB = field === "createdAt" ? b.createdAt : b.updatedAt;
963
1069
  const comparison = fieldA.getTime() - fieldB.getTime();
964
- return sortDirection === "DESC" ? -comparison : comparison;
1070
+ return direction === "DESC" ? -comparison : comparison;
965
1071
  });
966
1072
  }
967
1073
  async getThreadById({ threadId }) {
@@ -983,7 +1089,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
983
1089
  } catch (error) {
984
1090
  throw new MastraError(
985
1091
  {
986
- id: "STORAGE_DYNAMODB_STORE_GET_THREAD_BY_ID_FAILED",
1092
+ id: createStorageErrorId("DYNAMODB", "GET_THREAD_BY_ID", "FAILED"),
987
1093
  domain: ErrorDomain.STORAGE,
988
1094
  category: ErrorCategory.THIRD_PARTY,
989
1095
  details: { threadId }
@@ -992,32 +1098,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
992
1098
  );
993
1099
  }
994
1100
  }
995
- /**
996
- * @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
997
- */
998
- async getThreadsByResourceId(args) {
999
- const resourceId = args.resourceId;
1000
- const orderBy = this.castThreadOrderBy(args.orderBy);
1001
- const sortDirection = this.castThreadSortDirection(args.sortDirection);
1002
- this.logger.debug("Getting threads by resource ID", { resourceId, orderBy, sortDirection });
1003
- try {
1004
- const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
1005
- if (!result.data.length) {
1006
- return [];
1007
- }
1008
- return this.transformAndSortThreads(result.data, orderBy, sortDirection);
1009
- } catch (error) {
1010
- throw new MastraError(
1011
- {
1012
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1013
- domain: ErrorDomain.STORAGE,
1014
- category: ErrorCategory.THIRD_PARTY,
1015
- details: { resourceId }
1016
- },
1017
- error
1018
- );
1019
- }
1020
- }
1021
1101
  async saveThread({ thread }) {
1022
1102
  this.logger.debug("Saving thread", { threadId: thread.id });
1023
1103
  const now = /* @__PURE__ */ new Date();
@@ -1043,7 +1123,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1043
1123
  } catch (error) {
1044
1124
  throw new MastraError(
1045
1125
  {
1046
- id: "STORAGE_DYNAMODB_STORE_SAVE_THREAD_FAILED",
1126
+ id: createStorageErrorId("DYNAMODB", "SAVE_THREAD", "FAILED"),
1047
1127
  domain: ErrorDomain.STORAGE,
1048
1128
  category: ErrorCategory.THIRD_PARTY,
1049
1129
  details: { threadId: thread.id }
@@ -1085,7 +1165,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1085
1165
  } catch (error) {
1086
1166
  throw new MastraError(
1087
1167
  {
1088
- id: "STORAGE_DYNAMODB_STORE_UPDATE_THREAD_FAILED",
1168
+ id: createStorageErrorId("DYNAMODB", "UPDATE_THREAD", "FAILED"),
1089
1169
  domain: ErrorDomain.STORAGE,
1090
1170
  category: ErrorCategory.THIRD_PARTY,
1091
1171
  details: { threadId: id }
@@ -1097,7 +1177,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1097
1177
  async deleteThread({ threadId }) {
1098
1178
  this.logger.debug("Deleting thread", { threadId });
1099
1179
  try {
1100
- const messages = await this.getMessages({ threadId });
1180
+ const { messages } = await this.listMessages({ threadId, perPage: false });
1101
1181
  if (messages.length > 0) {
1102
1182
  const batchSize = 25;
1103
1183
  for (let i = 0; i < messages.length; i += batchSize) {
@@ -1117,7 +1197,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1117
1197
  } catch (error) {
1118
1198
  throw new MastraError(
1119
1199
  {
1120
- id: "STORAGE_DYNAMODB_STORE_DELETE_THREAD_FAILED",
1200
+ id: createStorageErrorId("DYNAMODB", "DELETE_THREAD", "FAILED"),
1121
1201
  domain: ErrorDomain.STORAGE,
1122
1202
  category: ErrorCategory.THIRD_PARTY,
1123
1203
  details: { threadId }
@@ -1126,72 +1206,9 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1126
1206
  );
1127
1207
  }
1128
1208
  }
1129
- async getMessages({
1130
- threadId,
1131
- resourceId,
1132
- selectBy,
1133
- format
1134
- }) {
1135
- this.logger.debug("Getting messages", { threadId, selectBy });
1136
- try {
1137
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1138
- const messages = [];
1139
- const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1140
- if (selectBy?.include?.length) {
1141
- const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1142
- if (includeMessages) {
1143
- messages.push(...includeMessages);
1144
- }
1145
- }
1146
- if (limit !== 0) {
1147
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1148
- let results;
1149
- if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1150
- results = await query.go({ limit, order: "desc" });
1151
- results.data = results.data.reverse();
1152
- } else {
1153
- results = await query.go();
1154
- }
1155
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1156
- allThreadMessages.sort((a, b) => {
1157
- const timeA = a.createdAt.getTime();
1158
- const timeB = b.createdAt.getTime();
1159
- if (timeA === timeB) {
1160
- return a.id.localeCompare(b.id);
1161
- }
1162
- return timeA - timeB;
1163
- });
1164
- messages.push(...allThreadMessages);
1165
- }
1166
- messages.sort((a, b) => {
1167
- const timeA = a.createdAt.getTime();
1168
- const timeB = b.createdAt.getTime();
1169
- if (timeA === timeB) {
1170
- return a.id.localeCompare(b.id);
1171
- }
1172
- return timeA - timeB;
1173
- });
1174
- const uniqueMessages = messages.filter(
1175
- (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1176
- );
1177
- const list = new MessageList({ threadId, resourceId }).add(uniqueMessages, "memory");
1178
- if (format === `v2`) return list.get.all.v2();
1179
- return list.get.all.v1();
1180
- } catch (error) {
1181
- throw new MastraError(
1182
- {
1183
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED",
1184
- domain: ErrorDomain.STORAGE,
1185
- category: ErrorCategory.THIRD_PARTY,
1186
- details: { threadId, resourceId: resourceId ?? "" }
1187
- },
1188
- error
1189
- );
1190
- }
1191
- }
1192
1209
  async listMessagesById({ messageIds }) {
1193
1210
  this.logger.debug("Getting messages by ID", { messageIds });
1194
- if (messageIds.length === 0) return [];
1211
+ if (messageIds.length === 0) return { messages: [] };
1195
1212
  try {
1196
1213
  const results = await Promise.all(
1197
1214
  messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
@@ -1202,11 +1219,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1202
1219
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1203
1220
  );
1204
1221
  const list = new MessageList().add(uniqueMessages, "memory");
1205
- return list.get.all.v2();
1222
+ return { messages: list.get.all.db() };
1206
1223
  } catch (error) {
1207
1224
  throw new MastraError(
1208
1225
  {
1209
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_BY_ID_FAILED",
1226
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES_BY_ID", "FAILED"),
1210
1227
  domain: ErrorDomain.STORAGE,
1211
1228
  category: ErrorCategory.THIRD_PARTY,
1212
1229
  details: { messageIds: JSON.stringify(messageIds) }
@@ -1216,41 +1233,43 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1216
1233
  }
1217
1234
  }
1218
1235
  async listMessages(args) {
1219
- const { threadId, resourceId, include, filter, limit, offset = 0, orderBy } = args;
1220
- if (!threadId.trim()) {
1236
+ const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
1237
+ const threadIds = Array.isArray(threadId) ? threadId : [threadId];
1238
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
1221
1239
  throw new MastraError(
1222
1240
  {
1223
- id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_THREAD_ID",
1241
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "INVALID_THREAD_ID"),
1224
1242
  domain: ErrorDomain.STORAGE,
1225
1243
  category: ErrorCategory.THIRD_PARTY,
1226
- details: { threadId }
1244
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
1227
1245
  },
1228
- new Error("threadId must be a non-empty string")
1246
+ new Error("threadId must be a non-empty string or array of non-empty strings")
1229
1247
  );
1230
1248
  }
1249
+ const perPage = normalizePerPage(perPageInput, 40);
1250
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1231
1251
  try {
1232
- let perPage = 40;
1233
- if (limit !== void 0) {
1234
- if (limit === false) {
1235
- perPage = Number.MAX_SAFE_INTEGER;
1236
- } else if (limit === 0) {
1237
- perPage = 0;
1238
- } else if (typeof limit === "number" && limit > 0) {
1239
- perPage = limit;
1240
- }
1252
+ if (page < 0) {
1253
+ throw new MastraError(
1254
+ {
1255
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "INVALID_PAGE"),
1256
+ domain: ErrorDomain.STORAGE,
1257
+ category: ErrorCategory.USER,
1258
+ details: { page }
1259
+ },
1260
+ new Error("page must be >= 0")
1261
+ );
1241
1262
  }
1242
- const page = perPage === 0 ? 0 : Math.floor(offset / perPage);
1243
- const sortField = orderBy?.field || "createdAt";
1244
- const sortDirection = orderBy?.direction || "DESC";
1263
+ const { field, direction } = this.parseOrderBy(orderBy, "ASC");
1245
1264
  this.logger.debug("Getting messages with listMessages", {
1246
1265
  threadId,
1247
1266
  resourceId,
1248
- limit,
1267
+ perPageInput,
1249
1268
  offset,
1250
1269
  perPage,
1251
1270
  page,
1252
- sortField,
1253
- sortDirection
1271
+ field,
1272
+ direction
1254
1273
  });
1255
1274
  const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1256
1275
  const results = await query.go();
@@ -1258,38 +1277,28 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1258
1277
  if (resourceId) {
1259
1278
  allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1260
1279
  }
1261
- if (filter?.dateRange) {
1262
- const dateRange = filter.dateRange;
1263
- allThreadMessages = allThreadMessages.filter((msg) => {
1264
- const createdAt = new Date(msg.createdAt).getTime();
1265
- if (dateRange.start) {
1266
- const startTime = dateRange.start instanceof Date ? dateRange.start.getTime() : new Date(dateRange.start).getTime();
1267
- if (createdAt < startTime) return false;
1268
- }
1269
- if (dateRange.end) {
1270
- const endTime = dateRange.end instanceof Date ? dateRange.end.getTime() : new Date(dateRange.end).getTime();
1271
- if (createdAt > endTime) return false;
1272
- }
1273
- return true;
1274
- });
1275
- }
1280
+ allThreadMessages = filterByDateRange(
1281
+ allThreadMessages,
1282
+ (msg) => new Date(msg.createdAt),
1283
+ filter?.dateRange
1284
+ );
1276
1285
  allThreadMessages.sort((a, b) => {
1277
- const aValue = sortField === "createdAt" ? new Date(a.createdAt).getTime() : a[sortField];
1278
- const bValue = sortField === "createdAt" ? new Date(b.createdAt).getTime() : b[sortField];
1286
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1287
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1279
1288
  if (aValue === bValue) {
1280
1289
  return a.id.localeCompare(b.id);
1281
1290
  }
1282
- return sortDirection === "ASC" ? aValue - bValue : bValue - aValue;
1291
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1283
1292
  });
1284
1293
  const total = allThreadMessages.length;
1285
1294
  const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1286
1295
  const paginatedCount = paginatedMessages.length;
1287
- if (total === 0 && paginatedCount === 0) {
1296
+ if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1288
1297
  return {
1289
1298
  messages: [],
1290
1299
  total: 0,
1291
1300
  page,
1292
- perPage,
1301
+ perPage: perPageForResponse,
1293
1302
  hasMore: false
1294
1303
  };
1295
1304
  }
@@ -1297,7 +1306,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1297
1306
  let includeMessages = [];
1298
1307
  if (include && include.length > 0) {
1299
1308
  const selectBy = { include };
1300
- includeMessages = await this._getIncludedMessages(threadId, selectBy);
1309
+ includeMessages = await this._getIncludedMessages(selectBy);
1301
1310
  for (const includeMsg of includeMessages) {
1302
1311
  if (!messageIds.has(includeMsg.id)) {
1303
1312
  paginatedMessages.push(includeMsg);
@@ -1306,33 +1315,36 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1306
1315
  }
1307
1316
  }
1308
1317
  const list = new MessageList().add(paginatedMessages, "memory");
1309
- let finalMessages = list.get.all.v2();
1318
+ let finalMessages = list.get.all.db();
1310
1319
  finalMessages = finalMessages.sort((a, b) => {
1311
- const aValue = sortField === "createdAt" ? new Date(a.createdAt).getTime() : a[sortField];
1312
- const bValue = sortField === "createdAt" ? new Date(b.createdAt).getTime() : b[sortField];
1320
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1321
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1313
1322
  if (aValue === bValue) {
1314
1323
  return a.id.localeCompare(b.id);
1315
1324
  }
1316
- return sortDirection === "ASC" ? aValue - bValue : bValue - aValue;
1325
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1317
1326
  });
1318
1327
  const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1319
1328
  const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1320
- const hasMore = limit === false ? false : allThreadMessagesReturned ? false : offset + paginatedCount < total;
1329
+ let hasMore = false;
1330
+ if (perPageInput !== false && !allThreadMessagesReturned) {
1331
+ hasMore = offset + paginatedCount < total;
1332
+ }
1321
1333
  return {
1322
1334
  messages: finalMessages,
1323
1335
  total,
1324
1336
  page,
1325
- perPage,
1337
+ perPage: perPageForResponse,
1326
1338
  hasMore
1327
1339
  };
1328
1340
  } catch (error) {
1329
1341
  const mastraError = new MastraError(
1330
1342
  {
1331
- id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_FAILED",
1343
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "FAILED"),
1332
1344
  domain: ErrorDomain.STORAGE,
1333
1345
  category: ErrorCategory.THIRD_PARTY,
1334
1346
  details: {
1335
- threadId,
1347
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
1336
1348
  resourceId: resourceId ?? ""
1337
1349
  }
1338
1350
  },
@@ -1343,27 +1355,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1343
1355
  return {
1344
1356
  messages: [],
1345
1357
  total: 0,
1346
- page: Math.floor(offset / (limit === false ? Number.MAX_SAFE_INTEGER : limit || 40)),
1347
- perPage: limit === false ? Number.MAX_SAFE_INTEGER : limit || 40,
1358
+ page,
1359
+ perPage: perPageForResponse,
1348
1360
  hasMore: false
1349
1361
  };
1350
1362
  }
1351
1363
  }
1352
- /**
1353
- * @todo When migrating from getThreadsByResourceIdPaginated to this method,
1354
- * implement orderBy and sortDirection support for full sorting capabilities
1355
- */
1356
- async listThreadsByResourceId(args) {
1357
- const { resourceId, limit, offset } = args;
1358
- const page = Math.floor(offset / limit);
1359
- const perPage = limit;
1360
- return this.getThreadsByResourceIdPaginated({ resourceId, page, perPage });
1361
- }
1362
1364
  async saveMessages(args) {
1363
- const { messages, format = "v1" } = args;
1365
+ const { messages } = args;
1364
1366
  this.logger.debug("Saving messages", { count: messages.length });
1365
1367
  if (!messages.length) {
1366
- return [];
1368
+ return { messages: [] };
1367
1369
  }
1368
1370
  const threadId = messages[0]?.threadId;
1369
1371
  if (!threadId) {
@@ -1417,12 +1419,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1417
1419
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1418
1420
  }).go();
1419
1421
  const list = new MessageList().add(messages, "memory");
1420
- if (format === `v1`) return list.get.all.v1();
1421
- return list.get.all.v2();
1422
+ return { messages: list.get.all.db() };
1422
1423
  } catch (error) {
1423
1424
  throw new MastraError(
1424
1425
  {
1425
- id: "STORAGE_DYNAMODB_STORE_SAVE_MESSAGES_FAILED",
1426
+ id: createStorageErrorId("DYNAMODB", "SAVE_MESSAGES", "FAILED"),
1426
1427
  domain: ErrorDomain.STORAGE,
1427
1428
  category: ErrorCategory.THIRD_PARTY,
1428
1429
  details: { count: messages.length }
@@ -1431,37 +1432,48 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1431
1432
  );
1432
1433
  }
1433
1434
  }
1434
- async getThreadsByResourceIdPaginated(args) {
1435
- const { resourceId, page = 0, perPage = 100 } = args;
1436
- const orderBy = this.castThreadOrderBy(args.orderBy);
1437
- const sortDirection = this.castThreadSortDirection(args.sortDirection);
1435
+ async listThreadsByResourceId(args) {
1436
+ const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
1437
+ const perPage = normalizePerPage(perPageInput, 100);
1438
+ if (page < 0) {
1439
+ throw new MastraError(
1440
+ {
1441
+ id: createStorageErrorId("DYNAMODB", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
1442
+ domain: ErrorDomain.STORAGE,
1443
+ category: ErrorCategory.USER,
1444
+ details: { page }
1445
+ },
1446
+ new Error("page must be >= 0")
1447
+ );
1448
+ }
1449
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1450
+ const { field, direction } = this.parseOrderBy(orderBy);
1438
1451
  this.logger.debug("Getting threads by resource ID with pagination", {
1439
1452
  resourceId,
1440
1453
  page,
1441
1454
  perPage,
1442
- orderBy,
1443
- sortDirection
1455
+ field,
1456
+ direction
1444
1457
  });
1445
1458
  try {
1446
1459
  const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1447
1460
  const results = await query.go();
1448
- const allThreads = this.transformAndSortThreads(results.data, orderBy, sortDirection);
1449
- const startIndex = page * perPage;
1450
- const endIndex = startIndex + perPage;
1451
- const paginatedThreads = allThreads.slice(startIndex, endIndex);
1461
+ const allThreads = this.transformAndSortThreads(results.data, field, direction);
1462
+ const endIndex = offset + perPage;
1463
+ const paginatedThreads = allThreads.slice(offset, endIndex);
1452
1464
  const total = allThreads.length;
1453
- const hasMore = endIndex < total;
1465
+ const hasMore = offset + perPage < total;
1454
1466
  return {
1455
1467
  threads: paginatedThreads,
1456
1468
  total,
1457
1469
  page,
1458
- perPage,
1470
+ perPage: perPageForResponse,
1459
1471
  hasMore
1460
1472
  };
1461
1473
  } catch (error) {
1462
1474
  throw new MastraError(
1463
1475
  {
1464
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1476
+ id: createStorageErrorId("DYNAMODB", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
1465
1477
  domain: ErrorDomain.STORAGE,
1466
1478
  category: ErrorCategory.THIRD_PARTY,
1467
1479
  details: { resourceId, page, perPage }
@@ -1470,98 +1482,24 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1470
1482
  );
1471
1483
  }
1472
1484
  }
1473
- async getMessagesPaginated(args) {
1474
- const { threadId, resourceId, selectBy, format = "v1" } = args;
1475
- const { page = 0, perPage = 40, dateRange } = selectBy?.pagination || {};
1476
- const fromDate = dateRange?.start;
1477
- const toDate = dateRange?.end;
1478
- const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1479
- this.logger.debug("Getting messages with pagination", { threadId, page, perPage, fromDate, toDate, limit });
1480
- try {
1481
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1482
- let messages = [];
1483
- if (selectBy?.include?.length) {
1484
- const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1485
- if (includeMessages) {
1486
- messages.push(...includeMessages);
1487
- }
1488
- }
1489
- if (limit !== 0) {
1490
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1491
- let results;
1492
- if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1493
- results = await query.go({ limit, order: "desc" });
1494
- results.data = results.data.reverse();
1495
- } else {
1496
- results = await query.go();
1497
- }
1498
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1499
- allThreadMessages.sort((a, b) => {
1500
- const timeA = a.createdAt.getTime();
1501
- const timeB = b.createdAt.getTime();
1502
- if (timeA === timeB) {
1503
- return a.id.localeCompare(b.id);
1504
- }
1505
- return timeA - timeB;
1506
- });
1507
- const excludeIds = messages.map((m) => m.id);
1508
- if (excludeIds.length > 0) {
1509
- allThreadMessages = allThreadMessages.filter((msg) => !excludeIds.includes(msg.id));
1510
- }
1511
- messages.push(...allThreadMessages);
1512
- }
1513
- messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1514
- if (fromDate || toDate) {
1515
- messages = messages.filter((msg) => {
1516
- const createdAt = new Date(msg.createdAt).getTime();
1517
- if (fromDate && createdAt < new Date(fromDate).getTime()) return false;
1518
- if (toDate && createdAt > new Date(toDate).getTime()) return false;
1519
- return true;
1520
- });
1521
- }
1522
- const total = messages.length;
1523
- const start = page * perPage;
1524
- const end = start + perPage;
1525
- const paginatedMessages = messages.slice(start, end);
1526
- const hasMore = end < total;
1527
- const list = new MessageList({ threadId, resourceId }).add(paginatedMessages, "memory");
1528
- const finalMessages = format === "v2" ? list.get.all.v2() : list.get.all.v1();
1529
- return {
1530
- messages: finalMessages,
1531
- total,
1532
- page,
1533
- perPage,
1534
- hasMore
1535
- };
1536
- } catch (error) {
1537
- const mastraError = new MastraError(
1538
- {
1539
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1540
- domain: ErrorDomain.STORAGE,
1541
- category: ErrorCategory.THIRD_PARTY,
1542
- details: { threadId, resourceId: resourceId ?? "" }
1543
- },
1544
- error
1545
- );
1546
- this.logger?.trackException?.(mastraError);
1547
- this.logger?.error?.(mastraError.toString());
1548
- return { messages: [], total: 0, page, perPage, hasMore: false };
1549
- }
1550
- }
1551
1485
  // Helper method to get included messages with context
1552
- async _getIncludedMessages(threadId, selectBy) {
1553
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1486
+ async _getIncludedMessages(selectBy) {
1554
1487
  if (!selectBy?.include?.length) {
1555
1488
  return [];
1556
1489
  }
1557
1490
  const includeMessages = [];
1558
1491
  for (const includeItem of selectBy.include) {
1559
1492
  try {
1560
- const { id, threadId: targetThreadId, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1561
- const searchThreadId = targetThreadId || threadId;
1493
+ const { id, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1494
+ const targetResult = await this.service.entities.message.get({ entity: "message", id }).go();
1495
+ if (!targetResult.data) {
1496
+ this.logger.warn("Target message not found", { id });
1497
+ continue;
1498
+ }
1499
+ const targetMessageData = targetResult.data;
1500
+ const searchThreadId = targetMessageData.threadId;
1562
1501
  this.logger.debug("Getting included messages for", {
1563
1502
  id,
1564
- targetThreadId,
1565
1503
  searchThreadId,
1566
1504
  withPreviousMessages,
1567
1505
  withNextMessages
@@ -1584,7 +1522,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1584
1522
  });
1585
1523
  const targetIndex = allMessages.findIndex((msg) => msg.id === id);
1586
1524
  if (targetIndex === -1) {
1587
- this.logger.warn("Target message not found", { id, threadId: searchThreadId });
1525
+ this.logger.warn("Target message not found in thread", { id, threadId: searchThreadId });
1588
1526
  continue;
1589
1527
  }
1590
1528
  this.logger.debug("Found target message at index", { id, targetIndex, totalMessages: allMessages.length });
@@ -1669,7 +1607,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1669
1607
  } catch (error) {
1670
1608
  throw new MastraError(
1671
1609
  {
1672
- id: "STORAGE_DYNAMODB_STORE_UPDATE_MESSAGES_FAILED",
1610
+ id: createStorageErrorId("DYNAMODB", "UPDATE_MESSAGES", "FAILED"),
1673
1611
  domain: ErrorDomain.STORAGE,
1674
1612
  category: ErrorCategory.THIRD_PARTY,
1675
1613
  details: { count: messages.length }
@@ -1698,7 +1636,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1698
1636
  } catch (error) {
1699
1637
  throw new MastraError(
1700
1638
  {
1701
- id: "STORAGE_DYNAMODB_STORE_GET_RESOURCE_BY_ID_FAILED",
1639
+ id: createStorageErrorId("DYNAMODB", "GET_RESOURCE_BY_ID", "FAILED"),
1702
1640
  domain: ErrorDomain.STORAGE,
1703
1641
  category: ErrorCategory.THIRD_PARTY,
1704
1642
  details: { resourceId }
@@ -1730,7 +1668,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1730
1668
  } catch (error) {
1731
1669
  throw new MastraError(
1732
1670
  {
1733
- id: "STORAGE_DYNAMODB_STORE_SAVE_RESOURCE_FAILED",
1671
+ id: createStorageErrorId("DYNAMODB", "SAVE_RESOURCE", "FAILED"),
1734
1672
  domain: ErrorDomain.STORAGE,
1735
1673
  category: ErrorCategory.THIRD_PARTY,
1736
1674
  details: { resourceId: resource.id }
@@ -1779,7 +1717,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1779
1717
  } catch (error) {
1780
1718
  throw new MastraError(
1781
1719
  {
1782
- id: "STORAGE_DYNAMODB_STORE_UPDATE_RESOURCE_FAILED",
1720
+ id: createStorageErrorId("DYNAMODB", "UPDATE_RESOURCE", "FAILED"),
1783
1721
  domain: ErrorDomain.STORAGE,
1784
1722
  category: ErrorCategory.THIRD_PARTY,
1785
1723
  details: { resourceId }
@@ -1789,342 +1727,37 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1789
1727
  }
1790
1728
  }
1791
1729
  };
1792
- var StoreOperationsDynamoDB = class extends StoreOperations {
1793
- client;
1794
- tableName;
1730
+ var ScoresStorageDynamoDB = class extends ScoresStorage {
1795
1731
  service;
1796
- constructor({
1797
- service,
1798
- tableName,
1799
- client
1800
- }) {
1732
+ constructor(config) {
1801
1733
  super();
1802
- this.service = service;
1803
- this.client = client;
1804
- this.tableName = tableName;
1805
- }
1806
- async hasColumn() {
1807
- return true;
1808
- }
1809
- async dropTable() {
1734
+ this.service = resolveDynamoDBConfig(config);
1810
1735
  }
1811
- // Helper methods for entity/table mapping
1812
- getEntityNameForTable(tableName) {
1813
- const mapping = {
1814
- [TABLE_THREADS]: "thread",
1815
- [TABLE_MESSAGES]: "message",
1816
- [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1817
- [TABLE_SCORERS]: "score",
1818
- [TABLE_TRACES]: "trace",
1819
- [TABLE_RESOURCES]: "resource",
1820
- [TABLE_AI_SPANS]: "ai_span"
1821
- };
1822
- return mapping[tableName] || null;
1823
- }
1824
- /**
1825
- * Pre-processes a record to ensure Date objects are converted to ISO strings
1826
- * This is necessary because ElectroDB validation happens before setters are applied
1827
- */
1828
- preprocessRecord(record) {
1829
- const processed = { ...record };
1830
- if (processed.createdAt instanceof Date) {
1831
- processed.createdAt = processed.createdAt.toISOString();
1832
- }
1833
- if (processed.updatedAt instanceof Date) {
1834
- processed.updatedAt = processed.updatedAt.toISOString();
1835
- }
1836
- if (processed.created_at instanceof Date) {
1837
- processed.created_at = processed.created_at.toISOString();
1838
- }
1839
- if (processed.result && typeof processed.result === "object") {
1840
- processed.result = JSON.stringify(processed.result);
1841
- }
1842
- if (processed.test_info && typeof processed.test_info === "object") {
1843
- processed.test_info = JSON.stringify(processed.test_info);
1844
- } else if (processed.test_info === void 0 || processed.test_info === null) {
1845
- delete processed.test_info;
1846
- }
1847
- if (processed.snapshot && typeof processed.snapshot === "object") {
1848
- processed.snapshot = JSON.stringify(processed.snapshot);
1849
- }
1850
- if (processed.attributes && typeof processed.attributes === "object") {
1851
- processed.attributes = JSON.stringify(processed.attributes);
1852
- }
1853
- if (processed.status && typeof processed.status === "object") {
1854
- processed.status = JSON.stringify(processed.status);
1855
- }
1856
- if (processed.events && typeof processed.events === "object") {
1857
- processed.events = JSON.stringify(processed.events);
1858
- }
1859
- if (processed.links && typeof processed.links === "object") {
1860
- processed.links = JSON.stringify(processed.links);
1861
- }
1862
- return processed;
1736
+ async dangerouslyClearAll() {
1737
+ await deleteTableData(this.service, TABLE_SCORERS);
1863
1738
  }
1864
1739
  /**
1865
- * Validates that the required DynamoDB table exists and is accessible.
1866
- * This does not check the table structure - it assumes the table
1867
- * was created with the correct structure via CDK/CloudFormation.
1868
- */
1869
- async validateTableExists() {
1870
- try {
1871
- const command = new DescribeTableCommand({
1872
- TableName: this.tableName
1873
- });
1874
- await this.client.send(command);
1875
- return true;
1876
- } catch (error) {
1877
- if (error.name === "ResourceNotFoundException") {
1878
- return false;
1879
- }
1880
- throw new MastraError(
1881
- {
1882
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
1883
- domain: ErrorDomain.STORAGE,
1884
- category: ErrorCategory.THIRD_PARTY,
1885
- details: { tableName: this.tableName }
1886
- },
1887
- error
1888
- );
1889
- }
1890
- }
1891
- /**
1892
- * This method is modified for DynamoDB with ElectroDB single-table design.
1893
- * It assumes the table is created and managed externally via CDK/CloudFormation.
1740
+ * DynamoDB-specific score row transformation.
1894
1741
  *
1895
- * This implementation only validates that the required table exists and is accessible.
1896
- * No table creation is attempted - we simply check if we can access the table.
1742
+ * Note: This implementation does NOT use coreTransformScoreRow because:
1743
+ * 1. ElectroDB already parses JSON fields via its entity getters
1744
+ * 2. DynamoDB stores empty strings for null values (which need special handling)
1745
+ * 3. 'entity' is a reserved ElectroDB key, so we use 'entityData' column
1897
1746
  */
1898
- async createTable({ tableName }) {
1899
- this.logger.debug("Validating access to externally managed table", { tableName, physicalTable: this.tableName });
1900
- try {
1901
- const tableExists = await this.validateTableExists();
1902
- if (!tableExists) {
1903
- this.logger.error(
1904
- `Table ${this.tableName} does not exist or is not accessible. It should be created via CDK/CloudFormation.`
1905
- );
1906
- throw new Error(
1907
- `Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
1908
- );
1909
- }
1910
- this.logger.debug(`Table ${this.tableName} exists and is accessible`);
1911
- } catch (error) {
1912
- this.logger.error("Error validating table access", { tableName: this.tableName, error });
1913
- throw new MastraError(
1914
- {
1915
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_ACCESS_FAILED",
1916
- domain: ErrorDomain.STORAGE,
1917
- category: ErrorCategory.THIRD_PARTY,
1918
- details: { tableName: this.tableName }
1919
- },
1920
- error
1921
- );
1922
- }
1923
- }
1924
- async insert({ tableName, record }) {
1925
- this.logger.debug("DynamoDB insert called", { tableName });
1926
- const entityName = this.getEntityNameForTable(tableName);
1927
- if (!entityName || !this.service.entities[entityName]) {
1928
- throw new MastraError({
1929
- id: "STORAGE_DYNAMODB_STORE_INSERT_INVALID_ARGS",
1930
- domain: ErrorDomain.STORAGE,
1931
- category: ErrorCategory.USER,
1932
- text: "No entity defined for tableName",
1933
- details: { tableName }
1934
- });
1935
- }
1936
- try {
1937
- const dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
1938
- await this.service.entities[entityName].create(dataToSave).go();
1939
- } catch (error) {
1940
- throw new MastraError(
1941
- {
1942
- id: "STORAGE_DYNAMODB_STORE_INSERT_FAILED",
1943
- domain: ErrorDomain.STORAGE,
1944
- category: ErrorCategory.THIRD_PARTY,
1945
- details: { tableName }
1946
- },
1947
- error
1948
- );
1949
- }
1950
- }
1951
- async alterTable(_args) {
1952
- }
1953
- /**
1954
- * Clear all items from a logical "table" (entity type)
1955
- */
1956
- async clearTable({ tableName }) {
1957
- this.logger.debug("DynamoDB clearTable called", { tableName });
1958
- const entityName = this.getEntityNameForTable(tableName);
1959
- if (!entityName || !this.service.entities[entityName]) {
1960
- throw new MastraError({
1961
- id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_INVALID_ARGS",
1962
- domain: ErrorDomain.STORAGE,
1963
- category: ErrorCategory.USER,
1964
- text: "No entity defined for tableName",
1965
- details: { tableName }
1966
- });
1967
- }
1968
- try {
1969
- const result = await this.service.entities[entityName].scan.go({ pages: "all" });
1970
- if (!result.data.length) {
1971
- this.logger.debug(`No records found to clear for ${tableName}`);
1972
- return;
1973
- }
1974
- this.logger.debug(`Found ${result.data.length} records to delete for ${tableName}`);
1975
- const keysToDelete = result.data.map((item) => {
1976
- const key = { entity: entityName };
1977
- switch (entityName) {
1978
- case "thread":
1979
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'thread'`);
1980
- key.id = item.id;
1981
- break;
1982
- case "message":
1983
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'message'`);
1984
- key.id = item.id;
1985
- break;
1986
- case "workflow_snapshot":
1987
- if (!item.workflow_name)
1988
- throw new Error(`Missing required key 'workflow_name' for entity 'workflow_snapshot'`);
1989
- if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'workflow_snapshot'`);
1990
- key.workflow_name = item.workflow_name;
1991
- key.run_id = item.run_id;
1992
- break;
1993
- case "eval":
1994
- if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'eval'`);
1995
- key.run_id = item.run_id;
1996
- break;
1997
- case "trace":
1998
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'trace'`);
1999
- key.id = item.id;
2000
- break;
2001
- case "score":
2002
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
2003
- key.id = item.id;
2004
- break;
2005
- case "resource":
2006
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'resource'`);
2007
- key.id = item.id;
2008
- break;
2009
- default:
2010
- this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
2011
- throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
2012
- }
2013
- return key;
2014
- });
2015
- const batchSize = 25;
2016
- for (let i = 0; i < keysToDelete.length; i += batchSize) {
2017
- const batchKeys = keysToDelete.slice(i, i + batchSize);
2018
- await this.service.entities[entityName].delete(batchKeys).go();
2019
- }
2020
- this.logger.debug(`Successfully cleared all records for ${tableName}`);
2021
- } catch (error) {
2022
- throw new MastraError(
2023
- {
2024
- id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_FAILED",
2025
- domain: ErrorDomain.STORAGE,
2026
- category: ErrorCategory.THIRD_PARTY,
2027
- details: { tableName }
2028
- },
2029
- error
2030
- );
2031
- }
2032
- }
2033
- /**
2034
- * Insert multiple records as a batch
2035
- */
2036
- async batchInsert({ tableName, records }) {
2037
- this.logger.debug("DynamoDB batchInsert called", { tableName, count: records.length });
2038
- const entityName = this.getEntityNameForTable(tableName);
2039
- if (!entityName || !this.service.entities[entityName]) {
2040
- throw new MastraError({
2041
- id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_INVALID_ARGS",
2042
- domain: ErrorDomain.STORAGE,
2043
- category: ErrorCategory.USER,
2044
- text: "No entity defined for tableName",
2045
- details: { tableName }
2046
- });
2047
- }
2048
- const recordsToSave = records.map((rec) => ({ entity: entityName, ...this.preprocessRecord(rec) }));
2049
- const batchSize = 25;
2050
- const batches = [];
2051
- for (let i = 0; i < recordsToSave.length; i += batchSize) {
2052
- const batch = recordsToSave.slice(i, i + batchSize);
2053
- batches.push(batch);
2054
- }
2055
- try {
2056
- for (const batch of batches) {
2057
- for (const recordData of batch) {
2058
- if (!recordData.entity) {
2059
- this.logger.error("Missing entity property in record data for batchInsert", { recordData, tableName });
2060
- throw new Error(`Internal error: Missing entity property during batchInsert for ${tableName}`);
2061
- }
2062
- this.logger.debug("Attempting to create record in batchInsert:", { entityName, recordData });
2063
- await this.service.entities[entityName].create(recordData).go();
2064
- }
2065
- }
2066
- } catch (error) {
2067
- throw new MastraError(
2068
- {
2069
- id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_FAILED",
2070
- domain: ErrorDomain.STORAGE,
2071
- category: ErrorCategory.THIRD_PARTY,
2072
- details: { tableName }
2073
- },
2074
- error
2075
- );
2076
- }
2077
- }
2078
- /**
2079
- * Load a record by its keys
2080
- */
2081
- async load({ tableName, keys }) {
2082
- this.logger.debug("DynamoDB load called", { tableName, keys });
2083
- const entityName = this.getEntityNameForTable(tableName);
2084
- if (!entityName || !this.service.entities[entityName]) {
2085
- throw new MastraError({
2086
- id: "STORAGE_DYNAMODB_STORE_LOAD_INVALID_ARGS",
2087
- domain: ErrorDomain.STORAGE,
2088
- category: ErrorCategory.USER,
2089
- text: "No entity defined for tableName",
2090
- details: { tableName }
2091
- });
2092
- }
2093
- try {
2094
- const keyObject = { entity: entityName, ...keys };
2095
- const result = await this.service.entities[entityName].get(keyObject).go();
2096
- if (!result.data) {
2097
- return null;
1747
+ parseScoreData(data) {
1748
+ const result = {};
1749
+ for (const key of Object.keys(SCORERS_SCHEMA)) {
1750
+ if (["traceId", "resourceId", "threadId", "spanId"].includes(key)) {
1751
+ result[key] = data[key] === "" ? null : data[key];
1752
+ continue;
2098
1753
  }
2099
- let data = result.data;
2100
- return data;
2101
- } catch (error) {
2102
- throw new MastraError(
2103
- {
2104
- id: "STORAGE_DYNAMODB_STORE_LOAD_FAILED",
2105
- domain: ErrorDomain.STORAGE,
2106
- category: ErrorCategory.THIRD_PARTY,
2107
- details: { tableName }
2108
- },
2109
- error
2110
- );
1754
+ result[key] = data[key];
2111
1755
  }
2112
- }
2113
- };
2114
- var ScoresStorageDynamoDB = class extends ScoresStorage {
2115
- service;
2116
- constructor({ service }) {
2117
- super();
2118
- this.service = service;
2119
- }
2120
- // Helper function to parse score data (handle JSON fields)
2121
- parseScoreData(data) {
1756
+ result.entity = data.entityData ?? null;
2122
1757
  return {
2123
- ...data,
2124
- // Convert date strings back to Date objects for consistency
1758
+ ...result,
2125
1759
  createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
2126
1760
  updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
2127
- // JSON fields are already transformed by the entity's getters
2128
1761
  };
2129
1762
  }
2130
1763
  async getScoreById({ id }) {
@@ -2138,7 +1771,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2138
1771
  } catch (error) {
2139
1772
  throw new MastraError(
2140
1773
  {
2141
- id: "STORAGE_DYNAMODB_STORE_GET_SCORE_BY_ID_FAILED",
1774
+ id: createStorageErrorId("DYNAMODB", "GET_SCORE_BY_ID", "FAILED"),
2142
1775
  domain: ErrorDomain.STORAGE,
2143
1776
  category: ErrorCategory.THIRD_PARTY,
2144
1777
  details: { id }
@@ -2154,57 +1787,63 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2154
1787
  } catch (error) {
2155
1788
  throw new MastraError(
2156
1789
  {
2157
- id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
1790
+ id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "VALIDATION_FAILED"),
2158
1791
  domain: ErrorDomain.STORAGE,
2159
- category: ErrorCategory.THIRD_PARTY
1792
+ category: ErrorCategory.USER,
1793
+ details: {
1794
+ scorer: typeof score.scorer?.id === "string" ? score.scorer.id : String(score.scorer?.id ?? "unknown"),
1795
+ entityId: score.entityId ?? "unknown",
1796
+ entityType: score.entityType ?? "unknown",
1797
+ traceId: score.traceId ?? "",
1798
+ spanId: score.spanId ?? ""
1799
+ }
2160
1800
  },
2161
1801
  error
2162
1802
  );
2163
1803
  }
2164
1804
  const now = /* @__PURE__ */ new Date();
2165
- const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2166
- const scoreData = {
2167
- entity: "score",
2168
- id: scoreId,
2169
- scorerId: validatedScore.scorerId,
2170
- traceId: validatedScore.traceId || "",
2171
- spanId: validatedScore.spanId || "",
2172
- runId: validatedScore.runId,
2173
- scorer: typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer),
2174
- preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult),
2175
- analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult),
2176
- score: validatedScore.score,
2177
- reason: validatedScore.reason,
2178
- preprocessPrompt: validatedScore.preprocessPrompt,
2179
- generateScorePrompt: validatedScore.generateScorePrompt,
2180
- generateReasonPrompt: validatedScore.generateReasonPrompt,
2181
- analyzePrompt: validatedScore.analyzePrompt,
2182
- input: typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input),
2183
- output: typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output),
2184
- additionalContext: typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : JSON.stringify(validatedScore.additionalContext),
2185
- requestContext: typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext),
2186
- entityType: validatedScore.entityType,
2187
- entityData: typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity),
2188
- entityId: validatedScore.entityId,
2189
- source: validatedScore.source,
2190
- resourceId: validatedScore.resourceId || "",
2191
- threadId: validatedScore.threadId || "",
2192
- createdAt: now.toISOString(),
2193
- updatedAt: now.toISOString()
2194
- };
1805
+ const scoreId = crypto.randomUUID();
1806
+ const scorer = typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer);
1807
+ const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult);
1808
+ const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult);
1809
+ const input = typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input);
1810
+ const output = typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output);
1811
+ const requestContext = typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext);
1812
+ const entity = typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity);
1813
+ const scoreData = Object.fromEntries(
1814
+ Object.entries({
1815
+ ...validatedScore,
1816
+ entity: "score",
1817
+ id: scoreId,
1818
+ scorer,
1819
+ preprocessStepResult,
1820
+ analyzeStepResult,
1821
+ input,
1822
+ output,
1823
+ requestContext,
1824
+ entityData: entity,
1825
+ traceId: validatedScore.traceId || "",
1826
+ resourceId: validatedScore.resourceId || "",
1827
+ threadId: validatedScore.threadId || "",
1828
+ spanId: validatedScore.spanId || "",
1829
+ createdAt: now.toISOString(),
1830
+ updatedAt: now.toISOString()
1831
+ }).filter(([_, value]) => value !== void 0 && value !== null)
1832
+ );
2195
1833
  try {
2196
1834
  await this.service.entities.score.upsert(scoreData).go();
2197
- const savedScore = {
2198
- ...score,
2199
- id: scoreId,
2200
- createdAt: now,
2201
- updatedAt: now
1835
+ return {
1836
+ score: {
1837
+ ...validatedScore,
1838
+ id: scoreId,
1839
+ createdAt: now,
1840
+ updatedAt: now
1841
+ }
2202
1842
  };
2203
- return { score: savedScore };
2204
1843
  } catch (error) {
2205
1844
  throw new MastraError(
2206
1845
  {
2207
- id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
1846
+ id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "FAILED"),
2208
1847
  domain: ErrorDomain.STORAGE,
2209
1848
  category: ErrorCategory.THIRD_PARTY,
2210
1849
  details: { scorerId: score.scorerId, runId: score.runId }
@@ -2213,7 +1852,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2213
1852
  );
2214
1853
  }
2215
1854
  }
2216
- async getScoresByScorerId({
1855
+ async listScoresByScorerId({
2217
1856
  scorerId,
2218
1857
  pagination,
2219
1858
  entityId,
@@ -2234,24 +1873,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2234
1873
  allScores = allScores.filter((score) => score.source === source);
2235
1874
  }
2236
1875
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2237
- const startIndex = pagination.page * pagination.perPage;
2238
- const endIndex = startIndex + pagination.perPage;
2239
- const paginatedScores = allScores.slice(startIndex, endIndex);
1876
+ const { page, perPage: perPageInput } = pagination;
1877
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
1878
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2240
1879
  const total = allScores.length;
2241
- const hasMore = endIndex < total;
1880
+ const end = perPageInput === false ? allScores.length : start + perPage;
1881
+ const paginatedScores = allScores.slice(start, end);
2242
1882
  return {
2243
1883
  scores: paginatedScores,
2244
1884
  pagination: {
2245
1885
  total,
2246
- page: pagination.page,
2247
- perPage: pagination.perPage,
2248
- hasMore
1886
+ page,
1887
+ perPage: perPageForResponse,
1888
+ hasMore: end < total
2249
1889
  }
2250
1890
  };
2251
1891
  } catch (error) {
2252
1892
  throw new MastraError(
2253
1893
  {
2254
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SCORER_ID_FAILED",
1894
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
2255
1895
  domain: ErrorDomain.STORAGE,
2256
1896
  category: ErrorCategory.THIRD_PARTY,
2257
1897
  details: {
@@ -2267,7 +1907,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2267
1907
  );
2268
1908
  }
2269
1909
  }
2270
- async getScoresByRunId({
1910
+ async listScoresByRunId({
2271
1911
  runId,
2272
1912
  pagination
2273
1913
  }) {
@@ -2277,24 +1917,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2277
1917
  const results = await query.go();
2278
1918
  const allScores = results.data.map((data) => this.parseScoreData(data));
2279
1919
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2280
- const startIndex = pagination.page * pagination.perPage;
2281
- const endIndex = startIndex + pagination.perPage;
2282
- const paginatedScores = allScores.slice(startIndex, endIndex);
1920
+ const { page, perPage: perPageInput } = pagination;
1921
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
1922
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2283
1923
  const total = allScores.length;
2284
- const hasMore = endIndex < total;
1924
+ const end = perPageInput === false ? allScores.length : start + perPage;
1925
+ const paginatedScores = allScores.slice(start, end);
2285
1926
  return {
2286
1927
  scores: paginatedScores,
2287
1928
  pagination: {
2288
1929
  total,
2289
- page: pagination.page,
2290
- perPage: pagination.perPage,
2291
- hasMore
1930
+ page,
1931
+ perPage: perPageForResponse,
1932
+ hasMore: end < total
2292
1933
  }
2293
1934
  };
2294
1935
  } catch (error) {
2295
1936
  throw new MastraError(
2296
1937
  {
2297
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_RUN_ID_FAILED",
1938
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_RUN_ID", "FAILED"),
2298
1939
  domain: ErrorDomain.STORAGE,
2299
1940
  category: ErrorCategory.THIRD_PARTY,
2300
1941
  details: { runId, page: pagination.page, perPage: pagination.perPage }
@@ -2303,7 +1944,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2303
1944
  );
2304
1945
  }
2305
1946
  }
2306
- async getScoresByEntityId({
1947
+ async listScoresByEntityId({
2307
1948
  entityId,
2308
1949
  entityType,
2309
1950
  pagination
@@ -2315,24 +1956,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2315
1956
  let allScores = results.data.map((data) => this.parseScoreData(data));
2316
1957
  allScores = allScores.filter((score) => score.entityType === entityType);
2317
1958
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2318
- const startIndex = pagination.page * pagination.perPage;
2319
- const endIndex = startIndex + pagination.perPage;
2320
- const paginatedScores = allScores.slice(startIndex, endIndex);
1959
+ const { page, perPage: perPageInput } = pagination;
1960
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
1961
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2321
1962
  const total = allScores.length;
2322
- const hasMore = endIndex < total;
1963
+ const end = perPageInput === false ? allScores.length : start + perPage;
1964
+ const paginatedScores = allScores.slice(start, end);
2323
1965
  return {
2324
1966
  scores: paginatedScores,
2325
1967
  pagination: {
2326
1968
  total,
2327
- page: pagination.page,
2328
- perPage: pagination.perPage,
2329
- hasMore
1969
+ page,
1970
+ perPage: perPageForResponse,
1971
+ hasMore: end < total
2330
1972
  }
2331
1973
  };
2332
1974
  } catch (error) {
2333
1975
  throw new MastraError(
2334
1976
  {
2335
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_ENTITY_ID_FAILED",
1977
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
2336
1978
  domain: ErrorDomain.STORAGE,
2337
1979
  category: ErrorCategory.THIRD_PARTY,
2338
1980
  details: { entityId, entityType, page: pagination.page, perPage: pagination.perPage }
@@ -2341,7 +1983,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2341
1983
  );
2342
1984
  }
2343
1985
  }
2344
- async getScoresBySpan({
1986
+ async listScoresBySpan({
2345
1987
  traceId,
2346
1988
  spanId,
2347
1989
  pagination
@@ -2352,24 +1994,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2352
1994
  const results = await query.go();
2353
1995
  const allScores = results.data.map((data) => this.parseScoreData(data));
2354
1996
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2355
- const startIndex = pagination.page * pagination.perPage;
2356
- const endIndex = startIndex + pagination.perPage;
2357
- const paginatedScores = allScores.slice(startIndex, endIndex);
1997
+ const { page, perPage: perPageInput } = pagination;
1998
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
1999
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2358
2000
  const total = allScores.length;
2359
- const hasMore = endIndex < total;
2001
+ const end = perPageInput === false ? allScores.length : start + perPage;
2002
+ const paginatedScores = allScores.slice(start, end);
2360
2003
  return {
2361
2004
  scores: paginatedScores,
2362
2005
  pagination: {
2363
2006
  total,
2364
- page: pagination.page,
2365
- perPage: pagination.perPage,
2366
- hasMore
2007
+ page,
2008
+ perPage: perPageForResponse,
2009
+ hasMore: end < total
2367
2010
  }
2368
2011
  };
2369
2012
  } catch (error) {
2370
2013
  throw new MastraError(
2371
2014
  {
2372
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SPAN_FAILED",
2015
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SPAN", "FAILED"),
2373
2016
  domain: ErrorDomain.STORAGE,
2374
2017
  category: ErrorCategory.THIRD_PARTY,
2375
2018
  details: { traceId, spanId, page: pagination.page, perPage: pagination.perPage }
@@ -2391,52 +2034,111 @@ function formatWorkflowRun(snapshotData) {
2391
2034
  }
2392
2035
  var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2393
2036
  service;
2394
- constructor({ service }) {
2037
+ constructor(config) {
2395
2038
  super();
2396
- this.service = service;
2039
+ this.service = resolveDynamoDBConfig(config);
2040
+ }
2041
+ async dangerouslyClearAll() {
2042
+ await deleteTableData(this.service, TABLE_WORKFLOW_SNAPSHOT);
2397
2043
  }
2398
- updateWorkflowResults({
2399
- // workflowName,
2400
- // runId,
2401
- // stepId,
2402
- // result,
2403
- // requestContext,
2044
+ async updateWorkflowResults({
2045
+ workflowName,
2046
+ runId,
2047
+ stepId,
2048
+ result,
2049
+ requestContext
2404
2050
  }) {
2405
- throw new Error("Method not implemented.");
2051
+ try {
2052
+ const existingSnapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
2053
+ let snapshot;
2054
+ if (!existingSnapshot) {
2055
+ snapshot = {
2056
+ context: {},
2057
+ activePaths: [],
2058
+ timestamp: Date.now(),
2059
+ suspendedPaths: {},
2060
+ activeStepsPath: {},
2061
+ resumeLabels: {},
2062
+ serializedStepGraph: [],
2063
+ status: "pending",
2064
+ value: {},
2065
+ waitingPaths: {},
2066
+ runId,
2067
+ requestContext: {}
2068
+ };
2069
+ } else {
2070
+ snapshot = existingSnapshot;
2071
+ }
2072
+ snapshot.context[stepId] = result;
2073
+ snapshot.requestContext = { ...snapshot.requestContext, ...requestContext };
2074
+ await this.persistWorkflowSnapshot({ workflowName, runId, snapshot });
2075
+ return snapshot.context;
2076
+ } catch (error) {
2077
+ if (error instanceof MastraError) throw error;
2078
+ throw new MastraError(
2079
+ {
2080
+ id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
2081
+ domain: ErrorDomain.STORAGE,
2082
+ category: ErrorCategory.THIRD_PARTY,
2083
+ details: { workflowName, runId, stepId }
2084
+ },
2085
+ error
2086
+ );
2087
+ }
2406
2088
  }
2407
- updateWorkflowState({
2408
- // workflowName,
2409
- // runId,
2410
- // opts,
2089
+ async updateWorkflowState({
2090
+ workflowName,
2091
+ runId,
2092
+ opts
2411
2093
  }) {
2412
- throw new Error("Method not implemented.");
2094
+ try {
2095
+ const existingSnapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
2096
+ if (!existingSnapshot || !existingSnapshot.context) {
2097
+ return void 0;
2098
+ }
2099
+ const updatedSnapshot = { ...existingSnapshot, ...opts };
2100
+ await this.persistWorkflowSnapshot({ workflowName, runId, snapshot: updatedSnapshot });
2101
+ return updatedSnapshot;
2102
+ } catch (error) {
2103
+ if (error instanceof MastraError) throw error;
2104
+ throw new MastraError(
2105
+ {
2106
+ id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_STATE", "FAILED"),
2107
+ domain: ErrorDomain.STORAGE,
2108
+ category: ErrorCategory.THIRD_PARTY,
2109
+ details: { workflowName, runId }
2110
+ },
2111
+ error
2112
+ );
2113
+ }
2413
2114
  }
2414
2115
  // Workflow operations
2415
2116
  async persistWorkflowSnapshot({
2416
2117
  workflowName,
2417
2118
  runId,
2418
2119
  resourceId,
2419
- snapshot
2120
+ snapshot,
2121
+ createdAt,
2122
+ updatedAt
2420
2123
  }) {
2421
2124
  this.logger.debug("Persisting workflow snapshot", { workflowName, runId });
2422
2125
  try {
2423
- const now = (/* @__PURE__ */ new Date()).toISOString();
2126
+ const now = /* @__PURE__ */ new Date();
2424
2127
  const data = {
2425
2128
  entity: "workflow_snapshot",
2426
2129
  // Add entity type
2427
2130
  workflow_name: workflowName,
2428
2131
  run_id: runId,
2429
2132
  snapshot: JSON.stringify(snapshot),
2430
- // Stringify the snapshot object
2431
- createdAt: now,
2432
- updatedAt: now,
2133
+ createdAt: (createdAt ?? now).toISOString(),
2134
+ updatedAt: (updatedAt ?? now).toISOString(),
2433
2135
  resourceId
2434
2136
  };
2435
2137
  await this.service.entities.workflow_snapshot.upsert(data).go();
2436
2138
  } catch (error) {
2437
2139
  throw new MastraError(
2438
2140
  {
2439
- id: "STORAGE_DYNAMODB_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
2141
+ id: createStorageErrorId("DYNAMODB", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
2440
2142
  domain: ErrorDomain.STORAGE,
2441
2143
  category: ErrorCategory.THIRD_PARTY,
2442
2144
  details: { workflowName, runId }
@@ -2464,7 +2166,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2464
2166
  } catch (error) {
2465
2167
  throw new MastraError(
2466
2168
  {
2467
- id: "STORAGE_DYNAMODB_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
2169
+ id: createStorageErrorId("DYNAMODB", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
2468
2170
  domain: ErrorDomain.STORAGE,
2469
2171
  category: ErrorCategory.THIRD_PARTY,
2470
2172
  details: { workflowName, runId }
@@ -2476,8 +2178,21 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2476
2178
  async listWorkflowRuns(args) {
2477
2179
  this.logger.debug("Getting workflow runs", { args });
2478
2180
  try {
2479
- const limit = args?.limit || 10;
2480
- const offset = args?.offset || 0;
2181
+ const perPage = args?.perPage !== void 0 ? args.perPage : 10;
2182
+ const page = args?.page !== void 0 ? args.page : 0;
2183
+ if (page < 0) {
2184
+ throw new MastraError(
2185
+ {
2186
+ id: createStorageErrorId("DYNAMODB", "LIST_WORKFLOW_RUNS", "INVALID_PAGE"),
2187
+ domain: ErrorDomain.STORAGE,
2188
+ category: ErrorCategory.USER,
2189
+ details: { page }
2190
+ },
2191
+ new Error("page must be >= 0")
2192
+ );
2193
+ }
2194
+ const normalizedPerPage = normalizePerPage(perPage, 10);
2195
+ const offset = page * normalizedPerPage;
2481
2196
  let query;
2482
2197
  if (args?.workflowName) {
2483
2198
  query = this.service.entities.workflow_snapshot.query.primary({
@@ -2499,6 +2214,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2499
2214
  });
2500
2215
  if (pageResults.data && pageResults.data.length > 0) {
2501
2216
  let pageFilteredData = pageResults.data;
2217
+ if (args?.status) {
2218
+ pageFilteredData = pageFilteredData.filter((snapshot) => {
2219
+ return snapshot.snapshot.status === args.status;
2220
+ });
2221
+ }
2502
2222
  if (args?.fromDate || args?.toDate) {
2503
2223
  pageFilteredData = pageFilteredData.filter((snapshot) => {
2504
2224
  const createdAt = new Date(snapshot.createdAt);
@@ -2524,7 +2244,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2524
2244
  return { runs: [], total: 0 };
2525
2245
  }
2526
2246
  const total = allMatchingSnapshots.length;
2527
- const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
2247
+ const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
2528
2248
  const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
2529
2249
  return {
2530
2250
  runs,
@@ -2533,7 +2253,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2533
2253
  } catch (error) {
2534
2254
  throw new MastraError(
2535
2255
  {
2536
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2256
+ id: createStorageErrorId("DYNAMODB", "LIST_WORKFLOW_RUNS", "FAILED"),
2537
2257
  domain: ErrorDomain.STORAGE,
2538
2258
  category: ErrorCategory.THIRD_PARTY,
2539
2259
  details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
@@ -2587,7 +2307,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2587
2307
  } catch (error) {
2588
2308
  throw new MastraError(
2589
2309
  {
2590
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
2310
+ id: createStorageErrorId("DYNAMODB", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
2591
2311
  domain: ErrorDomain.STORAGE,
2592
2312
  category: ErrorCategory.THIRD_PARTY,
2593
2313
  details: { runId, workflowName: args?.workflowName || "" }
@@ -2596,9 +2316,32 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2596
2316
  );
2597
2317
  }
2598
2318
  }
2319
+ async deleteWorkflowRunById({ runId, workflowName }) {
2320
+ this.logger.debug("Deleting workflow run by ID", { runId, workflowName });
2321
+ try {
2322
+ await this.service.entities.workflow_snapshot.delete({
2323
+ entity: "workflow_snapshot",
2324
+ workflow_name: workflowName,
2325
+ run_id: runId
2326
+ }).go();
2327
+ } catch (error) {
2328
+ throw new MastraError(
2329
+ {
2330
+ id: createStorageErrorId("DYNAMODB", "DELETE_WORKFLOW_RUN_BY_ID", "FAILED"),
2331
+ domain: ErrorDomain.STORAGE,
2332
+ category: ErrorCategory.THIRD_PARTY,
2333
+ details: { runId, workflowName }
2334
+ },
2335
+ error
2336
+ );
2337
+ }
2338
+ }
2599
2339
  };
2600
2340
 
2601
2341
  // src/storage/index.ts
2342
+ var isClientConfig = (config) => {
2343
+ return "client" in config;
2344
+ };
2602
2345
  var DynamoDBStore = class extends MastraStorage {
2603
2346
  tableName;
2604
2347
  client;
@@ -2606,7 +2349,7 @@ var DynamoDBStore = class extends MastraStorage {
2606
2349
  hasInitialized = null;
2607
2350
  stores;
2608
2351
  constructor({ name, config }) {
2609
- super({ name });
2352
+ super({ id: config.id, name, disableInit: config.disableInit });
2610
2353
  try {
2611
2354
  if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
2612
2355
  throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
@@ -2616,24 +2359,23 @@ var DynamoDBStore = class extends MastraStorage {
2616
2359
  `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`
2617
2360
  );
2618
2361
  }
2619
- const dynamoClient = new DynamoDBClient({
2620
- region: config.region || "us-east-1",
2621
- endpoint: config.endpoint,
2622
- credentials: config.credentials
2623
- });
2624
2362
  this.tableName = config.tableName;
2625
- this.client = DynamoDBDocumentClient.from(dynamoClient);
2363
+ if (isClientConfig(config)) {
2364
+ this.client = config.client;
2365
+ } else {
2366
+ const dynamoClient = new DynamoDBClient({
2367
+ region: config.region || "us-east-1",
2368
+ endpoint: config.endpoint,
2369
+ credentials: config.credentials
2370
+ });
2371
+ this.client = DynamoDBDocumentClient.from(dynamoClient);
2372
+ }
2626
2373
  this.service = getElectroDbService(this.client, this.tableName);
2627
- const operations = new StoreOperationsDynamoDB({
2628
- service: this.service,
2629
- tableName: this.tableName,
2630
- client: this.client
2631
- });
2632
- const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2633
- const memory = new MemoryStorageDynamoDB({ service: this.service });
2634
- const scores = new ScoresStorageDynamoDB({ service: this.service });
2374
+ const domainConfig = { service: this.service };
2375
+ const workflows = new WorkflowStorageDynamoDB(domainConfig);
2376
+ const memory = new MemoryStorageDynamoDB(domainConfig);
2377
+ const scores = new ScoresStorageDynamoDB(domainConfig);
2635
2378
  this.stores = {
2636
- operations,
2637
2379
  workflows,
2638
2380
  memory,
2639
2381
  scores
@@ -2641,7 +2383,7 @@ var DynamoDBStore = class extends MastraStorage {
2641
2383
  } catch (error) {
2642
2384
  throw new MastraError(
2643
2385
  {
2644
- id: "STORAGE_DYNAMODB_STORE_CONSTRUCTOR_FAILED",
2386
+ id: createStorageErrorId("DYNAMODB", "CONSTRUCTOR", "FAILED"),
2645
2387
  domain: ErrorDomain.STORAGE,
2646
2388
  category: ErrorCategory.USER
2647
2389
  },
@@ -2649,16 +2391,6 @@ var DynamoDBStore = class extends MastraStorage {
2649
2391
  );
2650
2392
  }
2651
2393
  }
2652
- get supports() {
2653
- return {
2654
- selectByIncludeResourceScope: true,
2655
- resourceWorkingMemory: true,
2656
- hasColumn: false,
2657
- createTable: false,
2658
- deleteMessages: false,
2659
- getScoresBySpan: true
2660
- };
2661
- }
2662
2394
  /**
2663
2395
  * Validates that the required DynamoDB table exists and is accessible.
2664
2396
  * This does not check the table structure - it assumes the table
@@ -2677,7 +2409,7 @@ var DynamoDBStore = class extends MastraStorage {
2677
2409
  }
2678
2410
  throw new MastraError(
2679
2411
  {
2680
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
2412
+ id: createStorageErrorId("DYNAMODB", "VALIDATE_TABLE_EXISTS", "FAILED"),
2681
2413
  domain: ErrorDomain.STORAGE,
2682
2414
  category: ErrorCategory.THIRD_PARTY,
2683
2415
  details: { tableName: this.tableName }
@@ -2700,7 +2432,7 @@ var DynamoDBStore = class extends MastraStorage {
2700
2432
  } catch (error) {
2701
2433
  throw new MastraError(
2702
2434
  {
2703
- id: "STORAGE_DYNAMODB_STORE_INIT_FAILED",
2435
+ id: createStorageErrorId("DYNAMODB", "INIT", "FAILED"),
2704
2436
  domain: ErrorDomain.STORAGE,
2705
2437
  category: ErrorCategory.THIRD_PARTY,
2706
2438
  details: { tableName: this.tableName }
@@ -2726,120 +2458,10 @@ var DynamoDBStore = class extends MastraStorage {
2726
2458
  throw err;
2727
2459
  });
2728
2460
  }
2729
- async createTable({ tableName, schema }) {
2730
- return this.stores.operations.createTable({ tableName, schema });
2731
- }
2732
- async alterTable(_args) {
2733
- return this.stores.operations.alterTable(_args);
2734
- }
2735
- async clearTable({ tableName }) {
2736
- return this.stores.operations.clearTable({ tableName });
2737
- }
2738
- async dropTable({ tableName }) {
2739
- return this.stores.operations.dropTable({ tableName });
2740
- }
2741
- async insert({ tableName, record }) {
2742
- return this.stores.operations.insert({ tableName, record });
2743
- }
2744
- async batchInsert({ tableName, records }) {
2745
- return this.stores.operations.batchInsert({ tableName, records });
2746
- }
2747
- async load({ tableName, keys }) {
2748
- return this.stores.operations.load({ tableName, keys });
2749
- }
2750
- // Thread operations
2751
- async getThreadById({ threadId }) {
2752
- return this.stores.memory.getThreadById({ threadId });
2753
- }
2754
- async getThreadsByResourceId(args) {
2755
- return this.stores.memory.getThreadsByResourceId(args);
2756
- }
2757
- async saveThread({ thread }) {
2758
- return this.stores.memory.saveThread({ thread });
2759
- }
2760
- async updateThread({
2761
- id,
2762
- title,
2763
- metadata
2764
- }) {
2765
- return this.stores.memory.updateThread({ id, title, metadata });
2766
- }
2767
- async deleteThread({ threadId }) {
2768
- return this.stores.memory.deleteThread({ threadId });
2769
- }
2770
- async getMessages({
2771
- threadId,
2772
- resourceId,
2773
- selectBy,
2774
- format
2775
- }) {
2776
- return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2777
- }
2778
- async saveMessages(args) {
2779
- return this.stores.memory.saveMessages(args);
2780
- }
2781
- async getThreadsByResourceIdPaginated(args) {
2782
- return this.stores.memory.getThreadsByResourceIdPaginated(args);
2783
- }
2784
- async getMessagesPaginated(args) {
2785
- return this.stores.memory.getMessagesPaginated(args);
2786
- }
2787
- async updateMessages(_args) {
2788
- return this.stores.memory.updateMessages(_args);
2789
- }
2790
- // Workflow operations
2791
- async updateWorkflowResults({
2792
- workflowName,
2793
- runId,
2794
- stepId,
2795
- result,
2796
- requestContext
2797
- }) {
2798
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
2799
- }
2800
- async updateWorkflowState({
2801
- workflowName,
2802
- runId,
2803
- opts
2804
- }) {
2805
- return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
2806
- }
2807
- async persistWorkflowSnapshot({
2808
- workflowName,
2809
- runId,
2810
- resourceId,
2811
- snapshot
2812
- }) {
2813
- return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
2814
- }
2815
- async loadWorkflowSnapshot({
2816
- workflowName,
2817
- runId
2818
- }) {
2819
- return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2820
- }
2821
- async listWorkflowRuns(args) {
2822
- return this.stores.workflows.listWorkflowRuns(args);
2823
- }
2824
- async getWorkflowRunById(args) {
2825
- return this.stores.workflows.getWorkflowRunById(args);
2826
- }
2827
- async getResourceById({ resourceId }) {
2828
- return this.stores.memory.getResourceById({ resourceId });
2829
- }
2830
- async saveResource({ resource }) {
2831
- return this.stores.memory.saveResource({ resource });
2832
- }
2833
- async updateResource({
2834
- resourceId,
2835
- workingMemory,
2836
- metadata
2837
- }) {
2838
- return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
2839
- }
2840
2461
  /**
2841
2462
  * Closes the DynamoDB client connection and cleans up resources.
2842
- * Should be called when the store is no longer needed, e.g., at the end of tests or application shutdown.
2463
+ *
2464
+ * This will close the DynamoDB client, including pre-configured clients.
2843
2465
  */
2844
2466
  async close() {
2845
2467
  this.logger.debug("Closing DynamoDB client for store:", { name: this.name });
@@ -2849,7 +2471,7 @@ var DynamoDBStore = class extends MastraStorage {
2849
2471
  } catch (error) {
2850
2472
  throw new MastraError(
2851
2473
  {
2852
- id: "STORAGE_DYNAMODB_STORE_CLOSE_FAILED",
2474
+ id: createStorageErrorId("DYNAMODB", "CLOSE", "FAILED"),
2853
2475
  domain: ErrorDomain.STORAGE,
2854
2476
  category: ErrorCategory.THIRD_PARTY
2855
2477
  },
@@ -2857,50 +2479,8 @@ var DynamoDBStore = class extends MastraStorage {
2857
2479
  );
2858
2480
  }
2859
2481
  }
2860
- /**
2861
- * SCORERS - Not implemented
2862
- */
2863
- async getScoreById({ id: _id }) {
2864
- return this.stores.scores.getScoreById({ id: _id });
2865
- }
2866
- async saveScore(_score) {
2867
- return this.stores.scores.saveScore(_score);
2868
- }
2869
- async getScoresByRunId({
2870
- runId: _runId,
2871
- pagination: _pagination
2872
- }) {
2873
- return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
2874
- }
2875
- async getScoresByEntityId({
2876
- entityId: _entityId,
2877
- entityType: _entityType,
2878
- pagination: _pagination
2879
- }) {
2880
- return this.stores.scores.getScoresByEntityId({
2881
- entityId: _entityId,
2882
- entityType: _entityType,
2883
- pagination: _pagination
2884
- });
2885
- }
2886
- async getScoresByScorerId({
2887
- scorerId,
2888
- source,
2889
- entityId,
2890
- entityType,
2891
- pagination
2892
- }) {
2893
- return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2894
- }
2895
- async getScoresBySpan({
2896
- traceId,
2897
- spanId,
2898
- pagination
2899
- }) {
2900
- return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination });
2901
- }
2902
2482
  };
2903
2483
 
2904
- export { DynamoDBStore };
2484
+ export { DynamoDBStore, MemoryStorageDynamoDB, ScoresStorageDynamoDB, WorkflowStorageDynamoDB };
2905
2485
  //# sourceMappingURL=index.js.map
2906
2486
  //# sourceMappingURL=index.js.map