@mastra/dynamodb 0.0.0-netlify-no-bundle-20251127120354 → 0.0.0-partial-response-backport-20251204204441

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { DynamoDBClient, DescribeTableCommand } from '@aws-sdk/client-dynamodb';
2
2
  import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
3
3
  import { MastraError, ErrorCategory, ErrorDomain } from '@mastra/core/error';
4
- import { MastraStorage, StoreOperations, WorkflowsStorage, normalizePerPage, MemoryStorage, calculatePagination, ScoresStorage, SCORERS_SCHEMA, TABLE_SPANS, TABLE_RESOURCES, TABLE_TRACES, TABLE_SCORERS, TABLE_WORKFLOW_SNAPSHOT, TABLE_MESSAGES, TABLE_THREADS } from '@mastra/core/storage';
4
+ import { MastraStorage, StoreOperations, TracesStorage, TABLE_TRACES, WorkflowsStorage, MemoryStorage, resolveMessageLimit, ScoresStorage, SCORERS_SCHEMA, LegacyEvalsStorage, TABLE_AI_SPANS, TABLE_RESOURCES, TABLE_SCORERS, TABLE_EVALS, TABLE_WORKFLOW_SNAPSHOT, 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
+ import { saveScorePayloadSchema } from '@mastra/core/scores';
8
8
 
9
9
  // src/storage/index.ts
10
10
 
@@ -566,7 +566,7 @@ var scoreEntity = new Entity({
566
566
  return value;
567
567
  }
568
568
  },
569
- requestContext: {
569
+ runtimeContext: {
570
570
  type: "string",
571
571
  required: false,
572
572
  set: (value) => {
@@ -937,6 +937,187 @@ function getElectroDbService(client, tableName) {
937
937
  }
938
938
  );
939
939
  }
940
+ var LegacyEvalsDynamoDB = class extends LegacyEvalsStorage {
941
+ service;
942
+ tableName;
943
+ constructor({ service, tableName }) {
944
+ super();
945
+ this.service = service;
946
+ this.tableName = tableName;
947
+ }
948
+ // Eval operations
949
+ async getEvalsByAgentName(agentName, type) {
950
+ this.logger.debug("Getting evals for agent", { agentName, type });
951
+ try {
952
+ const query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
953
+ const results = await query.go({ order: "desc", limit: 100 });
954
+ if (!results.data.length) {
955
+ return [];
956
+ }
957
+ let filteredData = results.data;
958
+ if (type) {
959
+ filteredData = filteredData.filter((evalRecord) => {
960
+ try {
961
+ const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
962
+ if (type === "test" && !testInfo) {
963
+ return false;
964
+ }
965
+ if (type === "live" && testInfo) {
966
+ return false;
967
+ }
968
+ } catch (e) {
969
+ this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
970
+ }
971
+ return true;
972
+ });
973
+ }
974
+ return filteredData.map((evalRecord) => {
975
+ try {
976
+ return {
977
+ input: evalRecord.input,
978
+ output: evalRecord.output,
979
+ // Safely parse result and test_info
980
+ result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
981
+ agentName: evalRecord.agent_name,
982
+ createdAt: evalRecord.created_at,
983
+ // Keep as string from DDB?
984
+ metricName: evalRecord.metric_name,
985
+ instructions: evalRecord.instructions,
986
+ runId: evalRecord.run_id,
987
+ globalRunId: evalRecord.global_run_id,
988
+ testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
989
+ };
990
+ } catch (parseError) {
991
+ this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
992
+ return {
993
+ agentName: evalRecord.agent_name,
994
+ createdAt: evalRecord.created_at,
995
+ runId: evalRecord.run_id,
996
+ globalRunId: evalRecord.global_run_id
997
+ };
998
+ }
999
+ });
1000
+ } catch (error) {
1001
+ throw new MastraError(
1002
+ {
1003
+ id: "STORAGE_DYNAMODB_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
1004
+ domain: ErrorDomain.STORAGE,
1005
+ category: ErrorCategory.THIRD_PARTY,
1006
+ details: { agentName }
1007
+ },
1008
+ error
1009
+ );
1010
+ }
1011
+ }
1012
+ async getEvals(options = {}) {
1013
+ const { agentName, type, page = 0, perPage = 100, dateRange } = options;
1014
+ this.logger.debug("Getting evals with pagination", { agentName, type, page, perPage, dateRange });
1015
+ try {
1016
+ let query;
1017
+ if (agentName) {
1018
+ query = this.service.entities.eval.query.byAgent({ entity: "eval", agent_name: agentName });
1019
+ } else {
1020
+ query = this.service.entities.eval.query.byEntity({ entity: "eval" });
1021
+ }
1022
+ const results = await query.go({
1023
+ order: "desc",
1024
+ pages: "all"
1025
+ // Get all pages to apply filtering and pagination
1026
+ });
1027
+ if (!results.data.length) {
1028
+ return {
1029
+ evals: [],
1030
+ total: 0,
1031
+ page,
1032
+ perPage,
1033
+ hasMore: false
1034
+ };
1035
+ }
1036
+ let filteredData = results.data;
1037
+ if (type) {
1038
+ filteredData = filteredData.filter((evalRecord) => {
1039
+ try {
1040
+ const testInfo = evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0;
1041
+ if (type === "test" && !testInfo) {
1042
+ return false;
1043
+ }
1044
+ if (type === "live" && testInfo) {
1045
+ return false;
1046
+ }
1047
+ } catch (e) {
1048
+ this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
1049
+ }
1050
+ return true;
1051
+ });
1052
+ }
1053
+ if (dateRange) {
1054
+ const fromDate = dateRange.start;
1055
+ const toDate = dateRange.end;
1056
+ filteredData = filteredData.filter((evalRecord) => {
1057
+ const recordDate = new Date(evalRecord.created_at);
1058
+ if (fromDate && recordDate < fromDate) {
1059
+ return false;
1060
+ }
1061
+ if (toDate && recordDate > toDate) {
1062
+ return false;
1063
+ }
1064
+ return true;
1065
+ });
1066
+ }
1067
+ const total = filteredData.length;
1068
+ const start = page * perPage;
1069
+ const end = start + perPage;
1070
+ const paginatedData = filteredData.slice(start, end);
1071
+ const evals = paginatedData.map((evalRecord) => {
1072
+ try {
1073
+ return {
1074
+ input: evalRecord.input,
1075
+ output: evalRecord.output,
1076
+ result: evalRecord.result && typeof evalRecord.result === "string" ? JSON.parse(evalRecord.result) : void 0,
1077
+ agentName: evalRecord.agent_name,
1078
+ createdAt: evalRecord.created_at,
1079
+ metricName: evalRecord.metric_name,
1080
+ instructions: evalRecord.instructions,
1081
+ runId: evalRecord.run_id,
1082
+ globalRunId: evalRecord.global_run_id,
1083
+ testInfo: evalRecord.test_info && typeof evalRecord.test_info === "string" ? JSON.parse(evalRecord.test_info) : void 0
1084
+ };
1085
+ } catch (parseError) {
1086
+ this.logger.error("Failed to parse eval record", { record: evalRecord, error: parseError });
1087
+ return {
1088
+ agentName: evalRecord.agent_name,
1089
+ createdAt: evalRecord.created_at,
1090
+ runId: evalRecord.run_id,
1091
+ globalRunId: evalRecord.global_run_id
1092
+ };
1093
+ }
1094
+ });
1095
+ const hasMore = end < total;
1096
+ return {
1097
+ evals,
1098
+ total,
1099
+ page,
1100
+ perPage,
1101
+ hasMore
1102
+ };
1103
+ } catch (error) {
1104
+ throw new MastraError(
1105
+ {
1106
+ id: "STORAGE_DYNAMODB_STORE_GET_EVALS_FAILED",
1107
+ domain: ErrorDomain.STORAGE,
1108
+ category: ErrorCategory.THIRD_PARTY,
1109
+ details: {
1110
+ agentName: agentName || "all",
1111
+ type: type || "all",
1112
+ page,
1113
+ perPage
1114
+ }
1115
+ },
1116
+ error
1117
+ );
1118
+ }
1119
+ }
1120
+ };
940
1121
  var MemoryStorageDynamoDB = class extends MemoryStorage {
941
1122
  service;
942
1123
  constructor({ service }) {
@@ -955,17 +1136,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
955
1136
  };
956
1137
  }
957
1138
  // Helper function to transform and sort threads
958
- transformAndSortThreads(rawThreads, field, direction) {
1139
+ transformAndSortThreads(rawThreads, orderBy, sortDirection) {
959
1140
  return rawThreads.map((data) => ({
960
1141
  ...data,
961
1142
  // Convert date strings back to Date objects for consistency
962
1143
  createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
963
1144
  updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
964
1145
  })).sort((a, b) => {
965
- const fieldA = field === "createdAt" ? a.createdAt : a.updatedAt;
966
- const fieldB = field === "createdAt" ? b.createdAt : b.updatedAt;
1146
+ const fieldA = orderBy === "createdAt" ? a.createdAt : a.updatedAt;
1147
+ const fieldB = orderBy === "createdAt" ? b.createdAt : b.updatedAt;
967
1148
  const comparison = fieldA.getTime() - fieldB.getTime();
968
- return direction === "DESC" ? -comparison : comparison;
1149
+ return sortDirection === "DESC" ? -comparison : comparison;
969
1150
  });
970
1151
  }
971
1152
  async getThreadById({ threadId }) {
@@ -996,6 +1177,32 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
996
1177
  );
997
1178
  }
998
1179
  }
1180
+ /**
1181
+ * @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
1182
+ */
1183
+ async getThreadsByResourceId(args) {
1184
+ const resourceId = args.resourceId;
1185
+ const orderBy = this.castThreadOrderBy(args.orderBy);
1186
+ const sortDirection = this.castThreadSortDirection(args.sortDirection);
1187
+ this.logger.debug("Getting threads by resource ID", { resourceId, orderBy, sortDirection });
1188
+ try {
1189
+ const result = await this.service.entities.thread.query.byResource({ entity: "thread", resourceId }).go();
1190
+ if (!result.data.length) {
1191
+ return [];
1192
+ }
1193
+ return this.transformAndSortThreads(result.data, orderBy, sortDirection);
1194
+ } catch (error) {
1195
+ throw new MastraError(
1196
+ {
1197
+ id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
1198
+ domain: ErrorDomain.STORAGE,
1199
+ category: ErrorCategory.THIRD_PARTY,
1200
+ details: { resourceId }
1201
+ },
1202
+ error
1203
+ );
1204
+ }
1205
+ }
999
1206
  async saveThread({ thread }) {
1000
1207
  this.logger.debug("Saving thread", { threadId: thread.id });
1001
1208
  const now = /* @__PURE__ */ new Date();
@@ -1015,7 +1222,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1015
1222
  resourceId: thread.resourceId,
1016
1223
  title: threadData.title,
1017
1224
  createdAt: thread.createdAt || now,
1018
- updatedAt: thread.updatedAt || now,
1225
+ updatedAt: now,
1019
1226
  metadata: thread.metadata
1020
1227
  };
1021
1228
  } catch (error) {
@@ -1075,7 +1282,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1075
1282
  async deleteThread({ threadId }) {
1076
1283
  this.logger.debug("Deleting thread", { threadId });
1077
1284
  try {
1078
- const { messages } = await this.listMessages({ threadId, perPage: false });
1285
+ const messages = await this.getMessages({ threadId });
1079
1286
  if (messages.length > 0) {
1080
1287
  const batchSize = 25;
1081
1288
  for (let i = 0; i < messages.length; i += batchSize) {
@@ -1104,175 +1311,104 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1104
1311
  );
1105
1312
  }
1106
1313
  }
1107
- async listMessagesById({ messageIds }) {
1108
- this.logger.debug("Getting messages by ID", { messageIds });
1109
- if (messageIds.length === 0) return { messages: [] };
1314
+ async getMessages({
1315
+ threadId,
1316
+ resourceId,
1317
+ selectBy,
1318
+ format
1319
+ }) {
1320
+ this.logger.debug("Getting messages", { threadId, selectBy });
1110
1321
  try {
1111
- const results = await Promise.all(
1112
- messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1113
- );
1114
- const data = results.map((result) => result.data).flat(1);
1115
- let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1116
- const uniqueMessages = parsedMessages.filter(
1322
+ if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1323
+ const messages = [];
1324
+ const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1325
+ if (selectBy?.include?.length) {
1326
+ const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1327
+ if (includeMessages) {
1328
+ messages.push(...includeMessages);
1329
+ }
1330
+ }
1331
+ if (limit !== 0) {
1332
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1333
+ let results;
1334
+ if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1335
+ results = await query.go({ limit, order: "desc" });
1336
+ results.data = results.data.reverse();
1337
+ } else {
1338
+ results = await query.go();
1339
+ }
1340
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1341
+ allThreadMessages.sort((a, b) => {
1342
+ const timeA = a.createdAt.getTime();
1343
+ const timeB = b.createdAt.getTime();
1344
+ if (timeA === timeB) {
1345
+ return a.id.localeCompare(b.id);
1346
+ }
1347
+ return timeA - timeB;
1348
+ });
1349
+ messages.push(...allThreadMessages);
1350
+ }
1351
+ messages.sort((a, b) => {
1352
+ const timeA = a.createdAt.getTime();
1353
+ const timeB = b.createdAt.getTime();
1354
+ if (timeA === timeB) {
1355
+ return a.id.localeCompare(b.id);
1356
+ }
1357
+ return timeA - timeB;
1358
+ });
1359
+ const uniqueMessages = messages.filter(
1117
1360
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1118
1361
  );
1119
- const list = new MessageList().add(uniqueMessages, "memory");
1120
- return { messages: list.get.all.db() };
1362
+ const list = new MessageList({ threadId, resourceId }).add(uniqueMessages, "memory");
1363
+ if (format === `v2`) return list.get.all.v2();
1364
+ return list.get.all.v1();
1121
1365
  } catch (error) {
1122
1366
  throw new MastraError(
1123
1367
  {
1124
- id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_BY_ID_FAILED",
1368
+ id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED",
1125
1369
  domain: ErrorDomain.STORAGE,
1126
1370
  category: ErrorCategory.THIRD_PARTY,
1127
- details: { messageIds: JSON.stringify(messageIds) }
1371
+ details: { threadId, resourceId: resourceId ?? "" }
1128
1372
  },
1129
1373
  error
1130
1374
  );
1131
1375
  }
1132
1376
  }
1133
- async listMessages(args) {
1134
- const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
1135
- if (!threadId.trim()) {
1136
- throw new MastraError(
1137
- {
1138
- id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_THREAD_ID",
1139
- domain: ErrorDomain.STORAGE,
1140
- category: ErrorCategory.THIRD_PARTY,
1141
- details: { threadId }
1142
- },
1143
- new Error("threadId must be a non-empty string")
1144
- );
1145
- }
1146
- const perPage = normalizePerPage(perPageInput, 40);
1147
- const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1377
+ async getMessagesById({
1378
+ messageIds,
1379
+ format
1380
+ }) {
1381
+ this.logger.debug("Getting messages by ID", { messageIds });
1382
+ if (messageIds.length === 0) return [];
1148
1383
  try {
1149
- if (page < 0) {
1150
- throw new MastraError(
1151
- {
1152
- id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_PAGE",
1153
- domain: ErrorDomain.STORAGE,
1154
- category: ErrorCategory.USER,
1155
- details: { page }
1156
- },
1157
- new Error("page must be >= 0")
1158
- );
1159
- }
1160
- const { field, direction } = this.parseOrderBy(orderBy, "ASC");
1161
- this.logger.debug("Getting messages with listMessages", {
1162
- threadId,
1163
- resourceId,
1164
- perPageInput,
1165
- offset,
1166
- perPage,
1167
- page,
1168
- field,
1169
- direction
1170
- });
1171
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1172
- const results = await query.go();
1173
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1174
- if (resourceId) {
1175
- allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1176
- }
1177
- if (filter?.dateRange) {
1178
- const dateRange = filter.dateRange;
1179
- allThreadMessages = allThreadMessages.filter((msg) => {
1180
- const createdAt = new Date(msg.createdAt).getTime();
1181
- if (dateRange.start) {
1182
- const startTime = dateRange.start instanceof Date ? dateRange.start.getTime() : new Date(dateRange.start).getTime();
1183
- if (createdAt < startTime) return false;
1184
- }
1185
- if (dateRange.end) {
1186
- const endTime = dateRange.end instanceof Date ? dateRange.end.getTime() : new Date(dateRange.end).getTime();
1187
- if (createdAt > endTime) return false;
1188
- }
1189
- return true;
1190
- });
1191
- }
1192
- allThreadMessages.sort((a, b) => {
1193
- const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1194
- const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1195
- if (aValue === bValue) {
1196
- return a.id.localeCompare(b.id);
1197
- }
1198
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
1199
- });
1200
- const total = allThreadMessages.length;
1201
- const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1202
- const paginatedCount = paginatedMessages.length;
1203
- if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1204
- return {
1205
- messages: [],
1206
- total: 0,
1207
- page,
1208
- perPage: perPageForResponse,
1209
- hasMore: false
1210
- };
1211
- }
1212
- const messageIds = new Set(paginatedMessages.map((m) => m.id));
1213
- let includeMessages = [];
1214
- if (include && include.length > 0) {
1215
- const selectBy = { include };
1216
- includeMessages = await this._getIncludedMessages(threadId, selectBy);
1217
- for (const includeMsg of includeMessages) {
1218
- if (!messageIds.has(includeMsg.id)) {
1219
- paginatedMessages.push(includeMsg);
1220
- messageIds.add(includeMsg.id);
1221
- }
1222
- }
1223
- }
1224
- const list = new MessageList().add(paginatedMessages, "memory");
1225
- let finalMessages = list.get.all.db();
1226
- finalMessages = finalMessages.sort((a, b) => {
1227
- const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1228
- const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1229
- if (aValue === bValue) {
1230
- return a.id.localeCompare(b.id);
1231
- }
1232
- return direction === "ASC" ? aValue - bValue : bValue - aValue;
1233
- });
1234
- const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1235
- const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1236
- let hasMore = false;
1237
- if (perPageInput !== false && !allThreadMessagesReturned) {
1238
- hasMore = offset + paginatedCount < total;
1239
- }
1240
- return {
1241
- messages: finalMessages,
1242
- total,
1243
- page,
1244
- perPage: perPageForResponse,
1245
- hasMore
1246
- };
1384
+ const results = await Promise.all(
1385
+ messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1386
+ );
1387
+ const data = results.map((result) => result.data).flat(1);
1388
+ let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1389
+ const uniqueMessages = parsedMessages.filter(
1390
+ (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1391
+ );
1392
+ const list = new MessageList().add(uniqueMessages, "memory");
1393
+ if (format === `v1`) return list.get.all.v1();
1394
+ return list.get.all.v2();
1247
1395
  } catch (error) {
1248
- const mastraError = new MastraError(
1396
+ throw new MastraError(
1249
1397
  {
1250
- id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_FAILED",
1398
+ id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_BY_ID_FAILED",
1251
1399
  domain: ErrorDomain.STORAGE,
1252
1400
  category: ErrorCategory.THIRD_PARTY,
1253
- details: {
1254
- threadId,
1255
- resourceId: resourceId ?? ""
1256
- }
1401
+ details: { messageIds: JSON.stringify(messageIds) }
1257
1402
  },
1258
1403
  error
1259
1404
  );
1260
- this.logger?.error?.(mastraError.toString());
1261
- this.logger?.trackException?.(mastraError);
1262
- return {
1263
- messages: [],
1264
- total: 0,
1265
- page,
1266
- perPage: perPageForResponse,
1267
- hasMore: false
1268
- };
1269
1405
  }
1270
1406
  }
1271
1407
  async saveMessages(args) {
1272
- const { messages } = args;
1408
+ const { messages, format = "v1" } = args;
1273
1409
  this.logger.debug("Saving messages", { count: messages.length });
1274
1410
  if (!messages.length) {
1275
- return { messages: [] };
1411
+ return [];
1276
1412
  }
1277
1413
  const threadId = messages[0]?.threadId;
1278
1414
  if (!threadId) {
@@ -1326,7 +1462,8 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1326
1462
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1327
1463
  }).go();
1328
1464
  const list = new MessageList().add(messages, "memory");
1329
- return { messages: list.get.all.db() };
1465
+ if (format === `v1`) return list.get.all.v1();
1466
+ return list.get.all.v2();
1330
1467
  } catch (error) {
1331
1468
  throw new MastraError(
1332
1469
  {
@@ -1339,48 +1476,37 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1339
1476
  );
1340
1477
  }
1341
1478
  }
1342
- async listThreadsByResourceId(args) {
1343
- const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
1344
- const perPage = normalizePerPage(perPageInput, 100);
1345
- if (page < 0) {
1346
- throw new MastraError(
1347
- {
1348
- id: "STORAGE_DYNAMODB_LIST_THREADS_BY_RESOURCE_ID_INVALID_PAGE",
1349
- domain: ErrorDomain.STORAGE,
1350
- category: ErrorCategory.USER,
1351
- details: { page }
1352
- },
1353
- new Error("page must be >= 0")
1354
- );
1355
- }
1356
- const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1357
- const { field, direction } = this.parseOrderBy(orderBy);
1479
+ async getThreadsByResourceIdPaginated(args) {
1480
+ const { resourceId, page = 0, perPage = 100 } = args;
1481
+ const orderBy = this.castThreadOrderBy(args.orderBy);
1482
+ const sortDirection = this.castThreadSortDirection(args.sortDirection);
1358
1483
  this.logger.debug("Getting threads by resource ID with pagination", {
1359
1484
  resourceId,
1360
1485
  page,
1361
1486
  perPage,
1362
- field,
1363
- direction
1487
+ orderBy,
1488
+ sortDirection
1364
1489
  });
1365
1490
  try {
1366
1491
  const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1367
1492
  const results = await query.go();
1368
- const allThreads = this.transformAndSortThreads(results.data, field, direction);
1369
- const endIndex = offset + perPage;
1370
- const paginatedThreads = allThreads.slice(offset, endIndex);
1493
+ const allThreads = this.transformAndSortThreads(results.data, orderBy, sortDirection);
1494
+ const startIndex = page * perPage;
1495
+ const endIndex = startIndex + perPage;
1496
+ const paginatedThreads = allThreads.slice(startIndex, endIndex);
1371
1497
  const total = allThreads.length;
1372
- const hasMore = offset + perPage < total;
1498
+ const hasMore = endIndex < total;
1373
1499
  return {
1374
1500
  threads: paginatedThreads,
1375
1501
  total,
1376
1502
  page,
1377
- perPage: perPageForResponse,
1503
+ perPage,
1378
1504
  hasMore
1379
1505
  };
1380
1506
  } catch (error) {
1381
1507
  throw new MastraError(
1382
1508
  {
1383
- id: "DYNAMODB_STORAGE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
1509
+ id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1384
1510
  domain: ErrorDomain.STORAGE,
1385
1511
  category: ErrorCategory.THIRD_PARTY,
1386
1512
  details: { resourceId, page, perPage }
@@ -1389,6 +1515,85 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1389
1515
  );
1390
1516
  }
1391
1517
  }
1518
+ async getMessagesPaginated(args) {
1519
+ const { threadId, resourceId, selectBy, format = "v1" } = args;
1520
+ const { page = 0, perPage = 40, dateRange } = selectBy?.pagination || {};
1521
+ const fromDate = dateRange?.start;
1522
+ const toDate = dateRange?.end;
1523
+ const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1524
+ this.logger.debug("Getting messages with pagination", { threadId, page, perPage, fromDate, toDate, limit });
1525
+ try {
1526
+ if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1527
+ let messages = [];
1528
+ if (selectBy?.include?.length) {
1529
+ const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1530
+ if (includeMessages) {
1531
+ messages.push(...includeMessages);
1532
+ }
1533
+ }
1534
+ if (limit !== 0) {
1535
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1536
+ let results;
1537
+ if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1538
+ results = await query.go({ limit, order: "desc" });
1539
+ results.data = results.data.reverse();
1540
+ } else {
1541
+ results = await query.go();
1542
+ }
1543
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1544
+ allThreadMessages.sort((a, b) => {
1545
+ const timeA = a.createdAt.getTime();
1546
+ const timeB = b.createdAt.getTime();
1547
+ if (timeA === timeB) {
1548
+ return a.id.localeCompare(b.id);
1549
+ }
1550
+ return timeA - timeB;
1551
+ });
1552
+ const excludeIds = messages.map((m) => m.id);
1553
+ if (excludeIds.length > 0) {
1554
+ allThreadMessages = allThreadMessages.filter((msg) => !excludeIds.includes(msg.id));
1555
+ }
1556
+ messages.push(...allThreadMessages);
1557
+ }
1558
+ messages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1559
+ if (fromDate || toDate) {
1560
+ messages = messages.filter((msg) => {
1561
+ const createdAt = new Date(msg.createdAt).getTime();
1562
+ if (fromDate && createdAt < new Date(fromDate).getTime()) return false;
1563
+ if (toDate && createdAt > new Date(toDate).getTime()) return false;
1564
+ return true;
1565
+ });
1566
+ }
1567
+ const total = messages.length;
1568
+ const start = page * perPage;
1569
+ const end = start + perPage;
1570
+ const paginatedMessages = messages.slice(start, end);
1571
+ const hasMore = end < total;
1572
+ const list = new MessageList({ threadId, resourceId }).add(paginatedMessages, "memory");
1573
+ let finalMessages = format === "v2" ? list.get.all.v2() : list.get.all.v1();
1574
+ finalMessages = finalMessages.sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
1575
+ return {
1576
+ messages: finalMessages,
1577
+ total,
1578
+ page,
1579
+ perPage,
1580
+ hasMore
1581
+ };
1582
+ } catch (error) {
1583
+ const mastraError = new MastraError(
1584
+ {
1585
+ id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_PAGINATED_FAILED",
1586
+ domain: ErrorDomain.STORAGE,
1587
+ category: ErrorCategory.THIRD_PARTY,
1588
+ details: { threadId, resourceId: resourceId ?? "" }
1589
+ },
1590
+ error
1591
+ );
1592
+ this.logger?.trackException?.(mastraError);
1593
+ this.logger?.error?.(mastraError.toString());
1594
+ return { messages: [], total: 0, page, perPage, hasMore: false };
1595
+ }
1596
+ }
1392
1597
  // Helper method to get included messages with context
1393
1598
  async _getIncludedMessages(threadId, selectBy) {
1394
1599
  if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
@@ -1655,10 +1860,11 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
1655
1860
  [TABLE_THREADS]: "thread",
1656
1861
  [TABLE_MESSAGES]: "message",
1657
1862
  [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1863
+ [TABLE_EVALS]: "eval",
1658
1864
  [TABLE_SCORERS]: "score",
1659
1865
  [TABLE_TRACES]: "trace",
1660
1866
  [TABLE_RESOURCES]: "resource",
1661
- [TABLE_SPANS]: "ai_span"
1867
+ [TABLE_AI_SPANS]: "ai_span"
1662
1868
  };
1663
1869
  return mapping[tableName] || null;
1664
1870
  }
@@ -1843,10 +2049,6 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
1843
2049
  if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
1844
2050
  key.id = item.id;
1845
2051
  break;
1846
- case "resource":
1847
- if (!item.id) throw new Error(`Missing required key 'id' for entity 'resource'`);
1848
- key.id = item.id;
1849
- break;
1850
2052
  default:
1851
2053
  this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
1852
2054
  throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
@@ -2013,33 +2215,35 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2013
2215
  }
2014
2216
  const now = /* @__PURE__ */ new Date();
2015
2217
  const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2016
- const scorer = typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer);
2017
- const preprocessStepResult = typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult);
2018
- const analyzeStepResult = typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult);
2019
- const input = typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input);
2020
- const output = typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output);
2021
- const requestContext = typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext);
2022
- const entity = typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity);
2023
- const scoreData = Object.fromEntries(
2024
- Object.entries({
2025
- ...validatedScore,
2026
- entity: "score",
2027
- id: scoreId,
2028
- scorer,
2029
- preprocessStepResult,
2030
- analyzeStepResult,
2031
- input,
2032
- output,
2033
- requestContext,
2034
- entityData: entity,
2035
- traceId: validatedScore.traceId || "",
2036
- resourceId: validatedScore.resourceId || "",
2037
- threadId: validatedScore.threadId || "",
2038
- spanId: validatedScore.spanId || "",
2039
- createdAt: now.toISOString(),
2040
- updatedAt: now.toISOString()
2041
- }).filter(([_, value]) => value !== void 0 && value !== null)
2042
- );
2218
+ const scoreData = {
2219
+ entity: "score",
2220
+ id: scoreId,
2221
+ scorerId: validatedScore.scorerId,
2222
+ traceId: validatedScore.traceId || "",
2223
+ spanId: validatedScore.spanId || "",
2224
+ runId: validatedScore.runId,
2225
+ scorer: typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer),
2226
+ preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult),
2227
+ analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult),
2228
+ score: validatedScore.score,
2229
+ reason: validatedScore.reason,
2230
+ preprocessPrompt: validatedScore.preprocessPrompt,
2231
+ generateScorePrompt: validatedScore.generateScorePrompt,
2232
+ generateReasonPrompt: validatedScore.generateReasonPrompt,
2233
+ analyzePrompt: validatedScore.analyzePrompt,
2234
+ input: typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input),
2235
+ output: typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output),
2236
+ additionalContext: typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : JSON.stringify(validatedScore.additionalContext),
2237
+ runtimeContext: typeof validatedScore.runtimeContext === "string" ? validatedScore.runtimeContext : JSON.stringify(validatedScore.runtimeContext),
2238
+ entityType: validatedScore.entityType,
2239
+ entityData: typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity),
2240
+ entityId: validatedScore.entityId,
2241
+ source: validatedScore.source,
2242
+ resourceId: validatedScore.resourceId || "",
2243
+ threadId: validatedScore.threadId || "",
2244
+ createdAt: now.toISOString(),
2245
+ updatedAt: now.toISOString()
2246
+ };
2043
2247
  try {
2044
2248
  await this.service.entities.score.upsert(scoreData).go();
2045
2249
  const savedScore = {
@@ -2061,7 +2265,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2061
2265
  );
2062
2266
  }
