@mastra/pg 0.10.2-alpha.0 → 0.10.2-alpha.2
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +20 -0
- package/dist/_tsup-dts-rollup.d.cts +33 -40
- package/dist/_tsup-dts-rollup.d.ts +33 -40
- package/dist/index.cjs +286 -225
- package/dist/index.js +286 -225
- package/package.json +4 -4
- package/src/storage/index.test.ts +308 -191
- package/src/storage/index.ts +348 -345
package/dist/index.cjs
CHANGED
|
@@ -944,6 +944,11 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
944
944
|
}
|
|
945
945
|
);
|
|
946
946
|
}
|
|
947
|
+
get supports() {
|
|
948
|
+
return {
|
|
949
|
+
selectByIncludeResourceScope: true
|
|
950
|
+
};
|
|
951
|
+
}
|
|
947
952
|
getTableName(indexName) {
|
|
948
953
|
const parsedIndexName = utils.parseSqlIdentifier(indexName, "table name");
|
|
949
954
|
const parsedSchemaName = this.schema ? utils.parseSqlIdentifier(this.schema, "schema name") : void 0;
|
|
@@ -1000,18 +1005,23 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1000
1005
|
throw error;
|
|
1001
1006
|
}
|
|
1002
1007
|
}
|
|
1008
|
+
/**
|
|
1009
|
+
* @deprecated use getTracesPaginated instead
|
|
1010
|
+
*/
|
|
1003
1011
|
async getTraces(args) {
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
} = args;
|
|
1012
|
+
if (args.fromDate || args.toDate) {
|
|
1013
|
+
args.dateRange = {
|
|
1014
|
+
start: args.fromDate,
|
|
1015
|
+
end: args.toDate
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
const result = await this.getTracesPaginated(args);
|
|
1019
|
+
return result.traces;
|
|
1020
|
+
}
|
|
1021
|
+
async getTracesPaginated(args) {
|
|
1022
|
+
const { name, scope, page = 0, perPage: perPageInput, attributes, filters, dateRange } = args;
|
|
1023
|
+
const fromDate = dateRange?.start;
|
|
1024
|
+
const toDate = dateRange?.end;
|
|
1015
1025
|
const perPage = perPageInput !== void 0 ? perPageInput : 100;
|
|
1016
1026
|
const currentOffset = page * perPage;
|
|
1017
1027
|
const queryParams = [];
|
|
@@ -1051,7 +1061,7 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1051
1061
|
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(storage.TABLE_TRACES)} ${whereClause}`;
|
|
1052
1062
|
const countResult = await this.db.one(countQuery, queryParams);
|
|
1053
1063
|
const total = parseInt(countResult.count, 10);
|
|
1054
|
-
if (total === 0
|
|
1064
|
+
if (total === 0) {
|
|
1055
1065
|
return {
|
|
1056
1066
|
traces: [],
|
|
1057
1067
|
total: 0,
|
|
@@ -1059,10 +1069,10 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1059
1069
|
perPage,
|
|
1060
1070
|
hasMore: false
|
|
1061
1071
|
};
|
|
1062
|
-
} else if (total === 0) {
|
|
1063
|
-
return [];
|
|
1064
1072
|
}
|
|
1065
|
-
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
1073
|
+
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
1074
|
+
storage.TABLE_TRACES
|
|
1075
|
+
)} ${whereClause} ORDER BY "createdAt" DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1066
1076
|
const finalQueryParams = [...queryParams, perPage, currentOffset];
|
|
1067
1077
|
const rows = await this.db.manyOrNone(dataQuery, finalQueryParams);
|
|
1068
1078
|
const traces = rows.map((row) => ({
|
|
@@ -1081,17 +1091,13 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1081
1091
|
other: row.other,
|
|
1082
1092
|
createdAt: row.createdAt
|
|
1083
1093
|
}));
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
};
|
|
1092
|
-
} else {
|
|
1093
|
-
return traces;
|
|
1094
|
-
}
|
|
1094
|
+
return {
|
|
1095
|
+
traces,
|
|
1096
|
+
total,
|
|
1097
|
+
page,
|
|
1098
|
+
perPage,
|
|
1099
|
+
hasMore: currentOffset + traces.length < total
|
|
1100
|
+
};
|
|
1095
1101
|
}
|
|
1096
1102
|
async setupSchema() {
|
|
1097
1103
|
if (!this.schema || this.schemaSetupComplete) {
|
|
@@ -1170,6 +1176,48 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1170
1176
|
throw error;
|
|
1171
1177
|
}
|
|
1172
1178
|
}
|
|
1179
|
+
getDefaultValue(type) {
|
|
1180
|
+
switch (type) {
|
|
1181
|
+
case "timestamp":
|
|
1182
|
+
return "DEFAULT NOW()";
|
|
1183
|
+
case "jsonb":
|
|
1184
|
+
return "DEFAULT '{}'::jsonb";
|
|
1185
|
+
default:
|
|
1186
|
+
return super.getDefaultValue(type);
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Alters table schema to add columns if they don't exist
|
|
1191
|
+
* @param tableName Name of the table
|
|
1192
|
+
* @param schema Schema of the table
|
|
1193
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
1194
|
+
*/
|
|
1195
|
+
async alterTable({
|
|
1196
|
+
tableName,
|
|
1197
|
+
schema,
|
|
1198
|
+
ifNotExists
|
|
1199
|
+
}) {
|
|
1200
|
+
const fullTableName = this.getTableName(tableName);
|
|
1201
|
+
try {
|
|
1202
|
+
for (const columnName of ifNotExists) {
|
|
1203
|
+
if (schema[columnName]) {
|
|
1204
|
+
const columnDef = schema[columnName];
|
|
1205
|
+
const sqlType = this.getSqlType(columnDef.type);
|
|
1206
|
+
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
1207
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
1208
|
+
const parsedColumnName = utils.parseSqlIdentifier(columnName, "column name");
|
|
1209
|
+
const alterSql = `ALTER TABLE ${fullTableName} ADD COLUMN IF NOT EXISTS "${parsedColumnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
1210
|
+
await this.db.none(alterSql);
|
|
1211
|
+
this.logger?.debug?.(`Ensured column ${parsedColumnName} exists in table ${fullTableName}`);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
} catch (error) {
|
|
1215
|
+
this.logger?.error?.(
|
|
1216
|
+
`Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
|
|
1217
|
+
);
|
|
1218
|
+
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1173
1221
|
async clearTable({ tableName }) {
|
|
1174
1222
|
try {
|
|
1175
1223
|
await this.db.none(`TRUNCATE TABLE ${this.getTableName(tableName)} CASCADE`);
|
|
@@ -1245,58 +1293,65 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1245
1293
|
throw error;
|
|
1246
1294
|
}
|
|
1247
1295
|
}
|
|
1296
|
+
/**
|
|
1297
|
+
* @deprecated use getThreadsByResourceIdPaginated instead
|
|
1298
|
+
*/
|
|
1248
1299
|
async getThreadsByResourceId(args) {
|
|
1249
|
-
const { resourceId
|
|
1300
|
+
const { resourceId } = args;
|
|
1250
1301
|
try {
|
|
1251
1302
|
const baseQuery = `FROM ${this.getTableName(storage.TABLE_THREADS)} WHERE "resourceId" = $1`;
|
|
1252
1303
|
const queryParams = [resourceId];
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1304
|
+
const dataQuery = `SELECT id, "resourceId", title, metadata, "createdAt", "updatedAt" ${baseQuery} ORDER BY "createdAt" DESC`;
|
|
1305
|
+
const rows = await this.db.manyOrNone(dataQuery, queryParams);
|
|
1306
|
+
return (rows || []).map((thread) => ({
|
|
1307
|
+
...thread,
|
|
1308
|
+
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
1309
|
+
createdAt: thread.createdAt,
|
|
1310
|
+
updatedAt: thread.updatedAt
|
|
1311
|
+
}));
|
|
1312
|
+
} catch (error) {
|
|
1313
|
+
this.logger.error(`Error getting threads for resource ${resourceId}:`, error);
|
|
1314
|
+
return [];
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
1318
|
+
const { resourceId, page = 0, perPage: perPageInput } = args;
|
|
1319
|
+
try {
|
|
1320
|
+
const baseQuery = `FROM ${this.getTableName(storage.TABLE_THREADS)} WHERE "resourceId" = $1`;
|
|
1321
|
+
const queryParams = [resourceId];
|
|
1322
|
+
const perPage = perPageInput !== void 0 ? perPageInput : 100;
|
|
1323
|
+
const currentOffset = page * perPage;
|
|
1324
|
+
const countQuery = `SELECT COUNT(*) ${baseQuery}`;
|
|
1325
|
+
const countResult = await this.db.one(countQuery, queryParams);
|
|
1326
|
+
const total = parseInt(countResult.count, 10);
|
|
1327
|
+
if (total === 0) {
|
|
1277
1328
|
return {
|
|
1278
|
-
threads,
|
|
1279
|
-
total,
|
|
1329
|
+
threads: [],
|
|
1330
|
+
total: 0,
|
|
1280
1331
|
page,
|
|
1281
1332
|
perPage,
|
|
1282
|
-
hasMore:
|
|
1333
|
+
hasMore: false
|
|
1283
1334
|
};
|
|
1284
|
-
} else {
|
|
1285
|
-
const dataQuery = `SELECT id, "resourceId", title, metadata, "createdAt", "updatedAt" ${baseQuery} ORDER BY "createdAt" DESC`;
|
|
1286
|
-
const rows = await this.db.manyOrNone(dataQuery, queryParams);
|
|
1287
|
-
return (rows || []).map((thread) => ({
|
|
1288
|
-
...thread,
|
|
1289
|
-
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
1290
|
-
createdAt: thread.createdAt,
|
|
1291
|
-
updatedAt: thread.updatedAt
|
|
1292
|
-
}));
|
|
1293
1335
|
}
|
|
1336
|
+
const dataQuery = `SELECT id, "resourceId", title, metadata, "createdAt", "updatedAt" ${baseQuery} ORDER BY "createdAt" DESC LIMIT $2 OFFSET $3`;
|
|
1337
|
+
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1338
|
+
const threads = (rows || []).map((thread) => ({
|
|
1339
|
+
...thread,
|
|
1340
|
+
metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
|
|
1341
|
+
createdAt: thread.createdAt,
|
|
1342
|
+
// Assuming already Date objects or ISO strings
|
|
1343
|
+
updatedAt: thread.updatedAt
|
|
1344
|
+
}));
|
|
1345
|
+
return {
|
|
1346
|
+
threads,
|
|
1347
|
+
total,
|
|
1348
|
+
page,
|
|
1349
|
+
perPage,
|
|
1350
|
+
hasMore: currentOffset + threads.length < total
|
|
1351
|
+
};
|
|
1294
1352
|
} catch (error) {
|
|
1295
1353
|
this.logger.error(`Error getting threads for resource ${resourceId}:`, error);
|
|
1296
|
-
|
|
1297
|
-
return { threads: [], total: 0, page, perPage: perPageInput || 100, hasMore: false };
|
|
1298
|
-
}
|
|
1299
|
-
return [];
|
|
1354
|
+
return { threads: [], total: 0, page, perPage: perPageInput || 100, hasMore: false };
|
|
1300
1355
|
}
|
|
1301
1356
|
}
|
|
1302
1357
|
async saveThread({ thread }) {
|
|
@@ -1377,144 +1432,156 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1377
1432
|
}
|
|
1378
1433
|
}
|
|
1379
1434
|
async getMessages(args) {
|
|
1380
|
-
const { threadId, format,
|
|
1435
|
+
const { threadId, format, selectBy } = args;
|
|
1381
1436
|
const selectStatement = `SELECT id, content, role, type, "createdAt", thread_id AS "threadId"`;
|
|
1382
1437
|
const orderByStatement = `ORDER BY "createdAt" DESC`;
|
|
1383
1438
|
try {
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
const
|
|
1388
|
-
const
|
|
1389
|
-
let
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
if (toDate) {
|
|
1395
|
-
conditions.push(`"createdAt" <= $${paramIndex++}`);
|
|
1396
|
-
queryParams.push(toDate);
|
|
1397
|
-
}
|
|
1398
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1399
|
-
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(storage.TABLE_MESSAGES)} ${whereClause}`;
|
|
1400
|
-
const countResult = await this.db.one(countQuery, queryParams);
|
|
1401
|
-
const total = parseInt(countResult.count, 10);
|
|
1402
|
-
if (total === 0) {
|
|
1403
|
-
return {
|
|
1404
|
-
messages: [],
|
|
1405
|
-
total: 0,
|
|
1406
|
-
page,
|
|
1407
|
-
perPage,
|
|
1408
|
-
hasMore: false
|
|
1409
|
-
};
|
|
1410
|
-
}
|
|
1411
|
-
const dataQuery = `${selectStatement} FROM ${this.getTableName(storage.TABLE_MESSAGES)} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1412
|
-
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1413
|
-
const fetchedMessages = (rows || []).map((message) => {
|
|
1414
|
-
if (typeof message.content === "string") {
|
|
1415
|
-
try {
|
|
1416
|
-
message.content = JSON.parse(message.content);
|
|
1417
|
-
} catch {
|
|
1418
|
-
}
|
|
1419
|
-
}
|
|
1420
|
-
if (message.type === "v2") delete message.type;
|
|
1421
|
-
return message;
|
|
1422
|
-
});
|
|
1423
|
-
const messagesToReturn = format === "v2" ? fetchedMessages.map(
|
|
1424
|
-
(m) => ({
|
|
1425
|
-
...m,
|
|
1426
|
-
content: m.content || { format: 2, parts: [{ type: "text", text: "" }] }
|
|
1427
|
-
})
|
|
1428
|
-
) : fetchedMessages;
|
|
1429
|
-
return {
|
|
1430
|
-
messages: messagesToReturn,
|
|
1431
|
-
total,
|
|
1432
|
-
page,
|
|
1433
|
-
perPage,
|
|
1434
|
-
hasMore: currentOffset + fetchedMessages.length < total
|
|
1435
|
-
};
|
|
1436
|
-
} else {
|
|
1437
|
-
let rows = [];
|
|
1438
|
-
const include = selectBy?.include || [];
|
|
1439
|
-
if (include.length) {
|
|
1440
|
-
rows = await this.db.manyOrNone(
|
|
1439
|
+
let rows = [];
|
|
1440
|
+
const include = selectBy?.include || [];
|
|
1441
|
+
if (include.length) {
|
|
1442
|
+
const unionQueries = [];
|
|
1443
|
+
const params = [];
|
|
1444
|
+
let paramIdx = 1;
|
|
1445
|
+
for (const inc of include) {
|
|
1446
|
+
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
1447
|
+
const searchId = inc.threadId || threadId;
|
|
1448
|
+
unionQueries.push(
|
|
1441
1449
|
`
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
SELECT
|
|
1450
|
-
m.id,
|
|
1451
|
-
m.content,
|
|
1452
|
-
m.role,
|
|
1453
|
-
m.type,
|
|
1454
|
-
m."createdAt",
|
|
1455
|
-
m.thread_id AS "threadId"
|
|
1456
|
-
FROM ordered_messages m
|
|
1457
|
-
WHERE m.id = ANY($2)
|
|
1458
|
-
OR EXISTS (
|
|
1459
|
-
SELECT 1 FROM ordered_messages target
|
|
1460
|
-
WHERE target.id = ANY($2)
|
|
1461
|
-
AND (
|
|
1462
|
-
-- Get previous messages based on the max withPreviousMessages
|
|
1463
|
-
(m.row_num <= target.row_num + $3 AND m.row_num > target.row_num)
|
|
1464
|
-
OR
|
|
1465
|
-
-- Get next messages based on the max withNextMessages
|
|
1466
|
-
(m.row_num >= target.row_num - $4 AND m.row_num < target.row_num)
|
|
1450
|
+
SELECT * FROM (
|
|
1451
|
+
WITH ordered_messages AS (
|
|
1452
|
+
SELECT
|
|
1453
|
+
*,
|
|
1454
|
+
ROW_NUMBER() OVER (${orderByStatement}) as row_num
|
|
1455
|
+
FROM ${this.getTableName(storage.TABLE_MESSAGES)}
|
|
1456
|
+
WHERE thread_id = $${paramIdx}
|
|
1467
1457
|
)
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1458
|
+
SELECT
|
|
1459
|
+
m.id,
|
|
1460
|
+
m.content,
|
|
1461
|
+
m.role,
|
|
1462
|
+
m.type,
|
|
1463
|
+
m."createdAt",
|
|
1464
|
+
m.thread_id AS "threadId",
|
|
1465
|
+
m."resourceId"
|
|
1466
|
+
FROM ordered_messages m
|
|
1467
|
+
WHERE m.id = $${paramIdx + 1}
|
|
1468
|
+
OR EXISTS (
|
|
1469
|
+
SELECT 1 FROM ordered_messages target
|
|
1470
|
+
WHERE target.id = $${paramIdx + 1}
|
|
1471
|
+
AND (
|
|
1472
|
+
-- Get previous messages based on the max withPreviousMessages
|
|
1473
|
+
(m.row_num <= target.row_num + $${paramIdx + 2} AND m.row_num > target.row_num)
|
|
1474
|
+
OR
|
|
1475
|
+
-- Get next messages based on the max withNextMessages
|
|
1476
|
+
(m.row_num >= target.row_num - $${paramIdx + 3} AND m.row_num < target.row_num)
|
|
1477
|
+
)
|
|
1478
|
+
)
|
|
1479
|
+
)
|
|
1480
|
+
`
|
|
1471
1481
|
// Keep ASC for final sorting after fetching context
|
|
1472
|
-
[
|
|
1473
|
-
threadId,
|
|
1474
|
-
include.map((i) => i.id),
|
|
1475
|
-
Math.max(0, ...include.map((i) => i.withPreviousMessages || 0)),
|
|
1476
|
-
// Ensure non-negative
|
|
1477
|
-
Math.max(0, ...include.map((i) => i.withNextMessages || 0))
|
|
1478
|
-
// Ensure non-negative
|
|
1479
|
-
]
|
|
1480
1482
|
);
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
if (limit === 0 && selectBy?.last !== false) ; else {
|
|
1484
|
-
let query = `${selectStatement} FROM ${this.getTableName(storage.TABLE_MESSAGES)} WHERE thread_id = $1 ${orderByStatement}`;
|
|
1485
|
-
const queryParams = [threadId];
|
|
1486
|
-
if (limit !== void 0 && selectBy?.last !== false) {
|
|
1487
|
-
query += ` LIMIT $2`;
|
|
1488
|
-
queryParams.push(limit);
|
|
1489
|
-
}
|
|
1490
|
-
rows = await this.db.manyOrNone(query, queryParams);
|
|
1491
|
-
}
|
|
1483
|
+
params.push(searchId, id, withPreviousMessages, withNextMessages);
|
|
1484
|
+
paramIdx += 4;
|
|
1492
1485
|
}
|
|
1493
|
-
const
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
const sortedMessages = fetchedMessages.sort(
|
|
1504
|
-
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
|
1486
|
+
const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
|
|
1487
|
+
const includedRows = await this.db.manyOrNone(finalQuery, params);
|
|
1488
|
+
const dedupedRows = Object.values(
|
|
1489
|
+
includedRows.reduce(
|
|
1490
|
+
(acc, row) => {
|
|
1491
|
+
acc[row.id] = row;
|
|
1492
|
+
return acc;
|
|
1493
|
+
},
|
|
1494
|
+
{}
|
|
1495
|
+
)
|
|
1505
1496
|
);
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1497
|
+
rows = dedupedRows;
|
|
1498
|
+
} else {
|
|
1499
|
+
const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
|
|
1500
|
+
if (limit === 0 && selectBy?.last !== false) ; else {
|
|
1501
|
+
let query = `${selectStatement} FROM ${this.getTableName(
|
|
1502
|
+
storage.TABLE_MESSAGES
|
|
1503
|
+
)} WHERE thread_id = $1 ${orderByStatement}`;
|
|
1504
|
+
const queryParams = [threadId];
|
|
1505
|
+
if (limit !== void 0 && selectBy?.last !== false) {
|
|
1506
|
+
query += ` LIMIT $2`;
|
|
1507
|
+
queryParams.push(limit);
|
|
1508
|
+
}
|
|
1509
|
+
rows = await this.db.manyOrNone(query, queryParams);
|
|
1510
|
+
}
|
|
1509
1511
|
}
|
|
1512
|
+
const fetchedMessages = (rows || []).map((message) => {
|
|
1513
|
+
if (typeof message.content === "string") {
|
|
1514
|
+
try {
|
|
1515
|
+
message.content = JSON.parse(message.content);
|
|
1516
|
+
} catch {
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (message.type === "v2") delete message.type;
|
|
1520
|
+
return message;
|
|
1521
|
+
});
|
|
1522
|
+
const sortedMessages = fetchedMessages.sort(
|
|
1523
|
+
(a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()
|
|
1524
|
+
);
|
|
1525
|
+
return format === "v2" ? sortedMessages.map(
|
|
1526
|
+
(m) => ({ ...m, content: m.content || { format: 2, parts: [{ type: "text", text: "" }] } })
|
|
1527
|
+
) : sortedMessages;
|
|
1510
1528
|
} catch (error) {
|
|
1511
1529
|
this.logger.error("Error getting messages:", error);
|
|
1512
|
-
if (page !== void 0) {
|
|
1513
|
-
return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
|
|
1514
|
-
}
|
|
1515
1530
|
return [];
|
|
1516
1531
|
}
|
|
1517
1532
|
}
|
|
1533
|
+
async getMessagesPaginated(args) {
|
|
1534
|
+
const { threadId, format, selectBy } = args;
|
|
1535
|
+
const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
|
|
1536
|
+
const fromDate = dateRange?.start;
|
|
1537
|
+
const toDate = dateRange?.end;
|
|
1538
|
+
const selectStatement = `SELECT id, content, role, type, "createdAt", thread_id AS "threadId"`;
|
|
1539
|
+
const orderByStatement = `ORDER BY "createdAt" DESC`;
|
|
1540
|
+
try {
|
|
1541
|
+
const perPage = perPageInput !== void 0 ? perPageInput : 40;
|
|
1542
|
+
const currentOffset = page * perPage;
|
|
1543
|
+
const conditions = [`thread_id = $1`];
|
|
1544
|
+
const queryParams = [threadId];
|
|
1545
|
+
let paramIndex = 2;
|
|
1546
|
+
if (fromDate) {
|
|
1547
|
+
conditions.push(`"createdAt" >= $${paramIndex++}`);
|
|
1548
|
+
queryParams.push(fromDate);
|
|
1549
|
+
}
|
|
1550
|
+
if (toDate) {
|
|
1551
|
+
conditions.push(`"createdAt" <= $${paramIndex++}`);
|
|
1552
|
+
queryParams.push(toDate);
|
|
1553
|
+
}
|
|
1554
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1555
|
+
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(storage.TABLE_MESSAGES)} ${whereClause}`;
|
|
1556
|
+
const countResult = await this.db.one(countQuery, queryParams);
|
|
1557
|
+
const total = parseInt(countResult.count, 10);
|
|
1558
|
+
if (total === 0) {
|
|
1559
|
+
return {
|
|
1560
|
+
messages: [],
|
|
1561
|
+
total: 0,
|
|
1562
|
+
page,
|
|
1563
|
+
perPage,
|
|
1564
|
+
hasMore: false
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
const dataQuery = `${selectStatement} FROM ${this.getTableName(
|
|
1568
|
+
storage.TABLE_MESSAGES
|
|
1569
|
+
)} ${whereClause} ${orderByStatement} LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1570
|
+
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1571
|
+
const list = new agent.MessageList().add(rows || [], "memory");
|
|
1572
|
+
const messagesToReturn = format === `v2` ? list.get.all.v2() : list.get.all.v1();
|
|
1573
|
+
return {
|
|
1574
|
+
messages: messagesToReturn,
|
|
1575
|
+
total,
|
|
1576
|
+
page,
|
|
1577
|
+
perPage,
|
|
1578
|
+
hasMore: currentOffset + rows.length < total
|
|
1579
|
+
};
|
|
1580
|
+
} catch (error) {
|
|
1581
|
+
this.logger.error("Error getting messages:", error);
|
|
1582
|
+
return { messages: [], total: 0, page, perPage: perPageInput || 40, hasMore: false };
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1518
1585
|
async saveMessages({
|
|
1519
1586
|
messages,
|
|
1520
1587
|
format
|
|
@@ -1531,16 +1598,27 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1531
1598
|
}
|
|
1532
1599
|
await this.db.tx(async (t) => {
|
|
1533
1600
|
for (const message of messages) {
|
|
1601
|
+
if (!message.threadId) {
|
|
1602
|
+
throw new Error(
|
|
1603
|
+
`Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred.`
|
|
1604
|
+
);
|
|
1605
|
+
}
|
|
1606
|
+
if (!message.resourceId) {
|
|
1607
|
+
throw new Error(
|
|
1608
|
+
`Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred.`
|
|
1609
|
+
);
|
|
1610
|
+
}
|
|
1534
1611
|
await t.none(
|
|
1535
|
-
`INSERT INTO ${this.getTableName(storage.TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type)
|
|
1536
|
-
VALUES ($1, $2, $3, $4, $5, $6)`,
|
|
1612
|
+
`INSERT INTO ${this.getTableName(storage.TABLE_MESSAGES)} (id, thread_id, content, "createdAt", role, type, "resourceId")
|
|
1613
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)`,
|
|
1537
1614
|
[
|
|
1538
1615
|
message.id,
|
|
1539
|
-
threadId,
|
|
1616
|
+
message.threadId,
|
|
1540
1617
|
typeof message.content === "string" ? message.content : JSON.stringify(message.content),
|
|
1541
1618
|
message.createdAt || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1542
1619
|
message.role,
|
|
1543
|
-
message.type || "v2"
|
|
1620
|
+
message.type || "v2",
|
|
1621
|
+
message.resourceId
|
|
1544
1622
|
]
|
|
1545
1623
|
);
|
|
1546
1624
|
}
|
|
@@ -1725,8 +1803,10 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1725
1803
|
async close() {
|
|
1726
1804
|
this.pgp.end();
|
|
1727
1805
|
}
|
|
1728
|
-
async getEvals(options) {
|
|
1729
|
-
const { agentName, type, page, perPage
|
|
1806
|
+
async getEvals(options = {}) {
|
|
1807
|
+
const { agentName, type, page = 0, perPage = 100, dateRange } = options;
|
|
1808
|
+
const fromDate = dateRange?.start;
|
|
1809
|
+
const toDate = dateRange?.end;
|
|
1730
1810
|
const conditions = [];
|
|
1731
1811
|
const queryParams = [];
|
|
1732
1812
|
let paramIndex = 1;
|
|
@@ -1751,45 +1831,26 @@ var PostgresStore = class extends storage.MastraStorage {
|
|
|
1751
1831
|
const countQuery = `SELECT COUNT(*) FROM ${this.getTableName(storage.TABLE_EVALS)} ${whereClause}`;
|
|
1752
1832
|
const countResult = await this.db.one(countQuery, queryParams);
|
|
1753
1833
|
const total = parseInt(countResult.count, 10);
|
|
1754
|
-
|
|
1755
|
-
let currentOffset;
|
|
1756
|
-
let currentPage = page;
|
|
1757
|
-
let currentPerPage = perPage;
|
|
1758
|
-
let hasMore = false;
|
|
1759
|
-
if (limit !== void 0 && offset !== void 0) {
|
|
1760
|
-
currentLimit = limit;
|
|
1761
|
-
currentOffset = offset;
|
|
1762
|
-
currentPage = void 0;
|
|
1763
|
-
currentPerPage = void 0;
|
|
1764
|
-
hasMore = currentOffset + currentLimit < total;
|
|
1765
|
-
} else if (page !== void 0 && perPage !== void 0) {
|
|
1766
|
-
currentLimit = perPage;
|
|
1767
|
-
currentOffset = page * perPage;
|
|
1768
|
-
hasMore = currentOffset + currentLimit < total;
|
|
1769
|
-
} else {
|
|
1770
|
-
currentLimit = perPage || 100;
|
|
1771
|
-
currentOffset = (page || 0) * currentLimit;
|
|
1772
|
-
if (page === void 0) currentPage = 0;
|
|
1773
|
-
if (currentPerPage === void 0) currentPerPage = currentLimit;
|
|
1774
|
-
hasMore = currentOffset + currentLimit < total;
|
|
1775
|
-
}
|
|
1834
|
+
const currentOffset = page * perPage;
|
|
1776
1835
|
if (total === 0) {
|
|
1777
1836
|
return {
|
|
1778
1837
|
evals: [],
|
|
1779
1838
|
total: 0,
|
|
1780
|
-
page
|
|
1781
|
-
perPage
|
|
1839
|
+
page,
|
|
1840
|
+
perPage,
|
|
1782
1841
|
hasMore: false
|
|
1783
1842
|
};
|
|
1784
1843
|
}
|
|
1785
|
-
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
1786
|
-
|
|
1844
|
+
const dataQuery = `SELECT * FROM ${this.getTableName(
|
|
1845
|
+
storage.TABLE_EVALS
|
|
1846
|
+
)} ${whereClause} ORDER BY created_at DESC LIMIT $${paramIndex++} OFFSET $${paramIndex++}`;
|
|
1847
|
+
const rows = await this.db.manyOrNone(dataQuery, [...queryParams, perPage, currentOffset]);
|
|
1787
1848
|
return {
|
|
1788
1849
|
evals: rows?.map((row) => this.transformEvalRow(row)) ?? [],
|
|
1789
1850
|
total,
|
|
1790
|
-
page
|
|
1791
|
-
perPage
|
|
1792
|
-
hasMore
|
|
1851
|
+
page,
|
|
1852
|
+
perPage,
|
|
1853
|
+
hasMore: currentOffset + (rows?.length ?? 0) < total
|
|
1793
1854
|
};
|
|
1794
1855
|
}
|
|
1795
1856
|
};
|