@mastra/libsql 0.10.1 → 0.10.2-alpha.1
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 +8 -8
- package/CHANGELOG.md +27 -0
- package/dist/_tsup-dts-rollup.d.cts +53 -3
- package/dist/_tsup-dts-rollup.d.ts +53 -3
- package/dist/index.cjs +347 -129
- package/dist/index.js +347 -129
- package/package.json +10 -10
- package/src/storage/index.test.ts +356 -6
- package/src/storage/index.ts +437 -157
package/dist/index.js
CHANGED
|
@@ -849,6 +849,52 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
849
849
|
throw error;
|
|
850
850
|
}
|
|
851
851
|
}
|
|
852
|
+
getSqlType(type) {
|
|
853
|
+
switch (type) {
|
|
854
|
+
case "bigint":
|
|
855
|
+
return "INTEGER";
|
|
856
|
+
// SQLite uses INTEGER for all integer sizes
|
|
857
|
+
case "jsonb":
|
|
858
|
+
return "TEXT";
|
|
859
|
+
// Store JSON as TEXT in SQLite
|
|
860
|
+
default:
|
|
861
|
+
return super.getSqlType(type);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Alters table schema to add columns if they don't exist
|
|
866
|
+
* @param tableName Name of the table
|
|
867
|
+
* @param schema Schema of the table
|
|
868
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
869
|
+
*/
|
|
870
|
+
async alterTable({
|
|
871
|
+
tableName,
|
|
872
|
+
schema,
|
|
873
|
+
ifNotExists
|
|
874
|
+
}) {
|
|
875
|
+
const parsedTableName = parseSqlIdentifier(tableName, "table name");
|
|
876
|
+
try {
|
|
877
|
+
const pragmaQuery = `PRAGMA table_info(${parsedTableName})`;
|
|
878
|
+
const result = await this.client.execute(pragmaQuery);
|
|
879
|
+
const existingColumnNames = new Set(result.rows.map((row) => row.name.toLowerCase()));
|
|
880
|
+
for (const columnName of ifNotExists) {
|
|
881
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
882
|
+
const columnDef = schema[columnName];
|
|
883
|
+
const sqlType = this.getSqlType(columnDef.type);
|
|
884
|
+
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
885
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
886
|
+
const alterSql = `ALTER TABLE ${parsedTableName} ADD COLUMN "${columnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
887
|
+
await this.client.execute(alterSql);
|
|
888
|
+
this.logger?.debug?.(`Added column ${columnName} to table ${parsedTableName}`);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
} catch (error) {
|
|
892
|
+
this.logger?.error?.(
|
|
893
|
+
`Error altering table ${tableName}: ${error instanceof Error ? error.message : String(error)}`
|
|
894
|
+
);
|
|
895
|
+
throw new Error(`Failed to alter table ${tableName}: ${error}`);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
852
898
|
async clearTable({ tableName }) {
|
|
853
899
|
const parsedTableName = parseSqlIdentifier(tableName, "table name");
|
|
854
900
|
try {
|
|
@@ -962,22 +1008,83 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
962
1008
|
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata
|
|
963
1009
|
};
|
|
964
1010
|
}
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
}
|
|
970
|
-
|
|
1011
|
+
/**
|
|
1012
|
+
* @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
|
|
1013
|
+
*/
|
|
1014
|
+
async getThreadsByResourceId(args) {
|
|
1015
|
+
const { resourceId } = args;
|
|
1016
|
+
try {
|
|
1017
|
+
const baseQuery = `FROM ${TABLE_THREADS} WHERE resourceId = ?`;
|
|
1018
|
+
const queryParams = [resourceId];
|
|
1019
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
1020
|
+
id: row.id,
|
|
1021
|
+
resourceId: row.resourceId,
|
|
1022
|
+
title: row.title,
|
|
1023
|
+
createdAt: new Date(row.createdAt),
|
|
1024
|
+
// Convert string to Date
|
|
1025
|
+
updatedAt: new Date(row.updatedAt),
|
|
1026
|
+
// Convert string to Date
|
|
1027
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
1028
|
+
});
|
|
1029
|
+
const result = await this.client.execute({
|
|
1030
|
+
sql: `SELECT * ${baseQuery} ORDER BY createdAt DESC`,
|
|
1031
|
+
args: queryParams
|
|
1032
|
+
});
|
|
1033
|
+
if (!result.rows) {
|
|
1034
|
+
return [];
|
|
1035
|
+
}
|
|
1036
|
+
return result.rows.map(mapRowToStorageThreadType);
|
|
1037
|
+
} catch (error) {
|
|
1038
|
+
this.logger.error(`Error getting threads for resource ${resourceId}:`, error);
|
|
971
1039
|
return [];
|
|
972
1040
|
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
1041
|
+
}
|
|
1042
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
1043
|
+
const { resourceId, page = 0, perPage = 100 } = args;
|
|
1044
|
+
try {
|
|
1045
|
+
const baseQuery = `FROM ${TABLE_THREADS} WHERE resourceId = ?`;
|
|
1046
|
+
const queryParams = [resourceId];
|
|
1047
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
1048
|
+
id: row.id,
|
|
1049
|
+
resourceId: row.resourceId,
|
|
1050
|
+
title: row.title,
|
|
1051
|
+
createdAt: new Date(row.createdAt),
|
|
1052
|
+
// Convert string to Date
|
|
1053
|
+
updatedAt: new Date(row.updatedAt),
|
|
1054
|
+
// Convert string to Date
|
|
1055
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
1056
|
+
});
|
|
1057
|
+
const currentOffset = page * perPage;
|
|
1058
|
+
const countResult = await this.client.execute({
|
|
1059
|
+
sql: `SELECT COUNT(*) as count ${baseQuery}`,
|
|
1060
|
+
args: queryParams
|
|
1061
|
+
});
|
|
1062
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1063
|
+
if (total === 0) {
|
|
1064
|
+
return {
|
|
1065
|
+
threads: [],
|
|
1066
|
+
total: 0,
|
|
1067
|
+
page,
|
|
1068
|
+
perPage,
|
|
1069
|
+
hasMore: false
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
const dataResult = await this.client.execute({
|
|
1073
|
+
sql: `SELECT * ${baseQuery} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
1074
|
+
args: [...queryParams, perPage, currentOffset]
|
|
1075
|
+
});
|
|
1076
|
+
const threads = (dataResult.rows || []).map(mapRowToStorageThreadType);
|
|
1077
|
+
return {
|
|
1078
|
+
threads,
|
|
1079
|
+
total,
|
|
1080
|
+
page,
|
|
1081
|
+
perPage,
|
|
1082
|
+
hasMore: currentOffset + threads.length < total
|
|
1083
|
+
};
|
|
1084
|
+
} catch (error) {
|
|
1085
|
+
this.logger.error(`Error getting threads for resource ${resourceId}:`, error);
|
|
1086
|
+
return { threads: [], total: 0, page, perPage, hasMore: false };
|
|
1087
|
+
}
|
|
981
1088
|
}
|
|
982
1089
|
async saveThread({ thread }) {
|
|
983
1090
|
await this.insert({
|
|
@@ -1013,6 +1120,10 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1013
1120
|
return updatedThread;
|
|
1014
1121
|
}
|
|
1015
1122
|
async deleteThread({ threadId }) {
|
|
1123
|
+
await this.client.execute({
|
|
1124
|
+
sql: `DELETE FROM ${TABLE_MESSAGES} WHERE thread_id = ?`,
|
|
1125
|
+
args: [threadId]
|
|
1126
|
+
});
|
|
1016
1127
|
await this.client.execute({
|
|
1017
1128
|
sql: `DELETE FROM ${TABLE_THREADS} WHERE id = ?`,
|
|
1018
1129
|
args: [threadId]
|
|
@@ -1029,11 +1140,42 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1029
1140
|
content,
|
|
1030
1141
|
role: row.role,
|
|
1031
1142
|
createdAt: new Date(row.createdAt),
|
|
1032
|
-
threadId: row.thread_id
|
|
1143
|
+
threadId: row.thread_id,
|
|
1144
|
+
resourceId: row.resourceId
|
|
1033
1145
|
};
|
|
1034
1146
|
if (row.type && row.type !== `v2`) result.type = row.type;
|
|
1035
1147
|
return result;
|
|
1036
1148
|
}
|
|
1149
|
+
async _getIncludedMessages(threadId, selectBy) {
|
|
1150
|
+
const include = selectBy?.include;
|
|
1151
|
+
if (!include) return null;
|
|
1152
|
+
const includeIds = include.map((i) => i.id);
|
|
1153
|
+
const maxPrev = Math.max(...include.map((i) => i.withPreviousMessages || 0));
|
|
1154
|
+
const maxNext = Math.max(...include.map((i) => i.withNextMessages || 0));
|
|
1155
|
+
const includeResult = await this.client.execute({
|
|
1156
|
+
sql: `
|
|
1157
|
+
WITH numbered_messages AS (
|
|
1158
|
+
SELECT
|
|
1159
|
+
id, content, role, type, "createdAt", thread_id,
|
|
1160
|
+
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
1161
|
+
FROM "${TABLE_MESSAGES}"
|
|
1162
|
+
WHERE thread_id = ?
|
|
1163
|
+
),
|
|
1164
|
+
target_positions AS (
|
|
1165
|
+
SELECT row_num as target_pos
|
|
1166
|
+
FROM numbered_messages
|
|
1167
|
+
WHERE id IN (${includeIds.map(() => "?").join(", ")})
|
|
1168
|
+
)
|
|
1169
|
+
SELECT DISTINCT m.*
|
|
1170
|
+
FROM numbered_messages m
|
|
1171
|
+
CROSS JOIN target_positions t
|
|
1172
|
+
WHERE m.row_num BETWEEN (t.target_pos - ?) AND (t.target_pos + ?)
|
|
1173
|
+
ORDER BY m."createdAt" ASC
|
|
1174
|
+
`,
|
|
1175
|
+
args: [threadId, ...includeIds, maxPrev, maxNext]
|
|
1176
|
+
});
|
|
1177
|
+
return includeResult.rows?.map((row) => this.parseRow(row));
|
|
1178
|
+
}
|
|
1037
1179
|
async getMessages({
|
|
1038
1180
|
threadId,
|
|
1039
1181
|
selectBy,
|
|
@@ -1043,60 +1185,21 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1043
1185
|
const messages = [];
|
|
1044
1186
|
const limit = typeof selectBy?.last === `number` ? selectBy.last : 40;
|
|
1045
1187
|
if (selectBy?.include?.length) {
|
|
1046
|
-
const
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
const includeResult = await this.client.execute({
|
|
1050
|
-
sql: `
|
|
1051
|
-
WITH numbered_messages AS (
|
|
1052
|
-
SELECT
|
|
1053
|
-
id,
|
|
1054
|
-
content,
|
|
1055
|
-
role,
|
|
1056
|
-
type,
|
|
1057
|
-
"createdAt",
|
|
1058
|
-
thread_id,
|
|
1059
|
-
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
1060
|
-
FROM "${TABLE_MESSAGES}"
|
|
1061
|
-
WHERE thread_id = ?
|
|
1062
|
-
),
|
|
1063
|
-
target_positions AS (
|
|
1064
|
-
SELECT row_num as target_pos
|
|
1065
|
-
FROM numbered_messages
|
|
1066
|
-
WHERE id IN (${includeIds.map(() => "?").join(", ")})
|
|
1067
|
-
)
|
|
1068
|
-
SELECT DISTINCT m.*
|
|
1069
|
-
FROM numbered_messages m
|
|
1070
|
-
CROSS JOIN target_positions t
|
|
1071
|
-
WHERE m.row_num BETWEEN (t.target_pos - ?) AND (t.target_pos + ?)
|
|
1072
|
-
ORDER BY m."createdAt" ASC
|
|
1073
|
-
`,
|
|
1074
|
-
args: [threadId, ...includeIds, maxPrev, maxNext]
|
|
1075
|
-
});
|
|
1076
|
-
if (includeResult.rows) {
|
|
1077
|
-
messages.push(...includeResult.rows.map((row) => this.parseRow(row)));
|
|
1188
|
+
const includeMessages = await this._getIncludedMessages(threadId, selectBy);
|
|
1189
|
+
if (includeMessages) {
|
|
1190
|
+
messages.push(...includeMessages);
|
|
1078
1191
|
}
|
|
1079
1192
|
}
|
|
1080
1193
|
const excludeIds = messages.map((m) => m.id);
|
|
1081
1194
|
const remainingSql = `
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
thread_id
|
|
1089
|
-
FROM "${TABLE_MESSAGES}"
|
|
1090
|
-
WHERE thread_id = ?
|
|
1091
|
-
${excludeIds.length ? `AND id NOT IN (${excludeIds.map(() => "?").join(", ")})` : ""}
|
|
1092
|
-
ORDER BY "createdAt" DESC
|
|
1093
|
-
LIMIT ?
|
|
1094
|
-
`;
|
|
1195
|
+
SELECT id, content, role, type, "createdAt", thread_id
|
|
1196
|
+
FROM "${TABLE_MESSAGES}"
|
|
1197
|
+
WHERE thread_id = ?
|
|
1198
|
+
${excludeIds.length ? `AND id NOT IN (${excludeIds.map(() => "?").join(", ")})` : ""}
|
|
1199
|
+
ORDER BY "createdAt" DESC LIMIT ?
|
|
1200
|
+
`;
|
|
1095
1201
|
const remainingArgs = [threadId, ...excludeIds.length ? excludeIds : [], limit];
|
|
1096
|
-
const remainingResult = await this.client.execute({
|
|
1097
|
-
sql: remainingSql,
|
|
1098
|
-
args: remainingArgs
|
|
1099
|
-
});
|
|
1202
|
+
const remainingResult = await this.client.execute({ sql: remainingSql, args: remainingArgs });
|
|
1100
1203
|
if (remainingResult.rows) {
|
|
1101
1204
|
messages.push(...remainingResult.rows.map((row) => this.parseRow(row)));
|
|
1102
1205
|
}
|
|
@@ -1109,6 +1212,63 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1109
1212
|
throw error;
|
|
1110
1213
|
}
|
|
1111
1214
|
}
|
|
1215
|
+
async getMessagesPaginated(args) {
|
|
1216
|
+
const { threadId, format, selectBy } = args;
|
|
1217
|
+
const { page = 0, perPage = 40, dateRange } = selectBy?.pagination || {};
|
|
1218
|
+
const fromDate = dateRange?.start;
|
|
1219
|
+
const toDate = dateRange?.end;
|
|
1220
|
+
const messages = [];
|
|
1221
|
+
if (selectBy?.include?.length) {
|
|
1222
|
+
const includeMessages = await this._getIncludedMessages(threadId, selectBy);
|
|
1223
|
+
if (includeMessages) {
|
|
1224
|
+
messages.push(...includeMessages);
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
try {
|
|
1228
|
+
const currentOffset = page * perPage;
|
|
1229
|
+
const conditions = [`thread_id = ?`];
|
|
1230
|
+
const queryParams = [threadId];
|
|
1231
|
+
if (fromDate) {
|
|
1232
|
+
conditions.push(`"createdAt" >= ?`);
|
|
1233
|
+
queryParams.push(fromDate.toISOString());
|
|
1234
|
+
}
|
|
1235
|
+
if (toDate) {
|
|
1236
|
+
conditions.push(`"createdAt" <= ?`);
|
|
1237
|
+
queryParams.push(toDate.toISOString());
|
|
1238
|
+
}
|
|
1239
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1240
|
+
const countResult = await this.client.execute({
|
|
1241
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_MESSAGES} ${whereClause}`,
|
|
1242
|
+
args: queryParams
|
|
1243
|
+
});
|
|
1244
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1245
|
+
if (total === 0) {
|
|
1246
|
+
return {
|
|
1247
|
+
messages: [],
|
|
1248
|
+
total: 0,
|
|
1249
|
+
page,
|
|
1250
|
+
perPage,
|
|
1251
|
+
hasMore: false
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
const dataResult = await this.client.execute({
|
|
1255
|
+
sql: `SELECT id, content, role, type, "createdAt", thread_id FROM ${TABLE_MESSAGES} ${whereClause} ORDER BY "createdAt" DESC LIMIT ? OFFSET ?`,
|
|
1256
|
+
args: [...queryParams, perPage, currentOffset]
|
|
1257
|
+
});
|
|
1258
|
+
messages.push(...(dataResult.rows || []).map((row) => this.parseRow(row)));
|
|
1259
|
+
const messagesToReturn = format === "v1" ? new MessageList().add(messages, "memory").get.all.v1() : new MessageList().add(messages, "memory").get.all.v2();
|
|
1260
|
+
return {
|
|
1261
|
+
messages: messagesToReturn,
|
|
1262
|
+
total,
|
|
1263
|
+
page,
|
|
1264
|
+
perPage,
|
|
1265
|
+
hasMore: currentOffset + messages.length < total
|
|
1266
|
+
};
|
|
1267
|
+
} catch (error) {
|
|
1268
|
+
this.logger.error("Error getting paginated messages:", error);
|
|
1269
|
+
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1112
1272
|
async saveMessages({
|
|
1113
1273
|
messages,
|
|
1114
1274
|
format
|
|
@@ -1167,6 +1327,7 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1167
1327
|
createdAt: row.created_at
|
|
1168
1328
|
};
|
|
1169
1329
|
}
|
|
1330
|
+
/** @deprecated use getEvals instead */
|
|
1170
1331
|
async getEvalsByAgentName(agentName, type) {
|
|
1171
1332
|
try {
|
|
1172
1333
|
const baseQuery = `SELECT * FROM ${TABLE_EVALS} WHERE agent_name = ?`;
|
|
@@ -1184,93 +1345,150 @@ var LibSQLStore = class extends MastraStorage {
|
|
|
1184
1345
|
throw error;
|
|
1185
1346
|
}
|
|
1186
1347
|
}
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
page,
|
|
1192
|
-
perPage,
|
|
1193
|
-
attributes,
|
|
1194
|
-
filters,
|
|
1195
|
-
fromDate,
|
|
1196
|
-
toDate
|
|
1197
|
-
} = {
|
|
1198
|
-
page: 0,
|
|
1199
|
-
perPage: 100
|
|
1200
|
-
}) {
|
|
1201
|
-
const limit = perPage;
|
|
1202
|
-
const offset = page * perPage;
|
|
1203
|
-
const args = [];
|
|
1348
|
+
async getEvals(options = {}) {
|
|
1349
|
+
const { agentName, type, page = 0, perPage = 100, dateRange } = options;
|
|
1350
|
+
const fromDate = dateRange?.start;
|
|
1351
|
+
const toDate = dateRange?.end;
|
|
1204
1352
|
const conditions = [];
|
|
1205
|
-
|
|
1206
|
-
|
|
1353
|
+
const queryParams = [];
|
|
1354
|
+
if (agentName) {
|
|
1355
|
+
conditions.push(`agent_name = ?`);
|
|
1356
|
+
queryParams.push(agentName);
|
|
1207
1357
|
}
|
|
1208
|
-
if (
|
|
1209
|
-
conditions.push(
|
|
1210
|
-
}
|
|
1211
|
-
|
|
1212
|
-
Object.keys(attributes).forEach((key) => {
|
|
1213
|
-
conditions.push(`attributes->>'$.${key}' = ?`);
|
|
1214
|
-
});
|
|
1215
|
-
}
|
|
1216
|
-
if (filters) {
|
|
1217
|
-
Object.entries(filters).forEach(([key, _value]) => {
|
|
1218
|
-
conditions.push(`${key} = ?`);
|
|
1219
|
-
});
|
|
1358
|
+
if (type === "test") {
|
|
1359
|
+
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
1360
|
+
} else if (type === "live") {
|
|
1361
|
+
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
1220
1362
|
}
|
|
1221
1363
|
if (fromDate) {
|
|
1222
|
-
conditions.push(
|
|
1364
|
+
conditions.push(`created_at >= ?`);
|
|
1365
|
+
queryParams.push(fromDate.toISOString());
|
|
1223
1366
|
}
|
|
1224
1367
|
if (toDate) {
|
|
1225
|
-
conditions.push(
|
|
1368
|
+
conditions.push(`created_at <= ?`);
|
|
1369
|
+
queryParams.push(toDate.toISOString());
|
|
1226
1370
|
}
|
|
1227
1371
|
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1372
|
+
const countResult = await this.client.execute({
|
|
1373
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_EVALS} ${whereClause}`,
|
|
1374
|
+
args: queryParams
|
|
1375
|
+
});
|
|
1376
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1377
|
+
const currentOffset = page * perPage;
|
|
1378
|
+
const hasMore = currentOffset + perPage < total;
|
|
1379
|
+
if (total === 0) {
|
|
1380
|
+
return {
|
|
1381
|
+
evals: [],
|
|
1382
|
+
total: 0,
|
|
1383
|
+
page,
|
|
1384
|
+
perPage,
|
|
1385
|
+
hasMore: false
|
|
1386
|
+
};
|
|
1387
|
+
}
|
|
1388
|
+
const dataResult = await this.client.execute({
|
|
1389
|
+
sql: `SELECT * FROM ${TABLE_EVALS} ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
|
|
1390
|
+
args: [...queryParams, perPage, currentOffset]
|
|
1391
|
+
});
|
|
1392
|
+
return {
|
|
1393
|
+
evals: dataResult.rows?.map((row) => this.transformEvalRow(row)) ?? [],
|
|
1394
|
+
total,
|
|
1395
|
+
page,
|
|
1396
|
+
perPage,
|
|
1397
|
+
hasMore
|
|
1398
|
+
};
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* @deprecated use getTracesPaginated instead.
|
|
1402
|
+
*/
|
|
1403
|
+
async getTraces(args) {
|
|
1404
|
+
if (args.fromDate || args.toDate) {
|
|
1405
|
+
args.dateRange = {
|
|
1406
|
+
start: args.fromDate,
|
|
1407
|
+
end: args.toDate
|
|
1408
|
+
};
|
|
1409
|
+
}
|
|
1410
|
+
const result = await this.getTracesPaginated(args);
|
|
1411
|
+
return result.traces;
|
|
1412
|
+
}
|
|
1413
|
+
async getTracesPaginated(args) {
|
|
1414
|
+
const { name, scope, page = 0, perPage = 100, attributes, filters, dateRange } = args;
|
|
1415
|
+
const fromDate = dateRange?.start;
|
|
1416
|
+
const toDate = dateRange?.end;
|
|
1417
|
+
const currentOffset = page * perPage;
|
|
1418
|
+
const queryArgs = [];
|
|
1419
|
+
const conditions = [];
|
|
1228
1420
|
if (name) {
|
|
1229
|
-
|
|
1421
|
+
conditions.push("name LIKE ?");
|
|
1422
|
+
queryArgs.push(`${name}%`);
|
|
1230
1423
|
}
|
|
1231
1424
|
if (scope) {
|
|
1232
|
-
|
|
1425
|
+
conditions.push("scope = ?");
|
|
1426
|
+
queryArgs.push(scope);
|
|
1233
1427
|
}
|
|
1234
1428
|
if (attributes) {
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1429
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
1430
|
+
conditions.push(`json_extract(attributes, '$.${key}') = ?`);
|
|
1431
|
+
queryArgs.push(value);
|
|
1432
|
+
});
|
|
1238
1433
|
}
|
|
1239
1434
|
if (filters) {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1435
|
+
Object.entries(filters).forEach(([key, value]) => {
|
|
1436
|
+
conditions.push(`${parseSqlIdentifier(key, "filter key")} = ?`);
|
|
1437
|
+
queryArgs.push(value);
|
|
1438
|
+
});
|
|
1243
1439
|
}
|
|
1244
1440
|
if (fromDate) {
|
|
1245
|
-
|
|
1441
|
+
conditions.push("createdAt >= ?");
|
|
1442
|
+
queryArgs.push(fromDate.toISOString());
|
|
1246
1443
|
}
|
|
1247
1444
|
if (toDate) {
|
|
1248
|
-
|
|
1445
|
+
conditions.push("createdAt <= ?");
|
|
1446
|
+
queryArgs.push(toDate.toISOString());
|
|
1249
1447
|
}
|
|
1250
|
-
|
|
1251
|
-
const
|
|
1252
|
-
sql: `SELECT * FROM ${TABLE_TRACES} ${whereClause}
|
|
1253
|
-
args
|
|
1448
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1449
|
+
const countResult = await this.client.execute({
|
|
1450
|
+
sql: `SELECT COUNT(*) as count FROM ${TABLE_TRACES} ${whereClause}`,
|
|
1451
|
+
args: queryArgs
|
|
1254
1452
|
});
|
|
1255
|
-
|
|
1256
|
-
|
|
1453
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1454
|
+
if (total === 0) {
|
|
1455
|
+
return {
|
|
1456
|
+
traces: [],
|
|
1457
|
+
total: 0,
|
|
1458
|
+
page,
|
|
1459
|
+
perPage,
|
|
1460
|
+
hasMore: false
|
|
1461
|
+
};
|
|
1257
1462
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1463
|
+
const dataResult = await this.client.execute({
|
|
1464
|
+
sql: `SELECT * FROM ${TABLE_TRACES} ${whereClause} ORDER BY "startTime" DESC LIMIT ? OFFSET ?`,
|
|
1465
|
+
args: [...queryArgs, perPage, currentOffset]
|
|
1466
|
+
});
|
|
1467
|
+
const traces = dataResult.rows?.map(
|
|
1468
|
+
(row) => ({
|
|
1469
|
+
id: row.id,
|
|
1470
|
+
parentSpanId: row.parentSpanId,
|
|
1471
|
+
traceId: row.traceId,
|
|
1472
|
+
name: row.name,
|
|
1473
|
+
scope: row.scope,
|
|
1474
|
+
kind: row.kind,
|
|
1475
|
+
status: safelyParseJSON(row.status),
|
|
1476
|
+
events: safelyParseJSON(row.events),
|
|
1477
|
+
links: safelyParseJSON(row.links),
|
|
1478
|
+
attributes: safelyParseJSON(row.attributes),
|
|
1479
|
+
startTime: row.startTime,
|
|
1480
|
+
endTime: row.endTime,
|
|
1481
|
+
other: safelyParseJSON(row.other),
|
|
1482
|
+
createdAt: row.createdAt
|
|
1483
|
+
})
|
|
1484
|
+
) ?? [];
|
|
1485
|
+
return {
|
|
1486
|
+
traces,
|
|
1487
|
+
total,
|
|
1488
|
+
page,
|
|
1489
|
+
perPage,
|
|
1490
|
+
hasMore: currentOffset + traces.length < total
|
|
1491
|
+
};
|
|
1274
1492
|
}
|
|
1275
1493
|
async getWorkflowRuns({
|
|
1276
1494
|
workflowName,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mastra/libsql",
|
|
3
|
-
"version": "0.10.1",
|
|
3
|
+
"version": "0.10.2-alpha.1",
|
|
4
4
|
"description": "Libsql provider for Mastra - includes both vector and db storage capabilities",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,18 +20,18 @@
|
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@libsql/client": "^0.15.
|
|
23
|
+
"@libsql/client": "^0.15.8"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@microsoft/api-extractor": "^7.52.
|
|
27
|
-
"@types/node": "^20.17.
|
|
28
|
-
"eslint": "^9.
|
|
29
|
-
"tsup": "^8.
|
|
26
|
+
"@microsoft/api-extractor": "^7.52.8",
|
|
27
|
+
"@types/node": "^20.17.57",
|
|
28
|
+
"eslint": "^9.28.0",
|
|
29
|
+
"tsup": "^8.5.0",
|
|
30
30
|
"typescript": "^5.8.3",
|
|
31
|
-
"vitest": "^3.
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
34
|
-
"@internal/
|
|
31
|
+
"vitest": "^3.2.2",
|
|
32
|
+
"@mastra/core": "0.10.4-alpha.1",
|
|
33
|
+
"@internal/storage-test-utils": "0.0.6",
|
|
34
|
+
"@internal/lint": "0.0.10"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@mastra/core": "^0.10.2-alpha.0"
|