@mastra/dynamodb 0.0.0-vector-extension-schema-20250922130418 → 0.0.0-vnext-20251104230439

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,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 { MastraStorage, StoreOperations, WorkflowsStorage, normalizePerPage, MemoryStorage, resolveMessageLimit, calculatePagination, ScoresStorage, TABLE_AI_SPANS, TABLE_RESOURCES, TABLE_TRACES, TABLE_SCORERS, 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
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
@@ -557,7 +562,7 @@ var scoreEntity = new Entity({
557
562
  return value;
558
563
  }
559
564
  },
560
- runtimeContext: {
565
+ requestContext: {
561
566
  type: "string",
562
567
  required: false,
563
568
  set: (value) => {
@@ -656,6 +661,11 @@ var scoreEntity = new Entity({
656
661
  index: "gsi6",
657
662
  pk: { field: "gsi6pk", composite: ["entity", "threadId"] },
658
663
  sk: { field: "gsi6sk", composite: ["createdAt"] }
664
+ },
665
+ bySpan: {
666
+ index: "gsi7",
667
+ pk: { field: "gsi7pk", composite: ["entity", "traceId", "spanId"] },
668
+ sk: { field: "gsi7sk", composite: ["createdAt"] }
659
669
  }
660
670
  }
661
671
  });
@@ -923,187 +933,6 @@ function getElectroDbService(client, tableName) {
923
933
  }
924
934
  );
925
935
  }
926
- var LegacyEvalsDynamoDB = class extends LegacyEvalsStorage {
927
- service;
928
- tableName;
929
- constructor({ service, tableName }) {
930
- super();
931
- this.service = service;
932
- this.tableName = tableName;
933
- }
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
- }
997
- }
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 });
1001
- 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;
1032
- }
1033
- } catch (e) {
1034
- this.logger.warn("Failed to parse test_info during filtering", { record: evalRecord, error: e });
1035
- }
1036
- return true;
1037
- });
1038
- }
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
- });
1052
- }
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
- } catch (error) {
1090
- throw new MastraError(
1091
- {
1092
- id: "STORAGE_DYNAMODB_STORE_GET_EVALS_FAILED",
1093
- domain: ErrorDomain.STORAGE,
1094
- category: ErrorCategory.THIRD_PARTY,
1095
- details: {
1096
- agentName: agentName || "all",
1097
- type: type || "all",
1098
- page,
1099
- perPage
1100
- }
1101
- },
1102
- error
1103
- );
1104
- }
1105
- }
1106
- };
1107
936
  var MemoryStorageDynamoDB = class extends MemoryStorage {
1108
937
  service;
1109
938
  constructor({ service }) {
@@ -1122,17 +951,17 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1122
951
  };
1123
952
  }
1124
953
  // Helper function to transform and sort threads
1125
- transformAndSortThreads(rawThreads, orderBy, sortDirection) {
954
+ transformAndSortThreads(rawThreads, field, direction) {
1126
955
  return rawThreads.map((data) => ({
1127
956
  ...data,
1128
957
  // Convert date strings back to Date objects for consistency
1129
958
  createdAt: typeof data.createdAt === "string" ? new Date(data.createdAt) : data.createdAt,
1130
959
  updatedAt: typeof data.updatedAt === "string" ? new Date(data.updatedAt) : data.updatedAt
1131
960
  })).sort((a, b) => {
1132
- const fieldA = orderBy === "createdAt" ? a.createdAt : a.updatedAt;
1133
- const fieldB = orderBy === "createdAt" ? b.createdAt : b.updatedAt;
961
+ const fieldA = field === "createdAt" ? a.createdAt : a.updatedAt;
962
+ const fieldB = field === "createdAt" ? b.createdAt : b.updatedAt;
1134
963
  const comparison = fieldA.getTime() - fieldB.getTime();
1135
- return sortDirection === "DESC" ? -comparison : comparison;
964
+ return direction === "DESC" ? -comparison : comparison;
1136
965
  });
1137
966
  }
1138
967
  async getThreadById({ threadId }) {
@@ -1163,32 +992,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1163
992
  );
1164
993
  }
