@mastra/dynamodb 0.0.0-remove-unused-import-20250909212718 → 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.
Files changed (35) hide show
  1. package/CHANGELOG.md +1312 -3
  2. package/README.md +0 -4
  3. package/dist/docs/README.md +31 -0
  4. package/dist/docs/SKILL.md +32 -0
  5. package/dist/docs/SOURCE_MAP.json +6 -0
  6. package/dist/docs/storage/01-reference.md +162 -0
  7. package/dist/entities/index.d.ts +20 -1
  8. package/dist/entities/index.d.ts.map +1 -1
  9. package/dist/entities/score.d.ts +20 -1
  10. package/dist/entities/score.d.ts.map +1 -1
  11. package/dist/index.cjs +574 -1222
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.js +573 -1224
  14. package/dist/index.js.map +1 -1
  15. package/dist/storage/db/index.d.ts +32 -0
  16. package/dist/storage/db/index.d.ts.map +1 -0
  17. package/dist/storage/domains/memory/index.d.ts +17 -45
  18. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  19. package/dist/storage/domains/scores/index.d.ts +46 -0
  20. package/dist/storage/domains/scores/index.d.ts.map +1 -0
  21. package/dist/storage/domains/utils.d.ts +7 -0
  22. package/dist/storage/domains/utils.d.ts.map +1 -0
  23. package/dist/storage/domains/workflows/index.d.ts +17 -24
  24. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  25. package/dist/storage/index.d.ts +87 -209
  26. package/dist/storage/index.d.ts.map +1 -1
  27. package/package.json +20 -18
  28. package/dist/storage/domains/legacy-evals/index.d.ts +0 -19
  29. package/dist/storage/domains/legacy-evals/index.d.ts.map +0 -1
  30. package/dist/storage/domains/operations/index.d.ts +0 -69
  31. package/dist/storage/domains/operations/index.d.ts.map +0 -1
  32. package/dist/storage/domains/score/index.d.ts +0 -43
  33. package/dist/storage/domains/score/index.d.ts.map +0 -1
  34. package/dist/storage/domains/traces/index.d.ts +0 -28
  35. package/dist/storage/domains/traces/index.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -1,9 +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, TracesStorage, TABLE_TRACES, WorkflowsStorage, MemoryStorage, resolveMessageLimit, ScoresStorage, LegacyEvalsStorage, TABLE_AI_SPANS, TABLE_RESOURCES, TABLE_SCORERS, TABLE_EVALS, 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/evals';
7
8
 
8
9
  // src/storage/index.ts
9
10
 