2063
2267
  }
2064
- async listScoresByScorerId({
2268
+ async getScoresByScorerId({
2065
2269
  scorerId,
2066
2270
  pagination,
2067
2271
  entityId,
@@ -2082,19 +2286,18 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2082
2286
  allScores = allScores.filter((score) => score.source === source);
2083
2287
  }
2084
2288
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2085
- const { page, perPage: perPageInput } = pagination;
2086
- const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2087
- const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2289
+ const startIndex = pagination.page * pagination.perPage;
2290
+ const endIndex = startIndex + pagination.perPage;
2291
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2088
2292
  const total = allScores.length;
2089
- const end = perPageInput === false ? allScores.length : start + perPage;
2090
- const paginatedScores = allScores.slice(start, end);
2293
+ const hasMore = endIndex < total;
2091
2294
  return {
2092
2295
  scores: paginatedScores,
2093
2296
  pagination: {
2094
2297
  total,
2095
- page,
2096
- perPage: perPageForResponse,
2097
- hasMore: end < total
2298
+ page: pagination.page,
2299
+ perPage: pagination.perPage,
2300
+ hasMore
2098
2301
  }
2099
2302
  };
2100
2303
  } catch (error) {
@@ -2116,7 +2319,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2116
2319
  );
2117
2320
  }
2118
2321
  }