1165
994
  }
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
995
  async saveThread({ thread }) {
1193
996
  this.logger.debug("Saving thread", { threadId: thread.id });
1194
997
  const now = /* @__PURE__ */ new Date();
@@ -1208,7 +1011,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1208
1011
  resourceId: thread.resourceId,
1209
1012
  title: threadData.title,
1210
1013
  createdAt: thread.createdAt || now,
1211
- updatedAt: now,
1014
+ updatedAt: thread.updatedAt || now,
1212
1015
  metadata: thread.metadata
1213
1016
  };
1214
1017
  } catch (error) {
@@ -1268,7 +1071,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1268
1071
  async deleteThread({ threadId }) {
1269
1072
  this.logger.debug("Deleting thread", { threadId });
1270
1073
  try {
1271
- const messages = await this.getMessages({ threadId });
1074
+ const { messages } = await this.getMessages({ threadId });
1272
1075
  if (messages.length > 0) {
1273
1076
  const batchSize = 25;
1274
1077
  for (let i = 0; i < messages.length; i += batchSize) {
@@ -1300,8 +1103,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1300
1103
  async getMessages({
1301
1104
  threadId,
1302
1105
  resourceId,
1303
- selectBy,
1304
- format
1106
+ selectBy
1305
1107
  }) {
1306
1108
  this.logger.debug("Getting messages", { threadId, selectBy });
1307
1109
  try {
@@ -1345,9 +1147,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1345
1147
  const uniqueMessages = messages.filter(
1346
1148
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1347
1149
  );
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();
1150
+ const list = new MessageList({ threadId, resourceId }).add(
1151
+ uniqueMessages,
1152
+ "memory"
1153
+ );
1154
+ return { messages: list.get.all.db() };
1351
1155
  } catch (error) {
1352
1156
  throw new MastraError(
1353
1157
  {
@@ -1360,12 +1164,9 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1360
1164
  );
1361
1165
  }
1362
1166
  }
1363
- async getMessagesById({
1364
- messageIds,
1365
- format
1366
- }) {
1167
+ async listMessagesById({ messageIds }) {
1367
1168
  this.logger.debug("Getting messages by ID", { messageIds });
1368
- if (messageIds.length === 0) return [];
1169
+ if (messageIds.length === 0) return { messages: [] };
1369
1170
  try {
1370
1171
  const results = await Promise.all(
1371
1172
  messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
@@ -1376,12 +1177,11 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1376
1177
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1377
1178
  );
1378
1179
  const list = new MessageList().add(uniqueMessages, "memory");
1379
- if (format === `v1`) return list.get.all.v1();
1380
- return list.get.all.v2();
1180
+ return { messages: list.get.all.db() };
1381
1181
  } catch (error) {
1382
1182
  throw new MastraError(
1383
1183
  {
1384
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_BY_ID_FAILED",
1184
+ id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_BY_ID_FAILED",
1385
1185
  domain: ErrorDomain.STORAGE,
1386
1186
  category: ErrorCategory.THIRD_PARTY,
1387
1187
  details: { messageIds: JSON.stringify(messageIds) }
@@ -1390,11 +1190,149 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1390
1190
  );
1391
1191
  }
1392
1192
  }
1193
+ async listMessages(args) {
1194
+ const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
1195
+ if (!threadId.trim()) {
1196
+ throw new MastraError(
1197
+ {
1198
+ id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_THREAD_ID",
1199
+ domain: ErrorDomain.STORAGE,
1200
+ category: ErrorCategory.THIRD_PARTY,
1201
+ details: { threadId }
1202
+ },
1203
+ new Error("threadId must be a non-empty string")
1204
+ );
1205
+ }
1206
+ const perPage = normalizePerPage(perPageInput, 40);
1207
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1208
+ try {
1209
+ if (page < 0) {
1210
+ throw new MastraError(
1211
+ {
1212
+ id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_PAGE",
1213
+ domain: ErrorDomain.STORAGE,
1214
+ category: ErrorCategory.USER,
1215
+ details: { page }
1216
+ },
1217
+ new Error("page must be >= 0")
1218
+ );
1219
+ }
1220
+ const { field, direction } = this.parseOrderBy(orderBy);
1221
+ this.logger.debug("Getting messages with listMessages", {
1222
+ threadId,
1223
+ resourceId,
1224
+ perPageInput,
1225
+ offset,
1226
+ perPage,
1227
+ page,
1228
+ field,
1229
+ direction
1230
+ });
1231
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1232
+ const results = await query.go();
1233
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1234
+ if (resourceId) {
1235
+ allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1236
+ }
1237
+ if (filter?.dateRange) {
1238
+ const dateRange = filter.dateRange;
1239
+ allThreadMessages = allThreadMessages.filter((msg) => {
1240
+ const createdAt = new Date(msg.createdAt).getTime();
1241
+ if (dateRange.start) {
1242
+ const startTime = dateRange.start instanceof Date ? dateRange.start.getTime() : new Date(dateRange.start).getTime();
1243
+ if (createdAt < startTime) return false;
1244
+ }
1245
+ if (dateRange.end) {
1246
+ const endTime = dateRange.end instanceof Date ? dateRange.end.getTime() : new Date(dateRange.end).getTime();
1247
+ if (createdAt > endTime) return false;
1248
+ }
1249
+ return true;
1250
+ });
1251
+ }
1252
+ allThreadMessages.sort((a, b) => {
1253
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1254
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1255
+ if (aValue === bValue) {
1256
+ return a.id.localeCompare(b.id);
1257
+ }
1258
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1259
+ });
1260
+ const total = allThreadMessages.length;
1261
+ const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1262
+ const paginatedCount = paginatedMessages.length;
1263
+ if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1264
+ return {
1265
+ messages: [],
1266
+ total: 0,
1267
+ page,
1268
+ perPage: perPageForResponse,
1269
+ hasMore: false
1270
+ };
1271
+ }
1272
+ const messageIds = new Set(paginatedMessages.map((m) => m.id));
1273
+ let includeMessages = [];
1274
+ if (include && include.length > 0) {
1275
+ const selectBy = { include };
1276
+ includeMessages = await this._getIncludedMessages(threadId, selectBy);
1277
+ for (const includeMsg of includeMessages) {
1278
+ if (!messageIds.has(includeMsg.id)) {
1279
+ paginatedMessages.push(includeMsg);
1280
+ messageIds.add(includeMsg.id);
1281
+ }
1282
+ }
1283
+ }
1284
+ const list = new MessageList().add(paginatedMessages, "memory");
1285
+ let finalMessages = list.get.all.db();
1286
+ finalMessages = finalMessages.sort((a, b) => {
1287
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1288
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1289
+ if (aValue === bValue) {
1290
+ return a.id.localeCompare(b.id);
1291
+ }
1292
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1293
+ });
1294
+ const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1295
+ const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1296
+ let hasMore = false;
1297
+ if (perPageInput !== false && !allThreadMessagesReturned) {
1298
+ hasMore = offset + paginatedCount < total;
1299
+ }
1300
+ return {
1301
+ messages: finalMessages,
1302
+ total,
1303
+ page,
1304
+ perPage: perPageForResponse,
1305
+ hasMore
1306
+ };
1307
+ } catch (error) {
1308
+ const mastraError = new MastraError(
1309
+ {
1310
+ id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_FAILED",
1311
+ domain: ErrorDomain.STORAGE,
1312
+ category: ErrorCategory.THIRD_PARTY,
1313
+ details: {
1314
+ threadId,
1315
+ resourceId: resourceId ?? ""
1316
+ }
1317
+ },
1318
+ error
1319
+ );
1320
+ this.logger?.error?.(mastraError.toString());
1321
+ this.logger?.trackException?.(mastraError);
1322
+ return {
1323
+ messages: [],
1324
+ total: 0,
1325
+ page,
1326
+ perPage: perPageForResponse,
1327
+ hasMore: false
1328
+ };
1329
+ }
1330
+ }
1393
1331
  async saveMessages(args) {
1394
- const { messages, format = "v1" } = args;
1332
+ const { messages } = args;
1395
1333
  this.logger.debug("Saving messages", { count: messages.length });
1396
1334
  if (!messages.length) {
1397
- return [];
1335
+ return { messages: [] };
1398
1336
  }
1399
1337
  const threadId = messages[0]?.threadId;
1400
1338
  if (!threadId) {
@@ -1448,8 +1386,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1448
1386
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1449
1387
  }).go();
1450
1388
  const list = new MessageList().add(messages, "memory");
1451
- if (format === `v1`) return list.get.all.v1();
1452
- return list.get.all.v2();
1389
+ return { messages: list.get.all.db() };
1453
1390
  } catch (error) {
1454
1391
  throw new MastraError(
1455
1392
  {
@@ -1462,37 +1399,48 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1462
1399
  );
1463
1400
  }
1464
1401
  }
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);
1402
+ async listThreadsByResourceId(args) {
1403
+ const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
1404
+ const perPage = normalizePerPage(perPageInput, 100);
1405
+ if (page < 0) {
1406
+ throw new MastraError(
1407
+ {
1408
+ id: "STORAGE_DYNAMODB_LIST_THREADS_BY_RESOURCE_ID_INVALID_PAGE",
1409
+ domain: ErrorDomain.STORAGE,
1410
+ category: ErrorCategory.USER,
1411
+ details: { page }
1412
+ },
1413
+ new Error("page must be >= 0")
1414
+ );
1415
+ }
1416
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1417
+ const { field, direction } = this.parseOrderBy(orderBy);
1469
1418
  this.logger.debug("Getting threads by resource ID with pagination", {
1470
1419
  resourceId,
1471
1420
  page,
1472
1421
  perPage,
1473
- orderBy,
1474
- sortDirection
1422
+ field,
1423
+ direction
1475
1424
  });
1476
1425
  try {
1477
1426
  const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1478
1427
  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);
1428
+ const allThreads = this.transformAndSortThreads(results.data, field, direction);
1429
+ const endIndex = offset + perPage;
1430
+ const paginatedThreads = allThreads.slice(offset, endIndex);
1483
1431
  const total = allThreads.length;
1484
- const hasMore = endIndex < total;
1432
+ const hasMore = offset + perPage < total;
1485
1433
  return {
1486
1434
  threads: paginatedThreads,
1487
1435
  total,
1488
1436
  page,
1489
- perPage,
1437
+ perPage: perPageForResponse,
1490
1438
  hasMore
1491
1439
  };
1492
1440
  } catch (error) {
1493
1441
  throw new MastraError(
1494
1442
  {
1495
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1443
+ id: "DYNAMODB_STORAGE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
1496
1444
  domain: ErrorDomain.STORAGE,
1497
1445
  category: ErrorCategory.THIRD_PARTY,
1498
1446
  details: { resourceId, page, perPage }
@@ -1501,84 +1449,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1501
1449
  );
1502
1450
  }
1503
1451
  }
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
1452
  // Helper method to get included messages with context
1583
1453
  async _getIncludedMessages(threadId, selectBy) {
1584
1454
  if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
@@ -1845,7 +1715,6 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
1845
1715
  [TABLE_THREADS]: "thread",
1846
1716
  [TABLE_MESSAGES]: "message",
1847
1717
  [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1848
- [TABLE_EVALS]: "eval",
1849
1718
  [TABLE_SCORERS]: "score",
1850
1719
  [TABLE_TRACES]: "trace",
1851
1720
  [TABLE_RESOURCES]: "resource",
@@ -2034,6 +1903,10 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
2034
1903
  if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
2035
1904
  key.id = item.id;
2036
1905
  break;
1906
+ case "resource":
1907
+ if (!item.id) throw new Error(`Missing required key 'id' for entity 'resource'`);
1908
+ key.id = item.id;
1909
+ break;
2037
1910
  default:
2038
1911
  this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
2039
1912
  throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
@@ -2176,34 +2049,47 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2176
2049
  }
2177
2050
  }
2178
2051
  async saveScore(score) {
2179
- this.logger.debug("Saving score", { scorerId: score.scorerId, runId: score.runId });
2052
+ let validatedScore;
2053
+ try {
2054
+ validatedScore = saveScorePayloadSchema.parse(score);
2055
+ } catch (error) {
2056
+ throw new MastraError(
2057
+ {
2058
+ id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
2059
+ domain: ErrorDomain.STORAGE,
2060
+ category: ErrorCategory.THIRD_PARTY
2061
+ },
2062
+ error
2063
+ );
2064
+ }
2180
2065
  const now = /* @__PURE__ */ new Date();
2181
2066
  const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2182
2067
  const scoreData = {
2183
2068
  entity: "score",
2184
2069
  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 || "",
2070
+ scorerId: validatedScore.scorerId,
2071
+ traceId: validatedScore.traceId || "",
2072
+ spanId: validatedScore.spanId || "",
2073
+ runId: validatedScore.runId,
2074
+ scorer: typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer),
2075
+ preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult),
2076
+ analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult),
2077
+ score: validatedScore.score,
2078
+ reason: validatedScore.reason,
2079
+ preprocessPrompt: validatedScore.preprocessPrompt,
2080
+ generateScorePrompt: validatedScore.generateScorePrompt,
2081
+ generateReasonPrompt: validatedScore.generateReasonPrompt,
2082
+ analyzePrompt: validatedScore.analyzePrompt,
2083
+ input: typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input),
2084
+ output: typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output),
2085
+ additionalContext: typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : JSON.stringify(validatedScore.additionalContext),
2086
+ requestContext: typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext),
2087
+ entityType: validatedScore.entityType,
2088
+ entityData: typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity),
2089
+ entityId: validatedScore.entityId,
2090
+ source: validatedScore.source,
2091
+ resourceId: validatedScore.resourceId || "",
2092
+ threadId: validatedScore.threadId || "",
2207
2093
  createdAt: now.toISOString(),