@@ -370,6 +371,10 @@ var scoreEntity = new Entity({
370
371
  type: "string",
371
372
  required: false
372
373
  },
374
+ spanId: {
375
+ type: "string",
376
+ required: false
377
+ },
373
378
  runId: {
374
379
  type: "string",
375
380
  required: true
@@ -418,6 +423,10 @@ var scoreEntity = new Entity({
418
423
  return value;
419
424
  }
420
425
  },
426
+ preprocessPrompt: {
427
+ type: "string",
428
+ required: false
429
+ },
421
430
  preprocessStepResult: {
422
431
  type: "string",
423
432
  required: false,
@@ -557,7 +566,7 @@ var scoreEntity = new Entity({
557
566
  return value;
558
567
  }
559
568
  },
560
- runtimeContext: {
569
+ requestContext: {
561
570
  type: "string",
562
571
  required: false,
563
572
  set: (value) => {
@@ -656,6 +665,11 @@ var scoreEntity = new Entity({
656
665
  index: "gsi6",
657
666
  pk: { field: "gsi6pk", composite: ["entity", "threadId"] },
658
667
  sk: { field: "gsi6sk", composite: ["createdAt"] }
668
+ },
669
+ bySpan: {
670
+ index: "gsi7",
671
+ pk: { field: "gsi7pk", composite: ["entity", "traceId", "spanId"] },
672
+ sk: { field: "gsi7sk", composite: ["createdAt"] }
659
673
  }
660
674
  }
661
675
  });
@@ -923,193 +937,114 @@ function getElectroDbService(client, tableName) {
923
937
  }
924
938
  );
925
939
  }
926
- var LegacyEvalsDynamoDB = class extends LegacyEvalsStorage {
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
996
+ var MemoryStorageDynamoDB = class extends MemoryStorage {
927
997
  service;
928
- tableName;
929
- constructor({ service, tableName }) {
998
+ constructor(config) {
930
999
  super();
931
- this.service = service;
932
- this.tableName = tableName;
1000
+ this.service = resolveDynamoDBConfig(config);
933
1001
  }
934
- // Eval operations
935
- async getEvalsByAgentName(agentName, type) {
936
- this.logger.debug("Getting evals for agent", { agentName, type });
937
- try {
938
- const query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
939
- const results = await query.go({ order: "desc", limit: 100 });
940
- if (!results.data.length) {
941
- return [];
942
- }
943
- let filteredData = results.data;
944
- if (type) {
945
- filteredData = filteredData.filter((evalRecord) => {
946
- try {
947
- const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
948
- if (type === "test" && !testInfo) {
949
- return false;
950
- }
951
- if (type === "live" && testInfo) {
952
- return false;
953
- }
954
- } catch (e) {
955
- this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
956
- }
957
- return true;
958
- });
959
- }
960
- return filteredData.map((evalRecord) => {
961
- try {
962
- return {
963
- input: evalRecord.input,
964
- output: evalRecord.output,
965
- // Safely parse result and test_info
966
- result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
967
- agentName: evalRecord.agent_name,
968
- createdAt: evalRecord.created_at,
969
- // Keep as string from DDB?
970
- metricName: evalRecord.metric_name,
971
- instructions: evalRecord.instructions,
972
- runId: evalRecord.run_id,
973
- globalRunId: evalRecord.global_run_id,
974
- testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
975
- };
976
- } catch (parseError) {
977
- this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
978
- return {
979
- agentName: evalRecord.agent_name,
980
- createdAt: evalRecord.created_at,
981
- runId: evalRecord.run_id,
982
- globalRunId: evalRecord.global_run_id
983
- };
984
- }
985
- });
986
- } catch (error) {
987
- throw new MastraError(
988
- {
989
- id: "STORAGE_DYNAMODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
990
- domain: ErrorDomain.STORAGE,
991
- category: ErrorCategory.THIRD_PARTY,
992
- details: { agentName }
993
- },
994
- error
995
- );
996
- }
1002
+ async dangerouslyClearAll() {
1003
+ await deleteTableData(this.service, TABLE_THREADS);
1004
+ await deleteTableData(this.service, TABLE_MESSAGES);
1005
+ await deleteTableData(this.service, TABLE_RESOURCES);
997
1006
  }
998
- async getEvals(options = {}) {
999
- const { agentName, type, page = 0, perPage = 100, dateRange } = options;
1000
- this.logger.debug("Getting evals with pagination", { agentName, type, page, perPage, dateRange });
1007
+ async deleteMessages(messageIds) {
1008
+ if (!messageIds || messageIds.length === 0) {
1009
+ return;
1010
+ }
1011
+ this.logger.debug("Deleting messages", { count: messageIds.length });
1001
1012
  try {
1002
- let query;
1003
- if (agentName) {
1004
- query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
1005
- } else {
1006
- query = this.service.entities.eval.query.byEntity({ entity: "eval" });
1007
- }
1008
- const results = await query.go({
1009
- order: "desc",
1010
- pages: "all"
1011
- // Get all pages to apply filtering and pagination
1012
- });
1013
- if (!results.data.length) {
1014
- return {
1015
- evals: [],
1016
- total: 0,
1017
- page,
1018
- perPage,
1019
- hasMore: false
1020
- };
1021
- }
1022
- let filteredData = results.data;
1023
- if (type) {
1024
- filteredData = filteredData.filter((evalRecord) => {
1025
- try {
1026
- const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
1027
- if (type === "test" && !testInfo) {
1028
- return false;
1029
- }
1030
- if (type === "live" && testInfo) {
1031
- return false;
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);
1032
1027
  }
1033
- } catch (e) {
1034
- this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
1028
+ await this.service.entities.message.delete({ entity: "message", id: message.id }).go();
1035
1029
  }
1036
- return true;
1037
- });
1030
+ }
1038
1031
  }
1039
- if (dateRange) {
1040
- const fromDate = dateRange.start;
1041
- const toDate = dateRange.end;
1042
- filteredData = filteredData.filter((evalRecord) => {
1043
- const recordDate = new Date(evalRecord.created_at);
1044
- if (fromDate && recordDate < fromDate) {
1045
- return false;
1046
- }
1047
- if (toDate && recordDate > toDate) {
1048
- return false;
1049
- }
1050
- return true;
1051
- });
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();
1052
1035
  }
1053
- const total = filteredData.length;
1054
- const start = page * perPage;
1055
- const end = start + perPage;
1056
- const paginatedData = filteredData.slice(start, end);
1057
- const evals = paginatedData.map((evalRecord) => {
1058
- try {
1059
- return {
1060
- input: evalRecord.input,
1061
- output: evalRecord.output,
1062
- result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
1063
- agentName: evalRecord.agent_name,
1064
- createdAt: evalRecord.created_at,
1065
- metricName: evalRecord.metric_name,
1066
- instructions: evalRecord.instructions,
1067
- runId: evalRecord.run_id,
1068
- globalRunId: evalRecord.global_run_id,
1069
- testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
1070
- };
1071
- } catch (parseError) {
1072
- this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
1073
- return {
1074
- agentName: evalRecord.agent_name,
1075
- createdAt: evalRecord.created_at,
1076
- runId: evalRecord.run_id,
1077
- globalRunId: evalRecord.global_run_id
1078
- };
1079
- }
1080
- });
1081
- const hasMore = end < total;
1082
- return {
1083
- evals,
1084
- total,
1085
- page,
1086
- perPage,
1087
- hasMore
1088
- };
1089
1036
  } catch (error) {
1090
1037
  throw new MastraError(
1091
1038
  {
1092
- id: "STORAGE_DYNAMODB_STORE_GET_EVALS_FAILED",
1039
+ id: createStorageErrorId("DYNAMODB", "DELETE_MESSAGES", "FAILED"),
1093
1040
  domain: ErrorDomain.STORAGE,
1094
1041
  category: ErrorCategory.THIRD_PARTY,
1095
- details: {
1096
- agentName: agentName || "all",
1097
- type: type || "all",
1098
- page,
1099
- perPage
1100
- }
1042
+ details: { count: messageIds.length }
1101
1043
  },
1102
1044
  error
1103
1045
  );
1104
1046
  }
1105
1047
  }
1106
- };
1107
- var MemoryStorageDynamoDB = class extends MemoryStorage {
1108
- service;
1109
- constructor({ service }) {
1110
- super();
1111
- this.service = service;
1112
- }
1113
1048
  // Helper function to parse message data (handle JSON fields)
1114
1049
  parseMessageData(data) {
1115
1050
  return {
@@ -1122,17 +1057,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1122
1057
  };
1123
1058
  }
1124
1059
  // Helper function to transform and sort threads
1125
- transformAndSortThreads(rawThreads, orderBy, sortDirection) {
1060
+ transformAndSortThreads(rawThreads, field, direction) {
1126
1061
  return rawThreads.map((data) => ({
1127
1062
  ...data,
1128
1063
  // Convert date strings back to Date objects for consistency
1129
1064
  createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
1130
1065
  updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
1131
1066
  })).sort((a, b) => {
1132
- const fieldA = orderBy === "createdAt" ? a.createdAt : a.updatedAt;
1133
- 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;
1134
1069
  const comparison = fieldA.getTime() - fieldB.getTime();
1135
- return sortDirection === "DESC" ? -comparison : comparison;
1070
+ return direction === "DESC" ? -comparison : comparison;
1136
1071
  });
1137
1072
  }
1138
1073
  async getThreadById({ threadId }) {
@@ -1154,7 +1089,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1154
1089
  } catch (error) {
1155
1090
  throw new MastraError(
1156
1091
  {
1157
- id: "STORAGE_DYNAMODB_STORE_GET_THREAD_BY_ID_FAILED",
1092
+ id: createStorageErrorId("DYNAMODB", "GET_THREAD_BY_ID", "FAILED"),
1158
1093
  domain: ErrorDomain.STORAGE,
1159
1094
  category: ErrorCategory.THIRD_PARTY,
1160
1095
  details: { threadId }
@@ -1163,32 +1098,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1163
1098
  );
1164
1099
  }
1165
1100
  }
1166
- /**
1167
- * @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
1168
- */
1169
- async getThreadsByResourceId(args) {
1170
- const resourceId = args.resourceId;
1171
- const orderBy = this.castThreadOrderBy(args.orderBy);
1172
- const sortDirection = this.castThreadSortDirection(args.sortDirection);
1173
- this.logger.debug("Getting threads by resource ID", { resourceId, orderBy, sortDirection });
1174
- try {
1175
- const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
1176
- if (!result.data.length) {
1177
- return [];
1178
- }
1179
- return this.transformAndSortThreads(result.data, orderBy, sortDirection);
1180
- } catch (error) {
1181
- throw new MastraError(
1182
- {
1183
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1184
- domain: ErrorDomain.STORAGE,
1185
- category: ErrorCategory.THIRD_PARTY,
1186
- details: { resourceId }
1187
- },
1188
- error
1189
- );
1190
- }
1191
- }
1192
1101
  async saveThread({ thread }) {
1193
1102
  this.logger.debug("Saving thread", { threadId: thread.id });
1194
1103
  const now = /* @__PURE__ */ new Date();
@@ -1208,13 +1117,13 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1208
1117
  resourceId: thread.resourceId,
1209
1118
  title: threadData.title,
1210
1119
  createdAt: thread.createdAt || now,
1211
- updatedAt: now,
1120
+ updatedAt: thread.updatedAt || now,
1212
1121
  metadata: thread.metadata
1213
1122
  };
1214
1123
  } catch (error) {
1215
1124
  throw new MastraError(
1216
1125
  {
1217
- id: "STORAGE_DYNAMODB_STORE_SAVE_THREAD_FAILED",
1126
+ id: createStorageErrorId("DYNAMODB", "SAVE_THREAD", "FAILED"),
1218
1127
  domain: ErrorDomain.STORAGE,
1219
1128
  category: ErrorCategory.THIRD_PARTY,
1220
1129
  details: { threadId: thread.id }
@@ -1256,7 +1165,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1256
1165
  } catch (error) {
1257
1166
  throw new MastraError(
1258
1167
  {
1259
- id: "STORAGE_DYNAMODB_STORE_UPDATE_THREAD_FAILED",
1168
+ id: createStorageErrorId("DYNAMODB", "UPDATE_THREAD", "FAILED"),
1260
1169
  domain: ErrorDomain.STORAGE,
1261
1170
  category: ErrorCategory.THIRD_PARTY,
1262
1171
  details: { threadId: id }
@@ -1268,7 +1177,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1268
1177
  async deleteThread({ threadId }) {
1269
1178
  this.logger.debug("Deleting thread", { threadId });
1270
1179
  try {
1271
- const messages = await this.getMessages({ threadId });
1180
+ const { messages } = await this.listMessages({ threadId, perPage: false });
1272
1181
  if (messages.length > 0) {
1273
1182
  const batchSize = 25;
1274
1183
  for (let i = 0; i < messages.length; i += batchSize) {
@@ -1288,7 +1197,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1288
1197
  } catch (error) {
1289
1198
  throw new MastraError(
1290
1199
  {
1291
- id: "STORAGE_DYNAMODB_STORE_DELETE_THREAD_FAILED",
1200
+ id: createStorageErrorId("DYNAMODB", "DELETE_THREAD", "FAILED"),
1292
1201
  domain: ErrorDomain.STORAGE,
1293
1202
  category: ErrorCategory.THIRD_PARTY,
1294
1203
  details: { threadId }
@@ -1297,104 +1206,166 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1297
1206
  );
1298
1207
  }
1299
1208
  }
1300
- async getMessages({
1301
- threadId,
1302
- resourceId,
1303
- selectBy,
1304
- format
1305
- }) {
1306
- this.logger.debug("Getting messages", { threadId, selectBy });
1209
+ async listMessagesById({ messageIds }) {
1210
+ this.logger.debug("Getting messages by ID", { messageIds });
1211
+ if (messageIds.length === 0) return { messages: [] };
1307
1212
  try {
1308
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1309
- const messages = [];
1310
- const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1311
- if (selectBy?.include?.length) {
1312
- const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1313
- if (includeMessages) {
1314
- messages.push(...includeMessages);
1315
- }
1316
- }
1317
- if (limit !== 0) {
1318
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1319
- let results;
1320
- if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1321
- results = await query.go({ limit, order: "desc" });
1322
- results.data = results.data.reverse();
1323
- } else {
1324
- results = await query.go();
1325
- }
1326
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1327
- allThreadMessages.sort((a, b) => {
1328
- const timeA = a.createdAt.getTime();
1329
- const timeB = b.createdAt.getTime();
1330
- if (timeA === timeB) {
1331
- return a.id.localeCompare(b.id);
1332
- }
1333
- return timeA - timeB;
1334
- });
1335
- messages.push(...allThreadMessages);
1336
- }
1337
- messages.sort((a, b) => {
1338
- const timeA = a.createdAt.getTime();
1339
- const timeB = b.createdAt.getTime();
1340
- if (timeA === timeB) {
1341
- return a.id.localeCompare(b.id);
1342
- }
1343
- return timeA - timeB;
1344
- });
1345
- const uniqueMessages = messages.filter(
1213
+ const results = await Promise.all(
1214
+ messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1215
+ );
1216
+ const data = results.map((result) => result.data).flat(1);
1217
+ let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1218
+ const uniqueMessages = parsedMessages.filter(
1346
1219
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1347
1220
  );
1348
- const list = new MessageList({ threadId, resourceId }).add(uniqueMessages, "memory");
1349
- if (format === `v2`) return list.get.all.v2();
1350
- return list.get.all.v1();
1221
+ const list = new MessageList().add(uniqueMessages, "memory");
1222
+ return { messages: list.get.all.db() };
1351
1223
  } catch (error) {
1352
1224
  throw new MastraError(
1353
1225
  {
1354
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED",
1226
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES_BY_ID", "FAILED"),
1355
1227
  domain: ErrorDomain.STORAGE,
1356
1228
  category: ErrorCategory.THIRD_PARTY,
1357
- details: { threadId, resourceId: resourceId ?? "" }
1229
+ details: { messageIds: JSON.stringify(messageIds) }
1358
1230
  },
1359
1231
  error
1360
1232
  );
1361
1233
  }
1362
1234
  }
1363
- async getMessagesById({
1364
- messageIds,
1365
- format
1366
- }) {
1367
- this.logger.debug("Getting messages by ID", { messageIds });
1368
- if (messageIds.length === 0) return [];
1369
- try {
1370
- const results = await Promise.all(
1371
- messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1235
+ async listMessages(args) {
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())) {
1239
+ throw new MastraError(
1240
+ {
1241
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "INVALID_THREAD_ID"),
1242
+ domain: ErrorDomain.STORAGE,
1243
+ category: ErrorCategory.THIRD_PARTY,
1244
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
1245
+ },
1246
+ new Error("threadId must be a non-empty string or array of non-empty strings")
1372
1247
  );
1373
- const data = results.map((result) => result.data).flat(1);
1374
- let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1375
- const uniqueMessages = parsedMessages.filter(
1376
- (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1248
+ }
1249
+ const perPage = normalizePerPage(perPageInput, 40);
1250
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1251
+ try {
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
+ );
1262
+ }
1263
+ const { field, direction } = this.parseOrderBy(orderBy, "ASC");
1264
+ this.logger.debug("Getting messages with listMessages", {
1265
+ threadId,
1266
+ resourceId,
1267
+ perPageInput,
1268
+ offset,
1269
+ perPage,
1270
+ page,
1271
+ field,
1272
+ direction
1273
+ });
1274
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1275
+ const results = await query.go();
1276
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1277
+ if (resourceId) {
1278
+ allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1279
+ }
1280
+ allThreadMessages = filterByDateRange(
1281
+ allThreadMessages,
1282
+ (msg) => new Date(msg.createdAt),
1283
+ filter?.dateRange
1377
1284
  );
1378
- const list = new MessageList().add(uniqueMessages, "memory");
1379
- if (format === `v1`) return list.get.all.v1();
1380
- return list.get.all.v2();
1285
+ allThreadMessages.sort((a, b) => {
1286
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1287
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1288
+ if (aValue === bValue) {
1289
+ return a.id.localeCompare(b.id);
1290
+ }
1291
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1292
+ });
1293
+ const total = allThreadMessages.length;
1294
+ const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1295
+ const paginatedCount = paginatedMessages.length;
1296
+ if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1297
+ return {
1298
+ messages: [],
1299
+ total: 0,
1300
+ page,
1301
+ perPage: perPageForResponse,
1302
+ hasMore: false
1303
+ };
1304
+ }
1305
+ const messageIds = new Set(paginatedMessages.map((m) => m.id));
1306
+ let includeMessages = [];
1307
+ if (include && include.length > 0) {
1308
+ const selectBy = { include };
1309
+ includeMessages = await this._getIncludedMessages(selectBy);
1310
+ for (const includeMsg of includeMessages) {
1311
+ if (!messageIds.has(includeMsg.id)) {
1312
+ paginatedMessages.push(includeMsg);
1313
+ messageIds.add(includeMsg.id);
1314
+ }
1315
+ }
1316
+ }
1317
+ const list = new MessageList().add(paginatedMessages, "memory");
1318
+ let finalMessages = list.get.all.db();
1319
+ finalMessages = finalMessages.sort((a, b) => {
1320
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1321
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1322
+ if (aValue === bValue) {
1323
+ return a.id.localeCompare(b.id);
1324
+ }
1325
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1326
+ });
1327
+ const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1328
+ const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1329
+ let hasMore = false;
1330
+ if (perPageInput !== false && !allThreadMessagesReturned) {
1331
+ hasMore = offset + paginatedCount < total;
1332
+ }
1333
+ return {
1334
+ messages: finalMessages,
1335
+ total,
1336
+ page,
1337
+ perPage: perPageForResponse,
1338
+ hasMore
1339
+ };
1381
1340
  } catch (error) {
1382
- throw new MastraError(
1341
+ const mastraError = new MastraError(
1383
1342
  {
1384
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_BY_ID_FAILED",
1343
+ id: createStorageErrorId("DYNAMODB", "LIST_MESSAGES", "FAILED"),
1385
1344
  domain: ErrorDomain.STORAGE,
1386
1345
  category: ErrorCategory.THIRD_PARTY,
1387
- details: { messageIds: JSON.stringify(messageIds) }
1346
+ details: {
1347
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
1348
+ resourceId: resourceId ?? ""
1349
+ }
1388
1350
  },
1389
1351
  error
1390
1352
  );
1353
+ this.logger?.error?.(mastraError.toString());
1354
+ this.logger?.trackException?.(mastraError);
1355
+ return {
1356
+ messages: [],
1357
+ total: 0,
1358
+ page,
1359
+ perPage: perPageForResponse,
1360
+ hasMore: false
1361
+ };
1391
1362
  }
1392
1363
  }
1393
1364
  async saveMessages(args) {
1394
- const { messages, format = "v1" } = args;
1365
+ const { messages } = args;
1395
1366
  this.logger.debug("Saving messages", { count: messages.length });
1396
1367
  if (!messages.length) {
1397
- return [];
1368
+ return { messages: [] };
1398
1369
  }
1399
1370
  const threadId = messages[0]?.threadId;
1400
1371
  if (!threadId) {
@@ -1448,12 +1419,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1448
1419
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1449
1420
  }).go();
1450
1421
  const list = new MessageList().add(messages, "memory");
1451
- if (format === `v1`) return list.get.all.v1();
1452
- return list.get.all.v2();
1422
+ return { messages: list.get.all.db() };
1453
1423
  } catch (error) {
1454
1424
  throw new MastraError(
1455
1425
  {
1456
- id: "STORAGE_DYNAMODB_STORE_SAVE_MESSAGES_FAILED",
1426
+ id: createStorageErrorId("DYNAMODB", "SAVE_MESSAGES", "FAILED"),
1457
1427
  domain: ErrorDomain.STORAGE,
1458
1428
  category: ErrorCategory.THIRD_PARTY,
1459
1429
  details: { count: messages.length }
@@ -1462,37 +1432,48 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1462
1432
  );
1463
1433
  }
1464
1434
  }
1465
- async getThreadsByResourceIdPaginated(args) {
1466
- const { resourceId, page = 0, perPage = 100 } = args;
1467
- const orderBy = this.castThreadOrderBy(args.orderBy);
1468
- 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);
1469
1451
  this.logger.debug("Getting threads by resource ID with pagination", {
1470
1452
  resourceId,
1471
1453
  page,
1472
1454
  perPage,
1473
- orderBy,
1474
- sortDirection
1455
+ field,
1456
+ direction
1475
1457
  });
1476
1458
  try {
1477
1459
  const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1478
1460
  const results = await query.go();
1479
- const allThreads = this.transformAndSortThreads(results.data, orderBy, sortDirection);
1480
- const startIndex = page * perPage;
1481
- const endIndex = startIndex + perPage;
1482
- 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);
1483
1464
  const total = allThreads.length;
1484
- const hasMore = endIndex < total;
1465
+ const hasMore = offset + perPage < total;
1485
1466
  return {
1486
1467
  threads: paginatedThreads,
1487
1468
  total,
1488
1469
  page,
1489
- perPage,
1470
+ perPage: perPageForResponse,
1490
1471
  hasMore
1491
1472
  };
1492
1473
  } catch (error) {
1493
1474
  throw new MastraError(
1494
1475
  {
1495
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1476
+ id: createStorageErrorId("DYNAMODB", "LIST_THREADS_BY_RESOURCE_ID", "FAILED"),
1496
1477
  domain: ErrorDomain.STORAGE,
1497
1478
  category: ErrorCategory.THIRD_PARTY,
1498
1479
  details: { resourceId, page, perPage }
@@ -1501,98 +1482,24 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1501
1482
  );
1502
1483
  }
1503
1484
  }
1504
- async getMessagesPaginated(args) {
1505
- const { threadId, resourceId, selectBy, format = "v1" } = args;
1506
- const { page = 0, perPage = 40, dateRange } = selectBy?.pagination || {};
1507
- const fromDate = dateRange?.start;
1508
- const toDate = dateRange?.end;
1509
- const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1510
- this.logger.debug("Getting messages with pagination", { threadId, page, perPage, fromDate, toDate, limit });
1511
- try {
1512
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1513
- let messages = [];
1514
- if (selectBy?.include?.length) {
1515
- const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1516
- if (includeMessages) {
1517
- messages.push(...includeMessages);
1518
- }
1519
- }
1520
- if (limit !== 0) {
1521
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1522
- let results;
1523
- if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1524
- results = await query.go({ limit, order: "desc" });
1525
- results.data = results.data.reverse();
1526
- } else {
1527
- results = await query.go();
1528
- }
1529
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1530
- allThreadMessages.sort((a, b) => {
1531
- const timeA = a.createdAt.getTime();
1532
- const timeB = b.createdAt.getTime();
1533
- if (timeA === timeB) {
1534
- return a.id.localeCompare(b.id);
1535
- }
1536
- return timeA - timeB;
1537
- });
1538
- const excludeIds = messages.map((m) => m.id);
1539
- if (excludeIds.length > 0) {
1540
- allThreadMessages = allThreadMessages.filter((msg) => !excludeIds.includes(msg.id));
1541
- }
1542
- messages.push(...allThreadMessages);
1543
- }
1544
- messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1545
- if (fromDate || toDate) {
1546
- messages = messages.filter((msg) => {
1547
- const createdAt = new Date(msg.createdAt).getTime();
1548
- if (fromDate && createdAt < new Date(fromDate).getTime()) return false;
1549
- if (toDate && createdAt > new Date(toDate).getTime()) return false;
1550
- return true;
1551
- });
1552
- }
1553
- const total = messages.length;
1554
- const start = page * perPage;
1555
- const end = start + perPage;
1556
- const paginatedMessages = messages.slice(start, end);
1557
- const hasMore = end < total;
1558
- const list = new MessageList({ threadId, resourceId }).add(paginatedMessages, "memory");
1559
- const finalMessages = format === "v2" ? list.get.all.v2() : list.get.all.v1();
1560
- return {
1561
- messages: finalMessages,
1562
- total,
1563
- page,
1564
- perPage,
1565
- hasMore
1566
- };
1567
- } catch (error) {
1568
- const mastraError = new MastraError(
1569
- {
1570
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1571
- domain: ErrorDomain.STORAGE,
1572
- category: ErrorCategory.THIRD_PARTY,
1573
- details: { threadId, resourceId: resourceId ?? "" }
1574
- },
1575
- error
1576
- );
1577
- this.logger?.trackException?.(mastraError);
1578
- this.logger?.error?.(mastraError.toString());
1579
- return { messages: [], total: 0, page, perPage, hasMore: false };
1580
- }
1581
- }
1582
1485
  // Helper method to get included messages with context
1583
- async _getIncludedMessages(threadId, selectBy) {
1584
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1486
+ async _getIncludedMessages(selectBy) {
1585
1487
  if (!selectBy?.include?.length) {
1586
1488
  return [];
1587
1489
  }
1588
1490
  const includeMessages = [];
1589
1491
  for (const includeItem of selectBy.include) {
1590
1492
  try {
1591
- const { id, threadId: targetThreadId, withPreviousMessages = 0, withNextMessages = 0 } = includeItem;
1592
- 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;
1593
1501
  this.logger.debug("Getting included messages for", {
1594
1502
  id,
1595
- targetThreadId,
1596
1503
  searchThreadId,
1597
1504
  withPreviousMessages,
1598
1505
  withNextMessages
@@ -1615,7 +1522,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1615
1522
  });
1616
1523
  const targetIndex = allMessages.findIndex((msg) => msg.id === id);
1617
1524
  if (targetIndex === -1) {
1618
- this.logger.warn("Target message not found", { id, threadId: searchThreadId });
1525
+ this.logger.warn("Target message not found in thread", { id, threadId: searchThreadId });
1619
1526
  continue;
1620
1527
  }
1621
1528
  this.logger.debug("Found target message at index", { id, targetIndex, totalMessages: allMessages.length });
@@ -1700,7 +1607,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1700
1607
  } catch (error) {
1701
1608
  throw new MastraError(
1702
1609
  {
1703
- id: "STORAGE_DYNAMODB_STORE_UPDATE_MESSAGES_FAILED",
1610
+ id: createStorageErrorId("DYNAMODB", "UPDATE_MESSAGES", "FAILED"),
1704
1611
  domain: ErrorDomain.STORAGE,
1705
1612
  category: ErrorCategory.THIRD_PARTY,
1706
1613
  details: { count: messages.length }
@@ -1729,7 +1636,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1729
1636
  } catch (error) {
1730
1637
  throw new MastraError(
1731
1638
  {
1732
- id: "STORAGE_DYNAMODB_STORE_GET_RESOURCE_BY_ID_FAILED",
1639
+ id: createStorageErrorId("DYNAMODB", "GET_RESOURCE_BY_ID", "FAILED"),
1733
1640
  domain: ErrorDomain.STORAGE,
1734
1641
  category: ErrorCategory.THIRD_PARTY,
1735
1642
  details: { resourceId }
@@ -1761,7 +1668,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1761
1668
  } catch (error) {
1762
1669
  throw new MastraError(
1763
1670
  {
1764
- id: "STORAGE_DYNAMODB_STORE_SAVE_RESOURCE_FAILED",
1671
+ id: createStorageErrorId("DYNAMODB", "SAVE_RESOURCE", "FAILED"),
1765
1672
  domain: ErrorDomain.STORAGE,
1766
1673
  category: ErrorCategory.THIRD_PARTY,
1767
1674
  details: { resourceId: resource.id }
@@ -1810,7 +1717,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1810
1717
  } catch (error) {
1811
1718
  throw new MastraError(
1812
1719
  {
1813
- id: "STORAGE_DYNAMODB_STORE_UPDATE_RESOURCE_FAILED",
1720
+ id: createStorageErrorId("DYNAMODB", "UPDATE_RESOURCE", "FAILED"),
1814
1721
  domain: ErrorDomain.STORAGE,
1815
1722
  category: ErrorCategory.THIRD_PARTY,
1816
1723
  details: { resourceId }
@@ -1820,406 +1727,123 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1820
1727
  }
1821
1728
  }
1822
1729
  };
1823
- var StoreOperationsDynamoDB = class extends StoreOperations {
1824
- client;
1825
- tableName;
1730
+ var ScoresStorageDynamoDB = class extends ScoresStorage {
1826
1731
  service;
1827
- constructor({
1828
- service,
1829
- tableName,
1830
- client
1831
- }) {
1732
+ constructor(config) {
1832
1733
  super();
1833
- this.service = service;
1834
- this.client = client;
1835
- this.tableName = tableName;
1836
- }
1837
- async hasColumn() {
1838
- return true;
1734
+ this.service = resolveDynamoDBConfig(config);
1839
1735
  }
1840
- async dropTable() {
1841
- }
1842
- // Helper methods for entity/table mapping
1843
- getEntityNameForTable(tableName) {
1844
- const mapping = {
1845
- [TABLE_THREADS]: "thread",
1846
- [TABLE_MESSAGES]: "message",
1847
- [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1848
- [TABLE_EVALS]: "eval",
1849
- [TABLE_SCORERS]: "score",
1850
- [TABLE_TRACES]: "trace",
1851
- [TABLE_RESOURCES]: "resource",
1852
- [TABLE_AI_SPANS]: "ai_span"
1853
- };
1854
- return mapping[tableName] || null;
1736
+ async dangerouslyClearAll() {
1737
+ await deleteTableData(this.service, TABLE_SCORERS);
1855
1738
  }
1856
1739
  /**
1857
- * Pre-processes a record to ensure Date objects are converted to ISO strings
1858
- * This is necessary because ElectroDB validation happens before setters are applied
1740
+ * DynamoDB-specific score row transformation.
1741
+ *
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
1859
1746
  */
1860
- preprocessRecord(record) {
1861
- const processed = { ...record };
1862
- if (processed.createdAt instanceof Date) {
1863
- processed.createdAt = processed.createdAt.toISOString();
1864
- }
1865
- if (processed.updatedAt instanceof Date) {
1866
- processed.updatedAt = processed.updatedAt.toISOString();
1867
- }
1868
- if (processed.created_at instanceof Date) {
1869
- processed.created_at = processed.created_at.toISOString();
1870
- }
1871
- if (processed.result && typeof processed.result === "object") {
1872
- processed.result = JSON.stringify(processed.result);
1873
- }
1874
- if (processed.test_info && typeof processed.test_info === "object") {
1875
- processed.test_info = JSON.stringify(processed.test_info);
1876
- } else if (processed.test_info === void 0 || processed.test_info === null) {
1877
- delete processed.test_info;
1878
- }
1879
- if (processed.snapshot && typeof processed.snapshot === "object") {
1880
- processed.snapshot = JSON.stringify(processed.snapshot);
1881
- }
1882
- if (processed.attributes && typeof processed.attributes === "object") {
1883
- processed.attributes = JSON.stringify(processed.attributes);
1884
- }
1885
- if (processed.status && typeof processed.status === "object") {
1886
- processed.status = JSON.stringify(processed.status);
1887
- }
1888
- if (processed.events && typeof processed.events === "object") {
1889
- processed.events = JSON.stringify(processed.events);
1890
- }
1891
- if (processed.links && typeof processed.links === "object") {
1892
- processed.links = JSON.stringify(processed.links);
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;
1753
+ }
1754
+ result[key] = data[key];
1893
1755
  }
1894
- return processed;
1756
+ result.entity = data.entityData ?? null;
1757
+ return {
1758
+ ...result,
1759
+ createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
1760
+ updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
1761
+ };
1895
1762
  }
1896
- /**
1897
- * Validates that the required DynamoDB table exists and is accessible.
1898
- * This does not check the table structure - it assumes the table
1899
- * was created with the correct structure via CDK/CloudFormation.
1900
- */
1901
- async validateTableExists() {
1763
+ async getScoreById({ id }) {
1764
+ this.logger.debug("Getting score by ID", { id });
1902
1765
  try {
1903
- const command = new DescribeTableCommand({
1904
- TableName: this.tableName
1905
- });
1906
- await this.client.send(command);
1907
- return true;
1908
- } catch (error) {
1909
- if (error.name === "ResourceNotFoundException") {
1910
- return false;
1766
+ const result = await this.service.entities.score.get({ entity: "score", id }).go();
1767
+ if (!result.data) {
1768
+ return null;
1911
1769
  }
1770
+ return this.parseScoreData(result.data);
1771
+ } catch (error) {
1912
1772
  throw new MastraError(
1913
1773
  {
1914
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
1774
+ id: createStorageErrorId("DYNAMODB", "GET_SCORE_BY_ID", "FAILED"),
1915
1775
  domain: ErrorDomain.STORAGE,
1916
1776
  category: ErrorCategory.THIRD_PARTY,
1917
- details: { tableName: this.tableName }
1918
- },
1919
- error
1920
- );
1921
- }
1922
- }
1923
- /**
1924
- * This method is modified for DynamoDB with ElectroDB single-table design.
1925
- * It assumes the table is created and managed externally via CDK/CloudFormation.
1926
- *
1927
- * This implementation only validates that the required table exists and is accessible.
1928
- * No table creation is attempted - we simply check if we can access the table.
1929
- */
1930
- async createTable({ tableName }) {
1931
- this.logger.debug("Validating access to externally managed table", { tableName, physicalTable: this.tableName });
1932
- try {
1933
- const tableExists = await this.validateTableExists();
1934
- if (!tableExists) {
1935
- this.logger.error(
1936
- `Table ${this.tableName} does not exist or is not accessible. It should be created via CDK/CloudFormation.`
1937
- );
1938
- throw new Error(
1939
- `Table ${this.tableName} does not exist or is not accessible. Ensure it's created via CDK/CloudFormation before using this store.`
1940
- );
1941
- }
1942
- this.logger.debug(`Table ${this.tableName} exists and is accessible`);
1943
- } catch (error) {
1944
- this.logger.error("Error validating table access", { tableName: this.tableName, error });
1945
- throw new MastraError(
1946
- {
1947
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_ACCESS_FAILED",
1948
- domain: ErrorDomain.STORAGE,
1949
- category: ErrorCategory.THIRD_PARTY,
1950
- details: { tableName: this.tableName }
1951
- },
1952
- error
1953
- );
1954
- }
1955
- }
1956
- async insert({ tableName, record }) {
1957
- this.logger.debug("DynamoDB insert called", { tableName });
1958
- const entityName = this.getEntityNameForTable(tableName);
1959
- if (!entityName || !this.service.entities[entityName]) {
1960
- throw new MastraError({
1961
- id: "STORAGE_DYNAMODB_STORE_INSERT_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 dataToSave = { entity: entityName, ...this.preprocessRecord(record) };
1970
- await this.service.entities[entityName].create(dataToSave).go();
1971
- } catch (error) {
1972
- throw new MastraError(
1973
- {
1974
- id: "STORAGE_DYNAMODB_STORE_INSERT_FAILED",
1975
- domain: ErrorDomain.STORAGE,
1976
- category: ErrorCategory.THIRD_PARTY,
1977
- details: { tableName }
1777
+ details: { id }
1978
1778
  },
1979
1779
  error
1980
1780
  );
1981
1781
  }
1982
1782
  }
1983
- async alterTable(_args) {
1984
- }
1985
- /**
1986
- * Clear all items from a logical "table" (entity type)
1987
- */
1988
- async clearTable({ tableName }) {
1989
- this.logger.debug("DynamoDB clearTable called", { tableName });
1990
- const entityName = this.getEntityNameForTable(tableName);
1991
- if (!entityName || !this.service.entities[entityName]) {
1992
- throw new MastraError({
1993
- id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_INVALID_ARGS",
1994
- domain: ErrorDomain.STORAGE,
1995
- category: ErrorCategory.USER,
1996
- text: "No entity defined for tableName",
1997
- details: { tableName }
1998
- });
1999
- }
1783
+ async saveScore(score) {
1784
+ let validatedScore;
2000
1785
  try {
2001
- const result = await this.service.entities[entityName].scan.go({ pages: "all" });
2002
- if (!result.data.length) {
2003
- this.logger.debug(`No records found to clear for ${tableName}`);
2004
- return;
2005
- }
2006
- this.logger.debug(`Found ${result.data.length} records to delete for ${tableName}`);
2007
- const keysToDelete = result.data.map((item) => {
2008
- const key = { entity: entityName };
2009
- switch (entityName) {
2010
- case "thread":
2011
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'thread'`);
2012
- key.id = item.id;
2013
- break;
2014
- case "message":
2015
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'message'`);
2016
- key.id = item.id;
2017
- break;
2018
- case "workflow_snapshot":
2019
- if (!item.workflow_name)
2020
- throw new Error(`Missing required key 'workflow_name' for entity 'workflow_snapshot'`);
2021
- if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'workflow_snapshot'`);
2022
- key.workflow_name = item.workflow_name;
2023
- key.run_id = item.run_id;
2024
- break;
2025
- case "eval":
2026
- if (!item.run_id) throw new Error(`Missing required key 'run_id' for entity 'eval'`);
2027
- key.run_id = item.run_id;
2028
- break;
2029
- case "trace":
2030
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'trace'`);
2031
- key.id = item.id;
2032
- break;
2033
- case "score":
2034
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
2035
- key.id = item.id;
2036
- break;
2037
- default:
2038
- this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
2039
- throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
2040
- }
2041
- return key;
2042
- });
2043
- const batchSize = 25;
2044
- for (let i = 0; i < keysToDelete.length; i += batchSize) {
2045
- const batchKeys = keysToDelete.slice(i, i + batchSize);
2046
- await this.service.entities[entityName].delete(batchKeys).go();
2047
- }
2048
- this.logger.debug(`Successfully cleared all records for ${tableName}`);
1786
+ validatedScore = saveScorePayloadSchema.parse(score);
2049
1787
  } catch (error) {
2050
1788
  throw new MastraError(
2051
1789
  {
2052
- id: "STORAGE_DYNAMODB_STORE_CLEAR_TABLE_FAILED",
1790
+ id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "VALIDATION_FAILED"),
2053
1791
  domain: ErrorDomain.STORAGE,
2054
- category: ErrorCategory.THIRD_PARTY,
2055
- details: { tableName }
2056
- },
2057
- error
2058
- );
2059
- }
2060
- }
2061
- /**
2062
- * Insert multiple records as a batch
2063
- */
2064
- async batchInsert({ tableName, records }) {
2065
- this.logger.debug("DynamoDB batchInsert called", { tableName, count: records.length });
2066
- const entityName = this.getEntityNameForTable(tableName);
2067
- if (!entityName || !this.service.entities[entityName]) {
2068
- throw new MastraError({
2069
- id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_INVALID_ARGS",
2070
- domain: ErrorDomain.STORAGE,
2071
- category: ErrorCategory.USER,
2072
- text: "No entity defined for tableName",
2073
- details: { tableName }
2074
- });
2075
- }
2076
- const recordsToSave = records.map((rec) => ({ entity: entityName, ...this.preprocessRecord(rec) }));
2077
- const batchSize = 25;
2078
- const batches = [];
2079
- for (let i = 0; i < recordsToSave.length; i += batchSize) {
2080
- const batch = recordsToSave.slice(i, i + batchSize);
2081
- batches.push(batch);
2082
- }
2083
- try {
2084
- for (const batch of batches) {
2085
- for (const recordData of batch) {
2086
- if (!recordData.entity) {
2087
- this.logger.error("Missing entity property in record data for batchInsert", { recordData, tableName });
2088
- throw new Error(`Internal error: Missing entity property during batchInsert for ${tableName}`);
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 ?? ""
2089
1799
  }
2090
- this.logger.debug("Attempting to create record in batchInsert:", { entityName, recordData });
2091
- await this.service.entities[entityName].create(recordData).go();
2092
- }
2093
- }
2094
- } catch (error) {
2095
- throw new MastraError(
2096
- {
2097
- id: "STORAGE_DYNAMODB_STORE_BATCH_INSERT_FAILED",
2098
- domain: ErrorDomain.STORAGE,
2099
- category: ErrorCategory.THIRD_PARTY,
2100
- details: { tableName }
2101
- },
2102
- error
2103
- );
2104
- }
2105
- }
2106
- /**
2107
- * Load a record by its keys
2108
- */
2109
- async load({ tableName, keys }) {
2110
- this.logger.debug("DynamoDB load called", { tableName, keys });
2111
- const entityName = this.getEntityNameForTable(tableName);
2112
- if (!entityName || !this.service.entities[entityName]) {
2113
- throw new MastraError({
2114
- id: "STORAGE_DYNAMODB_STORE_LOAD_INVALID_ARGS",
2115
- domain: ErrorDomain.STORAGE,
2116
- category: ErrorCategory.USER,
2117
- text: "No entity defined for tableName",
2118
- details: { tableName }
2119
- });
2120
- }
2121
- try {
2122
- const keyObject = { entity: entityName, ...keys };
2123
- const result = await this.service.entities[entityName].get(keyObject).go();
2124
- if (!result.data) {
2125
- return null;
2126
- }
2127
- let data = result.data;
2128
- return data;
2129
- } catch (error) {
2130
- throw new MastraError(
2131
- {
2132
- id: "STORAGE_DYNAMODB_STORE_LOAD_FAILED",
2133
- domain: ErrorDomain.STORAGE,
2134
- category: ErrorCategory.THIRD_PARTY,
2135
- details: { tableName }
2136
1800
  },
2137
1801
  error
2138
1802
  );
2139
1803
  }
2140
- }
2141
- };
2142
- var ScoresStorageDynamoDB = class extends ScoresStorage {
2143
- service;
2144
- constructor({ service }) {
2145
- super();
2146
- this.service = service;
2147
- }
2148
- // Helper function to parse score data (handle JSON fields)
2149
- parseScoreData(data) {
2150
- return {
2151
- ...data,
2152
- // Convert date strings back to Date objects for consistency
2153
- createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
2154
- updatedAt: data.updatedAt ? new Date(data.updatedAt) : /* @__PURE__ */ new Date()
2155
- // JSON fields are already transformed by the entity's getters
2156
- };
2157
- }
2158
- async getScoreById({ id }) {
2159
- this.logger.debug("Getting score by ID", { id });
2160
- try {
2161
- const result = await this.service.entities.score.get({ entity: "score", id }).go();
2162
- if (!result.data) {
2163
- return null;
2164
- }
2165
- return this.parseScoreData(result.data);
2166
- } catch (error) {
2167
- throw new MastraError(
2168
- {
2169
- id: "STORAGE_DYNAMODB_STORE_GET_SCORE_BY_ID_FAILED",
2170
- domain: ErrorDomain.STORAGE,
2171
- category: ErrorCategory.THIRD_PARTY,
2172
- details: { id }
2173
- },
2174
- error
2175
- );
2176
- }
2177
- }
2178
- async saveScore(score) {
2179
- this.logger.debug("Saving score", { scorerId: score.scorerId, runId: score.runId });
2180
1804
  const now = /* @__PURE__ */ new Date();
2181
- const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2182
- const scoreData = {
2183
- entity: "score",
2184
- id: scoreId,
2185
- scorerId: score.scorerId,
2186
- traceId: score.traceId || "",
2187
- runId: score.runId,
2188
- scorer: typeof score.scorer === "string" ? score.scorer : JSON.stringify(score.scorer),
2189
- preprocessStepResult: typeof score.preprocessStepResult === "string" ? score.preprocessStepResult : JSON.stringify(score.preprocessStepResult),
2190
- analyzeStepResult: typeof score.analyzeStepResult === "string" ? score.analyzeStepResult : JSON.stringify(score.analyzeStepResult),
2191
- score: score.score,
2192
- reason: score.reason,
2193
- preprocessPrompt: score.preprocessPrompt,
2194
- generateScorePrompt: score.generateScorePrompt,
2195
- analyzePrompt: score.analyzePrompt,
2196
- reasonPrompt: score.reasonPrompt,
2197
- input: typeof score.input === "string" ? score.input : JSON.stringify(score.input),
2198
- output: typeof score.output === "string" ? score.output : JSON.stringify(score.output),
2199
- additionalContext: typeof score.additionalContext === "string" ? score.additionalContext : JSON.stringify(score.additionalContext),
2200
- runtimeContext: typeof score.runtimeContext === "string" ? score.runtimeContext : JSON.stringify(score.runtimeContext),
2201
- entityType: score.entityType,
2202
- entityData: typeof score.entity === "string" ? score.entity : JSON.stringify(score.entity),
2203
- entityId: score.entityId,
2204
- source: score.source,
2205
- resourceId: score.resourceId || "",
2206
- threadId: score.threadId || "",
2207
- createdAt: now.toISOString(),
2208
- updatedAt: now.toISOString()
2209
- };
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
+ );
2210
1833
  try {
2211
1834
  await this.service.entities.score.upsert(scoreData).go();
2212
- const savedScore = {
2213
- ...score,
2214
- id: scoreId,
2215
- createdAt: now,
2216
- updatedAt: now
1835
+ return {
1836
+ score: {
1837
+ ...validatedScore,
1838
+ id: scoreId,
1839
+ createdAt: now,
1840
+ updatedAt: now
1841
+ }
2217
1842
  };
2218
- return { score: savedScore };
2219
1843
  } catch (error) {
2220
1844
  throw new MastraError(
2221
1845
  {
2222
- id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
1846
+ id: createStorageErrorId("DYNAMODB", "SAVE_SCORE", "FAILED"),
2223
1847
  domain: ErrorDomain.STORAGE,
2224
1848
  category: ErrorCategory.THIRD_PARTY,
2225
1849
  details: { scorerId: score.scorerId, runId: score.runId }
@@ -2228,7 +1852,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2228
1852
  );
2229
1853
  }
2230
1854
  }
2231
- async getScoresByScorerId({
1855
+ async listScoresByScorerId({
2232
1856
  scorerId,
2233
1857
  pagination,
2234
1858
  entityId,
@@ -2249,24 +1873,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2249
1873
  allScores = allScores.filter((score) => score.source === source);
2250
1874
  }
2251
1875
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2252
- const startIndex = pagination.page * pagination.perPage;
2253
- const endIndex = startIndex + pagination.perPage;
2254
- 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);
2255
1879
  const total = allScores.length;
2256
- const hasMore = endIndex < total;
1880
+ const end = perPageInput === false ? allScores.length : start + perPage;
1881
+ const paginatedScores = allScores.slice(start, end);
2257
1882
  return {
2258
1883
  scores: paginatedScores,
2259
1884
  pagination: {
2260
1885
  total,
2261
- page: pagination.page,
2262
- perPage: pagination.perPage,
2263
- hasMore
1886
+ page,
1887
+ perPage: perPageForResponse,
1888
+ hasMore: end < total
2264
1889
  }
2265
1890
  };
2266
1891
  } catch (error) {
2267
1892
  throw new MastraError(
2268
1893
  {
2269
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SCORER_ID_FAILED",
1894
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SCORER_ID", "FAILED"),
2270
1895
  domain: ErrorDomain.STORAGE,
2271
1896
  category: ErrorCategory.THIRD_PARTY,
2272
1897
  details: {
@@ -2282,7 +1907,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2282
1907
  );
2283
1908
  }
2284
1909
  }
2285
- async getScoresByRunId({
1910
+ async listScoresByRunId({
2286
1911
  runId,
2287
1912
  pagination
2288
1913
  }) {
@@ -2292,24 +1917,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2292
1917
  const results = await query.go();
2293
1918
  const allScores = results.data.map((data) => this.parseScoreData(data));
2294
1919
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2295
- const startIndex = pagination.page * pagination.perPage;
2296
- const endIndex = startIndex + pagination.perPage;
2297
- 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);
2298
1923
  const total = allScores.length;
2299
- const hasMore = endIndex < total;
1924
+ const end = perPageInput === false ? allScores.length : start + perPage;
1925
+ const paginatedScores = allScores.slice(start, end);
2300
1926
  return {
2301
1927
  scores: paginatedScores,
2302
1928
  pagination: {
2303
1929
  total,
2304
- page: pagination.page,
2305
- perPage: pagination.perPage,
2306
- hasMore
1930
+ page,
1931
+ perPage: perPageForResponse,
1932
+ hasMore: end < total
2307
1933
  }
2308
1934
  };
2309
1935
  } catch (error) {
2310
1936
  throw new MastraError(
2311
1937
  {
2312
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_RUN_ID_FAILED",
1938
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_RUN_ID", "FAILED"),
2313
1939
  domain: ErrorDomain.STORAGE,
2314
1940
  category: ErrorCategory.THIRD_PARTY,
2315
1941
  details: { runId, page: pagination.page, perPage: pagination.perPage }
@@ -2318,7 +1944,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2318
1944
  );
2319
1945
  }
2320
1946
  }
2321
- async getScoresByEntityId({
1947
+ async listScoresByEntityId({
2322
1948
  entityId,
2323
1949
  entityType,
2324
1950
  pagination
@@ -2330,24 +1956,25 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2330
1956
  let allScores = results.data.map((data) => this.parseScoreData(data));
2331
1957
  allScores = allScores.filter((score) => score.entityType === entityType);
2332
1958
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2333
- const startIndex = pagination.page * pagination.perPage;
2334
- const endIndex = startIndex + pagination.perPage;
2335
- 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);
2336
1962
  const total = allScores.length;
2337
- const hasMore = endIndex < total;
1963
+ const end = perPageInput === false ? allScores.length : start + perPage;
1964
+ const paginatedScores = allScores.slice(start, end);
2338
1965
  return {
2339
1966
  scores: paginatedScores,
2340
1967
  pagination: {
2341
1968
  total,
2342
- page: pagination.page,
2343
- perPage: pagination.perPage,
2344
- hasMore
1969
+ page,
1970
+ perPage: perPageForResponse,
1971
+ hasMore: end < total
2345
1972
  }
2346
1973
  };
2347
1974
  } catch (error) {
2348
1975
  throw new MastraError(
2349
1976
  {
2350
- id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_ENTITY_ID_FAILED",
1977
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_ENTITY_ID", "FAILED"),
2351
1978
  domain: ErrorDomain.STORAGE,
2352
1979
  category: ErrorCategory.THIRD_PARTY,
2353
1980
  details: { entityId, entityType, page: pagination.page, perPage: pagination.perPage }
@@ -2356,298 +1983,162 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2356
1983
  );
2357
1984
  }
2358
1985
  }
2359
- };
2360
- var TracesStorageDynamoDB = class extends TracesStorage {
2361
- service;
2362
- operations;
2363
- constructor({ service, operations }) {
2364
- super();
2365
- this.service = service;
2366
- this.operations = operations;
2367
- }
2368
- // Trace operations
2369
- async getTraces(args) {
2370
- const { name, scope, page, perPage } = args;
2371
- this.logger.debug("Getting traces", { name, scope, page, perPage });
1986
+ async listScoresBySpan({
1987
+ traceId,
1988
+ spanId,
1989
+ pagination
1990
+ }) {
1991
+ this.logger.debug("Getting scores by span", { traceId, spanId, pagination });
2372
1992
  try {
2373
- let query;
2374
- if (name) {
2375
- query = this.service.entities.trace.query.byName({ entity: "trace", name });
2376
- } else if (scope) {
2377
- query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
2378
- } else {
2379
- this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
2380
- query = this.service.entities.trace.scan;
2381
- }
2382
- let items = [];
2383
- let cursor = null;
2384
- let pagesFetched = 0;
2385
- const startPage = page > 0 ? page : 1;
2386
- do {
2387
- const results = await query.go({ cursor, limit: perPage });
2388
- pagesFetched++;
2389
- if (pagesFetched === startPage) {
2390
- items = results.data;
2391
- break;
2392
- }
2393
- cursor = results.cursor;
2394
- if (!cursor && results.data.length > 0 && pagesFetched < startPage) {
2395
- break;
1993
+ const query = this.service.entities.score.query.bySpan({ entity: "score", traceId, spanId });
1994
+ const results = await query.go();
1995
+ const allScores = results.data.map((data) => this.parseScoreData(data));
1996
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
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);
2000
+ const total = allScores.length;
2001
+ const end = perPageInput === false ? allScores.length : start + perPage;
2002
+ const paginatedScores = allScores.slice(start, end);
2003
+ return {
2004
+ scores: paginatedScores,
2005
+ pagination: {
2006
+ total,
2007
+ page,
2008
+ perPage: perPageForResponse,
2009
+ hasMore: end < total
2396
2010
  }
2397
- } while (cursor && pagesFetched < startPage);
2398
- return items;
2011
+ };
2399
2012
  } catch (error) {
2400
2013
  throw new MastraError(
2401
2014
  {
2402
- id: "STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED",
2015
+ id: createStorageErrorId("DYNAMODB", "LIST_SCORES_BY_SPAN", "FAILED"),
2403
2016
  domain: ErrorDomain.STORAGE,
2404
- category: ErrorCategory.THIRD_PARTY
2017
+ category: ErrorCategory.THIRD_PARTY,
2018
+ details: { traceId, spanId, page: pagination.page, perPage: pagination.perPage }
2405
2019
  },
2406
2020
  error
2407
2021
  );
2408
2022
  }
2409
2023
  }
2410
- async batchTraceInsert({ records }) {
2411
- this.logger.debug("Batch inserting traces", { count: records.length });
2412
- if (!records.length) {
2413
- return;
2414
- }
2024
+ };
2025
+ function formatWorkflowRun(snapshotData) {
2026
+ return {
2027
+ workflowName: snapshotData.workflow_name,
2028
+ runId: snapshotData.run_id,
2029
+ snapshot: snapshotData.snapshot,
2030
+ createdAt: new Date(snapshotData.createdAt),
2031
+ updatedAt: new Date(snapshotData.updatedAt),
2032
+ resourceId: snapshotData.resourceId
2033
+ };
2034
+ }
2035
+ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2036
+ service;
2037
+ constructor(config) {
2038
+ super();
2039
+ this.service = resolveDynamoDBConfig(config);
2040
+ }
2041
+ async dangerouslyClearAll() {
2042
+ await deleteTableData(this.service, TABLE_WORKFLOW_SNAPSHOT);
2043
+ }
2044
+ async updateWorkflowResults({
2045
+ workflowName,
2046
+ runId,
2047
+ stepId,
2048
+ result,
2049
+ requestContext
2050
+ }) {
2415
2051
  try {
2416
- const recordsToSave = records.map((rec) => ({ entity: "trace", ...rec }));
2417
- await this.operations.batchInsert({
2418
- tableName: TABLE_TRACES,
2419
- records: recordsToSave
2420
- // Pass records with 'entity' included
2421
- });
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;
2422
2076
  } catch (error) {
2077
+ if (error instanceof MastraError) throw error;
2423
2078
  throw new MastraError(
2424
2079
  {
2425
- id: "STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED",
2080
+ id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
2426
2081
  domain: ErrorDomain.STORAGE,
2427
2082
  category: ErrorCategory.THIRD_PARTY,
2428
- details: { count: records.length }
2083
+ details: { workflowName, runId, stepId }
2429
2084
  },
2430
2085
  error
2431
2086
  );
2432
2087
  }
2433
2088
  }
2434
- async getTracesPaginated(args) {
2435
- const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
2436
- this.logger.debug("Getting traces with pagination", { name, scope, page, perPage, attributes, filters, dateRange });
2089
+ async updateWorkflowState({
2090
+ workflowName,
2091
+ runId,
2092
+ opts
2093
+ }) {
2437
2094
  try {
2438
- let query;
2439
- if (name) {
2440
- query = this.service.entities.trace.query.byName({ entity: "trace", name });
2441
- } else if (scope) {
2442
- query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
2443
- } else {
2444
- this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
2445
- query = this.service.entities.trace.scan;
2446
- }
2447
- const results = await query.go({
2448
- order: "desc",
2449
- pages: "all"
2450
- // Get all pages to apply filtering and pagination
2451
- });
2452
- if (!results.data.length) {
2453
- return {
2454
- traces: [],
2455
- total: 0,
2456
- page,
2457
- perPage,
2458
- hasMore: false
2459
- };
2095
+ const existingSnapshot = await this.loadWorkflowSnapshot({ workflowName, runId });
2096
+ if (!existingSnapshot || !existingSnapshot.context) {
2097
+ return void 0;
2460
2098
  }
2461
- let filteredData = results.data;
2462
- if (attributes) {
2463
- filteredData = filteredData.filter((item) => {
2464
- try {
2465
- let itemAttributes = {};
2466
- if (item.attributes) {
2467
- if (typeof item.attributes === "string") {
2468
- if (item.attributes === "[object Object]") {
2469
- itemAttributes = {};
2470
- } else {
2471
- try {
2472
- itemAttributes = JSON.parse(item.attributes);
2473
- } catch {
2474
- itemAttributes = {};
2475
- }
2476
- }
2477
- } else if (typeof item.attributes === "object") {
2478
- itemAttributes = item.attributes;
2479
- }
2480
- }
2481
- return Object.entries(attributes).every(([key, value]) => itemAttributes[key] === value);
2482
- } catch (e) {
2483
- this.logger.warn("Failed to parse attributes during filtering", { item, error: e });
2484
- return false;
2485
- }
2486
- });
2487
- }
2488
- if (dateRange?.start) {
2489
- filteredData = filteredData.filter((item) => {
2490
- const itemDate = new Date(item.createdAt);
2491
- return itemDate >= dateRange.start;
2492
- });
2493
- }
2494
- if (dateRange?.end) {
2495
- filteredData = filteredData.filter((item) => {
2496
- const itemDate = new Date(item.createdAt);
2497
- return itemDate <= dateRange.end;
2498
- });
2499
- }
2500
- const total = filteredData.length;
2501
- const start = page * perPage;
2502
- const end = start + perPage;
2503
- const paginatedData = filteredData.slice(start, end);
2504
- const traces = paginatedData.map((item) => {
2505
- let attributes2;
2506
- if (item.attributes) {
2507
- if (typeof item.attributes === "string") {
2508
- if (item.attributes === "[object Object]") {
2509
- attributes2 = void 0;
2510
- } else {
2511
- try {
2512
- attributes2 = JSON.parse(item.attributes);
2513
- } catch {
2514
- attributes2 = void 0;
2515
- }
2516
- }
2517
- } else if (typeof item.attributes === "object") {
2518
- attributes2 = item.attributes;
2519
- }
2520
- }
2521
- let status;
2522
- if (item.status) {
2523
- if (typeof item.status === "string") {
2524
- try {
2525
- status = JSON.parse(item.status);
2526
- } catch {
2527
- status = void 0;
2528
- }
2529
- } else if (typeof item.status === "object") {
2530
- status = item.status;
2531
- }
2532
- }
2533
- let events;
2534
- if (item.events) {
2535
- if (typeof item.events === "string") {
2536
- try {
2537
- events = JSON.parse(item.events);
2538
- } catch {
2539
- events = void 0;
2540
- }
2541
- } else if (Array.isArray(item.events)) {
2542
- events = item.events;
2543
- }
2544
- }
2545
- let links;
2546
- if (item.links) {
2547
- if (typeof item.links === "string") {
2548
- try {
2549
- links = JSON.parse(item.links);
2550
- } catch {
2551
- links = void 0;
2552
- }
2553
- } else if (Array.isArray(item.links)) {
2554
- links = item.links;
2555
- }
2556
- }
2557
- return {
2558
- id: item.id,
2559
- parentSpanId: item.parentSpanId,
2560
- name: item.name,
2561
- traceId: item.traceId,
2562
- scope: item.scope,
2563
- kind: item.kind,
2564
- attributes: attributes2,
2565
- status,
2566
- events,
2567
- links,
2568
- other: item.other,
2569
- startTime: item.startTime,
2570
- endTime: item.endTime,
2571
- createdAt: item.createdAt
2572
- };
2573
- });
2574
- return {
2575
- traces,
2576
- total,
2577
- page,
2578
- perPage,
2579
- hasMore: end < total
2580
- };
2099
+ const updatedSnapshot = { ...existingSnapshot, ...opts };
2100
+ await this.persistWorkflowSnapshot({ workflowName, runId, snapshot: updatedSnapshot });
2101
+ return updatedSnapshot;
2581
2102
  } catch (error) {
2103
+ if (error instanceof MastraError) throw error;
2582
2104
  throw new MastraError(
2583
2105
  {
2584
- id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
2106
+ id: createStorageErrorId("DYNAMODB", "UPDATE_WORKFLOW_STATE", "FAILED"),
2585
2107
  domain: ErrorDomain.STORAGE,
2586
- category: ErrorCategory.THIRD_PARTY
2108
+ category: ErrorCategory.THIRD_PARTY,
2109
+ details: { workflowName, runId }
2587
2110
  },
2588
2111
  error
2589
2112
  );
2590
2113
  }
2591
2114
  }
2592
- };
2593
- function formatWorkflowRun(snapshotData) {
2594
- return {
2595
- workflowName: snapshotData.workflow_name,
2596
- runId: snapshotData.run_id,
2597
- snapshot: snapshotData.snapshot,
2598
- createdAt: new Date(snapshotData.createdAt),
2599
- updatedAt: new Date(snapshotData.updatedAt),
2600
- resourceId: snapshotData.resourceId
2601
- };
2602
- }
2603
- var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2604
- service;
2605
- constructor({ service }) {
2606
- super();
2607
- this.service = service;
2608
- }
2609
- updateWorkflowResults({
2610
- // workflowName,
2611
- // runId,
2612
- // stepId,
2613
- // result,
2614
- // runtimeContext,
2615
- }) {
2616
- throw new Error("Method not implemented.");
2617
- }
2618
- updateWorkflowState({
2619
- // workflowName,
2620
- // runId,
2621
- // opts,
2622
- }) {
2623
- throw new Error("Method not implemented.");
2624
- }
2625
2115
  // Workflow operations
2626
2116
  async persistWorkflowSnapshot({
2627
2117
  workflowName,
2628
2118
  runId,
2629
- snapshot
2119
+ resourceId,
2120
+ snapshot,
2121
+ createdAt,
2122
+ updatedAt
2630
2123
  }) {
2631
2124
  this.logger.debug("Persisting workflow snapshot", { workflowName, runId });
2632
2125
  try {
2633
- const resourceId = "resourceId" in snapshot ? snapshot.resourceId : void 0;
2634
- const now = (/* @__PURE__ */ new Date()).toISOString();
2126
+ const now = /* @__PURE__ */ new Date();
2635
2127
  const data = {
2636
2128
  entity: "workflow_snapshot",
2637
2129
  // Add entity type
2638
2130
  workflow_name: workflowName,
2639
2131
  run_id: runId,
2640
2132
  snapshot: JSON.stringify(snapshot),
2641
- // Stringify the snapshot object
2642
- createdAt: now,
2643
- updatedAt: now,
2133
+ createdAt: (createdAt ?? now).toISOString(),
2134
+ updatedAt: (updatedAt ?? now).toISOString(),
2644
2135
  resourceId
2645
2136
  };
2646
2137
  await this.service.entities.workflow_snapshot.upsert(data).go();
2647
2138
  } catch (error) {
2648
2139
  throw new MastraError(
2649
2140
  {
2650
- id: "STORAGE_DYNAMODB_STORE_PERSIST_WORKFLOW_SNAPSHOT_FAILED",
2141
+ id: createStorageErrorId("DYNAMODB", "PERSIST_WORKFLOW_SNAPSHOT", "FAILED"),
2651
2142
  domain: ErrorDomain.STORAGE,
2652
2143
  category: ErrorCategory.THIRD_PARTY,
2653
2144
  details: { workflowName, runId }
@@ -2675,7 +2166,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2675
2166
  } catch (error) {
2676
2167
  throw new MastraError(
2677
2168
  {
2678
- id: "STORAGE_DYNAMODB_STORE_LOAD_WORKFLOW_SNAPSHOT_FAILED",
2169
+ id: createStorageErrorId("DYNAMODB", "LOAD_WORKFLOW_SNAPSHOT", "FAILED"),
2679
2170
  domain: ErrorDomain.STORAGE,
2680
2171
  category: ErrorCategory.THIRD_PARTY,
2681
2172
  details: { workflowName, runId }
@@ -2684,11 +2175,24 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2684
2175
  );
2685
2176
  }
2686
2177
  }
2687
- async getWorkflowRuns(args) {
2178
+ async listWorkflowRuns(args) {
2688
2179
  this.logger.debug("Getting workflow runs", { args });
2689
2180
  try {
2690
- const limit = args?.limit || 10;
2691
- 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;
2692
2196
  let query;
2693
2197
  if (args?.workflowName) {
2694
2198
  query = this.service.entities.workflow_snapshot.query.primary({
@@ -2710,6 +2214,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2710
2214
  });
2711
2215
  if (pageResults.data && pageResults.data.length > 0) {
2712
2216
  let pageFilteredData = pageResults.data;
2217
+ if (args?.status) {
2218
+ pageFilteredData = pageFilteredData.filter((snapshot) => {
2219
+ return snapshot.snapshot.status === args.status;
2220
+ });
2221
+ }
2713
2222
  if (args?.fromDate || args?.toDate) {
2714
2223
  pageFilteredData = pageFilteredData.filter((snapshot) => {
2715
2224
  const createdAt = new Date(snapshot.createdAt);
@@ -2735,7 +2244,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2735
2244
  return { runs: [], total: 0 };
2736
2245
  }
2737
2246
  const total = allMatchingSnapshots.length;
2738
- const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
2247
+ const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
2739
2248
  const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
2740
2249
  return {
2741
2250
  runs,
@@ -2744,7 +2253,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2744
2253
  } catch (error) {
2745
2254
  throw new MastraError(
2746
2255
  {
2747
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2256
+ id: createStorageErrorId("DYNAMODB", "LIST_WORKFLOW_RUNS", "FAILED"),
2748
2257
  domain: ErrorDomain.STORAGE,
2749
2258
  category: ErrorCategory.THIRD_PARTY,
2750
2259
  details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
@@ -2756,8 +2265,6 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2756
2265
  async getWorkflowRunById(args) {
2757
2266
  const { runId, workflowName } = args;
2758
2267
  this.logger.debug("Getting workflow run by ID", { runId, workflowName });
2759
- console.log("workflowName", workflowName);
2760
- console.log("runId", runId);
2761
2268
  try {
2762
2269
  if (workflowName) {
2763
2270
  this.logger.debug("WorkflowName provided, using direct GET operation.");
@@ -2767,7 +2274,6 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2767
2274
  workflow_name: workflowName,
2768
2275
  run_id: runId
2769
2276
  }).go();
2770
- console.log("result", result2);
2771
2277
  if (!result2.data) {
2772
2278
  return null;
2773
2279
  }
@@ -2801,7 +2307,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2801
2307
  } catch (error) {
2802
2308
  throw new MastraError(
2803
2309
  {
2804
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
2310
+ id: createStorageErrorId("DYNAMODB", "GET_WORKFLOW_RUN_BY_ID", "FAILED"),
2805
2311
  domain: ErrorDomain.STORAGE,
2806
2312
  category: ErrorCategory.THIRD_PARTY,
2807
2313
  details: { runId, workflowName: args?.workflowName || "" }
@@ -2810,9 +2316,32 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2810
2316
  );
2811
2317
  }
2812
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
+ }
2813
2339
  };
2814
2340
 
2815
2341
  // src/storage/index.ts
2342
+ var isClientConfig = (config) => {
2343
+ return "client" in config;
2344
+ };
2816
2345
  var DynamoDBStore = class extends MastraStorage {
2817
2346
  tableName;
2818
2347
  client;
@@ -2820,7 +2349,7 @@ var DynamoDBStore = class extends MastraStorage {
2820
2349
  hasInitialized = null;
2821
2350
  stores;
2822
2351
  constructor({ name, config }) {
2823
- super({ name });
2352
+ super({ id: config.id, name, disableInit: config.disableInit });
2824
2353
  try {
2825
2354
  if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
2826
2355
  throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
@@ -2830,27 +2359,23 @@ var DynamoDBStore = class extends MastraStorage {
2830
2359
  `DynamoDBStore: config.tableName "${config.tableName}" contains invalid characters or is not between 3 and 255 characters long.`
2831
2360
  );
2832
2361
  }
2833
- const dynamoClient = new DynamoDBClient({
2834
- region: config.region || "us-east-1",
2835
- endpoint: config.endpoint,
2836
- credentials: config.credentials
2837
- });
2838
2362
  this.tableName = config.tableName;
2839
- 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
+ }
2840
2373
  this.service = getElectroDbService(this.client, this.tableName);
2841
- const operations = new StoreOperationsDynamoDB({
2842
- service: this.service,
2843
- tableName: this.tableName,
2844
- client: this.client
2845
- });
2846
- const traces = new TracesStorageDynamoDB({ service: this.service, operations });
2847
- const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2848
- const memory = new MemoryStorageDynamoDB({ service: this.service });
2849
- 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);
2850
2378
  this.stores = {
2851
- operations,
2852
- legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
2853
- traces,
2854
2379
  workflows,
2855
2380
  memory,
2856
2381
  scores
@@ -2858,7 +2383,7 @@ var DynamoDBStore = class extends MastraStorage {
2858
2383
  } catch (error) {
2859
2384
  throw new MastraError(
2860
2385
  {
2861
- id: "STORAGE_DYNAMODB_STORE_CONSTRUCTOR_FAILED",
2386
+ id: createStorageErrorId("DYNAMODB", "CONSTRUCTOR", "FAILED"),
2862
2387
  domain: ErrorDomain.STORAGE,
2863
2388
  category: ErrorCategory.USER
2864
2389
  },
@@ -2866,15 +2391,6 @@ var DynamoDBStore = class extends MastraStorage {
2866
2391
  );
2867
2392
  }
2868
2393
  }
2869
- get supports() {
2870
- return {
2871
- selectByIncludeResourceScope: true,
2872
- resourceWorkingMemory: true,
2873
- hasColumn: false,
2874
- createTable: false,
2875
- deleteMessages: false
2876
- };
2877
- }
2878
2394
  /**
2879
2395
  * Validates that the required DynamoDB table exists and is accessible.
2880
2396
  * This does not check the table structure - it assumes the table
@@ -2893,7 +2409,7 @@ var DynamoDBStore = class extends MastraStorage {
2893
2409
  }
2894
2410
  throw new MastraError(
2895
2411
  {
2896
- id: "STORAGE_DYNAMODB_STORE_VALIDATE_TABLE_EXISTS_FAILED",
2412
+ id: createStorageErrorId("DYNAMODB", "VALIDATE_TABLE_EXISTS", "FAILED"),
2897
2413
  domain: ErrorDomain.STORAGE,
2898
2414
  category: ErrorCategory.THIRD_PARTY,
2899
2415
  details: { tableName: this.tableName }
@@ -2916,7 +2432,7 @@ var DynamoDBStore = class extends MastraStorage {
2916
2432
  } catch (error) {
2917
2433
  throw new MastraError(
2918
2434
  {
2919
- id: "STORAGE_DYNAMODB_STORE_INIT_FAILED",
2435
+ id: createStorageErrorId("DYNAMODB", "INIT", "FAILED"),
2920
2436
  domain: ErrorDomain.STORAGE,
2921
2437
  category: ErrorCategory.THIRD_PARTY,
2922
2438
  details: { tableName: this.tableName }
@@ -2942,142 +2458,10 @@ var DynamoDBStore = class extends MastraStorage {
2942
2458
  throw err;
2943
2459
  });
2944
2460
  }
2945
- async createTable({ tableName, schema }) {
2946
- return this.stores.operations.createTable({ tableName, schema });
2947
- }
2948
- async alterTable(_args) {
2949
- return this.stores.operations.alterTable(_args);
2950
- }
2951
- async clearTable({ tableName }) {
2952
- return this.stores.operations.clearTable({ tableName });
2953
- }
2954
- async dropTable({ tableName }) {
2955
- return this.stores.operations.dropTable({ tableName });
2956
- }
2957
- async insert({ tableName, record }) {
2958
- return this.stores.operations.insert({ tableName, record });
2959
- }
2960
- async batchInsert({ tableName, records }) {
2961
- return this.stores.operations.batchInsert({ tableName, records });
2962
- }
2963
- async load({ tableName, keys }) {
2964
- return this.stores.operations.load({ tableName, keys });
2965
- }
2966
- // Thread operations
2967
- async getThreadById({ threadId }) {
2968
- return this.stores.memory.getThreadById({ threadId });
2969
- }
2970
- async getThreadsByResourceId(args) {
2971
- return this.stores.memory.getThreadsByResourceId(args);
2972
- }
2973
- async saveThread({ thread }) {
2974
- return this.stores.memory.saveThread({ thread });
2975
- }
2976
- async updateThread({
2977
- id,
2978
- title,
2979
- metadata
2980
- }) {
2981
- return this.stores.memory.updateThread({ id, title, metadata });
2982
- }
2983
- async deleteThread({ threadId }) {
2984
- return this.stores.memory.deleteThread({ threadId });
2985
- }
2986
- async getMessages({
2987
- threadId,
2988
- resourceId,
2989
- selectBy,
2990
- format
2991
- }) {
2992
- return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2993
- }
2994
- async getMessagesById({
2995
- messageIds,
2996
- format
2997
- }) {
2998
- return this.stores.memory.getMessagesById({ messageIds, format });
2999
- }
3000
- async saveMessages(args) {
3001
- return this.stores.memory.saveMessages(args);
3002
- }
3003
- async getThreadsByResourceIdPaginated(args) {
3004
- return this.stores.memory.getThreadsByResourceIdPaginated(args);
3005
- }
3006
- async getMessagesPaginated(args) {
3007
- return this.stores.memory.getMessagesPaginated(args);
3008
- }
3009
- async updateMessages(_args) {
3010
- return this.stores.memory.updateMessages(_args);
3011
- }
3012
- // Trace operations
3013
- async getTraces(args) {
3014
- return this.stores.traces.getTraces(args);
3015
- }
3016
- async batchTraceInsert({ records }) {
3017
- return this.stores.traces.batchTraceInsert({ records });
3018
- }
3019
- async getTracesPaginated(_args) {
3020
- return this.stores.traces.getTracesPaginated(_args);
3021
- }
3022
- // Workflow operations
3023
- async updateWorkflowResults({
3024
- workflowName,
3025
- runId,
3026
- stepId,
3027
- result,
3028
- runtimeContext
3029
- }) {
3030
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
3031
- }
3032
- async updateWorkflowState({
3033
- workflowName,
3034
- runId,
3035
- opts
3036
- }) {
3037
- return this.stores.workflows.updateWorkflowState({ workflowName, runId, opts });
3038
- }
3039
- async persistWorkflowSnapshot({
3040
- workflowName,
3041
- runId,
3042
- snapshot
3043
- }) {
3044
- return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
3045
- }
3046
- async loadWorkflowSnapshot({
3047
- workflowName,
3048
- runId
3049
- }) {
3050
- return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
3051
- }
3052
- async getWorkflowRuns(args) {
3053
- return this.stores.workflows.getWorkflowRuns(args);
3054
- }
3055
- async getWorkflowRunById(args) {
3056
- return this.stores.workflows.getWorkflowRunById(args);
3057
- }
3058
- async getResourceById({ resourceId }) {
3059
- return this.stores.memory.getResourceById({ resourceId });
3060
- }
3061
- async saveResource({ resource }) {
3062
- return this.stores.memory.saveResource({ resource });
3063
- }
3064
- async updateResource({
3065
- resourceId,
3066
- workingMemory,
3067
- metadata
3068
- }) {
3069
- return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
3070
- }
3071
- // Eval operations
3072
- async getEvalsByAgentName(agentName, type) {
3073
- return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
3074
- }
3075
- async getEvals(options) {
3076
- return this.stores.legacyEvals.getEvals(options);
3077
- }
3078
2461
  /**
3079
2462
  * Closes the DynamoDB client connection and cleans up resources.
3080
- * 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.
3081
2465
  */
3082
2466
  async close() {
3083
2467
  this.logger.debug("Closing DynamoDB client for store:", { name: this.name });
@@ -3087,7 +2471,7 @@ var DynamoDBStore = class extends MastraStorage {
3087
2471
  } catch (error) {
3088
2472
  throw new MastraError(
3089
2473
  {
3090
- id: "STORAGE_DYNAMODB_STORE_CLOSE_FAILED",
2474
+ id: createStorageErrorId("DYNAMODB", "CLOSE", "FAILED"),
3091
2475
  domain: ErrorDomain.STORAGE,
3092
2476
  category: ErrorCategory.THIRD_PARTY
3093
2477
  },
@@ -3095,43 +2479,8 @@ var DynamoDBStore = class extends MastraStorage {
3095
2479
  );
3096
2480
  }
3097
2481
  }
3098
- /**
3099
- * SCORERS - Not implemented
3100
- */
3101
- async getScoreById({ id: _id }) {
3102
- return this.stores.scores.getScoreById({ id: _id });
3103
- }
3104
- async saveScore(_score) {
3105
- return this.stores.scores.saveScore(_score);
3106
- }
3107
- async getScoresByRunId({
3108
- runId: _runId,
3109
- pagination: _pagination
3110
- }) {
3111
- return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
3112
- }
3113
- async getScoresByEntityId({
3114
- entityId: _entityId,
3115
- entityType: _entityType,
3116
- pagination: _pagination
3117
- }) {
3118
- return this.stores.scores.getScoresByEntityId({
3119
- entityId: _entityId,
3120
- entityType: _entityType,
3121
- pagination: _pagination
3122
- });
3123
- }
3124
- async getScoresByScorerId({
3125
- scorerId,
3126
- source,
3127
- entityId,
3128
- entityType,
3129
- pagination
3130
- }) {
3131
- return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
3132
- }
3133
2482
  };
3134
2483
 
3135
- export { DynamoDBStore };
2484
+ export { DynamoDBStore, MemoryStorageDynamoDB, ScoresStorageDynamoDB, WorkflowStorageDynamoDB };
3136
2485
  //# sourceMappingURL=index.js.map
3137
2486
  //# sourceMappingURL=index.js.map