2119
- async listScoresByRunId({
2322
+ async getScoresByRunId({
2120
2323
  runId,
2121
2324
  pagination
2122
2325
  }) {
@@ -2126,19 +2329,18 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2126
2329
  const results = await query.go();
2127
2330
  const allScores = results.data.map((data) => this.parseScoreData(data));
2128
2331
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2129
- const { page, perPage: perPageInput } = pagination;
2130
- const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2131
- const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2332
+ const startIndex = pagination.page * pagination.perPage;
2333
+ const endIndex = startIndex + pagination.perPage;
2334
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2132
2335
  const total = allScores.length;
2133
- const end = perPageInput === false ? allScores.length : start + perPage;
2134
- const paginatedScores = allScores.slice(start, end);
2336
+ const hasMore = endIndex < total;
2135
2337
  return {
2136
2338
  scores: paginatedScores,
2137
2339
  pagination: {
2138
2340
  total,
2139
- page,
2140
- perPage: perPageForResponse,
2141
- hasMore: end < total
2341
+ page: pagination.page,
2342
+ perPage: pagination.perPage,
2343
+ hasMore
2142
2344
  }
2143
2345
  };
2144
2346
  } catch (error) {
@@ -2153,7 +2355,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2153
2355
  );
2154
2356
  }
2155
2357
  }