2208
2094
  updatedAt: now.toISOString()
2209
2095
  };
@@ -2228,7 +2114,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2228
2114
  );
2229
2115
  }
2230
2116
  }
2231
- async getScoresByScorerId({
2117
+ async listScoresByScorerId({
2232
2118
  scorerId,
2233
2119
  pagination,
2234
2120
  entityId,
@@ -2249,18 +2135,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2249
2135
  allScores = allScores.filter((score) => score.source === source);
2250
2136
  }
2251
2137
  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);
2138
+ const { page, perPage: perPageInput } = pagination;
2139
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2140
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2255
2141
  const total = allScores.length;
2256
- const hasMore = endIndex < total;
2142
+ const end = perPageInput === false ? allScores.length : start + perPage;
2143
+ const paginatedScores = allScores.slice(start, end);
2257
2144
  return {
2258
2145
  scores: paginatedScores,
2259
2146
  pagination: {
2260
2147
  total,
2261
- page: pagination.page,
2262
- perPage: pagination.perPage,
2263
- hasMore
2148
+ page,
2149
+ perPage: perPageForResponse,
2150
+ hasMore: end < total
2264
2151
  }
2265
2152
  };
2266
2153
  } catch (error) {
@@ -2282,7 +2169,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2282
2169
  );
2283
2170
  }
