@mastra/dynamodb 0.0.0-pgvector-index-fix-20250905222058 → 0.0.0-playground-studio-again-20251114100107

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, calculatePagination, ScoresStorage, TABLE_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.listMessages({ threadId, perPage: false });
1272
1075
  if (messages.length > 0) {
1273
1076
  const batchSize = 25;
1274
1077
  for (let i = 0; i < messages.length; i += batchSize) {
@@ -1297,104 +1100,175 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1297
1100
  );
1298
1101
  }
1299
1102
  }
1300
- async getMessages({
1301
- threadId,
1302
- resourceId,
1303
- selectBy,
1304
- format
1305
- }) {
1306
- this.logger.debug("Getting messages", { threadId, selectBy });
1103
+ async listMessagesById({ messageIds }) {
1104
+ this.logger.debug("Getting messages by ID", { messageIds });
1105
+ if (messageIds.length === 0) return { messages: [] };
1307
1106
  try {
1308
- if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
1309
- const messages = [];
1310
- const limit = resolveMessageLimit({ last: selectBy?.last, defaultLimit: Number.MAX_SAFE_INTEGER });
1311
- if (selectBy?.include?.length) {
1312
- const includeMessages = await this._getIncludedMessages(threadId, selectBy);
1313
- if (includeMessages) {
1314
- messages.push(...includeMessages);
1315
- }
1316
- }
1317
- if (limit !== 0) {
1318
- const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1319
- let results;
1320
- if (limit !== Number.MAX_SAFE_INTEGER && limit > 0) {
1321
- results = await query.go({ limit, order: "desc" });
1322
- results.data = results.data.reverse();
1323
- } else {
1324
- results = await query.go();
1325
- }
1326
- let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg);
1327
- allThreadMessages.sort((a, b) => {
1328
- const timeA = a.createdAt.getTime();
1329
- const timeB = b.createdAt.getTime();
1330
- if (timeA === timeB) {
1331
- return a.id.localeCompare(b.id);
1332
- }
1333
- return timeA - timeB;
1334
- });
1335
- messages.push(...allThreadMessages);
1336
- }
1337
- messages.sort((a, b) => {
1338
- const timeA = a.createdAt.getTime();
1339
- const timeB = b.createdAt.getTime();
1340
- if (timeA === timeB) {
1341
- return a.id.localeCompare(b.id);
1342
- }
1343
- return timeA - timeB;
1344
- });
1345
- const uniqueMessages = messages.filter(
1107
+ const results = await Promise.all(
1108
+ messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1109
+ );
1110
+ const data = results.map((result) => result.data).flat(1);
1111
+ let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1112
+ const uniqueMessages = parsedMessages.filter(
1346
1113
  (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1347
1114
  );
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();
1115
+ const list = new MessageList().add(uniqueMessages, "memory");
1116
+ return { messages: list.get.all.db() };
1351
1117
  } catch (error) {
1352
1118
  throw new MastraError(
1353
1119
  {
1354
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_FAILED",
1120
+ id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_BY_ID_FAILED",
1355
1121
  domain: ErrorDomain.STORAGE,
1356
1122
  category: ErrorCategory.THIRD_PARTY,
1357
- details: { threadId, resourceId: resourceId ?? "" }
1123
+ details: { messageIds: JSON.stringify(messageIds) }
1358
1124
  },
1359
1125
  error
1360
1126
  );
1361
1127
  }
1362
1128
  }
1363
- async getMessagesById({
1364
- messageIds,
1365
- format
1366
- }) {
1367
- this.logger.debug("Getting messages by ID", { messageIds });
1368
- if (messageIds.length === 0) return [];
1369
- try {
1370
- const results = await Promise.all(
1371
- messageIds.map((id) => this.service.entities.message.query.primary({ entity: "message", id }).go())
1372
- );
1373
- const data = results.map((result) => result.data).flat(1);
1374
- let parsedMessages = data.map((data2) => this.parseMessageData(data2)).filter((msg) => "content" in msg);
1375
- const uniqueMessages = parsedMessages.filter(
1376
- (message, index, self) => index === self.findIndex((m) => m.id === message.id)
1129
+ async listMessages(args) {
1130
+ const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
1131
+ if (!threadId.trim()) {
1132
+ throw new MastraError(
1133
+ {
1134
+ id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_THREAD_ID",
1135
+ domain: ErrorDomain.STORAGE,
1136
+ category: ErrorCategory.THIRD_PARTY,
1137
+ details: { threadId }
1138
+ },
1139
+ new Error("threadId must be a non-empty string")
1377
1140
  );
1378
- const list = new MessageList().add(uniqueMessages, "memory");
1379
- if (format === `v1`) return list.get.all.v1();
1380
- return list.get.all.v2();
1141
+ }
1142
+ const perPage = normalizePerPage(perPageInput, 40);
1143
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1144
+ try {
1145
+ if (page < 0) {
1146
+ throw new MastraError(
1147
+ {
1148
+ id: "STORAGE_DYNAMODB_LIST_MESSAGES_INVALID_PAGE",
1149
+ domain: ErrorDomain.STORAGE,
1150
+ category: ErrorCategory.USER,
1151
+ details: { page }
1152
+ },
1153
+ new Error("page must be >= 0")
1154
+ );
1155
+ }
1156
+ const { field, direction } = this.parseOrderBy(orderBy, "ASC");
1157
+ this.logger.debug("Getting messages with listMessages", {
1158
+ threadId,
1159
+ resourceId,
1160
+ perPageInput,
1161
+ offset,
1162
+ perPage,
1163
+ page,
1164
+ field,
1165
+ direction
1166
+ });
1167
+ const query = this.service.entities.message.query.byThread({ entity: "message", threadId });
1168
+ const results = await query.go();
1169
+ let allThreadMessages = results.data.map((data) => this.parseMessageData(data)).filter((msg) => "content" in msg && typeof msg.content === "object");
1170
+ if (resourceId) {
1171
+ allThreadMessages = allThreadMessages.filter((msg) => msg.resourceId === resourceId);
1172
+ }
1173
+ if (filter?.dateRange) {
1174
+ const dateRange = filter.dateRange;
1175
+ allThreadMessages = allThreadMessages.filter((msg) => {
1176
+ const createdAt = new Date(msg.createdAt).getTime();
1177
+ if (dateRange.start) {
1178
+ const startTime = dateRange.start instanceof Date ? dateRange.start.getTime() : new Date(dateRange.start).getTime();
1179
+ if (createdAt < startTime) return false;
1180
+ }
1181
+ if (dateRange.end) {
1182
+ const endTime = dateRange.end instanceof Date ? dateRange.end.getTime() : new Date(dateRange.end).getTime();
1183
+ if (createdAt > endTime) return false;
1184
+ }
1185
+ return true;
1186
+ });
1187
+ }
1188
+ allThreadMessages.sort((a, b) => {
1189
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1190
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1191
+ if (aValue === bValue) {
1192
+ return a.id.localeCompare(b.id);
1193
+ }
1194
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1195
+ });
1196
+ const total = allThreadMessages.length;
1197
+ const paginatedMessages = allThreadMessages.slice(offset, offset + perPage);
1198
+ const paginatedCount = paginatedMessages.length;
1199
+ if (total === 0 && paginatedCount === 0 && (!include || include.length === 0)) {
1200
+ return {
1201
+ messages: [],
1202
+ total: 0,
1203
+ page,
1204
+ perPage: perPageForResponse,
1205
+ hasMore: false
1206
+ };
1207
+ }
1208
+ const messageIds = new Set(paginatedMessages.map((m) => m.id));
1209
+ let includeMessages = [];
1210
+ if (include && include.length > 0) {
1211
+ const selectBy = { include };
1212
+ includeMessages = await this._getIncludedMessages(threadId, selectBy);
1213
+ for (const includeMsg of includeMessages) {
1214
+ if (!messageIds.has(includeMsg.id)) {
1215
+ paginatedMessages.push(includeMsg);
1216
+ messageIds.add(includeMsg.id);
1217
+ }
1218
+ }
1219
+ }
1220
+ const list = new MessageList().add(paginatedMessages, "memory");
1221
+ let finalMessages = list.get.all.db();
1222
+ finalMessages = finalMessages.sort((a, b) => {
1223
+ const aValue = field === "createdAt" ? new Date(a.createdAt).getTime() : a[field];
1224
+ const bValue = field === "createdAt" ? new Date(b.createdAt).getTime() : b[field];
1225
+ if (aValue === bValue) {
1226
+ return a.id.localeCompare(b.id);
1227
+ }
1228
+ return direction === "ASC" ? aValue - bValue : bValue - aValue;
1229
+ });
1230
+ const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
1231
+ const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
1232
+ let hasMore = false;
1233
+ if (perPageInput !== false && !allThreadMessagesReturned) {
1234
+ hasMore = offset + paginatedCount < total;
1235
+ }
1236
+ return {
1237
+ messages: finalMessages,
1238
+ total,
1239
+ page,
1240
+ perPage: perPageForResponse,
1241
+ hasMore
1242
+ };
1381
1243
  } catch (error) {
1382
- throw new MastraError(
1244
+ const mastraError = new MastraError(
1383
1245
  {
1384
- id: "STORAGE_DYNAMODB_STORE_GET_MESSAGES_BY_ID_FAILED",
1246
+ id: "STORAGE_DYNAMODB_STORE_LIST_MESSAGES_FAILED",
1385
1247
  domain: ErrorDomain.STORAGE,
1386
1248
  category: ErrorCategory.THIRD_PARTY,
1387
- details: { messageIds: JSON.stringify(messageIds) }
1249
+ details: {
1250
+ threadId,
1251
+ resourceId: resourceId ?? ""
1252
+ }
1388
1253
  },
1389
1254
  error
1390
1255
  );
1256
+ this.logger?.error?.(mastraError.toString());
1257
+ this.logger?.trackException?.(mastraError);
1258
+ return {
1259
+ messages: [],
1260
+ total: 0,
1261
+ page,
1262
+ perPage: perPageForResponse,
1263
+ hasMore: false
1264
+ };
1391
1265
  }
1392
1266
  }
1393
1267
  async saveMessages(args) {
1394
- const { messages, format = "v1" } = args;
1268
+ const { messages } = args;
1395
1269
  this.logger.debug("Saving messages", { count: messages.length });
1396
1270
  if (!messages.length) {
1397
- return [];
1271
+ return { messages: [] };
1398
1272
  }
1399
1273
  const threadId = messages[0]?.threadId;
1400
1274
  if (!threadId) {
@@ -1448,8 +1322,7 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1448
1322
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1449
1323
  }).go();
1450
1324
  const list = new MessageList().add(messages, "memory");
1451
- if (format === `v1`) return list.get.all.v1();
1452
- return list.get.all.v2();
1325
+ return { messages: list.get.all.db() };
1453
1326
  } catch (error) {
1454
1327
  throw new MastraError(
1455
1328
  {
@@ -1462,37 +1335,48 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1462
1335
  );
1463
1336
  }
1464
1337
  }
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);
1338
+ async listThreadsByResourceId(args) {
1339
+ const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
1340
+ const perPage = normalizePerPage(perPageInput, 100);
1341
+ if (page < 0) {
1342
+ throw new MastraError(
1343
+ {
1344
+ id: "STORAGE_DYNAMODB_LIST_THREADS_BY_RESOURCE_ID_INVALID_PAGE",
1345
+ domain: ErrorDomain.STORAGE,
1346
+ category: ErrorCategory.USER,
1347
+ details: { page }
1348
+ },
1349
+ new Error("page must be >= 0")
1350
+ );
1351
+ }
1352
+ const { offset, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
1353
+ const { field, direction } = this.parseOrderBy(orderBy);
1469
1354
  this.logger.debug("Getting threads by resource ID with pagination", {
1470
1355
  resourceId,
1471
1356
  page,
1472
1357
  perPage,
1473
- orderBy,
1474
- sortDirection
1358
+ field,
1359
+ direction
1475
1360
  });
1476
1361
  try {
1477
1362
  const query = this.service.entities.thread.query.byResource({ entity: "thread", resourceId });
1478
1363
  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);
1364
+ const allThreads = this.transformAndSortThreads(results.data, field, direction);
1365
+ const endIndex = offset + perPage;
1366
+ const paginatedThreads = allThreads.slice(offset, endIndex);
1483
1367
  const total = allThreads.length;
1484
- const hasMore = endIndex < total;
1368
+ const hasMore = offset + perPage < total;
1485
1369
  return {
1486
1370
  threads: paginatedThreads,
1487
1371
  total,
1488
1372
  page,
1489
- perPage,
1373
+ perPage: perPageForResponse,
1490
1374
  hasMore
1491
1375
  };
1492
1376
  } catch (error) {
1493
1377
  throw new MastraError(
1494
1378
  {
1495
- id: "STORAGE_DYNAMODB_STORE_GET_THREADS_BY_RESOURCE_ID_PAGINATED_FAILED",
1379
+ id: "DYNAMODB_STORAGE_LIST_THREADS_BY_RESOURCE_ID_FAILED",
1496
1380
  domain: ErrorDomain.STORAGE,
1497
1381
  category: ErrorCategory.THIRD_PARTY,
1498
1382
  details: { resourceId, page, perPage }
@@ -1501,84 +1385,6 @@ var MemoryStorageDynamoDB = class extends MemoryStorage {
1501
1385
  );
1502
1386
  }
1503
1387
  }
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
1388
  // Helper method to get included messages with context
1583
1389
  async _getIncludedMessages(threadId, selectBy) {
1584
1390
  if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
@@ -1845,11 +1651,10 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
1845
1651
  [TABLE_THREADS]: "thread",
1846
1652
  [TABLE_MESSAGES]: "message",
1847
1653
  [TABLE_WORKFLOW_SNAPSHOT]: "workflow_snapshot",
1848
- [TABLE_EVALS]: "eval",
1849
1654
  [TABLE_SCORERS]: "score",
1850
1655
  [TABLE_TRACES]: "trace",
1851
1656
  [TABLE_RESOURCES]: "resource",
1852
- [TABLE_AI_SPANS]: "ai_span"
1657
+ [TABLE_SPANS]: "ai_span"
1853
1658
  };
1854
1659
  return mapping[tableName] || null;
1855
1660
  }
@@ -2034,6 +1839,10 @@ var StoreOperationsDynamoDB = class extends StoreOperations {
2034
1839
  if (!item.id) throw new Error(`Missing required key 'id' for entity 'score'`);
2035
1840
  key.id = item.id;
2036
1841
  break;
1842
+ case "resource":
1843
+ if (!item.id) throw new Error(`Missing required key 'id' for entity 'resource'`);
1844
+ key.id = item.id;
1845
+ break;
2037
1846
  default:
2038
1847
  this.logger.warn(`Unknown entity type encountered during clearTable: ${entityName}`);
2039
1848
  throw new Error(`Cannot construct delete key for unknown entity type: ${entityName}`);
@@ -2176,34 +1985,47 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2176
1985
  }
2177
1986
  }
2178
1987
  async saveScore(score) {
2179
- this.logger.debug("Saving score", { scorerId: score.scorerId, runId: score.runId });
1988
+ let validatedScore;
1989
+ try {
1990
+ validatedScore = saveScorePayloadSchema.parse(score);
1991
+ } catch (error) {
1992
+ throw new MastraError(
1993
+ {
1994
+ id: "STORAGE_DYNAMODB_STORE_SAVE_SCORE_FAILED",
1995
+ domain: ErrorDomain.STORAGE,
1996
+ category: ErrorCategory.THIRD_PARTY
1997
+ },
1998
+ error
1999
+ );
2000
+ }
2180
2001
  const now = /* @__PURE__ */ new Date();
2181
2002
  const scoreId = `score-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
2182
2003
  const scoreData = {
2183
2004
  entity: "score",
2184
2005
  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 || "",
2006
+ scorerId: validatedScore.scorerId,
2007
+ traceId: validatedScore.traceId || "",
2008
+ spanId: validatedScore.spanId || "",
2009
+ runId: validatedScore.runId,
2010
+ scorer: typeof validatedScore.scorer === "string" ? validatedScore.scorer : JSON.stringify(validatedScore.scorer),
2011
+ preprocessStepResult: typeof validatedScore.preprocessStepResult === "string" ? validatedScore.preprocessStepResult : JSON.stringify(validatedScore.preprocessStepResult),
2012
+ analyzeStepResult: typeof validatedScore.analyzeStepResult === "string" ? validatedScore.analyzeStepResult : JSON.stringify(validatedScore.analyzeStepResult),
2013
+ score: validatedScore.score,
2014
+ reason: validatedScore.reason,
2015
+ preprocessPrompt: validatedScore.preprocessPrompt,
2016
+ generateScorePrompt: validatedScore.generateScorePrompt,
2017
+ generateReasonPrompt: validatedScore.generateReasonPrompt,
2018
+ analyzePrompt: validatedScore.analyzePrompt,
2019
+ input: typeof validatedScore.input === "string" ? validatedScore.input : JSON.stringify(validatedScore.input),
2020
+ output: typeof validatedScore.output === "string" ? validatedScore.output : JSON.stringify(validatedScore.output),
2021
+ additionalContext: typeof validatedScore.additionalContext === "string" ? validatedScore.additionalContext : JSON.stringify(validatedScore.additionalContext),
2022
+ requestContext: typeof validatedScore.requestContext === "string" ? validatedScore.requestContext : JSON.stringify(validatedScore.requestContext),
2023
+ entityType: validatedScore.entityType,
2024
+ entityData: typeof validatedScore.entity === "string" ? validatedScore.entity : JSON.stringify(validatedScore.entity),
2025
+ entityId: validatedScore.entityId,
2026
+ source: validatedScore.source,
2027
+ resourceId: validatedScore.resourceId || "",
2028
+ threadId: validatedScore.threadId || "",
2207
2029
  createdAt: now.toISOString(),
2208
2030
  updatedAt: now.toISOString()
2209
2031
  };
@@ -2228,7 +2050,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2228
2050
  );
2229
2051
  }
2230
2052
  }
2231
- async getScoresByScorerId({
2053
+ async listScoresByScorerId({
2232
2054
  scorerId,
2233
2055
  pagination,
2234
2056
  entityId,
@@ -2249,18 +2071,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2249
2071
  allScores = allScores.filter((score) => score.source === source);
2250
2072
  }
2251
2073
  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);
2074
+ const { page, perPage: perPageInput } = pagination;
2075
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2076
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2255
2077
  const total = allScores.length;
2256
- const hasMore = endIndex < total;
2078
+ const end = perPageInput === false ? allScores.length : start + perPage;
2079
+ const paginatedScores = allScores.slice(start, end);
2257
2080
  return {
2258
2081
  scores: paginatedScores,
2259
2082
  pagination: {
2260
2083
  total,
2261
- page: pagination.page,
2262
- perPage: pagination.perPage,
2263
- hasMore
2084
+ page,
2085
+ perPage: perPageForResponse,
2086
+ hasMore: end < total
2264
2087
  }
2265
2088
  };
2266
2089
  } catch (error) {
@@ -2282,7 +2105,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2282
2105
  );
2283
2106
  }
2284
2107
  }
2285
- async getScoresByRunId({
2108
+ async listScoresByRunId({
2286
2109
  runId,
2287
2110
  pagination
2288
2111
  }) {
@@ -2292,18 +2115,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2292
2115
  const results = await query.go();
2293
2116
  const allScores = results.data.map((data) => this.parseScoreData(data));
2294
2117
  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);
2118
+ const { page, perPage: perPageInput } = pagination;
2119
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2120
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2298
2121
  const total = allScores.length;
2299
- const hasMore = endIndex < total;
2122
+ const end = perPageInput === false ? allScores.length : start + perPage;
2123
+ const paginatedScores = allScores.slice(start, end);
2300
2124
  return {
2301
2125
  scores: paginatedScores,
2302
2126
  pagination: {
2303
2127
  total,
2304
- page: pagination.page,
2305
- perPage: pagination.perPage,
2306
- hasMore
2128
+ page,
2129
+ perPage: perPageForResponse,
2130
+ hasMore: end < total
2307
2131
  }
2308
2132
  };
2309
2133
  } catch (error) {
@@ -2318,7 +2142,7 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2318
2142
  );
2319
2143
  }
2320
2144
  }
2321
- async getScoresByEntityId({
2145
+ async listScoresByEntityId({
2322
2146
  entityId,
2323
2147
  entityType,
2324
2148
  pagination
@@ -2330,18 +2154,19 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2330
2154
  let allScores = results.data.map((data) => this.parseScoreData(data));
2331
2155
  allScores = allScores.filter((score) => score.entityType === entityType);
2332
2156
  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);
2157
+ const { page, perPage: perPageInput } = pagination;
2158
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2159
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2336
2160
  const total = allScores.length;
2337
- const hasMore = endIndex < total;
2161
+ const end = perPageInput === false ? allScores.length : start + perPage;
2162
+ const paginatedScores = allScores.slice(start, end);
2338
2163
  return {
2339
2164
  scores: paginatedScores,
2340
2165
  pagination: {
2341
2166
  total,
2342
- page: pagination.page,
2343
- perPage: pagination.perPage,
2344
- hasMore
2167
+ page,
2168
+ perPage: perPageForResponse,
2169
+ hasMore: end < total
2345
2170
  }
2346
2171
  };
2347
2172
  } catch (error) {
@@ -2356,234 +2181,39 @@ var ScoresStorageDynamoDB = class extends ScoresStorage {
2356
2181
  );
2357
2182
  }
2358
2183
  }
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 });
2184
+ async listScoresBySpan({
2185
+ traceId,
2186
+ spanId,
2187
+ pagination
2188
+ }) {
2189
+ this.logger.debug("Getting scores by span", { traceId, spanId, pagination });
2437
2190
  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,
2191
+ const query = this.service.entities.score.query.bySpan({ entity: "score", traceId, spanId });
2192
+ const results = await query.go();
2193
+ const allScores = results.data.map((data) => this.parseScoreData(data));
2194
+ allScores.sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
2195
+ const { page, perPage: perPageInput } = pagination;
2196
+ const perPage = normalizePerPage(perPageInput, Number.MAX_SAFE_INTEGER);
2197
+ const { offset: start, perPage: perPageForResponse } = calculatePagination(page, perPageInput, perPage);
2198
+ const total = allScores.length;
2199
+ const end = perPageInput === false ? allScores.length : start + perPage;
2200
+ const paginatedScores = allScores.slice(start, end);
2201
+ return {
2202
+ scores: paginatedScores,
2203
+ pagination: {
2204
+ total,
2456
2205
  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
- }
2544
- }
2545
- let links;
2546
- if (item.links) {
2547
- if (typeof item.links === "string") {
2548
- try {
2549
- links = JSON.parse(item.links);
2550
- } catch {
2551
- links = void 0;
2552
- }
2553
- } else if (Array.isArray(item.links)) {
2554
- links = item.links;
2555
- }
2206
+ perPage: perPageForResponse,
2207
+ hasMore: end < total
2556
2208
  }
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
2209
  };
2581
2210
  } catch (error) {
2582
2211
  throw new MastraError(
2583
2212
  {
2584
- id: "STORAGE_DYNAMODB_STORE_GET_TRACES_PAGINATED_FAILED",
2213
+ id: "STORAGE_DYNAMODB_STORE_GET_SCORES_BY_SPAN_FAILED",
2585
2214
  domain: ErrorDomain.STORAGE,
2586
- category: ErrorCategory.THIRD_PARTY
2215
+ category: ErrorCategory.THIRD_PARTY,
2216
+ details: { traceId, spanId, page: pagination.page, perPage: pagination.perPage }
2587
2217
  },
2588
2218
  error
2589
2219
  );
@@ -2611,7 +2241,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2611
2241
  // runId,
2612
2242
  // stepId,
2613
2243
  // result,
2614
- // runtimeContext,
2244
+ // requestContext,
2615
2245
  }) {
2616
2246
  throw new Error("Method not implemented.");
2617
2247
  }
@@ -2626,11 +2256,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2626
2256
  async persistWorkflowSnapshot({
2627
2257
  workflowName,
2628
2258
  runId,
2259
+ resourceId,
2629
2260
  snapshot
2630
2261
  }) {
2631
2262
  this.logger.debug("Persisting workflow snapshot", { workflowName, runId });
2632
2263
  try {
2633
- const resourceId = "resourceId" in snapshot ? snapshot.resourceId : void 0;
2634
2264
  const now = (/* @__PURE__ */ new Date()).toISOString();
2635
2265
  const data = {
2636
2266
  entity: "workflow_snapshot",
@@ -2638,7 +2268,6 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2638
2268
  workflow_name: workflowName,
2639
2269
  run_id: runId,
2640
2270
  snapshot: JSON.stringify(snapshot),
2641
- // Stringify the snapshot object
2642
2271
  createdAt: now,
2643
2272
  updatedAt: now,
2644
2273
  resourceId
@@ -2684,11 +2313,24 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2684
2313
  );
2685
2314
  }
2686
2315
  }
2687
- async getWorkflowRuns(args) {
2316
+ async listWorkflowRuns(args) {
2688
2317
  this.logger.debug("Getting workflow runs", { args });
2689
2318
  try {
2690
- const limit = args?.limit || 10;
2691
- const offset = args?.offset || 0;
2319
+ const perPage = args?.perPage !== void 0 ? args.perPage : 10;
2320
+ const page = args?.page !== void 0 ? args.page : 0;
2321
+ if (page < 0) {
2322
+ throw new MastraError(
2323
+ {
2324
+ id: "DYNAMODB_STORE_INVALID_PAGE",
2325
+ domain: ErrorDomain.STORAGE,
2326
+ category: ErrorCategory.USER,
2327
+ details: { page }
2328
+ },
2329
+ new Error("page must be >= 0")
2330
+ );
2331
+ }
2332
+ const normalizedPerPage = normalizePerPage(perPage, 10);
2333
+ const offset = page * normalizedPerPage;
2692
2334
  let query;
2693
2335
  if (args?.workflowName) {
2694
2336
  query = this.service.entities.workflow_snapshot.query.primary({
@@ -2710,6 +2352,11 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2710
2352
  });
2711
2353
  if (pageResults.data && pageResults.data.length > 0) {
2712
2354
  let pageFilteredData = pageResults.data;
2355
+ if (args?.status) {
2356
+ pageFilteredData = pageFilteredData.filter((snapshot) => {
2357
+ return snapshot.snapshot.status === args.status;
2358
+ });
2359
+ }
2713
2360
  if (args?.fromDate || args?.toDate) {
2714
2361
  pageFilteredData = pageFilteredData.filter((snapshot) => {
2715
2362
  const createdAt = new Date(snapshot.createdAt);
@@ -2735,7 +2382,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2735
2382
  return { runs: [], total: 0 };
2736
2383
  }
2737
2384
  const total = allMatchingSnapshots.length;
2738
- const paginatedData = allMatchingSnapshots.slice(offset, offset + limit);
2385
+ const paginatedData = allMatchingSnapshots.slice(offset, offset + normalizedPerPage);
2739
2386
  const runs = paginatedData.map((snapshot) => formatWorkflowRun(snapshot));
2740
2387
  return {
2741
2388
  runs,
@@ -2744,7 +2391,7 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2744
2391
  } catch (error) {
2745
2392
  throw new MastraError(
2746
2393
  {
2747
- id: "STORAGE_DYNAMODB_STORE_GET_WORKFLOW_RUNS_FAILED",
2394
+ id: "STORAGE_DYNAMODB_STORE_LIST_WORKFLOW_RUNS_FAILED",
2748
2395
  domain: ErrorDomain.STORAGE,
2749
2396
  category: ErrorCategory.THIRD_PARTY,
2750
2397
  details: { workflowName: args?.workflowName || "", resourceId: args?.resourceId || "" }
@@ -2756,8 +2403,6 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2756
2403
  async getWorkflowRunById(args) {
2757
2404
  const { runId, workflowName } = args;
2758
2405
  this.logger.debug("Getting workflow run by ID", { runId, workflowName });
2759
- console.log("workflowName", workflowName);
2760
- console.log("runId", runId);
2761
2406
  try {
2762
2407
  if (workflowName) {
2763
2408
  this.logger.debug("WorkflowName provided, using direct GET operation.");
@@ -2767,7 +2412,6 @@ var WorkflowStorageDynamoDB = class extends WorkflowsStorage {
2767
2412
  workflow_name: workflowName,
2768
2413
  run_id: runId
2769
2414
  }).go();
2770
- console.log("result", result2);
2771
2415
  if (!result2.data) {
2772
2416
  return null;
2773
2417
  }
@@ -2820,7 +2464,7 @@ var DynamoDBStore = class extends MastraStorage {
2820
2464
  hasInitialized = null;
2821
2465
  stores;
2822
2466
  constructor({ name, config }) {
2823
- super({ name });
2467
+ super({ id: config.id, name });
2824
2468
  try {
2825
2469
  if (!config.tableName || typeof config.tableName !== "string" || config.tableName.trim() === "") {
2826
2470
  throw new Error("DynamoDBStore: config.tableName must be provided and cannot be empty.");
@@ -2843,14 +2487,11 @@ var DynamoDBStore = class extends MastraStorage {
2843
2487
  tableName: this.tableName,
2844
2488
  client: this.client
2845
2489
  });
2846
- const traces = new TracesStorageDynamoDB({ service: this.service, operations });
2847
2490
  const workflows = new WorkflowStorageDynamoDB({ service: this.service });
2848
2491
  const memory = new MemoryStorageDynamoDB({ service: this.service });
2849
2492
  const scores = new ScoresStorageDynamoDB({ service: this.service });
2850
2493
  this.stores = {
2851
2494
  operations,
2852
- legacyEvals: new LegacyEvalsDynamoDB({ service: this.service, tableName: this.tableName }),
2853
- traces,
2854
2495
  workflows,
2855
2496
  memory,
2856
2497
  scores
@@ -2872,7 +2513,8 @@ var DynamoDBStore = class extends MastraStorage {
2872
2513
  resourceWorkingMemory: true,
2873
2514
  hasColumn: false,
2874
2515
  createTable: false,
2875
- deleteMessages: false
2516
+ deleteMessages: false,
2517
+ listScoresBySpan: true
2876
2518
  };
2877
2519
  }
2878
2520
  /**
@@ -2967,9 +2609,6 @@ var DynamoDBStore = class extends MastraStorage {
2967
2609
  async getThreadById({ threadId }) {
2968
2610
  return this.stores.memory.getThreadById({ threadId });
2969
2611
  }
2970
- async getThreadsByResourceId(args) {
2971
- return this.stores.memory.getThreadsByResourceId(args);
2972
- }
2973
2612
  async saveThread({ thread }) {
2974
2613
  return this.stores.memory.saveThread({ thread });
2975
2614
  }
@@ -2983,51 +2622,24 @@ var DynamoDBStore = class extends MastraStorage {
2983
2622
  async deleteThread({ threadId }) {
2984
2623
  return this.stores.memory.deleteThread({ threadId });
2985
2624
  }
2986
- async getMessages({
2987
- threadId,
2988
- resourceId,
2989
- selectBy,
2990
- format
2991
- }) {
2992
- return this.stores.memory.getMessages({ threadId, resourceId, selectBy, format });
2993
- }
2994
- async getMessagesById({
2995
- messageIds,
2996
- format
2997
- }) {
2998
- return this.stores.memory.getMessagesById({ messageIds, format });
2625
+ async listMessagesById(args) {
2626
+ return this.stores.memory.listMessagesById(args);
2999
2627
  }
3000
2628
  async saveMessages(args) {
3001
2629
  return this.stores.memory.saveMessages(args);
3002
2630
  }
3003
- async getThreadsByResourceIdPaginated(args) {
3004
- return this.stores.memory.getThreadsByResourceIdPaginated(args);
3005
- }
3006
- async getMessagesPaginated(args) {
3007
- return this.stores.memory.getMessagesPaginated(args);
3008
- }
3009
2631
  async updateMessages(_args) {
3010
2632
  return this.stores.memory.updateMessages(_args);
3011
2633
  }
3012
- // Trace operations
3013
- async getTraces(args) {
3014
- return this.stores.traces.getTraces(args);
3015
- }
3016
- async batchTraceInsert({ records }) {
3017
- return this.stores.traces.batchTraceInsert({ records });
3018
- }
3019
- async getTracesPaginated(_args) {
3020
- return this.stores.traces.getTracesPaginated(_args);
3021
- }
3022
2634
  // Workflow operations
3023
2635
  async updateWorkflowResults({
3024
2636
  workflowName,
3025
2637
  runId,
3026
2638
  stepId,
3027
2639
  result,
3028
- runtimeContext
2640
+ requestContext
3029
2641
  }) {
3030
- return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, runtimeContext });
2642
+ return this.stores.workflows.updateWorkflowResults({ workflowName, runId, stepId, result, requestContext });
3031
2643
  }
3032
2644
  async updateWorkflowState({
3033
2645
  workflowName,
@@ -3039,9 +2651,10 @@ var DynamoDBStore = class extends MastraStorage {
3039
2651
  async persistWorkflowSnapshot({
3040
2652
  workflowName,
3041
2653
  runId,
2654
+ resourceId,
3042
2655
  snapshot
3043
2656
  }) {
3044
- return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
2657
+ return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot });
3045
2658
  }
3046
2659
  async loadWorkflowSnapshot({
3047
2660
  workflowName,
@@ -3049,8 +2662,8 @@ var DynamoDBStore = class extends MastraStorage {
3049
2662
  }) {
3050
2663
  return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
3051
2664
  }
3052
- async getWorkflowRuns(args) {
3053
- return this.stores.workflows.getWorkflowRuns(args);
2665
+ async listWorkflowRuns(args) {
2666
+ return this.stores.workflows.listWorkflowRuns(args);
3054
2667
  }
3055
2668
  async getWorkflowRunById(args) {
3056
2669
  return this.stores.workflows.getWorkflowRunById(args);
@@ -3068,13 +2681,6 @@ var DynamoDBStore = class extends MastraStorage {
3068
2681
  }) {
3069
2682
  return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
3070
2683
  }
3071
- // Eval operations
3072
- async getEvalsByAgentName(agentName, type) {
3073
- return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
3074
- }
3075
- async getEvals(options) {
3076
- return this.stores.legacyEvals.getEvals(options);
3077
- }
3078
2684
  /**
3079
2685
  * Closes the DynamoDB client connection and cleans up resources.
3080
2686
  * Should be called when the store is no longer needed, e.g., at the end of tests or application shutdown.
@@ -3104,31 +2710,38 @@ var DynamoDBStore = class extends MastraStorage {
3104
2710
  async saveScore(_score) {
3105
2711
  return this.stores.scores.saveScore(_score);
3106
2712
  }
3107
- async getScoresByRunId({
2713
+ async listScoresByRunId({
3108
2714
  runId: _runId,
3109
2715
  pagination: _pagination
3110
2716
  }) {
3111
- return this.stores.scores.getScoresByRunId({ runId: _runId, pagination: _pagination });
2717
+ return this.stores.scores.listScoresByRunId({ runId: _runId, pagination: _pagination });
3112
2718
  }
3113
- async getScoresByEntityId({
2719
+ async listScoresByEntityId({
3114
2720
  entityId: _entityId,
3115
2721
  entityType: _entityType,
3116
2722
  pagination: _pagination
3117
2723
  }) {
3118
- return this.stores.scores.getScoresByEntityId({
2724
+ return this.stores.scores.listScoresByEntityId({
3119
2725
  entityId: _entityId,
3120
2726
  entityType: _entityType,
3121
2727
  pagination: _pagination
3122
2728
  });
3123
2729
  }
3124
- async getScoresByScorerId({
2730
+ async listScoresByScorerId({
3125
2731
  scorerId,
3126
2732
  source,
3127
2733
  entityId,
3128
2734
  entityType,
3129
2735
  pagination
3130
2736
  }) {
3131
- return this.stores.scores.getScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2737
+ return this.stores.scores.listScoresByScorerId({ scorerId, source, entityId, entityType, pagination });
2738
+ }
2739
+ async listScoresBySpan({
2740
+ traceId,
2741
+ spanId,
2742
+ pagination
2743
+ }) {
2744
+ return this.stores.scores.listScoresBySpan({ traceId, spanId, pagination });
3132
2745
  }
3133
2746
  };
3134
2747