2156
- async listScoresByEntityId({
2358
+ async getScoresByEntityId({
2157
2359
  entityId,
2158
2360
  entityType,
2159
2361
  pagination
@@ -2165,19 +2367,18 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2165
2367
  let allScores = results.data.map((data) => this.parseScoreData(data));
2166
2368
  allScores = allScores.filter((score) => score.entityType === entityType);
2167
2369
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2168
- const { page, perPage: perPageInput } = pagination;
2169
- const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2170
- const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2370
+ const startIndex = pagination.page * pagination.perPage;
2371
+ const endIndex = startIndex + pagination.perPage;
2372
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2171
2373
  const total = allScores.length;
2172
- const end = perPageInput === false ? allScores.length : start + perPage;
2173
- const paginatedScores = allScores.slice(start, end);
2374
+ const hasMore = endIndex < total;
2174
2375
  return {
2175
2376
  scores: paginatedScores,
2176
2377
  pagination: {
2177
2378
  total,
2178
- page,
2179
- perPage: perPageForResponse,
2180
- hasMore: end < total
2379
+ page: pagination.page,
2380
+ perPage: pagination.perPage,
2381
+ hasMore
2181
2382
  }
2182
2383
  };
2183
2384
  } catch (error) {
@@ -2192,7 +2393,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2192
2393
  );
2193
2394
  }
2194
2395
  }
2195
- async listScoresBySpan({
2396
+ async getScoresBySpan({
2196
2397
  traceId,
2197
2398
  spanId,
2198
2399
  pagination
@@ -2203,19 +2404,18 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2203
2404
  const results = await query.go();
2204
2405
  const allScores = results.data.map((data) => this.parseScoreData(data));
2205
2406
  allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2206
- const { page, perPage: perPageInput } = pagination;
2207
- const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2208
- const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2407
+ const startIndex = pagination.page * pagination.perPage;
2408
+ const endIndex = startIndex + pagination.perPage;
2409
+ const paginatedScores = allScores.slice(startIndex, endIndex);
2209
2410
  const total = allScores.length;
2210
- const end = perPageInput === false ? allScores.length : start + perPage;
2211
- const paginatedScores = allScores.slice(start, end);
2411
+ const hasMore = endIndex < total;
2212
2412
  return {
2213
2413
  scores: paginatedScores,
2214
2414
  pagination: {
2215
2415
  total,
2216
- page,
2217
- perPage: perPageForResponse,
2218
- hasMore: end < total
2416
+ page: pagination.page,
2417
+ perPage: pagination.perPage,
2418
+ hasMore
2219
2419
  }
2220
2420
  };
2221
2421
  } catch (error) {
@@ -2231,6 +2431,239 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2231
2431
  }
2232
2432
  }
2233
2433
  };
2434
+ var TracesStorageDynamoDB = class extends TracesStorage {
2435
+ service;
2436
+ operations;
2437
+ constructor({ service, operations }) {
2438
+ super();
2439
+ this.service = service;
2440
+ this.operations = operations;
2441
+ }
2442
+ // Trace operations
2443
+ async getTraces(args) {
2444
+ const { name, scope, page, perPage } = args;
2445
+ this.logger.debug("Getting traces", { name, scope, page, perPage });
2446
+ try {
2447
+ let query;
2448
+ if (name) {
2449
+ query = this.service.entities.trace.query.byName({ entity: "trace", name });
2450
+ } else if (scope) {
2451
+ query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
2452
+ } else {
2453
+ this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
2454
+ query = this.service.entities.trace.scan;
2455
+ }
2456
+ let items = [];
2457
+ let cursor = null;
2458
+ let pagesFetched = 0;
2459
+ const startPage = page > 0 ? page : 1;
2460
+ do {
2461
+ const results = await query.go({ cursor, limit: perPage });
2462
+ pagesFetched++;
2463
+ if (pagesFetched === startPage) {
2464
+ items = results.data;
2465
+ break;
2466
+ }
2467
+ cursor = results.cursor;
2468
+ if (!cursor && results.data.length > 0 && pagesFetched < startPage) {
2469
+ break;
2470
+ }
2471
+ } while (cursor && pagesFetched < startPage);
2472
+ return items;
2473
+ } catch (error) {
2474
+ throw new MastraError(
2475
+ {
2476
+ id: "STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED",
2477
+ domain: ErrorDomain.STORAGE,
2478
+ category: ErrorCategory.THIRD_PARTY
2479
+ },
2480
+ error
2481
+ );
2482
+ }
2483
+ }
2484
+ async batchTraceInsert({ records }) {
2485
+ this.logger.debug("Batch inserting traces", { count: records.length });
2486
+ if (!records.length) {
2487
+ return;
2488
+ }
2489
+ try {
2490
+ const recordsToSave = records.map((rec) => ({ entity: "trace", ...rec }));
2491
+ await this.operations.batchInsert({
2492
+ tableName: TABLE_TRACES,
2493
+ records: recordsToSave
2494
+ // Pass records with 'entity' included
2495
+ });
2496
+ } catch (error) {
2497
+ throw new MastraError(
2498
+ {
2499
+ id: "STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED",
2500
+ domain: ErrorDomain.STORAGE,
2501
+ category: ErrorCategory.THIRD_PARTY,
2502
+ details: { count: records.length }
2503
+ },
2504
+ error
2505
+ );
2506
+ }
2507
+ }
2508
+ async getTracesPaginated(args) {
2509
+ const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
2510
+ this.logger.debug("Getting traces with pagination", { name, scope, page, perPage, attributes, filters, dateRange });
2511
+ try {
2512
+ let query;
2513
+ if (name) {
2514
+ query = this.service.entities.trace.query.byName({ entity: "trace", name });
2515
+ } else if (scope) {
2516
+ query = this.service.entities.trace.query.byScope({ entity: "trace", scope });
2517
+ } else {
2518
+ this.logger.warn("Performing a scan operation on traces - consider using a more specific query");
2519
+ query = this.service.entities.trace.scan;
2520
+ }
2521
+ const results = await query.go({
2522
+ order: "desc",
2523
+ pages: "all"
2524
+ // Get all pages to apply filtering and pagination
2525
+ });
2526
+ if (!results.data.length) {
2527
+ return {
2528
+ traces: [],
2529
+ total: 0,
2530
+ page,
2531
+ perPage,
2532
+ hasMore: false
2533
+ };
2534
+ }
2535
+ let filteredData = results.data;
2536
+ if (attributes) {
2537
+ filteredData = filteredData.filter((item) => {
2538
+ try {
2539
+ let itemAttributes = {};
2540
+ if (item.attributes) {
2541
+ if (typeof item.attributes === "string") {
2542
+ if (item.attributes === "[object Object]") {
2543
+ itemAttributes = {};
2544
+ } else {
2545
+ try {
2546
+ itemAttributes = JSON.parse(item.attributes);
2547
+ } catch {
2548
+ itemAttributes = {};
2549
+ }
2550
+ }
2551
+ } else if (typeof item.attributes === "object") {
2552
+ itemAttributes = item.attributes;
2553
+ }
2554
+ }
2555
+ return Object.entries(attributes).every(([key, value]) => itemAttributes[key] === value);
2556
+ } catch (e) {
2557
+ this.logger.warn("Failed to parse attributes during filtering", { item, error: e });
2558
+ return false;
2559
+ }
2560
+ });
2561
+ }
2562
+ if (dateRange?.start) {
2563
+ filteredData = filteredData.filter((item) => {
2564
+ const itemDate = new Date(item.createdAt);
2565
+ return itemDate >= dateRange.start;
2566
+ });
2567
+ }
2568
+ if (dateRange?.end) {
2569
+ filteredData = filteredData.filter((item) => {
2570
+ const itemDate = new Date(item.createdAt);
2571
+ return itemDate <= dateRange.end;
2572
+ });
2573
+ }
2574
+ const total = filteredData.length;
2575
+ const start = page * perPage;
2576
+ const end = start + perPage;
2577
+ const paginatedData = filteredData.slice(start, end);
2578
+ const traces = paginatedData.map((item) => {
2579
+ let attributes2;
2580
+ if (item.attributes) {
2581
+ if (typeof item.attributes === "string") {
2582
+ if (item.attributes === "[object Object]") {
2583
+ attributes2 = void 0;
2584
+ } else {
2585
+ try {
2586
+ attributes2 = JSON.parse(item.attributes);
2587
+ } catch {
2588
+ attributes2 = void 0;
2589
+ }
2590
+ }
2591
+ } else if (typeof item.attributes === "object") {
2592
+ attributes2 = item.attributes;
2593
+ }
2594
+ }
2595
+ let status;
2596
+ if (item.status) {
2597
+ if (typeof item.status === "string") {
2598
+ try {
2599
+ status = JSON.parse(item.status);
2600
+ } catch {
2601
+ status = void 0;
2602
+ }
2603
+ } else if (typeof item.status === "object") {
2604
+ status = item.status;
2605
+ }
2606
+ }
2607
+ let events;
2608
+ if (item.events) {
2609
+ if (typeof item.events === "string") {
2610
+ try {
2611
+ events = JSON.parse(item.events);
2612
+ } catch {
2613
+ events = void 0;
2614
+ }
2615
+ } else if (Array.isArray(item.events)) {
2616
+ events = item.events;
2617
+ }
2618
+ }
2619
+ let links;
2620
+ if (item.links) {
2621
+ if (typeof item.links === "string") {
2622
+ try {
2623
+ links = JSON.parse(item.links);
2624
+ } catch {
2625
+ links = void 0;
2626
+ }
2627
+ } else if (Array.isArray(item.links)) {
2628
+ links = item.links;
2629
+ }
2630
+ }
2631
+ return {
2632
+ id: item.id,
2633
+ parentSpanId: item.parentSpanId,
2634
+ name: item.name,
2635
+ traceId: item.traceId,
2636
+ scope: item.scope,
2637
+ kind: item.kind,
2638
+ attributes: attributes2,
2639
+ status,
2640
+ events,
2641
+ links,
2642
+ other: item.other,
2643
+ startTime: item.startTime,
2644
+ endTime: item.endTime,
2645
+ createdAt: item.createdAt
2646
+ };
2647
+ });
2648
+ return {
2649
+ traces,
2650
+ total,
2651
+ page,
2652
+ perPage,
2653
+ hasMore: end < total
2654
+ };
2655
+ } catch (error) {
2656
+ throw new MastraError(
2657
+ {
2658
+ id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
2659
+ domain: ErrorDomain.STORAGE,
2660
+ category: ErrorCategory.THIRD_PARTY
2661
+ },
2662
+ error
2663
+ );
2664
+ }
2665
+ }
2666
+ };
2234
2667
  function formatWorkflowRun(snapshotData) {
2235
2668
  return {
2236
2669
  workflowName: snapshotData.workflow_name,
@@ -2252,7 +2685,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2252
2685
  // runId,
2253
2686
  // stepId,
2254
2687
  // result,
2255
- // requestContext,
2688
+ // runtimeContext,
2256
2689
  }) {
2257
2690
  throw new Error("Method not implemented.");
2258
2691
  }
@@ -2324,24 +2757,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2324
2757
  );
2325
2758
  }