2284
2171
  }
2285
- async getScoresByRunId({
2172
+ async listScoresByRunId({
2286
2173
  runId,
2287
2174
  pagination
2288
2175
  }) {
@@ -2292,18 +2179,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2292
2179
  const results = await query.go();
2293
2180
  const allScores = results.data.map((data) => this.parseScoreData(data));
2294
2181
  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);
2182
+ const { page, perPage: perPageInput } = pagination;
2183
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2184
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2298
2185
  const total = allScores.length;
2299
- const hasMore = endIndex < total;
2186
+ const end = perPageInput === false ? allScores.length : start + perPage;
2187
+ const paginatedScores = allScores.slice(start, end);
2300
2188
  return {
2301
2189
  scores: paginatedScores,
2302
2190
  pagination: {
2303
2191
  total,
2304
- page: pagination.page,
2305
- perPage: pagination.perPage,
2306
- hasMore
2192
+ page,
2193
+ perPage: perPageForResponse,
2194
+ hasMore: end < total
2307
2195
  }
2308
2196
  };
2309
2197
  } catch (error) {
@@ -2318,7 +2206,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2318
2206
  );
2319
2207
  }
2320
2208
  }
2321
- async getScoresByEntityId({
2209
+ async listScoresByEntityId({
2322
2210
  entityId,
2323
2211
  entityType,
2324
2212
  pagination
@@ -2330,18 +2218,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2330
2218
  let allScores = results.data.map((data) => this.parseScoreData(data));
2331
2219
  allScores = allScores.filter((score) => score.entityType === entityType);
2332
2220
  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);
2221
+ const { page, perPage: perPageInput } = pagination;
2222
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2223
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2336
2224
  const total = allScores.length;
2337
- const hasMore = endIndex < total;
2225
+ const end = perPageInput === false ? allScores.length : start + perPage;
2226
+ const paginatedScores = allScores.slice(start, end);
2338
2227
  return {
2339
2228
  scores: paginatedScores,
2340
2229
  pagination: {
2341
2230
  total,
2342
- page: pagination.page,
2343
- perPage: pagination.perPage,
2344
- hasMore
2231
+ page,
2232
+ perPage: perPageForResponse,
2233
+ hasMore: end < total
2345
2234
  }
2346
2235
  };
2347
2236
  } catch (error) {
@@ -2356,234 +2245,39 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2356
2245
  );
2357
2246
  }
2358
2247
  }
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 });
2372
- 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;
2396
- }
2397
- } while (cursor && pagesFetched < startPage);
2398
- return items;
2399
- } catch (error) {
2400
- throw new MastraError(
2401
- {
2402
- id: "STORAGE_DYNAMODB_STORE_GET_TRACES_FAILED",
2403
- domain: ErrorDomain.STORAGE,
2404
- category: ErrorCategory.THIRD_PARTY
2405
- },
2406
- error
2407
- );
2408
- }
2409
- }
2410
- async batchTraceInsert({ records }) {
2411
- this.logger.debug("Batch inserting traces", { count: records.length });
2412
- if (!records.length) {
2413
- return;
2414
- }
2415
- 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
- });
2422
- } catch (error) {
2423
- throw new MastraError(
2424
- {
2425
- id: "STORAGE_DYNAMODB_STORE_BATCH_TRACE_INSERT_FAILED",
2426
- domain: ErrorDomain.STORAGE,
2427
- category: ErrorCategory.THIRD_PARTY,
2428
- details: { count: records.length }
2429
- },
2430
- error
2431
- );
2432
- }
2433
- }
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 });
2248
+ async listScoresBySpan({
2249
+ traceId,
2250
+ spanId,
2251
+ pagination
2252
+ }) {
2253
+ this.logger.debug("Getting scores by span", { traceId, spanId, pagination });
2437
2254
  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,
2255
+ const query = this.service.entities.score.query.bySpan({ entity: "score", traceId, spanId });
2256
+ const results = await query.go();
2257
+ const allScores = results.data.map((data) => this.parseScoreData(data));
2258
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2259
+ const { page, perPage: perPageInput } = pagination;
2260
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2261
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2262
+ const total = allScores.length;
2263
+ const end = perPageInput === false ? allScores.length : start + perPage;
2264
+ const paginatedScores = allScores.slice(start, end);
2265
+ return {
2266
+ scores: paginatedScores,
2267
+ pagination: {
2268
+ total,
2456
2269
  page,
2457
- perPage,
2458
- hasMore: false
2459
- };
2460
- }
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
- }
2270
+ perPage: perPageForResponse,
2271
+ hasMore: end < total
2544
2272
  }
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
2273
  };
2581
2274
  } catch (error) {
2582
2275
  throw new MastraError(
2583
2276
  {
2584
- id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
2277
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SPAN_FAILED",
2585
2278
  domain: ErrorDomain.STORAGE,
2586
- category: ErrorCategory.THIRD_PARTY
2279
+ category: ErrorCategory.THIRD_PARTY,
2280
+ details: { traceId, spanId, page: pagination.page, perPage: pagination.perPage }
2587
2281
  },
2588
2282
  error
2589
2283
  );
@@ -2611,7 +2305,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2611
2305
  // runId,
2612
2306
  // stepId,
2613
2307
  // result,
2614
- // runtimeContext,
2308
+ // requestContext,
2615
2309
  }) {
2616
2310
  throw new Error("Method not implemented.");
2617
2311
  }
@@ -2684,11 +2378,24 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2684
2378
  );
2685
2379
  }
2686
2380
  }
2687
- async getWorkflowRuns(args) {
2381
+ async listWorkflowRuns(args) {
2688
2382
  this.logger.debug("Getting workflow runs", { args });
2689
2383
  try {
2690
- const limit = args?.limit || 10;
2691
- const offset = args?.offset || 0;
2384
+ const perPage = args?.perPage !== void 0 ? args.perPage : 10;
2385
+ const page = args?.page !== void 0 ? args.page : 0;
2386
+ if (page < 0) {
2387
+ throw new MastraError(
2388
+ {
2389
+ id: "DYNAMODB_STORE_INVALID_PAGE",
2390
+ domain: ErrorDomain.STORAGE,
2391
+ category: ErrorCategory.USER,
2392
+ details: { page }
2393
+ },
2394
+ new Error("page must be >= 0")
2395
+ );
2396
+ }
2397
+ const normalizedPerPage = normalizePerPage(perPage, 10);
2398
+ const offset = page * normalizedPerPage;
2692
2399
  let query;
2693
2400
  if (args?.workflowName) {
2694
2401
  query = this.service.entities.workflow_snapshot.query.primary({
@@ -2735,7 +2442,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2735
2442
  return { runs: [], total: 0 };
2736
2443
  }
2737
2444
  const total = allMatchingSnapshots.length;
2738
- const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
2445
+ const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
2739
2446
  const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
2740
2447
  return {
2741
2448
  runs,
@@ -2744,7 +2451,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2744
2451
  } catch (error) {
2745
2452
  throw new MastraError(
2746
2453
  {
2747
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2454
+ id: "STORAGE_DYNAMODB_STORE_LIST_WORKFLOW_RUNS_FAILED",
2748
2455
  domain: ErrorDomain.STORAGE,
2749
2456
  category: ErrorCategory.THIRD_PARTY,
2750
2457
  details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
@@ -2840,14 +2547,11 @@ var DynamoDBStore = class extends MastraStorage {
2840
2547
  tableName: this.tableName,
2841
2548
  client: this.client
2842
2549
  });
2843
- const traces = new TracesStorageDynamoDB({ service: this.service, operations });
2844
2550
  const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2845
2551
  const memory = new MemoryStorageDynamoDB({ service: this.service });
2846
2552
  const scores = new ScoresStorageDynamoDB({ service: this.service });
2847
2553
  this.stores = {
2848
2554
  operations,
2849
- legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
2850
- traces,
2851
2555
  workflows,
2852
2556
  memory,
2853
2557
  scores
@@ -2869,7 +2573,8 @@ var DynamoDBStore = class extends MastraStorage {
2869
2573
  resourceWorkingMemory: true,
2870
2574
  hasColumn: false,
2871
2575
  createTable: false,
2872
- deleteMessages: false
2576
+ deleteMessages: false,
2577
+ listScoresBySpan: true
2873
2578
  };
2874
2579
  }
2875
2580
  /**
@@ -2964,9 +2669,6 @@ var DynamoDBStore = class extends MastraStorage {
2964
2669
  async getThreadById({ threadId }) {
2965
2670
  return this.stores.memory.getThreadById({ threadId });
2966
2671
  }
2967
- async getThreadsByResourceId(args) {
2968
- return this.stores.memory.getThreadsByResourceId(args);
2969
- }
2970
2672
  async saveThread({ thread }) {
2971
2673
  return this.stores.memory.saveThread({ thread });
2972
2674
  }
@@ -2980,51 +2682,28 @@ var DynamoDBStore = class extends MastraStorage {
2980
2682
  async deleteThread({ threadId }) {
2981
2683
  return this.stores.memory.deleteThread({ threadId });
2982
2684
  }
2983
- async getMessages({
2984
- threadId,
2985
- resourceId,
2986
- selectBy,
2987
- format
2988
- }) {
2989
- return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2685
+ // Message operations
2686
+ async getMessages(args) {
2687
+ return this.stores.memory.getMessages(args);
2990
2688
  }
2991
- async getMessagesById({
2992
- messageIds,
2993
- format
2994
- }) {
2995
- return this.stores.memory.getMessagesById({ messageIds, format });
2689
+ async listMessagesById(args) {
2690
+ return this.stores.memory.listMessagesById(args);
2996
2691
  }
2997
2692
  async saveMessages(args) {
2998
2693
  return this.stores.memory.saveMessages(args);
2999
2694
  }
3000
- async getThreadsByResourceIdPaginated(args) {
3001
- return this.stores.memory.getThreadsByResourceIdPaginated(args);
3002
- }
3003
- async getMessagesPaginated(args) {
3004
- return this.stores.memory.getMessagesPaginated(args);
3005
- }
3006
2695
  async updateMessages(_args) {
3007
2696
  return this.stores.memory.updateMessages(_args);
3008
2697
  }
3009
- // Trace operations
3010
- async getTraces(args) {
3011
- return this.stores.traces.getTraces(args);
3012
- }
3013
- async batchTraceInsert({ records }) {
3014
- return this.stores.traces.batchTraceInsert({ records });
3015
- }
3016
- async getTracesPaginated(_args) {
3017
- return this.stores.traces.getTracesPaginated(_args);
3018
- }
3019
2698
  // Workflow operations
3020
2699
  async updateWorkflowResults({
3021
2700
  workflowName,
3022
2701
  runId,
3023
2702
  stepId,
3024
2703
  result,
3025
- runtimeContext
2704
+ requestContext
3026
2705
  }) {
3027
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
2706
+ return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
3028
2707
  }
3029
2708
  async updateWorkflowState({
3030
2709
  workflowName,
@@ -3047,8 +2726,8 @@ var DynamoDBStore = class extends MastraStorage {
3047
2726
  }) {
3048
2727
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
3049
2728
  }
3050
- async getWorkflowRuns(args) {
3051
- return this.stores.workflows.getWorkflowRuns(args);
2729
+ async listWorkflowRuns(args) {
2730
+ return this.stores.workflows.listWorkflowRuns(args);
3052
2731
  }
3053
2732
  async getWorkflowRunById(args) {
3054
2733
  return this.stores.workflows.getWorkflowRunById(args);
@@ -3066,13 +2745,6 @@ var DynamoDBStore = class extends MastraStorage {
3066
2745
  }) {
3067
2746
  return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
3068
2747
  }
3069
- // Eval operations
3070
- async getEvalsByAgentName(agentName, type) {
3071
- return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
3072
- }
3073
- async getEvals(options) {
3074
- return this.stores.legacyEvals.getEvals(options);
3075
- }
3076
2748
  /**
3077
2749
  * Closes the DynamoDB client connection and cleans up resources.
3078
2750
  * Should be called when the store is no longer needed, e.g., at the end of tests or application shutdown.
@@ -3102,31 +2774,38 @@ var DynamoDBStore = class extends MastraStorage {
3102
2774
  async saveScore(_score) {
3103
2775
  return this.stores.scores.saveScore(_score);
3104
2776
  }
3105
- async getScoresByRunId({
2777
+ async listScoresByRunId({
3106
2778
  runId: _runId,
3107
2779
  pagination: _pagination
3108
2780
  }) {
3109
- return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
2781
+ return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
3110
2782
  }
3111
- async getScoresByEntityId({
2783
+ async listScoresByEntityId({
3112
2784
  entityId: _entityId,
3113
2785
  entityType: _entityType,
3114
2786
  pagination: _pagination
3115
2787
  }) {
3116
- return this.stores.scores.getScoresByEntityId({
2788
+ return this.stores.scores.listScoresByEntityId({
3117
2789
  entityId: _entityId,
3118
2790
  entityType: _entityType,
3119
2791
  pagination: _pagination
3120
2792
  });
3121
2793
  }
3122
- async getScoresByScorerId({
2794
+ async listScoresByScorerId({
3123
2795
  scorerId,
3124
2796
  source,
3125
2797
  entityId,
3126
2798
  entityType,
3127
2799
  pagination
3128
2800
  }) {
3129
- return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2801
+ return this.stores.scores.listScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2802
+ }
2803
+ async listScoresBySpan({
2804
+ traceId,
2805
+ spanId,
2806
+ pagination
2807
+ }) {
2808
+ return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
3130
2809
  }
3131
2810
  };
3132
2811