2326
2759
  }
2327
- async listWorkflowRuns(args) {
2760
+ async getWorkflowRuns(args) {
2328
2761
  this.logger.debug("Getting workflow runs", { args });
2329
2762
  try {
2330
- const perPage = args?.perPage !== void 0 ? args.perPage : 10;
2331
- const page = args?.page !== void 0 ? args.page : 0;
2332
- if (page < 0) {
2333
- throw new MastraError(
2334
- {
2335
- id: "DYNAMODB_STORE_INVALID_PAGE",
2336
- domain: ErrorDomain.STORAGE,
2337
- category: ErrorCategory.USER,
2338
- details: { page }
2339
- },
2340
- new Error("page must be >= 0")
2341
- );
2342
- }
2343
- const normalizedPerPage = normalizePerPage(perPage, 10);
2344
- const offset = page * normalizedPerPage;
2763
+ const limit = args?.limit || 10;
2764
+ const offset = args?.offset || 0;
2345
2765
  let query;
2346
2766
  if (args?.workflowName) {
2347
2767
  query = this.service.entities.workflow_snapshot.query.primary({
@@ -2393,7 +2813,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2393
2813
  return { runs: [], total: 0 };
2394
2814
  }
2395
2815
  const total = allMatchingSnapshots.length;
2396
- const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
2816
+ const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
2397
2817
  const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
2398
2818
  return {
2399
2819
  runs,
@@ -2402,7 +2822,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2402
2822
  } catch (error) {
2403
2823
  throw new MastraError(
2404
2824
  {
2405
- id: "STORAGE_DYNAMODB_STORE_LIST_WORKFLOW_RUNS_FAILED",
2825
+ id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2406
2826
  domain: ErrorDomain.STORAGE,
2407
2827
  category: ErrorCategory.THIRD_PARTY,
2408
2828
  details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
@@ -2475,7 +2895,7 @@ var DynamoDBStore = class extends MastraStorage {
2475
2895
  hasInitialized = null;
2476
2896
  stores;
2477
2897
  constructor({ name, config }) {
2478
- super({ id: config.id, name });
2898
+ super({ name });
2479
2899
  try {
2480
2900
  if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
2481
2901
  throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
@@ -2498,11 +2918,14 @@ var DynamoDBStore = class extends MastraStorage {
2498
2918
  tableName: this.tableName,
2499
2919
  client: this.client
2500
2920
  });
2921
+ const traces = new TracesStorageDynamoDB({ service: this.service, operations });
2501
2922
  const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2502
2923
  const memory = new MemoryStorageDynamoDB({ service: this.service });
2503
2924
  const scores = new ScoresStorageDynamoDB({ service: this.service });
2504
2925
  this.stores = {
2505
2926
  operations,
2927
+ legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
2928
+ traces,
2506
2929
  workflows,
2507
2930
  memory,
2508
2931
  scores
@@ -2525,7 +2948,7 @@ var DynamoDBStore = class extends MastraStorage {
2525
2948
  hasColumn: false,
2526
2949
  createTable: false,
2527
2950
  deleteMessages: false,
2528
- listScoresBySpan: true
2951
+ getScoresBySpan: true
2529
2952
  };
2530
2953
  }
2531
2954
  /**
@@ -2620,6 +3043,9 @@ var DynamoDBStore = class extends MastraStorage {
2620
3043
  async getThreadById({ threadId }) {
2621
3044
  return this.stores.memory.getThreadById({ threadId });
2622
3045
  }
3046
+ async getThreadsByResourceId(args) {
3047
+ return this.stores.memory.getThreadsByResourceId(args);
3048
+ }
2623
3049
  async saveThread({ thread }) {
2624
3050
  return this.stores.memory.saveThread({ thread });
2625
3051
  }
@@ -2633,24 +3059,51 @@ var DynamoDBStore = class extends MastraStorage {
2633
3059
  async deleteThread({ threadId }) {
2634
3060
  return this.stores.memory.deleteThread({ threadId });
2635
3061
  }
2636
- async listMessagesById(args) {
2637
- return this.stores.memory.listMessagesById(args);
3062
+ async getMessages({
3063
+ threadId,
3064
+ resourceId,
3065
+ selectBy,
3066
+ format
3067
+ }) {
3068
+ return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
3069
+ }
3070
+ async getMessagesById({
3071
+ messageIds,
3072
+ format
3073
+ }) {
3074
+ return this.stores.memory.getMessagesById({ messageIds, format });
2638
3075
  }
2639
3076
  async saveMessages(args) {
2640
3077
  return this.stores.memory.saveMessages(args);
2641
3078
  }
3079
+ async getThreadsByResourceIdPaginated(args) {
3080
+ return this.stores.memory.getThreadsByResourceIdPaginated(args);
3081
+ }
3082
+ async getMessagesPaginated(args) {
3083
+ return this.stores.memory.getMessagesPaginated(args);
3084
+ }
2642
3085
  async updateMessages(_args) {
2643
3086
  return this.stores.memory.updateMessages(_args);
2644
3087
  }
3088
+ // Trace operations
3089
+ async getTraces(args) {
3090
+ return this.stores.traces.getTraces(args);
3091
+ }
3092
+ async batchTraceInsert({ records }) {
3093
+ return this.stores.traces.batchTraceInsert({ records });
3094
+ }
3095
+ async getTracesPaginated(_args) {
3096
+ return this.stores.traces.getTracesPaginated(_args);
3097
+ }
2645
3098
  // Workflow operations
2646
3099
  async updateWorkflowResults({
2647
3100
  workflowName,
2648
3101
  runId,
2649
3102
  stepId,
2650
3103
  result,
2651
- requestContext
3104
+ runtimeContext
2652
3105
  }) {
2653
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
3106
+ return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
2654
3107
  }
2655
3108
  async updateWorkflowState({
2656
3109
  workflowName,
@@ -2673,8 +3126,8 @@ var DynamoDBStore = class extends MastraStorage {
2673
3126
  }) {
2674
3127
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
2675
3128
  }
2676
- async listWorkflowRuns(args) {
2677
- return this.stores.workflows.listWorkflowRuns(args);
3129
+ async getWorkflowRuns(args) {
3130
+ return this.stores.workflows.getWorkflowRuns(args);
2678
3131
  }
2679
3132
  async getWorkflowRunById(args) {
2680
3133
  return this.stores.workflows.getWorkflowRunById(args);
@@ -2692,6 +3145,13 @@ var DynamoDBStore = class extends MastraStorage {
2692
3145
  }) {
2693
3146
  return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
2694
3147
  }
3148
+ // Eval operations
3149
+ async getEvalsByAgentName(agentName, type) {
3150
+ return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
3151
+ }
3152
+ async getEvals(options) {
3153
+ return this.stores.legacyEvals.getEvals(options);
3154
+ }
2695
3155
  /**
2696
3156
  * Closes the DynamoDB client connection and cleans up resources.
2697
3157
  * Should be called when the store is no longer needed, e.g., at the end of tests or application shutdown.
@@ -2721,38 +3181,38 @@ var DynamoDBStore = class extends MastraStorage {
2721
3181
  async saveScore(_score) {
2722
3182
  return this.stores.scores.saveScore(_score);
2723
3183
  }
2724
- async listScoresByRunId({
3184
+ async getScoresByRunId({
2725
3185
  runId: _runId,
2726
3186
  pagination: _pagination
2727
3187
  }) {
2728
- return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
3188
+ return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
2729
3189
  }
2730
- async listScoresByEntityId({
3190
+ async getScoresByEntityId({
2731
3191
  entityId: _entityId,
2732
3192
  entityType: _entityType,
2733
3193
  pagination: _pagination
2734
3194
  }) {
2735
- return this.stores.scores.listScoresByEntityId({
3195
+ return this.stores.scores.getScoresByEntityId({
2736
3196
  entityId: _entityId,
2737
3197
  entityType: _entityType,
2738
3198
  pagination: _pagination
2739
3199
  });
2740
3200
  }
2741
- async listScoresByScorerId({
3201
+ async getScoresByScorerId({
2742
3202
  scorerId,
2743
3203
  source,
2744
3204
  entityId,
2745
3205
  entityType,
2746
3206
  pagination
2747
3207
  }) {
2748
- return this.stores.scores.listScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
3208
+ return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2749
3209
  }
2750
- async listScoresBySpan({
3210
+ async getScoresBySpan({
2751
3211
  traceId,
2752
3212
  spanId,
2753
3213
  pagination
2754
3214
  }) {
2755
- return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
3215
+ return this.stores.scores.getScoresBySpan({ traceId, spanId, pagination });
2756
3216
  }
2757
3217
  };
2758
3218