@mastra/libsql 0.0.0-mcp-changeset-20250707162621 → 0.0.0-memory-system-message-error-20250813233316
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/CHANGELOG.md +288 -9
- package/LICENSE.md +12 -4
- package/dist/index.cjs +1469 -868
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1460 -859
- package/dist/index.js.map +1 -0
- package/dist/storage/domains/legacy-evals/index.d.ts +18 -0
- package/dist/storage/domains/legacy-evals/index.d.ts.map +1 -0
- package/dist/storage/domains/memory/index.d.ts +87 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -0
- package/dist/storage/domains/operations/index.d.ts +61 -0
- package/dist/storage/domains/operations/index.d.ts.map +1 -0
- package/dist/storage/domains/scores/index.d.ts +46 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -0
- package/dist/storage/domains/traces/index.d.ts +21 -0
- package/dist/storage/domains/traces/index.d.ts.map +1 -0
- package/dist/storage/domains/utils.d.ts +16 -0
- package/dist/storage/domains/utils.d.ts.map +1 -0
- package/dist/storage/domains/workflows/index.d.ts +34 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -0
- package/dist/storage/index.d.ts +222 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/vector/filter.d.ts +29 -0
- package/dist/vector/filter.d.ts.map +1 -0
- package/dist/vector/index.d.ts +72 -0
- package/dist/vector/index.d.ts.map +1 -0
- package/dist/vector/prompt.d.ts +6 -0
- package/dist/vector/prompt.d.ts.map +1 -0
- package/dist/vector/sql-builder.d.ts +9 -0
- package/dist/vector/sql-builder.d.ts.map +1 -0
- package/package.json +11 -10
- package/src/storage/domains/legacy-evals/index.ts +149 -0
- package/src/storage/domains/memory/index.ts +881 -0
- package/src/storage/domains/operations/index.ts +296 -0
- package/src/storage/domains/scores/index.ts +226 -0
- package/src/storage/domains/traces/index.ts +150 -0
- package/src/storage/domains/utils.ts +67 -0
- package/src/storage/domains/workflows/index.ts +198 -0
- package/src/storage/index.test.ts +2 -573
- package/src/storage/index.ts +194 -1336
- package/src/vector/index.test.ts +22 -1
- package/src/vector/index.ts +2 -2
- package/src/vector/sql-builder.ts +51 -33
- package/tsconfig.build.json +9 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +17 -0
- package/dist/_tsup-dts-rollup.d.cts +0 -332
- package/dist/_tsup-dts-rollup.d.ts +0 -332
- package/dist/index.d.cts +0 -6
package/dist/index.cjs
CHANGED
|
@@ -5,8 +5,9 @@ var error = require('@mastra/core/error');
|
|
|
5
5
|
var utils = require('@mastra/core/utils');
|
|
6
6
|
var vector = require('@mastra/core/vector');
|
|
7
7
|
var filter = require('@mastra/core/vector/filter');
|
|
8
|
-
var agent = require('@mastra/core/agent');
|
|
9
8
|
var storage = require('@mastra/core/storage');
|
|
9
|
+
var core = require('@mastra/core');
|
|
10
|
+
var agent = require('@mastra/core/agent');
|
|
10
11
|
|
|
11
12
|
// src/vector/index.ts
|
|
12
13
|
var LibSQLFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
@@ -77,11 +78,11 @@ var LibSQLFilterTranslator = class extends filter.BaseFilterTranslator {
|
|
|
77
78
|
};
|
|
78
79
|
var createBasicOperator = (symbol) => {
|
|
79
80
|
return (key, value) => {
|
|
80
|
-
const
|
|
81
|
+
const jsonPath = getJsonPath(key);
|
|
81
82
|
return {
|
|
82
83
|
sql: `CASE
|
|
83
|
-
WHEN ? IS NULL THEN json_extract(metadata,
|
|
84
|
-
ELSE json_extract(metadata,
|
|
84
|
+
WHEN ? IS NULL THEN json_extract(metadata, ${jsonPath}) IS ${symbol === "=" ? "" : "NOT"} NULL
|
|
85
|
+
ELSE json_extract(metadata, ${jsonPath}) ${symbol} ?
|
|
85
86
|
END`,
|
|
86
87
|
needsValue: true,
|
|
87
88
|
transformValue: () => {
|
|
@@ -92,16 +93,19 @@ var createBasicOperator = (symbol) => {
|
|
|
92
93
|
};
|
|
93
94
|
var createNumericOperator = (symbol) => {
|
|
94
95
|
return (key) => {
|
|
95
|
-
const
|
|
96
|
+
const jsonPath = getJsonPath(key);
|
|
96
97
|
return {
|
|
97
|
-
sql: `CAST(json_extract(metadata,
|
|
98
|
+
sql: `CAST(json_extract(metadata, ${jsonPath}) AS NUMERIC) ${symbol} ?`,
|
|
98
99
|
needsValue: true
|
|
99
100
|
};
|
|
100
101
|
};
|
|
101
102
|
};
|
|
102
|
-
var validateJsonArray = (key) =>
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
var validateJsonArray = (key) => {
|
|
104
|
+
const jsonPath = getJsonPath(key);
|
|
105
|
+
return `json_valid(json_extract(metadata, ${jsonPath}))
|
|
106
|
+
AND json_type(json_extract(metadata, ${jsonPath})) = 'array'`;
|
|
107
|
+
};
|
|
108
|
+
var pattern = /json_extract\(metadata, '\$\.(?:"[^"]*"(?:\."[^"]*")*|[^']+)'\)/g;
|
|
105
109
|
function buildElemMatchConditions(value) {
|
|
106
110
|
const conditions = Object.entries(value).map(([field, fieldValue]) => {
|
|
107
111
|
if (field.startsWith("$")) {
|
|
@@ -110,12 +114,13 @@ function buildElemMatchConditions(value) {
|
|
|
110
114
|
return { sql: elemSql, values };
|
|
111
115
|
} else if (typeof fieldValue === "object" && !Array.isArray(fieldValue)) {
|
|
112
116
|
const { sql, values } = buildCondition(field, fieldValue);
|
|
113
|
-
const
|
|
117
|
+
const jsonPath = parseJsonPathKey(field);
|
|
118
|
+
const elemSql = sql.replace(pattern, `json_extract(elem.value, '$.${jsonPath}')`);
|
|
114
119
|
return { sql: elemSql, values };
|
|
115
120
|
} else {
|
|
116
|
-
const
|
|
121
|
+
const jsonPath = parseJsonPathKey(field);
|
|
117
122
|
return {
|
|
118
|
-
sql: `json_extract(elem.value, '
|
|
123
|
+
sql: `json_extract(elem.value, '$.${jsonPath}') = ?`,
|
|
119
124
|
values: [fieldValue]
|
|
120
125
|
};
|
|
121
126
|
}
|
|
@@ -131,7 +136,7 @@ var FILTER_OPERATORS = {
|
|
|
131
136
|
$lte: createNumericOperator("<="),
|
|
132
137
|
// Array Operators
|
|
133
138
|
$in: (key, value) => {
|
|
134
|
-
const
|
|
139
|
+
const jsonPath = getJsonPath(key);
|
|
135
140
|
const arr = Array.isArray(value) ? value : [value];
|
|
136
141
|
if (arr.length === 0) {
|
|
137
142
|
return { sql: "1 = 0", needsValue: true, transformValue: () => [] };
|
|
@@ -140,12 +145,12 @@ var FILTER_OPERATORS = {
|
|
|
140
145
|
return {
|
|
141
146
|
sql: `(
|
|
142
147
|
CASE
|
|
143
|
-
WHEN ${validateJsonArray(
|
|
148
|
+
WHEN ${validateJsonArray(key)} THEN
|
|
144
149
|
EXISTS (
|
|
145
|
-
SELECT 1 FROM json_each(json_extract(metadata,
|
|
150
|
+
SELECT 1 FROM json_each(json_extract(metadata, ${jsonPath})) as elem
|
|
146
151
|
WHERE elem.value IN (SELECT value FROM json_each(?))
|
|
147
152
|
)
|
|
148
|
-
ELSE json_extract(metadata,
|
|
153
|
+
ELSE json_extract(metadata, ${jsonPath}) IN (${paramPlaceholders})
|
|
149
154
|
END
|
|
150
155
|
)`,
|
|
151
156
|
needsValue: true,
|
|
@@ -153,7 +158,7 @@ var FILTER_OPERATORS = {
|
|
|
153
158
|
};
|
|
154
159
|
},
|
|
155
160
|
$nin: (key, value) => {
|
|
156
|
-
const
|
|
161
|
+
const jsonPath = getJsonPath(key);
|
|
157
162
|
const arr = Array.isArray(value) ? value : [value];
|
|
158
163
|
if (arr.length === 0) {
|
|
159
164
|
return { sql: "1 = 1", needsValue: true, transformValue: () => [] };
|
|
@@ -162,12 +167,12 @@ var FILTER_OPERATORS = {
|
|
|
162
167
|
return {
|
|
163
168
|
sql: `(
|
|
164
169
|
CASE
|
|
165
|
-
WHEN ${validateJsonArray(
|
|
170
|
+
WHEN ${validateJsonArray(key)} THEN
|
|
166
171
|
NOT EXISTS (
|
|
167
|
-
SELECT 1 FROM json_each(json_extract(metadata,
|
|
172
|
+
SELECT 1 FROM json_each(json_extract(metadata, ${jsonPath})) as elem
|
|
168
173
|
WHERE elem.value IN (SELECT value FROM json_each(?))
|
|
169
174
|
)
|
|
170
|
-
ELSE json_extract(metadata,
|
|
175
|
+
ELSE json_extract(metadata, ${jsonPath}) NOT IN (${paramPlaceholders})
|
|
171
176
|
END
|
|
172
177
|
)`,
|
|
173
178
|
needsValue: true,
|
|
@@ -175,7 +180,7 @@ var FILTER_OPERATORS = {
|
|
|
175
180
|
};
|
|
176
181
|
},
|
|
177
182
|
$all: (key, value) => {
|
|
178
|
-
const
|
|
183
|
+
const jsonPath = getJsonPath(key);
|
|
179
184
|
let sql;
|
|
180
185
|
const arrayValue = Array.isArray(value) ? value : [value];
|
|
181
186
|
if (arrayValue.length === 0) {
|
|
@@ -183,13 +188,13 @@ var FILTER_OPERATORS = {
|
|
|
183
188
|
} else {
|
|
184
189
|
sql = `(
|
|
185
190
|
CASE
|
|
186
|
-
WHEN ${validateJsonArray(
|
|
191
|
+
WHEN ${validateJsonArray(key)} THEN
|
|
187
192
|
NOT EXISTS (
|
|
188
193
|
SELECT value
|
|
189
194
|
FROM json_each(?)
|
|
190
195
|
WHERE value NOT IN (
|
|
191
196
|
SELECT value
|
|
192
|
-
FROM json_each(json_extract(metadata,
|
|
197
|
+
FROM json_each(json_extract(metadata, ${jsonPath}))
|
|
193
198
|
)
|
|
194
199
|
)
|
|
195
200
|
ELSE FALSE
|
|
@@ -208,7 +213,7 @@ var FILTER_OPERATORS = {
|
|
|
208
213
|
};
|
|
209
214
|
},
|
|
210
215
|
$elemMatch: (key, value) => {
|
|
211
|
-
const
|
|
216
|
+
const jsonPath = getJsonPath(key);
|
|
212
217
|
if (typeof value !== "object" || Array.isArray(value)) {
|
|
213
218
|
throw new Error("$elemMatch requires an object with conditions");
|
|
214
219
|
}
|
|
@@ -216,10 +221,10 @@ var FILTER_OPERATORS = {
|
|
|
216
221
|
return {
|
|
217
222
|
sql: `(
|
|
218
223
|
CASE
|
|
219
|
-
WHEN ${validateJsonArray(
|
|
224
|
+
WHEN ${validateJsonArray(key)} THEN
|
|
220
225
|
EXISTS (
|
|
221
226
|
SELECT 1
|
|
222
|
-
FROM json_each(json_extract(metadata,
|
|
227
|
+
FROM json_each(json_extract(metadata, ${jsonPath})) as elem
|
|
223
228
|
WHERE ${conditions.map((c) => c.sql).join(" AND ")}
|
|
224
229
|
)
|
|
225
230
|
ELSE FALSE
|
|
@@ -231,9 +236,9 @@ var FILTER_OPERATORS = {
|
|
|
231
236
|
},
|
|
232
237
|
// Element Operators
|
|
233
238
|
$exists: (key) => {
|
|
234
|
-
const
|
|
239
|
+
const jsonPath = getJsonPath(key);
|
|
235
240
|
return {
|
|
236
|
-
sql: `json_extract(metadata,
|
|
241
|
+
sql: `json_extract(metadata, ${jsonPath}) IS NOT NULL`,
|
|
237
242
|
needsValue: false
|
|
238
243
|
};
|
|
239
244
|
},
|
|
@@ -252,12 +257,12 @@ var FILTER_OPERATORS = {
|
|
|
252
257
|
needsValue: false
|
|
253
258
|
}),
|
|
254
259
|
$size: (key, paramIndex) => {
|
|
255
|
-
const
|
|
260
|
+
const jsonPath = getJsonPath(key);
|
|
256
261
|
return {
|
|
257
262
|
sql: `(
|
|
258
263
|
CASE
|
|
259
|
-
WHEN json_type(json_extract(metadata,
|
|
260
|
-
json_array_length(json_extract(metadata,
|
|
264
|
+
WHEN json_type(json_extract(metadata, ${jsonPath})) = 'array' THEN
|
|
265
|
+
json_array_length(json_extract(metadata, ${jsonPath})) = $${paramIndex}
|
|
261
266
|
ELSE FALSE
|
|
262
267
|
END
|
|
263
268
|
)`,
|
|
@@ -376,7 +381,14 @@ function isFilterResult(obj) {
|
|
|
376
381
|
}
|
|
377
382
|
var parseJsonPathKey = (key) => {
|
|
378
383
|
const parsedKey = utils.parseFieldKey(key);
|
|
379
|
-
|
|
384
|
+
if (parsedKey.includes(".")) {
|
|
385
|
+
return parsedKey.split(".").map((segment) => `"${segment}"`).join(".");
|
|
386
|
+
}
|
|
387
|
+
return parsedKey;
|
|
388
|
+
};
|
|
389
|
+
var getJsonPath = (key) => {
|
|
390
|
+
const jsonPathKey = parseJsonPathKey(key);
|
|
391
|
+
return `'$.${jsonPathKey}'`;
|
|
380
392
|
};
|
|
381
393
|
function escapeLikePattern(str) {
|
|
382
394
|
return str.replace(/([%_\\])/g, "\\$1");
|
|
@@ -401,8 +413,9 @@ function buildCondition(key, value, parentPath) {
|
|
|
401
413
|
return handleLogicalOperator(key, value);
|
|
402
414
|
}
|
|
403
415
|
if (!value || typeof value !== "object") {
|
|
416
|
+
const jsonPath = getJsonPath(key);
|
|
404
417
|
return {
|
|
405
|
-
sql: `json_extract(metadata,
|
|
418
|
+
sql: `json_extract(metadata, ${jsonPath}) = ?`,
|
|
406
419
|
values: [value]
|
|
407
420
|
};
|
|
408
421
|
}
|
|
@@ -548,7 +561,8 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
548
561
|
topK = 10,
|
|
549
562
|
filter,
|
|
550
563
|
includeVector = false,
|
|
551
|
-
minScore =
|
|
564
|
+
minScore = -1
|
|
565
|
+
// Default to -1 to include all results (cosine similarity ranges from -1 to 1)
|
|
552
566
|
}) {
|
|
553
567
|
try {
|
|
554
568
|
if (!Number.isInteger(topK) || topK <= 0) {
|
|
@@ -651,7 +665,7 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
651
665
|
await tx.commit();
|
|
652
666
|
return vectorIds;
|
|
653
667
|
} catch (error) {
|
|
654
|
-
await tx.rollback();
|
|
668
|
+
!tx.closed && await tx.rollback();
|
|
655
669
|
if (error instanceof Error && error.message?.includes("dimensions are different")) {
|
|
656
670
|
const match = error.message.match(/dimensions are different: (\d+) != (\d+)/);
|
|
657
671
|
if (match) {
|
|
@@ -906,270 +920,235 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
906
920
|
});
|
|
907
921
|
}
|
|
908
922
|
};
|
|
909
|
-
function
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
923
|
+
function transformEvalRow(row) {
|
|
924
|
+
const resultValue = JSON.parse(row.result);
|
|
925
|
+
const testInfoValue = row.test_info ? JSON.parse(row.test_info) : void 0;
|
|
926
|
+
if (!resultValue || typeof resultValue !== "object" || !("score" in resultValue)) {
|
|
927
|
+
throw new Error(`Invalid MetricResult format: ${JSON.stringify(resultValue)}`);
|
|
914
928
|
}
|
|
929
|
+
return {
|
|
930
|
+
input: row.input,
|
|
931
|
+
output: row.output,
|
|
932
|
+
result: resultValue,
|
|
933
|
+
agentName: row.agent_name,
|
|
934
|
+
metricName: row.metric_name,
|
|
935
|
+
instructions: row.instructions,
|
|
936
|
+
testInfo: testInfoValue,
|
|
937
|
+
globalRunId: row.global_run_id,
|
|
938
|
+
runId: row.run_id,
|
|
939
|
+
createdAt: row.created_at
|
|
940
|
+
};
|
|
915
941
|
}
|
|
916
|
-
var
|
|
942
|
+
var LegacyEvalsLibSQL = class extends storage.LegacyEvalsStorage {
|
|
917
943
|
client;
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
super({ name: `LibSQLStore` });
|
|
922
|
-
this.maxRetries = config.maxRetries ?? 5;
|
|
923
|
-
this.initialBackoffMs = config.initialBackoffMs ?? 100;
|
|
924
|
-
if (config.url.endsWith(":memory:")) {
|
|
925
|
-
this.shouldCacheInit = false;
|
|
926
|
-
}
|
|
927
|
-
this.client = client.createClient(config);
|
|
928
|
-
if (config.url.startsWith("file:") || config.url.includes(":memory:")) {
|
|
929
|
-
this.client.execute("PRAGMA journal_mode=WAL;").then(() => this.logger.debug("LibSQLStore: PRAGMA journal_mode=WAL set.")).catch((err) => this.logger.warn("LibSQLStore: Failed to set PRAGMA journal_mode=WAL.", err));
|
|
930
|
-
this.client.execute("PRAGMA busy_timeout = 5000;").then(() => this.logger.debug("LibSQLStore: PRAGMA busy_timeout=5000 set.")).catch((err) => this.logger.warn("LibSQLStore: Failed to set PRAGMA busy_timeout.", err));
|
|
931
|
-
}
|
|
932
|
-
}
|
|
933
|
-
get supports() {
|
|
934
|
-
return {
|
|
935
|
-
selectByIncludeResourceScope: true,
|
|
936
|
-
resourceWorkingMemory: true
|
|
937
|
-
};
|
|
938
|
-
}
|
|
939
|
-
getCreateTableSQL(tableName, schema) {
|
|
940
|
-
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
941
|
-
const columns = Object.entries(schema).map(([name, col]) => {
|
|
942
|
-
const parsedColumnName = utils.parseSqlIdentifier(name, "column name");
|
|
943
|
-
let type = col.type.toUpperCase();
|
|
944
|
-
if (type === "TEXT") type = "TEXT";
|
|
945
|
-
if (type === "TIMESTAMP") type = "TEXT";
|
|
946
|
-
const nullable = col.nullable ? "" : "NOT NULL";
|
|
947
|
-
const primaryKey = col.primaryKey ? "PRIMARY KEY" : "";
|
|
948
|
-
return `${parsedColumnName} ${type} ${nullable} ${primaryKey}`.trim();
|
|
949
|
-
});
|
|
950
|
-
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
951
|
-
const stmnt = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (
|
|
952
|
-
${columns.join(",\n")},
|
|
953
|
-
PRIMARY KEY (workflow_name, run_id)
|
|
954
|
-
)`;
|
|
955
|
-
return stmnt;
|
|
956
|
-
}
|
|
957
|
-
return `CREATE TABLE IF NOT EXISTS ${parsedTableName} (${columns.join(", ")})`;
|
|
944
|
+
constructor({ client }) {
|
|
945
|
+
super();
|
|
946
|
+
this.client = client;
|
|
958
947
|
}
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
schema
|
|
962
|
-
}) {
|
|
948
|
+
/** @deprecated use getEvals instead */
|
|
949
|
+
async getEvalsByAgentName(agentName, type) {
|
|
963
950
|
try {
|
|
964
|
-
|
|
965
|
-
const
|
|
966
|
-
await this.client.execute(
|
|
951
|
+
const baseQuery = `SELECT * FROM ${storage.TABLE_EVALS} WHERE agent_name = ?`;
|
|
952
|
+
const typeCondition = type === "test" ? " AND test_info IS NOT NULL AND test_info->>'testPath' IS NOT NULL" : type === "live" ? " AND (test_info IS NULL OR test_info->>'testPath' IS NULL)" : "";
|
|
953
|
+
const result = await this.client.execute({
|
|
954
|
+
sql: `${baseQuery}${typeCondition} ORDER BY created_at DESC`,
|
|
955
|
+
args: [agentName]
|
|
956
|
+
});
|
|
957
|
+
return result.rows?.map((row) => transformEvalRow(row)) ?? [];
|
|
967
958
|
} catch (error$1) {
|
|
959
|
+
if (error$1 instanceof Error && error$1.message.includes("no such table")) {
|
|
960
|
+
return [];
|
|
961
|
+
}
|
|
968
962
|
throw new error.MastraError(
|
|
969
963
|
{
|
|
970
|
-
id: "
|
|
964
|
+
id: "LIBSQL_STORE_GET_EVALS_BY_AGENT_NAME_FAILED",
|
|
971
965
|
domain: error.ErrorDomain.STORAGE,
|
|
972
966
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
973
|
-
details: {
|
|
974
|
-
tableName
|
|
975
|
-
}
|
|
967
|
+
details: { agentName }
|
|
976
968
|
},
|
|
977
969
|
error$1
|
|
978
970
|
);
|
|
979
971
|
}
|
|
980
972
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
return super.getSqlType(type);
|
|
973
|
+
async getEvals(options = {}) {
|
|
974
|
+
const { agentName, type, page = 0, perPage = 100, dateRange } = options;
|
|
975
|
+
const fromDate = dateRange?.start;
|
|
976
|
+
const toDate = dateRange?.end;
|
|
977
|
+
const conditions = [];
|
|
978
|
+
const queryParams = [];
|
|
979
|
+
if (agentName) {
|
|
980
|
+
conditions.push(`agent_name = ?`);
|
|
981
|
+
queryParams.push(agentName);
|
|
991
982
|
}
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
983
|
+
if (type === "test") {
|
|
984
|
+
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
985
|
+
} else if (type === "live") {
|
|
986
|
+
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
987
|
+
}
|
|
988
|
+
if (fromDate) {
|
|
989
|
+
conditions.push(`created_at >= ?`);
|
|
990
|
+
queryParams.push(fromDate.toISOString());
|
|
991
|
+
}
|
|
992
|
+
if (toDate) {
|
|
993
|
+
conditions.push(`created_at <= ?`);
|
|
994
|
+
queryParams.push(toDate.toISOString());
|
|
995
|
+
}
|
|
996
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1005
997
|
try {
|
|
1006
|
-
const
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
998
|
+
const countResult = await this.client.execute({
|
|
999
|
+
sql: `SELECT COUNT(*) as count FROM ${storage.TABLE_EVALS} ${whereClause}`,
|
|
1000
|
+
args: queryParams
|
|
1001
|
+
});
|
|
1002
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1003
|
+
const currentOffset = page * perPage;
|
|
1004
|
+
const hasMore = currentOffset + perPage < total;
|
|
1005
|
+
if (total === 0) {
|
|
1006
|
+
return {
|
|
1007
|
+
evals: [],
|
|
1008
|
+
total: 0,
|
|
1009
|
+
page,
|
|
1010
|
+
perPage,
|
|
1011
|
+
hasMore: false
|
|
1012
|
+
};
|
|
1019
1013
|
}
|
|
1014
|
+
const dataResult = await this.client.execute({
|
|
1015
|
+
sql: `SELECT * FROM ${storage.TABLE_EVALS} ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
|
|
1016
|
+
args: [...queryParams, perPage, currentOffset]
|
|
1017
|
+
});
|
|
1018
|
+
return {
|
|
1019
|
+
evals: dataResult.rows?.map((row) => transformEvalRow(row)) ?? [],
|
|
1020
|
+
total,
|
|
1021
|
+
page,
|
|
1022
|
+
perPage,
|
|
1023
|
+
hasMore
|
|
1024
|
+
};
|
|
1020
1025
|
} catch (error$1) {
|
|
1021
1026
|
throw new error.MastraError(
|
|
1022
1027
|
{
|
|
1023
|
-
id: "
|
|
1028
|
+
id: "LIBSQL_STORE_GET_EVALS_FAILED",
|
|
1024
1029
|
domain: error.ErrorDomain.STORAGE,
|
|
1025
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1026
|
-
details: {
|
|
1027
|
-
tableName
|
|
1028
|
-
}
|
|
1030
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1029
1031
|
},
|
|
1030
1032
|
error$1
|
|
1031
1033
|
);
|
|
1032
1034
|
}
|
|
1033
1035
|
}
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
+
};
|
|
1037
|
+
var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
1038
|
+
client;
|
|
1039
|
+
operations;
|
|
1040
|
+
constructor({ client, operations }) {
|
|
1041
|
+
super();
|
|
1042
|
+
this.client = client;
|
|
1043
|
+
this.operations = operations;
|
|
1044
|
+
}
|
|
1045
|
+
parseRow(row) {
|
|
1046
|
+
let content = row.content;
|
|
1036
1047
|
try {
|
|
1037
|
-
|
|
1038
|
-
} catch
|
|
1039
|
-
const mastraError = new error.MastraError(
|
|
1040
|
-
{
|
|
1041
|
-
id: "LIBSQL_STORE_CLEAR_TABLE_FAILED",
|
|
1042
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1043
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1044
|
-
details: {
|
|
1045
|
-
tableName
|
|
1046
|
-
}
|
|
1047
|
-
},
|
|
1048
|
-
e
|
|
1049
|
-
);
|
|
1050
|
-
this.logger?.trackException?.(mastraError);
|
|
1051
|
-
this.logger?.error?.(mastraError.toString());
|
|
1048
|
+
content = JSON.parse(row.content);
|
|
1049
|
+
} catch {
|
|
1052
1050
|
}
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
}
|
|
1061
|
-
if (v instanceof Date) {
|
|
1062
|
-
return v.toISOString();
|
|
1063
|
-
}
|
|
1064
|
-
return typeof v === "object" ? JSON.stringify(v) : v;
|
|
1065
|
-
});
|
|
1066
|
-
const placeholders = values.map(() => "?").join(", ");
|
|
1067
|
-
return {
|
|
1068
|
-
sql: `INSERT OR REPLACE INTO ${parsedTableName} (${columns.join(", ")}) VALUES (${placeholders})`,
|
|
1069
|
-
args: values
|
|
1051
|
+
const result = {
|
|
1052
|
+
id: row.id,
|
|
1053
|
+
content,
|
|
1054
|
+
role: row.role,
|
|
1055
|
+
createdAt: new Date(row.createdAt),
|
|
1056
|
+
threadId: row.thread_id,
|
|
1057
|
+
resourceId: row.resourceId
|
|
1070
1058
|
};
|
|
1059
|
+
if (row.type && row.type !== `v2`) result.type = row.type;
|
|
1060
|
+
return result;
|
|
1071
1061
|
}
|
|
1072
|
-
async
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1062
|
+
async _getIncludedMessages({
|
|
1063
|
+
threadId,
|
|
1064
|
+
selectBy
|
|
1065
|
+
}) {
|
|
1066
|
+
const include = selectBy?.include;
|
|
1067
|
+
if (!include) return null;
|
|
1068
|
+
const unionQueries = [];
|
|
1069
|
+
const params = [];
|
|
1070
|
+
for (const inc of include) {
|
|
1071
|
+
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
1072
|
+
const searchId = inc.threadId || threadId;
|
|
1073
|
+
unionQueries.push(
|
|
1074
|
+
`
|
|
1075
|
+
SELECT * FROM (
|
|
1076
|
+
WITH numbered_messages AS (
|
|
1077
|
+
SELECT
|
|
1078
|
+
id, content, role, type, "createdAt", thread_id, "resourceId",
|
|
1079
|
+
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
1080
|
+
FROM "${storage.TABLE_MESSAGES}"
|
|
1081
|
+
WHERE thread_id = ?
|
|
1082
|
+
),
|
|
1083
|
+
target_positions AS (
|
|
1084
|
+
SELECT row_num as target_pos
|
|
1085
|
+
FROM numbered_messages
|
|
1086
|
+
WHERE id = ?
|
|
1087
|
+
)
|
|
1088
|
+
SELECT DISTINCT m.*
|
|
1089
|
+
FROM numbered_messages m
|
|
1090
|
+
CROSS JOIN target_positions t
|
|
1091
|
+
WHERE m.row_num BETWEEN (t.target_pos - ?) AND (t.target_pos + ?)
|
|
1092
|
+
)
|
|
1093
|
+
`
|
|
1094
|
+
// Keep ASC for final sorting after fetching context
|
|
1095
|
+
);
|
|
1096
|
+
params.push(searchId, id, withPreviousMessages, withNextMessages);
|
|
1090
1097
|
}
|
|
1098
|
+
const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
|
|
1099
|
+
const includedResult = await this.client.execute({ sql: finalQuery, args: params });
|
|
1100
|
+
const includedRows = includedResult.rows?.map((row) => this.parseRow(row));
|
|
1101
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1102
|
+
const dedupedRows = includedRows.filter((row) => {
|
|
1103
|
+
if (seen.has(row.id)) return false;
|
|
1104
|
+
seen.add(row.id);
|
|
1105
|
+
return true;
|
|
1106
|
+
});
|
|
1107
|
+
return dedupedRows;
|
|
1091
1108
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
tableName,
|
|
1097
|
-
record
|
|
1109
|
+
async getMessages({
|
|
1110
|
+
threadId,
|
|
1111
|
+
selectBy,
|
|
1112
|
+
format
|
|
1098
1113
|
}) {
|
|
1099
|
-
await this.client.execute(
|
|
1100
|
-
this.prepareStatement({
|
|
1101
|
-
tableName,
|
|
1102
|
-
record
|
|
1103
|
-
})
|
|
1104
|
-
);
|
|
1105
|
-
}
|
|
1106
|
-
batchInsert(args) {
|
|
1107
|
-
return this.executeWriteOperationWithRetry(
|
|
1108
|
-
() => this.doBatchInsert(args),
|
|
1109
|
-
`batch insert into table ${args.tableName}`
|
|
1110
|
-
).catch((error$1) => {
|
|
1111
|
-
throw new error.MastraError(
|
|
1112
|
-
{
|
|
1113
|
-
id: "LIBSQL_STORE_BATCH_INSERT_FAILED",
|
|
1114
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1115
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1116
|
-
details: {
|
|
1117
|
-
tableName: args.tableName
|
|
1118
|
-
}
|
|
1119
|
-
},
|
|
1120
|
-
error$1
|
|
1121
|
-
);
|
|
1122
|
-
});
|
|
1123
|
-
}
|
|
1124
|
-
async doBatchInsert({
|
|
1125
|
-
tableName,
|
|
1126
|
-
records
|
|
1127
|
-
}) {
|
|
1128
|
-
if (records.length === 0) return;
|
|
1129
|
-
const batchStatements = records.map((r) => this.prepareStatement({ tableName, record: r }));
|
|
1130
|
-
await this.client.batch(batchStatements, "write");
|
|
1131
|
-
}
|
|
1132
|
-
async load({ tableName, keys }) {
|
|
1133
|
-
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1134
|
-
const parsedKeys = Object.keys(keys).map((key) => utils.parseSqlIdentifier(key, "column name"));
|
|
1135
|
-
const conditions = parsedKeys.map((key) => `${key} = ?`).join(" AND ");
|
|
1136
|
-
const values = Object.values(keys);
|
|
1137
|
-
const result = await this.client.execute({
|
|
1138
|
-
sql: `SELECT * FROM ${parsedTableName} WHERE ${conditions} ORDER BY createdAt DESC LIMIT 1`,
|
|
1139
|
-
args: values
|
|
1140
|
-
});
|
|
1141
|
-
if (!result.rows || result.rows.length === 0) {
|
|
1142
|
-
return null;
|
|
1143
|
-
}
|
|
1144
|
-
const row = result.rows[0];
|
|
1145
|
-
const parsed = Object.fromEntries(
|
|
1146
|
-
Object.entries(row || {}).map(([k, v]) => {
|
|
1147
|
-
try {
|
|
1148
|
-
return [k, typeof v === "string" ? v.startsWith("{") || v.startsWith("[") ? JSON.parse(v) : v : v];
|
|
1149
|
-
} catch {
|
|
1150
|
-
return [k, v];
|
|
1151
|
-
}
|
|
1152
|
-
})
|
|
1153
|
-
);
|
|
1154
|
-
return parsed;
|
|
1155
|
-
}
|
|
1156
|
-
async getThreadById({ threadId }) {
|
|
1157
1114
|
try {
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1115
|
+
const messages = [];
|
|
1116
|
+
const limit = storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
1117
|
+
if (selectBy?.include?.length) {
|
|
1118
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
1119
|
+
if (includeMessages) {
|
|
1120
|
+
messages.push(...includeMessages);
|
|
1121
|
+
}
|
|
1164
1122
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1123
|
+
const excludeIds = messages.map((m) => m.id);
|
|
1124
|
+
const remainingSql = `
|
|
1125
|
+
SELECT
|
|
1126
|
+
id,
|
|
1127
|
+
content,
|
|
1128
|
+
role,
|
|
1129
|
+
type,
|
|
1130
|
+
"createdAt",
|
|
1131
|
+
thread_id,
|
|
1132
|
+
"resourceId"
|
|
1133
|
+
FROM "${storage.TABLE_MESSAGES}"
|
|
1134
|
+
WHERE thread_id = ?
|
|
1135
|
+
${excludeIds.length ? `AND id NOT IN (${excludeIds.map(() => "?").join(", ")})` : ""}
|
|
1136
|
+
ORDER BY "createdAt" DESC
|
|
1137
|
+
LIMIT ?
|
|
1138
|
+
`;
|
|
1139
|
+
const remainingArgs = [threadId, ...excludeIds.length ? excludeIds : [], limit];
|
|
1140
|
+
const remainingResult = await this.client.execute({ sql: remainingSql, args: remainingArgs });
|
|
1141
|
+
if (remainingResult.rows) {
|
|
1142
|
+
messages.push(...remainingResult.rows.map((row) => this.parseRow(row)));
|
|
1143
|
+
}
|
|
1144
|
+
messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
1145
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
1146
|
+
if (format === `v2`) return list.get.all.v2();
|
|
1147
|
+
return list.get.all.v1();
|
|
1169
1148
|
} catch (error$1) {
|
|
1170
1149
|
throw new error.MastraError(
|
|
1171
1150
|
{
|
|
1172
|
-
id: "
|
|
1151
|
+
id: "LIBSQL_STORE_GET_MESSAGES_FAILED",
|
|
1173
1152
|
domain: error.ErrorDomain.STORAGE,
|
|
1174
1153
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1175
1154
|
details: { threadId }
|
|
@@ -1178,126 +1157,513 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1178
1157
|
);
|
|
1179
1158
|
}
|
|
1180
1159
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
const
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
return [];
|
|
1160
|
+
async getMessagesPaginated(args) {
|
|
1161
|
+
const { threadId, format, selectBy } = args;
|
|
1162
|
+
const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
|
|
1163
|
+
const perPage = perPageInput !== void 0 ? perPageInput : storage.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
1164
|
+
const fromDate = dateRange?.start;
|
|
1165
|
+
const toDate = dateRange?.end;
|
|
1166
|
+
const messages = [];
|
|
1167
|
+
if (selectBy?.include?.length) {
|
|
1168
|
+
try {
|
|
1169
|
+
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
1170
|
+
if (includeMessages) {
|
|
1171
|
+
messages.push(...includeMessages);
|
|
1172
|
+
}
|
|
1173
|
+
} catch (error$1) {
|
|
1174
|
+
throw new error.MastraError(
|
|
1175
|
+
{
|
|
1176
|
+
id: "LIBSQL_STORE_GET_MESSAGES_PAGINATED_GET_INCLUDE_MESSAGES_FAILED",
|
|
1177
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1178
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1179
|
+
details: { threadId }
|
|
1180
|
+
},
|
|
1181
|
+
error$1
|
|
1182
|
+
);
|
|
1205
1183
|
}
|
|
1206
|
-
return result.rows.map(mapRowToStorageThreadType);
|
|
1207
|
-
} catch (error$1) {
|
|
1208
|
-
const mastraError = new error.MastraError(
|
|
1209
|
-
{
|
|
1210
|
-
id: "LIBSQL_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
1211
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1212
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1213
|
-
details: { resourceId }
|
|
1214
|
-
},
|
|
1215
|
-
error$1
|
|
1216
|
-
);
|
|
1217
|
-
this.logger?.trackException?.(mastraError);
|
|
1218
|
-
this.logger?.error?.(mastraError.toString());
|
|
1219
|
-
return [];
|
|
1220
1184
|
}
|
|
1221
|
-
}
|
|
1222
|
-
async getThreadsByResourceIdPaginated(args) {
|
|
1223
|
-
const { resourceId, page = 0, perPage = 100 } = args;
|
|
1224
1185
|
try {
|
|
1225
|
-
const baseQuery = `FROM ${storage.TABLE_THREADS} WHERE resourceId = ?`;
|
|
1226
|
-
const queryParams = [resourceId];
|
|
1227
|
-
const mapRowToStorageThreadType = (row) => ({
|
|
1228
|
-
id: row.id,
|
|
1229
|
-
resourceId: row.resourceId,
|
|
1230
|
-
title: row.title,
|
|
1231
|
-
createdAt: new Date(row.createdAt),
|
|
1232
|
-
// Convert string to Date
|
|
1233
|
-
updatedAt: new Date(row.updatedAt),
|
|
1234
|
-
// Convert string to Date
|
|
1235
|
-
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
1236
|
-
});
|
|
1237
1186
|
const currentOffset = page * perPage;
|
|
1187
|
+
const conditions = [`thread_id = ?`];
|
|
1188
|
+
const queryParams = [threadId];
|
|
1189
|
+
if (fromDate) {
|
|
1190
|
+
conditions.push(`"createdAt" >= ?`);
|
|
1191
|
+
queryParams.push(fromDate.toISOString());
|
|
1192
|
+
}
|
|
1193
|
+
if (toDate) {
|
|
1194
|
+
conditions.push(`"createdAt" <= ?`);
|
|
1195
|
+
queryParams.push(toDate.toISOString());
|
|
1196
|
+
}
|
|
1197
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1238
1198
|
const countResult = await this.client.execute({
|
|
1239
|
-
sql: `SELECT COUNT(*) as count ${
|
|
1199
|
+
sql: `SELECT COUNT(*) as count FROM ${storage.TABLE_MESSAGES} ${whereClause}`,
|
|
1240
1200
|
args: queryParams
|
|
1241
1201
|
});
|
|
1242
1202
|
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1243
|
-
if (total === 0) {
|
|
1203
|
+
if (total === 0 && messages.length === 0) {
|
|
1244
1204
|
return {
|
|
1245
|
-
|
|
1205
|
+
messages: [],
|
|
1246
1206
|
total: 0,
|
|
1247
1207
|
page,
|
|
1248
1208
|
perPage,
|
|
1249
1209
|
hasMore: false
|
|
1250
1210
|
};
|
|
1251
1211
|
}
|
|
1212
|
+
const excludeIds = messages.map((m) => m.id);
|
|
1213
|
+
const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + queryParams.length + 1}`).join(", ");
|
|
1252
1214
|
const dataResult = await this.client.execute({
|
|
1253
|
-
sql: `SELECT
|
|
1254
|
-
args: [...queryParams, perPage, currentOffset]
|
|
1215
|
+
sql: `SELECT id, content, role, type, "createdAt", "resourceId", "thread_id" FROM ${storage.TABLE_MESSAGES} ${whereClause} ${excludeIds.length ? `AND id NOT IN (${excludeIdsParam})` : ""} ORDER BY "createdAt" DESC LIMIT ? OFFSET ?`,
|
|
1216
|
+
args: [...queryParams, ...excludeIds, perPage, currentOffset]
|
|
1255
1217
|
});
|
|
1256
|
-
|
|
1218
|
+
messages.push(...(dataResult.rows || []).map((row) => this.parseRow(row)));
|
|
1219
|
+
const messagesToReturn = format === "v1" ? new agent.MessageList().add(messages, "memory").get.all.v1() : new agent.MessageList().add(messages, "memory").get.all.v2();
|
|
1257
1220
|
return {
|
|
1258
|
-
|
|
1221
|
+
messages: messagesToReturn,
|
|
1259
1222
|
total,
|
|
1260
1223
|
page,
|
|
1261
1224
|
perPage,
|
|
1262
|
-
hasMore: currentOffset +
|
|
1225
|
+
hasMore: currentOffset + messages.length < total
|
|
1263
1226
|
};
|
|
1264
1227
|
} catch (error$1) {
|
|
1265
1228
|
const mastraError = new error.MastraError(
|
|
1266
1229
|
{
|
|
1267
|
-
id: "
|
|
1230
|
+
id: "LIBSQL_STORE_GET_MESSAGES_PAGINATED_FAILED",
|
|
1268
1231
|
domain: error.ErrorDomain.STORAGE,
|
|
1269
1232
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1270
|
-
details: {
|
|
1233
|
+
details: { threadId }
|
|
1271
1234
|
},
|
|
1272
1235
|
error$1
|
|
1273
1236
|
);
|
|
1274
1237
|
this.logger?.trackException?.(mastraError);
|
|
1275
1238
|
this.logger?.error?.(mastraError.toString());
|
|
1276
|
-
return {
|
|
1239
|
+
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
1277
1240
|
}
|
|
1278
1241
|
}
|
|
1279
|
-
async
|
|
1242
|
+
async saveMessages({
|
|
1243
|
+
messages,
|
|
1244
|
+
format
|
|
1245
|
+
}) {
|
|
1246
|
+
if (messages.length === 0) return messages;
|
|
1280
1247
|
try {
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1248
|
+
const threadId = messages[0]?.threadId;
|
|
1249
|
+
if (!threadId) {
|
|
1250
|
+
throw new Error("Thread ID is required");
|
|
1251
|
+
}
|
|
1252
|
+
const batchStatements = messages.map((message) => {
|
|
1253
|
+
const time = message.createdAt || /* @__PURE__ */ new Date();
|
|
1254
|
+
if (!message.threadId) {
|
|
1255
|
+
throw new Error(
|
|
1256
|
+
`Expected to find a threadId for message, but couldn't find one. An unexpected error has occurred.`
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
if (!message.resourceId) {
|
|
1260
|
+
throw new Error(
|
|
1261
|
+
`Expected to find a resourceId for message, but couldn't find one. An unexpected error has occurred.`
|
|
1262
|
+
);
|
|
1286
1263
|
}
|
|
1264
|
+
return {
|
|
1265
|
+
sql: `INSERT INTO "${storage.TABLE_MESSAGES}" (id, thread_id, content, role, type, "createdAt", "resourceId")
|
|
1266
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
1267
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
1268
|
+
thread_id=excluded.thread_id,
|
|
1269
|
+
content=excluded.content,
|
|
1270
|
+
role=excluded.role,
|
|
1271
|
+
type=excluded.type,
|
|
1272
|
+
"resourceId"=excluded."resourceId"
|
|
1273
|
+
`,
|
|
1274
|
+
args: [
|
|
1275
|
+
message.id,
|
|
1276
|
+
message.threadId,
|
|
1277
|
+
typeof message.content === "object" ? JSON.stringify(message.content) : message.content,
|
|
1278
|
+
message.role,
|
|
1279
|
+
message.type || "v2",
|
|
1280
|
+
time instanceof Date ? time.toISOString() : time,
|
|
1281
|
+
message.resourceId
|
|
1282
|
+
]
|
|
1283
|
+
};
|
|
1287
1284
|
});
|
|
1288
|
-
|
|
1285
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1286
|
+
batchStatements.push({
|
|
1287
|
+
sql: `UPDATE "${storage.TABLE_THREADS}" SET "updatedAt" = ? WHERE id = ?`,
|
|
1288
|
+
args: [now, threadId]
|
|
1289
|
+
});
|
|
1290
|
+
const BATCH_SIZE = 50;
|
|
1291
|
+
const messageStatements = batchStatements.slice(0, -1);
|
|
1292
|
+
const threadUpdateStatement = batchStatements[batchStatements.length - 1];
|
|
1293
|
+
for (let i = 0; i < messageStatements.length; i += BATCH_SIZE) {
|
|
1294
|
+
const batch = messageStatements.slice(i, i + BATCH_SIZE);
|
|
1295
|
+
if (batch.length > 0) {
|
|
1296
|
+
await this.client.batch(batch, "write");
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
if (threadUpdateStatement) {
|
|
1300
|
+
await this.client.execute(threadUpdateStatement);
|
|
1301
|
+
}
|
|
1302
|
+
const list = new agent.MessageList().add(messages, "memory");
|
|
1303
|
+
if (format === `v2`) return list.get.all.v2();
|
|
1304
|
+
return list.get.all.v1();
|
|
1289
1305
|
} catch (error$1) {
|
|
1290
|
-
|
|
1306
|
+
throw new error.MastraError(
|
|
1291
1307
|
{
|
|
1292
|
-
id: "
|
|
1308
|
+
id: "LIBSQL_STORE_SAVE_MESSAGES_FAILED",
|
|
1293
1309
|
domain: error.ErrorDomain.STORAGE,
|
|
1294
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1295
|
-
details: { threadId: thread.id }
|
|
1310
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1296
1311
|
},
|
|
1297
1312
|
error$1
|
|
1298
1313
|
);
|
|
1299
|
-
|
|
1300
|
-
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
async updateMessages({
|
|
1317
|
+
messages
|
|
1318
|
+
}) {
|
|
1319
|
+
if (messages.length === 0) {
|
|
1320
|
+
return [];
|
|
1321
|
+
}
|
|
1322
|
+
const messageIds = messages.map((m) => m.id);
|
|
1323
|
+
const placeholders = messageIds.map(() => "?").join(",");
|
|
1324
|
+
const selectSql = `SELECT * FROM ${storage.TABLE_MESSAGES} WHERE id IN (${placeholders})`;
|
|
1325
|
+
const existingResult = await this.client.execute({ sql: selectSql, args: messageIds });
|
|
1326
|
+
const existingMessages = existingResult.rows.map((row) => this.parseRow(row));
|
|
1327
|
+
if (existingMessages.length === 0) {
|
|
1328
|
+
return [];
|
|
1329
|
+
}
|
|
1330
|
+
const batchStatements = [];
|
|
1331
|
+
const threadIdsToUpdate = /* @__PURE__ */ new Set();
|
|
1332
|
+
const columnMapping = {
|
|
1333
|
+
threadId: "thread_id"
|
|
1334
|
+
};
|
|
1335
|
+
for (const existingMessage of existingMessages) {
|
|
1336
|
+
const updatePayload = messages.find((m) => m.id === existingMessage.id);
|
|
1337
|
+
if (!updatePayload) continue;
|
|
1338
|
+
const { id, ...fieldsToUpdate } = updatePayload;
|
|
1339
|
+
if (Object.keys(fieldsToUpdate).length === 0) continue;
|
|
1340
|
+
threadIdsToUpdate.add(existingMessage.threadId);
|
|
1341
|
+
if (updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {
|
|
1342
|
+
threadIdsToUpdate.add(updatePayload.threadId);
|
|
1343
|
+
}
|
|
1344
|
+
const setClauses = [];
|
|
1345
|
+
const args = [];
|
|
1346
|
+
const updatableFields = { ...fieldsToUpdate };
|
|
1347
|
+
if (updatableFields.content) {
|
|
1348
|
+
const newContent = {
|
|
1349
|
+
...existingMessage.content,
|
|
1350
|
+
...updatableFields.content,
|
|
1351
|
+
// Deep merge metadata if it exists on both
|
|
1352
|
+
...existingMessage.content?.metadata && updatableFields.content.metadata ? {
|
|
1353
|
+
metadata: {
|
|
1354
|
+
...existingMessage.content.metadata,
|
|
1355
|
+
...updatableFields.content.metadata
|
|
1356
|
+
}
|
|
1357
|
+
} : {}
|
|
1358
|
+
};
|
|
1359
|
+
setClauses.push(`${core.parseSqlIdentifier("content", "column name")} = ?`);
|
|
1360
|
+
args.push(JSON.stringify(newContent));
|
|
1361
|
+
delete updatableFields.content;
|
|
1362
|
+
}
|
|
1363
|
+
for (const key in updatableFields) {
|
|
1364
|
+
if (Object.prototype.hasOwnProperty.call(updatableFields, key)) {
|
|
1365
|
+
const dbKey = columnMapping[key] || key;
|
|
1366
|
+
setClauses.push(`${core.parseSqlIdentifier(dbKey, "column name")} = ?`);
|
|
1367
|
+
let value = updatableFields[key];
|
|
1368
|
+
if (typeof value === "object" && value !== null) {
|
|
1369
|
+
value = JSON.stringify(value);
|
|
1370
|
+
}
|
|
1371
|
+
args.push(value);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
if (setClauses.length === 0) continue;
|
|
1375
|
+
args.push(id);
|
|
1376
|
+
const sql = `UPDATE ${storage.TABLE_MESSAGES} SET ${setClauses.join(", ")} WHERE id = ?`;
|
|
1377
|
+
batchStatements.push({ sql, args });
|
|
1378
|
+
}
|
|
1379
|
+
if (batchStatements.length === 0) {
|
|
1380
|
+
return existingMessages;
|
|
1381
|
+
}
|
|
1382
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1383
|
+
for (const threadId of threadIdsToUpdate) {
|
|
1384
|
+
if (threadId) {
|
|
1385
|
+
batchStatements.push({
|
|
1386
|
+
sql: `UPDATE ${storage.TABLE_THREADS} SET updatedAt = ? WHERE id = ?`,
|
|
1387
|
+
args: [now, threadId]
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
await this.client.batch(batchStatements, "write");
|
|
1392
|
+
const updatedResult = await this.client.execute({ sql: selectSql, args: messageIds });
|
|
1393
|
+
return updatedResult.rows.map((row) => this.parseRow(row));
|
|
1394
|
+
}
|
|
1395
|
+
async deleteMessages(messageIds) {
|
|
1396
|
+
if (!messageIds || messageIds.length === 0) {
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
try {
|
|
1400
|
+
const BATCH_SIZE = 100;
|
|
1401
|
+
const threadIds = /* @__PURE__ */ new Set();
|
|
1402
|
+
const tx = await this.client.transaction("write");
|
|
1403
|
+
try {
|
|
1404
|
+
for (let i = 0; i < messageIds.length; i += BATCH_SIZE) {
|
|
1405
|
+
const batch = messageIds.slice(i, i + BATCH_SIZE);
|
|
1406
|
+
const placeholders = batch.map(() => "?").join(",");
|
|
1407
|
+
const result = await tx.execute({
|
|
1408
|
+
sql: `SELECT DISTINCT thread_id FROM "${storage.TABLE_MESSAGES}" WHERE id IN (${placeholders})`,
|
|
1409
|
+
args: batch
|
|
1410
|
+
});
|
|
1411
|
+
result.rows?.forEach((row) => {
|
|
1412
|
+
if (row.thread_id) threadIds.add(row.thread_id);
|
|
1413
|
+
});
|
|
1414
|
+
await tx.execute({
|
|
1415
|
+
sql: `DELETE FROM "${storage.TABLE_MESSAGES}" WHERE id IN (${placeholders})`,
|
|
1416
|
+
args: batch
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
if (threadIds.size > 0) {
|
|
1420
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1421
|
+
for (const threadId of threadIds) {
|
|
1422
|
+
await tx.execute({
|
|
1423
|
+
sql: `UPDATE "${storage.TABLE_THREADS}" SET "updatedAt" = ? WHERE id = ?`,
|
|
1424
|
+
args: [now, threadId]
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
await tx.commit();
|
|
1429
|
+
} catch (error) {
|
|
1430
|
+
await tx.rollback();
|
|
1431
|
+
throw error;
|
|
1432
|
+
}
|
|
1433
|
+
} catch (error$1) {
|
|
1434
|
+
throw new error.MastraError(
|
|
1435
|
+
{
|
|
1436
|
+
id: "LIBSQL_STORE_DELETE_MESSAGES_FAILED",
|
|
1437
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1438
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1439
|
+
details: { messageIds: messageIds.join(", ") }
|
|
1440
|
+
},
|
|
1441
|
+
error$1
|
|
1442
|
+
);
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
async getResourceById({ resourceId }) {
|
|
1446
|
+
const result = await this.operations.load({
|
|
1447
|
+
tableName: storage.TABLE_RESOURCES,
|
|
1448
|
+
keys: { id: resourceId }
|
|
1449
|
+
});
|
|
1450
|
+
if (!result) {
|
|
1451
|
+
return null;
|
|
1452
|
+
}
|
|
1453
|
+
return {
|
|
1454
|
+
...result,
|
|
1455
|
+
// Ensure workingMemory is always returned as a string, even if auto-parsed as JSON
|
|
1456
|
+
workingMemory: result.workingMemory && typeof result.workingMemory === "object" ? JSON.stringify(result.workingMemory) : result.workingMemory,
|
|
1457
|
+
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata,
|
|
1458
|
+
createdAt: new Date(result.createdAt),
|
|
1459
|
+
updatedAt: new Date(result.updatedAt)
|
|
1460
|
+
};
|
|
1461
|
+
}
|
|
1462
|
+
async saveResource({ resource }) {
|
|
1463
|
+
await this.operations.insert({
|
|
1464
|
+
tableName: storage.TABLE_RESOURCES,
|
|
1465
|
+
record: {
|
|
1466
|
+
...resource,
|
|
1467
|
+
metadata: JSON.stringify(resource.metadata)
|
|
1468
|
+
}
|
|
1469
|
+
});
|
|
1470
|
+
return resource;
|
|
1471
|
+
}
|
|
1472
|
+
async updateResource({
|
|
1473
|
+
resourceId,
|
|
1474
|
+
workingMemory,
|
|
1475
|
+
metadata
|
|
1476
|
+
}) {
|
|
1477
|
+
const existingResource = await this.getResourceById({ resourceId });
|
|
1478
|
+
if (!existingResource) {
|
|
1479
|
+
const newResource = {
|
|
1480
|
+
id: resourceId,
|
|
1481
|
+
workingMemory,
|
|
1482
|
+
metadata: metadata || {},
|
|
1483
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
1484
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1485
|
+
};
|
|
1486
|
+
return this.saveResource({ resource: newResource });
|
|
1487
|
+
}
|
|
1488
|
+
const updatedResource = {
|
|
1489
|
+
...existingResource,
|
|
1490
|
+
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
1491
|
+
metadata: {
|
|
1492
|
+
...existingResource.metadata,
|
|
1493
|
+
...metadata
|
|
1494
|
+
},
|
|
1495
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
1496
|
+
};
|
|
1497
|
+
const updates = [];
|
|
1498
|
+
const values = [];
|
|
1499
|
+
if (workingMemory !== void 0) {
|
|
1500
|
+
updates.push("workingMemory = ?");
|
|
1501
|
+
values.push(workingMemory);
|
|
1502
|
+
}
|
|
1503
|
+
if (metadata) {
|
|
1504
|
+
updates.push("metadata = ?");
|
|
1505
|
+
values.push(JSON.stringify(updatedResource.metadata));
|
|
1506
|
+
}
|
|
1507
|
+
updates.push("updatedAt = ?");
|
|
1508
|
+
values.push(updatedResource.updatedAt.toISOString());
|
|
1509
|
+
values.push(resourceId);
|
|
1510
|
+
await this.client.execute({
|
|
1511
|
+
sql: `UPDATE ${storage.TABLE_RESOURCES} SET ${updates.join(", ")} WHERE id = ?`,
|
|
1512
|
+
args: values
|
|
1513
|
+
});
|
|
1514
|
+
return updatedResource;
|
|
1515
|
+
}
|
|
1516
|
+
async getThreadById({ threadId }) {
|
|
1517
|
+
try {
|
|
1518
|
+
const result = await this.operations.load({
|
|
1519
|
+
tableName: storage.TABLE_THREADS,
|
|
1520
|
+
keys: { id: threadId }
|
|
1521
|
+
});
|
|
1522
|
+
if (!result) {
|
|
1523
|
+
return null;
|
|
1524
|
+
}
|
|
1525
|
+
return {
|
|
1526
|
+
...result,
|
|
1527
|
+
metadata: typeof result.metadata === "string" ? JSON.parse(result.metadata) : result.metadata,
|
|
1528
|
+
createdAt: new Date(result.createdAt),
|
|
1529
|
+
updatedAt: new Date(result.updatedAt)
|
|
1530
|
+
};
|
|
1531
|
+
} catch (error$1) {
|
|
1532
|
+
throw new error.MastraError(
|
|
1533
|
+
{
|
|
1534
|
+
id: "LIBSQL_STORE_GET_THREAD_BY_ID_FAILED",
|
|
1535
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1536
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1537
|
+
details: { threadId }
|
|
1538
|
+
},
|
|
1539
|
+
error$1
|
|
1540
|
+
);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
/**
|
|
1544
|
+
* @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
|
|
1545
|
+
*/
|
|
1546
|
+
async getThreadsByResourceId(args) {
|
|
1547
|
+
const resourceId = args.resourceId;
|
|
1548
|
+
const orderBy = this.castThreadOrderBy(args.orderBy);
|
|
1549
|
+
const sortDirection = this.castThreadSortDirection(args.sortDirection);
|
|
1550
|
+
try {
|
|
1551
|
+
const baseQuery = `FROM ${storage.TABLE_THREADS} WHERE resourceId = ?`;
|
|
1552
|
+
const queryParams = [resourceId];
|
|
1553
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
1554
|
+
id: row.id,
|
|
1555
|
+
resourceId: row.resourceId,
|
|
1556
|
+
title: row.title,
|
|
1557
|
+
createdAt: new Date(row.createdAt),
|
|
1558
|
+
// Convert string to Date
|
|
1559
|
+
updatedAt: new Date(row.updatedAt),
|
|
1560
|
+
// Convert string to Date
|
|
1561
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
1562
|
+
});
|
|
1563
|
+
const result = await this.client.execute({
|
|
1564
|
+
sql: `SELECT * ${baseQuery} ORDER BY ${orderBy} ${sortDirection}`,
|
|
1565
|
+
args: queryParams
|
|
1566
|
+
});
|
|
1567
|
+
if (!result.rows) {
|
|
1568
|
+
return [];
|
|
1569
|
+
}
|
|
1570
|
+
return result.rows.map(mapRowToStorageThreadType);
|
|
1571
|
+
} catch (error$1) {
|
|
1572
|
+
const mastraError = new error.MastraError(
|
|
1573
|
+
{
|
|
1574
|
+
id: "LIBSQL_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
1575
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1576
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1577
|
+
details: { resourceId }
|
|
1578
|
+
},
|
|
1579
|
+
error$1
|
|
1580
|
+
);
|
|
1581
|
+
this.logger?.trackException?.(mastraError);
|
|
1582
|
+
this.logger?.error?.(mastraError.toString());
|
|
1583
|
+
return [];
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
1587
|
+
const { resourceId, page = 0, perPage = 100 } = args;
|
|
1588
|
+
const orderBy = this.castThreadOrderBy(args.orderBy);
|
|
1589
|
+
const sortDirection = this.castThreadSortDirection(args.sortDirection);
|
|
1590
|
+
try {
|
|
1591
|
+
const baseQuery = `FROM ${storage.TABLE_THREADS} WHERE resourceId = ?`;
|
|
1592
|
+
const queryParams = [resourceId];
|
|
1593
|
+
const mapRowToStorageThreadType = (row) => ({
|
|
1594
|
+
id: row.id,
|
|
1595
|
+
resourceId: row.resourceId,
|
|
1596
|
+
title: row.title,
|
|
1597
|
+
createdAt: new Date(row.createdAt),
|
|
1598
|
+
// Convert string to Date
|
|
1599
|
+
updatedAt: new Date(row.updatedAt),
|
|
1600
|
+
// Convert string to Date
|
|
1601
|
+
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
1602
|
+
});
|
|
1603
|
+
const currentOffset = page * perPage;
|
|
1604
|
+
const countResult = await this.client.execute({
|
|
1605
|
+
sql: `SELECT COUNT(*) as count ${baseQuery}`,
|
|
1606
|
+
args: queryParams
|
|
1607
|
+
});
|
|
1608
|
+
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1609
|
+
if (total === 0) {
|
|
1610
|
+
return {
|
|
1611
|
+
threads: [],
|
|
1612
|
+
total: 0,
|
|
1613
|
+
page,
|
|
1614
|
+
perPage,
|
|
1615
|
+
hasMore: false
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
const dataResult = await this.client.execute({
|
|
1619
|
+
sql: `SELECT * ${baseQuery} ORDER BY ${orderBy} ${sortDirection} LIMIT ? OFFSET ?`,
|
|
1620
|
+
args: [...queryParams, perPage, currentOffset]
|
|
1621
|
+
});
|
|
1622
|
+
const threads = (dataResult.rows || []).map(mapRowToStorageThreadType);
|
|
1623
|
+
return {
|
|
1624
|
+
threads,
|
|
1625
|
+
total,
|
|
1626
|
+
page,
|
|
1627
|
+
perPage,
|
|
1628
|
+
hasMore: currentOffset + threads.length < total
|
|
1629
|
+
};
|
|
1630
|
+
} catch (error$1) {
|
|
1631
|
+
const mastraError = new error.MastraError(
|
|
1632
|
+
{
|
|
1633
|
+
id: "LIBSQL_STORE_GET_THREADS_BY_RESOURCE_ID_FAILED",
|
|
1634
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1635
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1636
|
+
details: { resourceId }
|
|
1637
|
+
},
|
|
1638
|
+
error$1
|
|
1639
|
+
);
|
|
1640
|
+
this.logger?.trackException?.(mastraError);
|
|
1641
|
+
this.logger?.error?.(mastraError.toString());
|
|
1642
|
+
return { threads: [], total: 0, page, perPage, hasMore: false };
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
async saveThread({ thread }) {
|
|
1646
|
+
try {
|
|
1647
|
+
await this.operations.insert({
|
|
1648
|
+
tableName: storage.TABLE_THREADS,
|
|
1649
|
+
record: {
|
|
1650
|
+
...thread,
|
|
1651
|
+
metadata: JSON.stringify(thread.metadata)
|
|
1652
|
+
}
|
|
1653
|
+
});
|
|
1654
|
+
return thread;
|
|
1655
|
+
} catch (error$1) {
|
|
1656
|
+
const mastraError = new error.MastraError(
|
|
1657
|
+
{
|
|
1658
|
+
id: "LIBSQL_STORE_SAVE_THREAD_FAILED",
|
|
1659
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1660
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1661
|
+
details: { threadId: thread.id }
|
|
1662
|
+
},
|
|
1663
|
+
error$1
|
|
1664
|
+
);
|
|
1665
|
+
this.logger?.trackException?.(mastraError);
|
|
1666
|
+
this.logger?.error?.(mastraError.toString());
|
|
1301
1667
|
throw mastraError;
|
|
1302
1668
|
}
|
|
1303
1669
|
}
|
|
@@ -1346,281 +1712,342 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1346
1712
|
);
|
|
1347
1713
|
}
|
|
1348
1714
|
}
|
|
1349
|
-
async deleteThread({ threadId }) {
|
|
1350
|
-
try {
|
|
1351
|
-
await this.client.execute({
|
|
1352
|
-
sql: `DELETE FROM ${storage.TABLE_MESSAGES} WHERE thread_id = ?`,
|
|
1353
|
-
args: [threadId]
|
|
1354
|
-
});
|
|
1355
|
-
await this.client.execute({
|
|
1356
|
-
sql: `DELETE FROM ${storage.TABLE_THREADS} WHERE id = ?`,
|
|
1357
|
-
args: [threadId]
|
|
1358
|
-
});
|
|
1359
|
-
} catch (error$1) {
|
|
1715
|
+
async deleteThread({ threadId }) {
|
|
1716
|
+
try {
|
|
1717
|
+
await this.client.execute({
|
|
1718
|
+
sql: `DELETE FROM ${storage.TABLE_MESSAGES} WHERE thread_id = ?`,
|
|
1719
|
+
args: [threadId]
|
|
1720
|
+
});
|
|
1721
|
+
await this.client.execute({
|
|
1722
|
+
sql: `DELETE FROM ${storage.TABLE_THREADS} WHERE id = ?`,
|
|
1723
|
+
args: [threadId]
|
|
1724
|
+
});
|
|
1725
|
+
} catch (error$1) {
|
|
1726
|
+
throw new error.MastraError(
|
|
1727
|
+
{
|
|
1728
|
+
id: "LIBSQL_STORE_DELETE_THREAD_FAILED",
|
|
1729
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1730
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1731
|
+
details: { threadId }
|
|
1732
|
+
},
|
|
1733
|
+
error$1
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
};
|
|
1738
|
+
function createExecuteWriteOperationWithRetry({
|
|
1739
|
+
logger,
|
|
1740
|
+
maxRetries,
|
|
1741
|
+
initialBackoffMs
|
|
1742
|
+
}) {
|
|
1743
|
+
return async function executeWriteOperationWithRetry(operationFn, operationDescription) {
|
|
1744
|
+
let retries = 0;
|
|
1745
|
+
while (true) {
|
|
1746
|
+
try {
|
|
1747
|
+
return await operationFn();
|
|
1748
|
+
} catch (error) {
|
|
1749
|
+
if (error.message && (error.message.includes("SQLITE_BUSY") || error.message.includes("database is locked")) && retries < maxRetries) {
|
|
1750
|
+
retries++;
|
|
1751
|
+
const backoffTime = initialBackoffMs * Math.pow(2, retries - 1);
|
|
1752
|
+
logger.warn(
|
|
1753
|
+
`LibSQLStore: Encountered SQLITE_BUSY during ${operationDescription}. Retrying (${retries}/${maxRetries}) in ${backoffTime}ms...`
|
|
1754
|
+
);
|
|
1755
|
+
await new Promise((resolve) => setTimeout(resolve, backoffTime));
|
|
1756
|
+
} else {
|
|
1757
|
+
logger.error(`LibSQLStore: Error during ${operationDescription} after ${retries} retries: ${error}`);
|
|
1758
|
+
throw error;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
function prepareStatement({ tableName, record }) {
|
|
1765
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1766
|
+
const columns = Object.keys(record).map((col) => utils.parseSqlIdentifier(col, "column name"));
|
|
1767
|
+
const values = Object.values(record).map((v) => {
|
|
1768
|
+
if (typeof v === `undefined`) {
|
|
1769
|
+
return null;
|
|
1770
|
+
}
|
|
1771
|
+
if (v instanceof Date) {
|
|
1772
|
+
return v.toISOString();
|
|
1773
|
+
}
|
|
1774
|
+
return typeof v === "object" ? JSON.stringify(v) : v;
|
|
1775
|
+
});
|
|
1776
|
+
const placeholders = values.map(() => "?").join(", ");
|
|
1777
|
+
return {
|
|
1778
|
+
sql: `INSERT OR REPLACE INTO ${parsedTableName} (${columns.join(", ")}) VALUES (${placeholders})`,
|
|
1779
|
+
args: values
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// src/storage/domains/operations/index.ts
|
|
1784
|
+
var StoreOperationsLibSQL = class extends storage.StoreOperations {
|
|
1785
|
+
client;
|
|
1786
|
+
/**
|
|
1787
|
+
* Maximum number of retries for write operations if an SQLITE_BUSY error occurs.
|
|
1788
|
+
* @default 5
|
|
1789
|
+
*/
|
|
1790
|
+
maxRetries;
|
|
1791
|
+
/**
|
|
1792
|
+
* Initial backoff time in milliseconds for retrying write operations on SQLITE_BUSY.
|
|
1793
|
+
* The backoff time will double with each retry (exponential backoff).
|
|
1794
|
+
* @default 100
|
|
1795
|
+
*/
|
|
1796
|
+
initialBackoffMs;
|
|
1797
|
+
constructor({
|
|
1798
|
+
client,
|
|
1799
|
+
maxRetries,
|
|
1800
|
+
initialBackoffMs
|
|
1801
|
+
}) {
|
|
1802
|
+
super();
|
|
1803
|
+
this.client = client;
|
|
1804
|
+
this.maxRetries = maxRetries ?? 5;
|
|
1805
|
+
this.initialBackoffMs = initialBackoffMs ?? 100;
|
|
1806
|
+
}
|
|
1807
|
+
async hasColumn(table, column) {
|
|
1808
|
+
const result = await this.client.execute({
|
|
1809
|
+
sql: `PRAGMA table_info(${table})`
|
|
1810
|
+
});
|
|
1811
|
+
return (await result.rows)?.some((row) => row.name === column);
|
|
1812
|
+
}
|
|
1813
|
+
getCreateTableSQL(tableName, schema) {
|
|
1814
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1815
|
+
const columns = Object.entries(schema).map(([name, col]) => {
|
|
1816
|
+
const parsedColumnName = utils.parseSqlIdentifier(name, "column name");
|
|
1817
|
+
let type = col.type.toUpperCase();
|
|
1818
|
+
if (type === "TEXT") type = "TEXT";
|
|
1819
|
+
if (type === "TIMESTAMP") type = "TEXT";
|
|
1820
|
+
const nullable = col.nullable ? "" : "NOT NULL";
|
|
1821
|
+
const primaryKey = col.primaryKey ? "PRIMARY KEY" : "";
|
|
1822
|
+
return `${parsedColumnName} ${type} ${nullable} ${primaryKey}`.trim();
|
|
1823
|
+
});
|
|
1824
|
+
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
1825
|
+
const stmnt = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (
|
|
1826
|
+
${columns.join(",\n")},
|
|
1827
|
+
PRIMARY KEY (workflow_name, run_id)
|
|
1828
|
+
)`;
|
|
1829
|
+
return stmnt;
|
|
1830
|
+
}
|
|
1831
|
+
return `CREATE TABLE IF NOT EXISTS ${parsedTableName} (${columns.join(", ")})`;
|
|
1832
|
+
}
|
|
1833
|
+
async createTable({
|
|
1834
|
+
tableName,
|
|
1835
|
+
schema
|
|
1836
|
+
}) {
|
|
1837
|
+
try {
|
|
1838
|
+
this.logger.debug(`Creating database table`, { tableName, operation: "schema init" });
|
|
1839
|
+
const sql = this.getCreateTableSQL(tableName, schema);
|
|
1840
|
+
await this.client.execute(sql);
|
|
1841
|
+
} catch (error$1) {
|
|
1842
|
+
throw new error.MastraError(
|
|
1843
|
+
{
|
|
1844
|
+
id: "LIBSQL_STORE_CREATE_TABLE_FAILED",
|
|
1845
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1846
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1847
|
+
details: {
|
|
1848
|
+
tableName
|
|
1849
|
+
}
|
|
1850
|
+
},
|
|
1851
|
+
error$1
|
|
1852
|
+
);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
getSqlType(type) {
|
|
1856
|
+
switch (type) {
|
|
1857
|
+
case "bigint":
|
|
1858
|
+
return "INTEGER";
|
|
1859
|
+
// SQLite uses INTEGER for all integer sizes
|
|
1860
|
+
case "jsonb":
|
|
1861
|
+
return "TEXT";
|
|
1862
|
+
// Store JSON as TEXT in SQLite
|
|
1863
|
+
default:
|
|
1864
|
+
return super.getSqlType(type);
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
async doInsert({
|
|
1868
|
+
tableName,
|
|
1869
|
+
record
|
|
1870
|
+
}) {
|
|
1871
|
+
await this.client.execute(
|
|
1872
|
+
prepareStatement({
|
|
1873
|
+
tableName,
|
|
1874
|
+
record
|
|
1875
|
+
})
|
|
1876
|
+
);
|
|
1877
|
+
}
|
|
1878
|
+
insert(args) {
|
|
1879
|
+
const executeWriteOperationWithRetry = createExecuteWriteOperationWithRetry({
|
|
1880
|
+
logger: this.logger,
|
|
1881
|
+
maxRetries: this.maxRetries,
|
|
1882
|
+
initialBackoffMs: this.initialBackoffMs
|
|
1883
|
+
});
|
|
1884
|
+
return executeWriteOperationWithRetry(() => this.doInsert(args), `insert into table ${args.tableName}`);
|
|
1885
|
+
}
|
|
1886
|
+
async load({ tableName, keys }) {
|
|
1887
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1888
|
+
const parsedKeys = Object.keys(keys).map((key) => utils.parseSqlIdentifier(key, "column name"));
|
|
1889
|
+
const conditions = parsedKeys.map((key) => `${key} = ?`).join(" AND ");
|
|
1890
|
+
const values = Object.values(keys);
|
|
1891
|
+
const result = await this.client.execute({
|
|
1892
|
+
sql: `SELECT * FROM ${parsedTableName} WHERE ${conditions} ORDER BY createdAt DESC LIMIT 1`,
|
|
1893
|
+
args: values
|
|
1894
|
+
});
|
|
1895
|
+
if (!result.rows || result.rows.length === 0) {
|
|
1896
|
+
return null;
|
|
1897
|
+
}
|
|
1898
|
+
const row = result.rows[0];
|
|
1899
|
+
const parsed = Object.fromEntries(
|
|
1900
|
+
Object.entries(row || {}).map(([k, v]) => {
|
|
1901
|
+
try {
|
|
1902
|
+
return [k, typeof v === "string" ? v.startsWith("{") || v.startsWith("[") ? JSON.parse(v) : v : v];
|
|
1903
|
+
} catch {
|
|
1904
|
+
return [k, v];
|
|
1905
|
+
}
|
|
1906
|
+
})
|
|
1907
|
+
);
|
|
1908
|
+
return parsed;
|
|
1909
|
+
}
|
|
1910
|
+
async doBatchInsert({
|
|
1911
|
+
tableName,
|
|
1912
|
+
records
|
|
1913
|
+
}) {
|
|
1914
|
+
if (records.length === 0) return;
|
|
1915
|
+
const batchStatements = records.map((r) => prepareStatement({ tableName, record: r }));
|
|
1916
|
+
await this.client.batch(batchStatements, "write");
|
|
1917
|
+
}
|
|
1918
|
+
batchInsert(args) {
|
|
1919
|
+
const executeWriteOperationWithRetry = createExecuteWriteOperationWithRetry({
|
|
1920
|
+
logger: this.logger,
|
|
1921
|
+
maxRetries: this.maxRetries,
|
|
1922
|
+
initialBackoffMs: this.initialBackoffMs
|
|
1923
|
+
});
|
|
1924
|
+
return executeWriteOperationWithRetry(
|
|
1925
|
+
() => this.doBatchInsert(args),
|
|
1926
|
+
`batch insert into table ${args.tableName}`
|
|
1927
|
+
).catch((error$1) => {
|
|
1360
1928
|
throw new error.MastraError(
|
|
1361
1929
|
{
|
|
1362
|
-
id: "
|
|
1930
|
+
id: "LIBSQL_STORE_BATCH_INSERT_FAILED",
|
|
1363
1931
|
domain: error.ErrorDomain.STORAGE,
|
|
1364
1932
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1365
|
-
details: {
|
|
1933
|
+
details: {
|
|
1934
|
+
tableName: args.tableName
|
|
1935
|
+
}
|
|
1366
1936
|
},
|
|
1367
1937
|
error$1
|
|
1368
1938
|
);
|
|
1369
|
-
}
|
|
1370
|
-
}
|
|
1371
|
-
parseRow(row) {
|
|
1372
|
-
let content = row.content;
|
|
1373
|
-
try {
|
|
1374
|
-
content = JSON.parse(row.content);
|
|
1375
|
-
} catch {
|
|
1376
|
-
}
|
|
1377
|
-
const result = {
|
|
1378
|
-
id: row.id,
|
|
1379
|
-
content,
|
|
1380
|
-
role: row.role,
|
|
1381
|
-
createdAt: new Date(row.createdAt),
|
|
1382
|
-
threadId: row.thread_id,
|
|
1383
|
-
resourceId: row.resourceId
|
|
1384
|
-
};
|
|
1385
|
-
if (row.type && row.type !== `v2`) result.type = row.type;
|
|
1386
|
-
return result;
|
|
1387
|
-
}
|
|
1388
|
-
async _getIncludedMessages({
|
|
1389
|
-
threadId,
|
|
1390
|
-
selectBy
|
|
1391
|
-
}) {
|
|
1392
|
-
const include = selectBy?.include;
|
|
1393
|
-
if (!include) return null;
|
|
1394
|
-
const unionQueries = [];
|
|
1395
|
-
const params = [];
|
|
1396
|
-
for (const inc of include) {
|
|
1397
|
-
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
1398
|
-
const searchId = inc.threadId || threadId;
|
|
1399
|
-
unionQueries.push(
|
|
1400
|
-
`
|
|
1401
|
-
SELECT * FROM (
|
|
1402
|
-
WITH numbered_messages AS (
|
|
1403
|
-
SELECT
|
|
1404
|
-
id, content, role, type, "createdAt", thread_id, "resourceId",
|
|
1405
|
-
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
1406
|
-
FROM "${storage.TABLE_MESSAGES}"
|
|
1407
|
-
WHERE thread_id = ?
|
|
1408
|
-
),
|
|
1409
|
-
target_positions AS (
|
|
1410
|
-
SELECT row_num as target_pos
|
|
1411
|
-
FROM numbered_messages
|
|
1412
|
-
WHERE id = ?
|
|
1413
|
-
)
|
|
1414
|
-
SELECT DISTINCT m.*
|
|
1415
|
-
FROM numbered_messages m
|
|
1416
|
-
CROSS JOIN target_positions t
|
|
1417
|
-
WHERE m.row_num BETWEEN (t.target_pos - ?) AND (t.target_pos + ?)
|
|
1418
|
-
)
|
|
1419
|
-
`
|
|
1420
|
-
// Keep ASC for final sorting after fetching context
|
|
1421
|
-
);
|
|
1422
|
-
params.push(searchId, id, withPreviousMessages, withNextMessages);
|
|
1423
|
-
}
|
|
1424
|
-
const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
|
|
1425
|
-
const includedResult = await this.client.execute({ sql: finalQuery, args: params });
|
|
1426
|
-
const includedRows = includedResult.rows?.map((row) => this.parseRow(row));
|
|
1427
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1428
|
-
const dedupedRows = includedRows.filter((row) => {
|
|
1429
|
-
if (seen.has(row.id)) return false;
|
|
1430
|
-
seen.add(row.id);
|
|
1431
|
-
return true;
|
|
1432
1939
|
});
|
|
1433
|
-
return dedupedRows;
|
|
1434
1940
|
}
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1941
|
+
/**
|
|
1942
|
+
* Alters table schema to add columns if they don't exist
|
|
1943
|
+
* @param tableName Name of the table
|
|
1944
|
+
* @param schema Schema of the table
|
|
1945
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
1946
|
+
*/
|
|
1947
|
+
async alterTable({
|
|
1948
|
+
tableName,
|
|
1949
|
+
schema,
|
|
1950
|
+
ifNotExists
|
|
1439
1951
|
}) {
|
|
1952
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1440
1953
|
try {
|
|
1441
|
-
const
|
|
1442
|
-
const
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
if (
|
|
1446
|
-
|
|
1954
|
+
const pragmaQuery = `PRAGMA table_info(${parsedTableName})`;
|
|
1955
|
+
const result = await this.client.execute(pragmaQuery);
|
|
1956
|
+
const existingColumnNames = new Set(result.rows.map((row) => row.name.toLowerCase()));
|
|
1957
|
+
for (const columnName of ifNotExists) {
|
|
1958
|
+
if (!existingColumnNames.has(columnName.toLowerCase()) && schema[columnName]) {
|
|
1959
|
+
const columnDef = schema[columnName];
|
|
1960
|
+
const sqlType = this.getSqlType(columnDef.type);
|
|
1961
|
+
const nullable = columnDef.nullable === false ? "NOT NULL" : "";
|
|
1962
|
+
const defaultValue = columnDef.nullable === false ? this.getDefaultValue(columnDef.type) : "";
|
|
1963
|
+
const alterSql = `ALTER TABLE ${parsedTableName} ADD COLUMN "${columnName}" ${sqlType} ${nullable} ${defaultValue}`.trim();
|
|
1964
|
+
await this.client.execute(alterSql);
|
|
1965
|
+
this.logger?.debug?.(`Added column ${columnName} to table ${parsedTableName}`);
|
|
1447
1966
|
}
|
|
1448
1967
|
}
|
|
1449
|
-
const excludeIds = messages.map((m) => m.id);
|
|
1450
|
-
const remainingSql = `
|
|
1451
|
-
SELECT
|
|
1452
|
-
id,
|
|
1453
|
-
content,
|
|
1454
|
-
role,
|
|
1455
|
-
type,
|
|
1456
|
-
"createdAt",
|
|
1457
|
-
thread_id,
|
|
1458
|
-
"resourceId"
|
|
1459
|
-
FROM "${storage.TABLE_MESSAGES}"
|
|
1460
|
-
WHERE thread_id = ?
|
|
1461
|
-
${excludeIds.length ? `AND id NOT IN (${excludeIds.map(() => "?").join(", ")})` : ""}
|
|
1462
|
-
ORDER BY "createdAt" DESC
|
|
1463
|
-
LIMIT ?
|
|
1464
|
-
`;
|
|
1465
|
-
const remainingArgs = [threadId, ...excludeIds.length ? excludeIds : [], limit];
|
|
1466
|
-
const remainingResult = await this.client.execute({ sql: remainingSql, args: remainingArgs });
|
|
1467
|
-
if (remainingResult.rows) {
|
|
1468
|
-
messages.push(...remainingResult.rows.map((row) => this.parseRow(row)));
|
|
1469
|
-
}
|
|
1470
|
-
messages.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
|
|
1471
|
-
const list = new agent.MessageList().add(messages, "memory");
|
|
1472
|
-
if (format === `v2`) return list.get.all.v2();
|
|
1473
|
-
return list.get.all.v1();
|
|
1474
1968
|
} catch (error$1) {
|
|
1475
1969
|
throw new error.MastraError(
|
|
1476
1970
|
{
|
|
1477
|
-
id: "
|
|
1971
|
+
id: "LIBSQL_STORE_ALTER_TABLE_FAILED",
|
|
1478
1972
|
domain: error.ErrorDomain.STORAGE,
|
|
1479
1973
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1480
|
-
details: {
|
|
1974
|
+
details: {
|
|
1975
|
+
tableName
|
|
1976
|
+
}
|
|
1481
1977
|
},
|
|
1482
1978
|
error$1
|
|
1483
1979
|
);
|
|
1484
1980
|
}
|
|
1485
1981
|
}
|
|
1486
|
-
async
|
|
1487
|
-
const
|
|
1488
|
-
const { page = 0, perPage: perPageInput, dateRange } = selectBy?.pagination || {};
|
|
1489
|
-
const perPage = perPageInput !== void 0 ? perPageInput : this.resolveMessageLimit({ last: selectBy?.last, defaultLimit: 40 });
|
|
1490
|
-
const fromDate = dateRange?.start;
|
|
1491
|
-
const toDate = dateRange?.end;
|
|
1492
|
-
const messages = [];
|
|
1493
|
-
if (selectBy?.include?.length) {
|
|
1494
|
-
try {
|
|
1495
|
-
const includeMessages = await this._getIncludedMessages({ threadId, selectBy });
|
|
1496
|
-
if (includeMessages) {
|
|
1497
|
-
messages.push(...includeMessages);
|
|
1498
|
-
}
|
|
1499
|
-
} catch (error$1) {
|
|
1500
|
-
throw new error.MastraError(
|
|
1501
|
-
{
|
|
1502
|
-
id: "LIBSQL_STORE_GET_MESSAGES_PAGINATED_GET_INCLUDE_MESSAGES_FAILED",
|
|
1503
|
-
domain: error.ErrorDomain.STORAGE,
|
|
1504
|
-
category: error.ErrorCategory.THIRD_PARTY,
|
|
1505
|
-
details: { threadId }
|
|
1506
|
-
},
|
|
1507
|
-
error$1
|
|
1508
|
-
);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1982
|
+
async clearTable({ tableName }) {
|
|
1983
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1511
1984
|
try {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
const queryParams = [threadId];
|
|
1515
|
-
if (fromDate) {
|
|
1516
|
-
conditions.push(`"createdAt" >= ?`);
|
|
1517
|
-
queryParams.push(fromDate.toISOString());
|
|
1518
|
-
}
|
|
1519
|
-
if (toDate) {
|
|
1520
|
-
conditions.push(`"createdAt" <= ?`);
|
|
1521
|
-
queryParams.push(toDate.toISOString());
|
|
1522
|
-
}
|
|
1523
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
1524
|
-
const countResult = await this.client.execute({
|
|
1525
|
-
sql: `SELECT COUNT(*) as count FROM ${storage.TABLE_MESSAGES} ${whereClause}`,
|
|
1526
|
-
args: queryParams
|
|
1527
|
-
});
|
|
1528
|
-
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1529
|
-
if (total === 0 && messages.length === 0) {
|
|
1530
|
-
return {
|
|
1531
|
-
messages: [],
|
|
1532
|
-
total: 0,
|
|
1533
|
-
page,
|
|
1534
|
-
perPage,
|
|
1535
|
-
hasMore: false
|
|
1536
|
-
};
|
|
1537
|
-
}
|
|
1538
|
-
const excludeIds = messages.map((m) => m.id);
|
|
1539
|
-
const excludeIdsParam = excludeIds.map((_, idx) => `$${idx + queryParams.length + 1}`).join(", ");
|
|
1540
|
-
const dataResult = await this.client.execute({
|
|
1541
|
-
sql: `SELECT id, content, role, type, "createdAt", "resourceId", "thread_id" FROM ${storage.TABLE_MESSAGES} ${whereClause} ${excludeIds.length ? `AND id NOT IN (${excludeIdsParam})` : ""} ORDER BY "createdAt" DESC LIMIT ? OFFSET ?`,
|
|
1542
|
-
args: [...queryParams, ...excludeIds, perPage, currentOffset]
|
|
1543
|
-
});
|
|
1544
|
-
messages.push(...(dataResult.rows || []).map((row) => this.parseRow(row)));
|
|
1545
|
-
const messagesToReturn = format === "v1" ? new agent.MessageList().add(messages, "memory").get.all.v1() : new agent.MessageList().add(messages, "memory").get.all.v2();
|
|
1546
|
-
return {
|
|
1547
|
-
messages: messagesToReturn,
|
|
1548
|
-
total,
|
|
1549
|
-
page,
|
|
1550
|
-
perPage,
|
|
1551
|
-
hasMore: currentOffset + messages.length < total
|
|
1552
|
-
};
|
|
1553
|
-
} catch (error$1) {
|
|
1985
|
+
await this.client.execute(`DELETE FROM ${parsedTableName}`);
|
|
1986
|
+
} catch (e) {
|
|
1554
1987
|
const mastraError = new error.MastraError(
|
|
1555
1988
|
{
|
|
1556
|
-
id: "
|
|
1989
|
+
id: "LIBSQL_STORE_CLEAR_TABLE_FAILED",
|
|
1557
1990
|
domain: error.ErrorDomain.STORAGE,
|
|
1558
1991
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1559
|
-
details: {
|
|
1992
|
+
details: {
|
|
1993
|
+
tableName
|
|
1994
|
+
}
|
|
1560
1995
|
},
|
|
1561
|
-
|
|
1996
|
+
e
|
|
1562
1997
|
);
|
|
1563
1998
|
this.logger?.trackException?.(mastraError);
|
|
1564
1999
|
this.logger?.error?.(mastraError.toString());
|
|
1565
|
-
return { messages: [], total: 0, page, perPage, hasMore: false };
|
|
1566
2000
|
}
|
|
1567
2001
|
}
|
|
1568
|
-
async
|
|
1569
|
-
|
|
1570
|
-
format
|
|
1571
|
-
}) {
|
|
1572
|
-
if (messages.length === 0) return messages;
|
|
2002
|
+
async dropTable({ tableName }) {
|
|
2003
|
+
const parsedTableName = utils.parseSqlIdentifier(tableName, "table name");
|
|
1573
2004
|
try {
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
time instanceof Date ? time.toISOString() : time,
|
|
1607
|
-
message.resourceId
|
|
1608
|
-
]
|
|
1609
|
-
};
|
|
1610
|
-
});
|
|
1611
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1612
|
-
batchStatements.push({
|
|
1613
|
-
sql: `UPDATE ${storage.TABLE_THREADS} SET updatedAt = ? WHERE id = ?`,
|
|
1614
|
-
args: [now, threadId]
|
|
2005
|
+
await this.client.execute(`DROP TABLE IF EXISTS ${parsedTableName}`);
|
|
2006
|
+
} catch (e) {
|
|
2007
|
+
throw new error.MastraError(
|
|
2008
|
+
{
|
|
2009
|
+
id: "LIBSQL_STORE_DROP_TABLE_FAILED",
|
|
2010
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2011
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
2012
|
+
details: {
|
|
2013
|
+
tableName
|
|
2014
|
+
}
|
|
2015
|
+
},
|
|
2016
|
+
e
|
|
2017
|
+
);
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
};
|
|
2021
|
+
var ScoresLibSQL = class extends storage.ScoresStorage {
|
|
2022
|
+
operations;
|
|
2023
|
+
client;
|
|
2024
|
+
constructor({ client, operations }) {
|
|
2025
|
+
super();
|
|
2026
|
+
this.operations = operations;
|
|
2027
|
+
this.client = client;
|
|
2028
|
+
}
|
|
2029
|
+
async getScoresByRunId({
|
|
2030
|
+
runId,
|
|
2031
|
+
pagination
|
|
2032
|
+
}) {
|
|
2033
|
+
try {
|
|
2034
|
+
const result = await this.client.execute({
|
|
2035
|
+
sql: `SELECT * FROM ${storage.TABLE_SCORERS} WHERE runId = ? ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
2036
|
+
args: [runId, pagination.perPage + 1, pagination.page * pagination.perPage]
|
|
1615
2037
|
});
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
2038
|
+
return {
|
|
2039
|
+
scores: result.rows?.slice(0, pagination.perPage).map((row) => this.transformScoreRow(row)) ?? [],
|
|
2040
|
+
pagination: {
|
|
2041
|
+
total: result.rows?.length ?? 0,
|
|
2042
|
+
page: pagination.page,
|
|
2043
|
+
perPage: pagination.perPage,
|
|
2044
|
+
hasMore: result.rows?.length > pagination.perPage
|
|
2045
|
+
}
|
|
2046
|
+
};
|
|
1620
2047
|
} catch (error$1) {
|
|
1621
2048
|
throw new error.MastraError(
|
|
1622
2049
|
{
|
|
1623
|
-
id: "
|
|
2050
|
+
id: "LIBSQL_STORE_GET_SCORES_BY_RUN_ID_FAILED",
|
|
1624
2051
|
domain: error.ErrorDomain.STORAGE,
|
|
1625
2052
|
category: error.ErrorCategory.THIRD_PARTY
|
|
1626
2053
|
},
|
|
@@ -1628,185 +2055,151 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1628
2055
|
);
|
|
1629
2056
|
}
|
|
1630
2057
|
}
|
|
1631
|
-
async
|
|
1632
|
-
|
|
2058
|
+
async getScoresByScorerId({
|
|
2059
|
+
scorerId,
|
|
2060
|
+
entityId,
|
|
2061
|
+
entityType,
|
|
2062
|
+
source,
|
|
2063
|
+
pagination
|
|
1633
2064
|
}) {
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
const existingResult = await this.client.execute({ sql: selectSql, args: messageIds });
|
|
1641
|
-
const existingMessages = existingResult.rows.map((row) => this.parseRow(row));
|
|
1642
|
-
if (existingMessages.length === 0) {
|
|
1643
|
-
return [];
|
|
1644
|
-
}
|
|
1645
|
-
const batchStatements = [];
|
|
1646
|
-
const threadIdsToUpdate = /* @__PURE__ */ new Set();
|
|
1647
|
-
const columnMapping = {
|
|
1648
|
-
threadId: "thread_id"
|
|
1649
|
-
};
|
|
1650
|
-
for (const existingMessage of existingMessages) {
|
|
1651
|
-
const updatePayload = messages.find((m) => m.id === existingMessage.id);
|
|
1652
|
-
if (!updatePayload) continue;
|
|
1653
|
-
const { id, ...fieldsToUpdate } = updatePayload;
|
|
1654
|
-
if (Object.keys(fieldsToUpdate).length === 0) continue;
|
|
1655
|
-
threadIdsToUpdate.add(existingMessage.threadId);
|
|
1656
|
-
if (updatePayload.threadId && updatePayload.threadId !== existingMessage.threadId) {
|
|
1657
|
-
threadIdsToUpdate.add(updatePayload.threadId);
|
|
2065
|
+
try {
|
|
2066
|
+
const conditions = [];
|
|
2067
|
+
const queryParams = [];
|
|
2068
|
+
if (scorerId) {
|
|
2069
|
+
conditions.push(`scorerId = ?`);
|
|
2070
|
+
queryParams.push(scorerId);
|
|
1658
2071
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
if (updatableFields.content) {
|
|
1663
|
-
const newContent = {
|
|
1664
|
-
...existingMessage.content,
|
|
1665
|
-
...updatableFields.content,
|
|
1666
|
-
// Deep merge metadata if it exists on both
|
|
1667
|
-
...existingMessage.content?.metadata && updatableFields.content.metadata ? {
|
|
1668
|
-
metadata: {
|
|
1669
|
-
...existingMessage.content.metadata,
|
|
1670
|
-
...updatableFields.content.metadata
|
|
1671
|
-
}
|
|
1672
|
-
} : {}
|
|
1673
|
-
};
|
|
1674
|
-
setClauses.push(`${utils.parseSqlIdentifier("content", "column name")} = ?`);
|
|
1675
|
-
args.push(JSON.stringify(newContent));
|
|
1676
|
-
delete updatableFields.content;
|
|
2072
|
+
if (entityId) {
|
|
2073
|
+
conditions.push(`entityId = ?`);
|
|
2074
|
+
queryParams.push(entityId);
|
|
1677
2075
|
}
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
setClauses.push(`${utils.parseSqlIdentifier(dbKey, "column name")} = ?`);
|
|
1682
|
-
let value = updatableFields[key];
|
|
1683
|
-
if (typeof value === "object" && value !== null) {
|
|
1684
|
-
value = JSON.stringify(value);
|
|
1685
|
-
}
|
|
1686
|
-
args.push(value);
|
|
1687
|
-
}
|
|
2076
|
+
if (entityType) {
|
|
2077
|
+
conditions.push(`entityType = ?`);
|
|
2078
|
+
queryParams.push(entityType);
|
|
1688
2079
|
}
|
|
1689
|
-
if (
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
batchStatements.push({ sql, args });
|
|
1693
|
-
}
|
|
1694
|
-
if (batchStatements.length === 0) {
|
|
1695
|
-
return existingMessages;
|
|
1696
|
-
}
|
|
1697
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1698
|
-
for (const threadId of threadIdsToUpdate) {
|
|
1699
|
-
if (threadId) {
|
|
1700
|
-
batchStatements.push({
|
|
1701
|
-
sql: `UPDATE ${storage.TABLE_THREADS} SET updatedAt = ? WHERE id = ?`,
|
|
1702
|
-
args: [now, threadId]
|
|
1703
|
-
});
|
|
2080
|
+
if (source) {
|
|
2081
|
+
conditions.push(`source = ?`);
|
|
2082
|
+
queryParams.push(source);
|
|
1704
2083
|
}
|
|
2084
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2085
|
+
const result = await this.client.execute({
|
|
2086
|
+
sql: `SELECT * FROM ${storage.TABLE_SCORERS} ${whereClause} ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
2087
|
+
args: [...queryParams, pagination.perPage + 1, pagination.page * pagination.perPage]
|
|
2088
|
+
});
|
|
2089
|
+
return {
|
|
2090
|
+
scores: result.rows?.slice(0, pagination.perPage).map((row) => this.transformScoreRow(row)) ?? [],
|
|
2091
|
+
pagination: {
|
|
2092
|
+
total: result.rows?.length ?? 0,
|
|
2093
|
+
page: pagination.page,
|
|
2094
|
+
perPage: pagination.perPage,
|
|
2095
|
+
hasMore: result.rows?.length > pagination.perPage
|
|
2096
|
+
}
|
|
2097
|
+
};
|
|
2098
|
+
} catch (error$1) {
|
|
2099
|
+
throw new error.MastraError(
|
|
2100
|
+
{
|
|
2101
|
+
id: "LIBSQL_STORE_GET_SCORES_BY_SCORER_ID_FAILED",
|
|
2102
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2103
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
2104
|
+
},
|
|
2105
|
+
error$1
|
|
2106
|
+
);
|
|
1705
2107
|
}
|
|
1706
|
-
await this.client.batch(batchStatements, "write");
|
|
1707
|
-
const updatedResult = await this.client.execute({ sql: selectSql, args: messageIds });
|
|
1708
|
-
return updatedResult.rows.map((row) => this.parseRow(row));
|
|
1709
2108
|
}
|
|
1710
|
-
|
|
1711
|
-
const
|
|
1712
|
-
const
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
2109
|
+
transformScoreRow(row) {
|
|
2110
|
+
const scorerValue = storage.safelyParseJSON(row.scorer);
|
|
2111
|
+
const inputValue = storage.safelyParseJSON(row.input ?? "{}");
|
|
2112
|
+
const outputValue = storage.safelyParseJSON(row.output ?? "{}");
|
|
2113
|
+
const additionalLLMContextValue = row.additionalLLMContext ? storage.safelyParseJSON(row.additionalLLMContext) : null;
|
|
2114
|
+
const runtimeContextValue = row.runtimeContext ? storage.safelyParseJSON(row.runtimeContext) : null;
|
|
2115
|
+
const metadataValue = row.metadata ? storage.safelyParseJSON(row.metadata) : null;
|
|
2116
|
+
const entityValue = row.entity ? storage.safelyParseJSON(row.entity) : null;
|
|
2117
|
+
const preprocessStepResultValue = row.preprocessStepResult ? storage.safelyParseJSON(row.preprocessStepResult) : null;
|
|
2118
|
+
const analyzeStepResultValue = row.analyzeStepResult ? storage.safelyParseJSON(row.analyzeStepResult) : null;
|
|
1716
2119
|
return {
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
2120
|
+
id: row.id,
|
|
2121
|
+
traceId: row.traceId,
|
|
2122
|
+
runId: row.runId,
|
|
2123
|
+
scorer: scorerValue,
|
|
2124
|
+
score: row.score,
|
|
2125
|
+
reason: row.reason,
|
|
2126
|
+
preprocessStepResult: preprocessStepResultValue,
|
|
2127
|
+
analyzeStepResult: analyzeStepResultValue,
|
|
2128
|
+
analyzePrompt: row.analyzePrompt,
|
|
2129
|
+
preprocessPrompt: row.preprocessPrompt,
|
|
2130
|
+
generateScorePrompt: row.generateScorePrompt,
|
|
2131
|
+
generateReasonPrompt: row.generateReasonPrompt,
|
|
2132
|
+
metadata: metadataValue,
|
|
2133
|
+
input: inputValue,
|
|
2134
|
+
output: outputValue,
|
|
2135
|
+
additionalContext: additionalLLMContextValue,
|
|
2136
|
+
runtimeContext: runtimeContextValue,
|
|
2137
|
+
entityType: row.entityType,
|
|
2138
|
+
entity: entityValue,
|
|
2139
|
+
entityId: row.entityId,
|
|
2140
|
+
scorerId: row.scorerId,
|
|
2141
|
+
source: row.source,
|
|
2142
|
+
resourceId: row.resourceId,
|
|
2143
|
+
threadId: row.threadId,
|
|
2144
|
+
createdAt: row.createdAt,
|
|
2145
|
+
updatedAt: row.updatedAt
|
|
1727
2146
|
};
|
|
1728
2147
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
2148
|
+
async getScoreById({ id }) {
|
|
2149
|
+
const result = await this.client.execute({
|
|
2150
|
+
sql: `SELECT * FROM ${storage.TABLE_SCORERS} WHERE id = ?`,
|
|
2151
|
+
args: [id]
|
|
2152
|
+
});
|
|
2153
|
+
return result.rows?.[0] ? this.transformScoreRow(result.rows[0]) : null;
|
|
2154
|
+
}
|
|
2155
|
+
async saveScore(score) {
|
|
1731
2156
|
try {
|
|
1732
|
-
const
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
2157
|
+
const id = crypto.randomUUID();
|
|
2158
|
+
await this.operations.insert({
|
|
2159
|
+
tableName: storage.TABLE_SCORERS,
|
|
2160
|
+
record: {
|
|
2161
|
+
id,
|
|
2162
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2163
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2164
|
+
...score
|
|
2165
|
+
}
|
|
1737
2166
|
});
|
|
1738
|
-
|
|
2167
|
+
const scoreFromDb = await this.getScoreById({ id });
|
|
2168
|
+
return { score: scoreFromDb };
|
|
1739
2169
|
} catch (error$1) {
|
|
1740
|
-
if (error$1 instanceof Error && error$1.message.includes("no such table")) {
|
|
1741
|
-
return [];
|
|
1742
|
-
}
|
|
1743
2170
|
throw new error.MastraError(
|
|
1744
2171
|
{
|
|
1745
|
-
id: "
|
|
2172
|
+
id: "LIBSQL_STORE_SAVE_SCORE_FAILED",
|
|
1746
2173
|
domain: error.ErrorDomain.STORAGE,
|
|
1747
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
1748
|
-
details: { agentName }
|
|
2174
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
1749
2175
|
},
|
|
1750
2176
|
error$1
|
|
1751
2177
|
);
|
|
1752
2178
|
}
|
|
1753
2179
|
}
|
|
1754
|
-
async
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
const queryParams = [];
|
|
1760
|
-
if (agentName) {
|
|
1761
|
-
conditions.push(`agent_name = ?`);
|
|
1762
|
-
queryParams.push(agentName);
|
|
1763
|
-
}
|
|
1764
|
-
if (type === "test") {
|
|
1765
|
-
conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
|
|
1766
|
-
} else if (type === "live") {
|
|
1767
|
-
conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
|
|
1768
|
-
}
|
|
1769
|
-
if (fromDate) {
|
|
1770
|
-
conditions.push(`created_at >= ?`);
|
|
1771
|
-
queryParams.push(fromDate.toISOString());
|
|
1772
|
-
}
|
|
1773
|
-
if (toDate) {
|
|
1774
|
-
conditions.push(`created_at <= ?`);
|
|
1775
|
-
queryParams.push(toDate.toISOString());
|
|
1776
|
-
}
|
|
1777
|
-
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2180
|
+
async getScoresByEntityId({
|
|
2181
|
+
entityId,
|
|
2182
|
+
entityType,
|
|
2183
|
+
pagination
|
|
2184
|
+
}) {
|
|
1778
2185
|
try {
|
|
1779
|
-
const
|
|
1780
|
-
sql: `SELECT
|
|
1781
|
-
args:
|
|
1782
|
-
});
|
|
1783
|
-
const total = Number(countResult.rows?.[0]?.count ?? 0);
|
|
1784
|
-
const currentOffset = page * perPage;
|
|
1785
|
-
const hasMore = currentOffset + perPage < total;
|
|
1786
|
-
if (total === 0) {
|
|
1787
|
-
return {
|
|
1788
|
-
evals: [],
|
|
1789
|
-
total: 0,
|
|
1790
|
-
page,
|
|
1791
|
-
perPage,
|
|
1792
|
-
hasMore: false
|
|
1793
|
-
};
|
|
1794
|
-
}
|
|
1795
|
-
const dataResult = await this.client.execute({
|
|
1796
|
-
sql: `SELECT * FROM ${storage.TABLE_EVALS} ${whereClause} ORDER BY created_at DESC LIMIT ? OFFSET ?`,
|
|
1797
|
-
args: [...queryParams, perPage, currentOffset]
|
|
2186
|
+
const result = await this.client.execute({
|
|
2187
|
+
sql: `SELECT * FROM ${storage.TABLE_SCORERS} WHERE entityId = ? AND entityType = ? ORDER BY createdAt DESC LIMIT ? OFFSET ?`,
|
|
2188
|
+
args: [entityId, entityType, pagination.perPage + 1, pagination.page * pagination.perPage]
|
|
1798
2189
|
});
|
|
1799
2190
|
return {
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
2191
|
+
scores: result.rows?.slice(0, pagination.perPage).map((row) => this.transformScoreRow(row)) ?? [],
|
|
2192
|
+
pagination: {
|
|
2193
|
+
total: result.rows?.length ?? 0,
|
|
2194
|
+
page: pagination.page,
|
|
2195
|
+
perPage: pagination.perPage,
|
|
2196
|
+
hasMore: result.rows?.length > pagination.perPage
|
|
2197
|
+
}
|
|
1805
2198
|
};
|
|
1806
2199
|
} catch (error$1) {
|
|
1807
2200
|
throw new error.MastraError(
|
|
1808
2201
|
{
|
|
1809
|
-
id: "
|
|
2202
|
+
id: "LIBSQL_STORE_GET_SCORES_BY_ENTITY_ID_FAILED",
|
|
1810
2203
|
domain: error.ErrorDomain.STORAGE,
|
|
1811
2204
|
category: error.ErrorCategory.THIRD_PARTY
|
|
1812
2205
|
},
|
|
@@ -1814,9 +2207,15 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1814
2207
|
);
|
|
1815
2208
|
}
|
|
1816
2209
|
}
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
2210
|
+
};
|
|
2211
|
+
var TracesLibSQL = class extends storage.TracesStorage {
|
|
2212
|
+
client;
|
|
2213
|
+
operations;
|
|
2214
|
+
constructor({ client, operations }) {
|
|
2215
|
+
super();
|
|
2216
|
+
this.client = client;
|
|
2217
|
+
this.operations = operations;
|
|
2218
|
+
}
|
|
1820
2219
|
async getTraces(args) {
|
|
1821
2220
|
if (args.fromDate || args.toDate) {
|
|
1822
2221
|
args.dateRange = {
|
|
@@ -1893,35 +2292,133 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1893
2292
|
sql: `SELECT * FROM ${storage.TABLE_TRACES} ${whereClause} ORDER BY "startTime" DESC LIMIT ? OFFSET ?`,
|
|
1894
2293
|
args: [...queryArgs, perPage, currentOffset]
|
|
1895
2294
|
});
|
|
1896
|
-
const traces = dataResult.rows?.map(
|
|
1897
|
-
(row) => ({
|
|
1898
|
-
id: row.id,
|
|
1899
|
-
parentSpanId: row.parentSpanId,
|
|
1900
|
-
traceId: row.traceId,
|
|
1901
|
-
name: row.name,
|
|
1902
|
-
scope: row.scope,
|
|
1903
|
-
kind: row.kind,
|
|
1904
|
-
status: safelyParseJSON(row.status),
|
|
1905
|
-
events: safelyParseJSON(row.events),
|
|
1906
|
-
links: safelyParseJSON(row.links),
|
|
1907
|
-
attributes: safelyParseJSON(row.attributes),
|
|
1908
|
-
startTime: row.startTime,
|
|
1909
|
-
endTime: row.endTime,
|
|
1910
|
-
other: safelyParseJSON(row.other),
|
|
1911
|
-
createdAt: row.createdAt
|
|
1912
|
-
})
|
|
1913
|
-
) ?? [];
|
|
1914
|
-
return {
|
|
1915
|
-
traces,
|
|
1916
|
-
total,
|
|
1917
|
-
page,
|
|
1918
|
-
perPage,
|
|
1919
|
-
hasMore: currentOffset + traces.length < total
|
|
1920
|
-
};
|
|
2295
|
+
const traces = dataResult.rows?.map(
|
|
2296
|
+
(row) => ({
|
|
2297
|
+
id: row.id,
|
|
2298
|
+
parentSpanId: row.parentSpanId,
|
|
2299
|
+
traceId: row.traceId,
|
|
2300
|
+
name: row.name,
|
|
2301
|
+
scope: row.scope,
|
|
2302
|
+
kind: row.kind,
|
|
2303
|
+
status: storage.safelyParseJSON(row.status),
|
|
2304
|
+
events: storage.safelyParseJSON(row.events),
|
|
2305
|
+
links: storage.safelyParseJSON(row.links),
|
|
2306
|
+
attributes: storage.safelyParseJSON(row.attributes),
|
|
2307
|
+
startTime: row.startTime,
|
|
2308
|
+
endTime: row.endTime,
|
|
2309
|
+
other: storage.safelyParseJSON(row.other),
|
|
2310
|
+
createdAt: row.createdAt
|
|
2311
|
+
})
|
|
2312
|
+
) ?? [];
|
|
2313
|
+
return {
|
|
2314
|
+
traces,
|
|
2315
|
+
total,
|
|
2316
|
+
page,
|
|
2317
|
+
perPage,
|
|
2318
|
+
hasMore: currentOffset + traces.length < total
|
|
2319
|
+
};
|
|
2320
|
+
} catch (error$1) {
|
|
2321
|
+
throw new error.MastraError(
|
|
2322
|
+
{
|
|
2323
|
+
id: "LIBSQL_STORE_GET_TRACES_PAGINATED_FAILED",
|
|
2324
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2325
|
+
category: error.ErrorCategory.THIRD_PARTY
|
|
2326
|
+
},
|
|
2327
|
+
error$1
|
|
2328
|
+
);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
async batchTraceInsert({ records }) {
|
|
2332
|
+
this.logger.debug("Batch inserting traces", { count: records.length });
|
|
2333
|
+
await this.operations.batchInsert({
|
|
2334
|
+
tableName: storage.TABLE_TRACES,
|
|
2335
|
+
records
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
};
|
|
2339
|
+
function parseWorkflowRun(row) {
|
|
2340
|
+
let parsedSnapshot = row.snapshot;
|
|
2341
|
+
if (typeof parsedSnapshot === "string") {
|
|
2342
|
+
try {
|
|
2343
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
2344
|
+
} catch (e) {
|
|
2345
|
+
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
return {
|
|
2349
|
+
workflowName: row.workflow_name,
|
|
2350
|
+
runId: row.run_id,
|
|
2351
|
+
snapshot: parsedSnapshot,
|
|
2352
|
+
resourceId: row.resourceId,
|
|
2353
|
+
createdAt: new Date(row.createdAt),
|
|
2354
|
+
updatedAt: new Date(row.updatedAt)
|
|
2355
|
+
};
|
|
2356
|
+
}
|
|
2357
|
+
var WorkflowsLibSQL = class extends storage.WorkflowsStorage {
|
|
2358
|
+
operations;
|
|
2359
|
+
client;
|
|
2360
|
+
constructor({ operations, client }) {
|
|
2361
|
+
super();
|
|
2362
|
+
this.operations = operations;
|
|
2363
|
+
this.client = client;
|
|
2364
|
+
}
|
|
2365
|
+
async persistWorkflowSnapshot({
|
|
2366
|
+
workflowName,
|
|
2367
|
+
runId,
|
|
2368
|
+
snapshot
|
|
2369
|
+
}) {
|
|
2370
|
+
const data = {
|
|
2371
|
+
workflow_name: workflowName,
|
|
2372
|
+
run_id: runId,
|
|
2373
|
+
snapshot,
|
|
2374
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
2375
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
2376
|
+
};
|
|
2377
|
+
this.logger.debug("Persisting workflow snapshot", { workflowName, runId, data });
|
|
2378
|
+
await this.operations.insert({
|
|
2379
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
2380
|
+
record: data
|
|
2381
|
+
});
|
|
2382
|
+
}
|
|
2383
|
+
async loadWorkflowSnapshot({
|
|
2384
|
+
workflowName,
|
|
2385
|
+
runId
|
|
2386
|
+
}) {
|
|
2387
|
+
this.logger.debug("Loading workflow snapshot", { workflowName, runId });
|
|
2388
|
+
const d = await this.operations.load({
|
|
2389
|
+
tableName: storage.TABLE_WORKFLOW_SNAPSHOT,
|
|
2390
|
+
keys: { workflow_name: workflowName, run_id: runId }
|
|
2391
|
+
});
|
|
2392
|
+
return d ? d.snapshot : null;
|
|
2393
|
+
}
|
|
2394
|
+
async getWorkflowRunById({
|
|
2395
|
+
runId,
|
|
2396
|
+
workflowName
|
|
2397
|
+
}) {
|
|
2398
|
+
const conditions = [];
|
|
2399
|
+
const args = [];
|
|
2400
|
+
if (runId) {
|
|
2401
|
+
conditions.push("run_id = ?");
|
|
2402
|
+
args.push(runId);
|
|
2403
|
+
}
|
|
2404
|
+
if (workflowName) {
|
|
2405
|
+
conditions.push("workflow_name = ?");
|
|
2406
|
+
args.push(workflowName);
|
|
2407
|
+
}
|
|
2408
|
+
const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
2409
|
+
try {
|
|
2410
|
+
const result = await this.client.execute({
|
|
2411
|
+
sql: `SELECT * FROM ${storage.TABLE_WORKFLOW_SNAPSHOT} ${whereClause}`,
|
|
2412
|
+
args
|
|
2413
|
+
});
|
|
2414
|
+
if (!result.rows?.[0]) {
|
|
2415
|
+
return null;
|
|
2416
|
+
}
|
|
2417
|
+
return parseWorkflowRun(result.rows[0]);
|
|
1921
2418
|
} catch (error$1) {
|
|
1922
2419
|
throw new error.MastraError(
|
|
1923
2420
|
{
|
|
1924
|
-
id: "
|
|
2421
|
+
id: "LIBSQL_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
|
|
1925
2422
|
domain: error.ErrorDomain.STORAGE,
|
|
1926
2423
|
category: error.ErrorCategory.THIRD_PARTY
|
|
1927
2424
|
},
|
|
@@ -1953,7 +2450,7 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1953
2450
|
args.push(toDate.toISOString());
|
|
1954
2451
|
}
|
|
1955
2452
|
if (resourceId) {
|
|
1956
|
-
const hasResourceId = await this.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
2453
|
+
const hasResourceId = await this.operations.hasColumn(storage.TABLE_WORKFLOW_SNAPSHOT, "resourceId");
|
|
1957
2454
|
if (hasResourceId) {
|
|
1958
2455
|
conditions.push("resourceId = ?");
|
|
1959
2456
|
args.push(resourceId);
|
|
@@ -1974,7 +2471,7 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1974
2471
|
sql: `SELECT * FROM ${storage.TABLE_WORKFLOW_SNAPSHOT} ${whereClause} ORDER BY createdAt DESC${limit !== void 0 && offset !== void 0 ? ` LIMIT ? OFFSET ?` : ""}`,
|
|
1975
2472
|
args: limit !== void 0 && offset !== void 0 ? [...args, limit, offset] : args
|
|
1976
2473
|
});
|
|
1977
|
-
const runs = (result.rows || []).map((row) =>
|
|
2474
|
+
const runs = (result.rows || []).map((row) => parseWorkflowRun(row));
|
|
1978
2475
|
return { runs, total: total || runs.length };
|
|
1979
2476
|
} catch (error$1) {
|
|
1980
2477
|
throw new error.MastraError(
|
|
@@ -1987,133 +2484,235 @@ var LibSQLStore = class extends storage.MastraStorage {
|
|
|
1987
2484
|
);
|
|
1988
2485
|
}
|
|
1989
2486
|
}
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
}
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2487
|
+
};
|
|
2488
|
+
|
|
2489
|
+
// src/storage/index.ts
|
|
2490
|
+
var LibSQLStore = class extends storage.MastraStorage {
|
|
2491
|
+
client;
|
|
2492
|
+
maxRetries;
|
|
2493
|
+
initialBackoffMs;
|
|
2494
|
+
stores;
|
|
2495
|
+
constructor(config) {
|
|
2496
|
+
super({ name: `LibSQLStore` });
|
|
2497
|
+
this.maxRetries = config.maxRetries ?? 5;
|
|
2498
|
+
this.initialBackoffMs = config.initialBackoffMs ?? 100;
|
|
2499
|
+
if ("url" in config) {
|
|
2500
|
+
if (config.url.endsWith(":memory:")) {
|
|
2501
|
+
this.shouldCacheInit = false;
|
|
2502
|
+
}
|
|
2503
|
+
this.client = client.createClient({
|
|
2504
|
+
url: config.url,
|
|
2505
|
+
...config.authToken ? { authToken: config.authToken } : {}
|
|
2009
2506
|
});
|
|
2010
|
-
if (
|
|
2011
|
-
|
|
2507
|
+
if (config.url.startsWith("file:") || config.url.includes(":memory:")) {
|
|
2508
|
+
this.client.execute("PRAGMA journal_mode=WAL;").then(() => this.logger.debug("LibSQLStore: PRAGMA journal_mode=WAL set.")).catch((err) => this.logger.warn("LibSQLStore: Failed to set PRAGMA journal_mode=WAL.", err));
|
|
2509
|
+
this.client.execute("PRAGMA busy_timeout = 5000;").then(() => this.logger.debug("LibSQLStore: PRAGMA busy_timeout=5000 set.")).catch((err) => this.logger.warn("LibSQLStore: Failed to set PRAGMA busy_timeout.", err));
|
|
2012
2510
|
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
throw new error.MastraError(
|
|
2016
|
-
{
|
|
2017
|
-
id: "LIBSQL_STORE_GET_WORKFLOW_RUN_BY_ID_FAILED",
|
|
2018
|
-
domain: error.ErrorDomain.STORAGE,
|
|
2019
|
-
category: error.ErrorCategory.THIRD_PARTY
|
|
2020
|
-
},
|
|
2021
|
-
error$1
|
|
2022
|
-
);
|
|
2511
|
+
} else {
|
|
2512
|
+
this.client = config.client;
|
|
2023
2513
|
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
keys: { id: resourceId }
|
|
2514
|
+
const operations = new StoreOperationsLibSQL({
|
|
2515
|
+
client: this.client,
|
|
2516
|
+
maxRetries: this.maxRetries,
|
|
2517
|
+
initialBackoffMs: this.initialBackoffMs
|
|
2029
2518
|
});
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
}
|
|
2519
|
+
const scores = new ScoresLibSQL({ client: this.client, operations });
|
|
2520
|
+
const traces = new TracesLibSQL({ client: this.client, operations });
|
|
2521
|
+
const workflows = new WorkflowsLibSQL({ client: this.client, operations });
|
|
2522
|
+
const memory = new MemoryLibSQL({ client: this.client, operations });
|
|
2523
|
+
const legacyEvals = new LegacyEvalsLibSQL({ client: this.client });
|
|
2524
|
+
this.stores = {
|
|
2525
|
+
operations,
|
|
2526
|
+
scores,
|
|
2527
|
+
traces,
|
|
2528
|
+
workflows,
|
|
2529
|
+
memory,
|
|
2530
|
+
legacyEvals
|
|
2531
|
+
};
|
|
2532
|
+
}
|
|
2533
|
+
get supports() {
|
|
2033
2534
|
return {
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2535
|
+
selectByIncludeResourceScope: true,
|
|
2536
|
+
resourceWorkingMemory: true,
|
|
2537
|
+
hasColumn: true,
|
|
2538
|
+
createTable: true,
|
|
2539
|
+
deleteMessages: true
|
|
2038
2540
|
};
|
|
2039
2541
|
}
|
|
2542
|
+
async createTable({
|
|
2543
|
+
tableName,
|
|
2544
|
+
schema
|
|
2545
|
+
}) {
|
|
2546
|
+
await this.stores.operations.createTable({ tableName, schema });
|
|
2547
|
+
}
|
|
2548
|
+
/**
|
|
2549
|
+
* Alters table schema to add columns if they don't exist
|
|
2550
|
+
* @param tableName Name of the table
|
|
2551
|
+
* @param schema Schema of the table
|
|
2552
|
+
* @param ifNotExists Array of column names to add if they don't exist
|
|
2553
|
+
*/
|
|
2554
|
+
async alterTable({
|
|
2555
|
+
tableName,
|
|
2556
|
+
schema,
|
|
2557
|
+
ifNotExists
|
|
2558
|
+
}) {
|
|
2559
|
+
await this.stores.operations.alterTable({ tableName, schema, ifNotExists });
|
|
2560
|
+
}
|
|
2561
|
+
async clearTable({ tableName }) {
|
|
2562
|
+
await this.stores.operations.clearTable({ tableName });
|
|
2563
|
+
}
|
|
2564
|
+
async dropTable({ tableName }) {
|
|
2565
|
+
await this.stores.operations.dropTable({ tableName });
|
|
2566
|
+
}
|
|
2567
|
+
insert(args) {
|
|
2568
|
+
return this.stores.operations.insert(args);
|
|
2569
|
+
}
|
|
2570
|
+
batchInsert(args) {
|
|
2571
|
+
return this.stores.operations.batchInsert(args);
|
|
2572
|
+
}
|
|
2573
|
+
async load({ tableName, keys }) {
|
|
2574
|
+
return this.stores.operations.load({ tableName, keys });
|
|
2575
|
+
}
|
|
2576
|
+
async getThreadById({ threadId }) {
|
|
2577
|
+
return this.stores.memory.getThreadById({ threadId });
|
|
2578
|
+
}
|
|
2579
|
+
/**
|
|
2580
|
+
* @deprecated use getThreadsByResourceIdPaginated instead for paginated results.
|
|
2581
|
+
*/
|
|
2582
|
+
async getThreadsByResourceId(args) {
|
|
2583
|
+
return this.stores.memory.getThreadsByResourceId(args);
|
|
2584
|
+
}
|
|
2585
|
+
async getThreadsByResourceIdPaginated(args) {
|
|
2586
|
+
return this.stores.memory.getThreadsByResourceIdPaginated(args);
|
|
2587
|
+
}
|
|
2588
|
+
async saveThread({ thread }) {
|
|
2589
|
+
return this.stores.memory.saveThread({ thread });
|
|
2590
|
+
}
|
|
2591
|
+
async updateThread({
|
|
2592
|
+
id,
|
|
2593
|
+
title,
|
|
2594
|
+
metadata
|
|
2595
|
+
}) {
|
|
2596
|
+
return this.stores.memory.updateThread({ id, title, metadata });
|
|
2597
|
+
}
|
|
2598
|
+
async deleteThread({ threadId }) {
|
|
2599
|
+
return this.stores.memory.deleteThread({ threadId });
|
|
2600
|
+
}
|
|
2601
|
+
async getMessages({
|
|
2602
|
+
threadId,
|
|
2603
|
+
selectBy,
|
|
2604
|
+
format
|
|
2605
|
+
}) {
|
|
2606
|
+
return this.stores.memory.getMessages({ threadId, selectBy, format });
|
|
2607
|
+
}
|
|
2608
|
+
async getMessagesPaginated(args) {
|
|
2609
|
+
return this.stores.memory.getMessagesPaginated(args);
|
|
2610
|
+
}
|
|
2611
|
+
async saveMessages(args) {
|
|
2612
|
+
return this.stores.memory.saveMessages(args);
|
|
2613
|
+
}
|
|
2614
|
+
async updateMessages({
|
|
2615
|
+
messages
|
|
2616
|
+
}) {
|
|
2617
|
+
return this.stores.memory.updateMessages({ messages });
|
|
2618
|
+
}
|
|
2619
|
+
async deleteMessages(messageIds) {
|
|
2620
|
+
return this.stores.memory.deleteMessages(messageIds);
|
|
2621
|
+
}
|
|
2622
|
+
/** @deprecated use getEvals instead */
|
|
2623
|
+
async getEvalsByAgentName(agentName, type) {
|
|
2624
|
+
return this.stores.legacyEvals.getEvalsByAgentName(agentName, type);
|
|
2625
|
+
}
|
|
2626
|
+
async getEvals(options = {}) {
|
|
2627
|
+
return this.stores.legacyEvals.getEvals(options);
|
|
2628
|
+
}
|
|
2629
|
+
async getScoreById({ id }) {
|
|
2630
|
+
return this.stores.scores.getScoreById({ id });
|
|
2631
|
+
}
|
|
2632
|
+
async saveScore(score) {
|
|
2633
|
+
return this.stores.scores.saveScore(score);
|
|
2634
|
+
}
|
|
2635
|
+
async getScoresByScorerId({
|
|
2636
|
+
scorerId,
|
|
2637
|
+
entityId,
|
|
2638
|
+
entityType,
|
|
2639
|
+
source,
|
|
2640
|
+
pagination
|
|
2641
|
+
}) {
|
|
2642
|
+
return this.stores.scores.getScoresByScorerId({ scorerId, entityId, entityType, source, pagination });
|
|
2643
|
+
}
|
|
2644
|
+
async getScoresByRunId({
|
|
2645
|
+
runId,
|
|
2646
|
+
pagination
|
|
2647
|
+
}) {
|
|
2648
|
+
return this.stores.scores.getScoresByRunId({ runId, pagination });
|
|
2649
|
+
}
|
|
2650
|
+
async getScoresByEntityId({
|
|
2651
|
+
entityId,
|
|
2652
|
+
entityType,
|
|
2653
|
+
pagination
|
|
2654
|
+
}) {
|
|
2655
|
+
return this.stores.scores.getScoresByEntityId({ entityId, entityType, pagination });
|
|
2656
|
+
}
|
|
2657
|
+
/**
|
|
2658
|
+
* TRACES
|
|
2659
|
+
*/
|
|
2660
|
+
/**
|
|
2661
|
+
* @deprecated use getTracesPaginated instead.
|
|
2662
|
+
*/
|
|
2663
|
+
async getTraces(args) {
|
|
2664
|
+
return this.stores.traces.getTraces(args);
|
|
2665
|
+
}
|
|
2666
|
+
async getTracesPaginated(args) {
|
|
2667
|
+
return this.stores.traces.getTracesPaginated(args);
|
|
2668
|
+
}
|
|
2669
|
+
async batchTraceInsert(args) {
|
|
2670
|
+
return this.stores.traces.batchTraceInsert(args);
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* WORKFLOWS
|
|
2674
|
+
*/
|
|
2675
|
+
async persistWorkflowSnapshot({
|
|
2676
|
+
workflowName,
|
|
2677
|
+
runId,
|
|
2678
|
+
snapshot
|
|
2679
|
+
}) {
|
|
2680
|
+
return this.stores.workflows.persistWorkflowSnapshot({ workflowName, runId, snapshot });
|
|
2681
|
+
}
|
|
2682
|
+
async loadWorkflowSnapshot({
|
|
2683
|
+
workflowName,
|
|
2684
|
+
runId
|
|
2685
|
+
}) {
|
|
2686
|
+
return this.stores.workflows.loadWorkflowSnapshot({ workflowName, runId });
|
|
2687
|
+
}
|
|
2688
|
+
async getWorkflowRuns({
|
|
2689
|
+
workflowName,
|
|
2690
|
+
fromDate,
|
|
2691
|
+
toDate,
|
|
2692
|
+
limit,
|
|
2693
|
+
offset,
|
|
2694
|
+
resourceId
|
|
2695
|
+
} = {}) {
|
|
2696
|
+
return this.stores.workflows.getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId });
|
|
2697
|
+
}
|
|
2698
|
+
async getWorkflowRunById({
|
|
2699
|
+
runId,
|
|
2700
|
+
workflowName
|
|
2701
|
+
}) {
|
|
2702
|
+
return this.stores.workflows.getWorkflowRunById({ runId, workflowName });
|
|
2703
|
+
}
|
|
2704
|
+
async getResourceById({ resourceId }) {
|
|
2705
|
+
return this.stores.memory.getResourceById({ resourceId });
|
|
2706
|
+
}
|
|
2040
2707
|
async saveResource({ resource }) {
|
|
2041
|
-
|
|
2042
|
-
tableName: storage.TABLE_RESOURCES,
|
|
2043
|
-
record: {
|
|
2044
|
-
...resource,
|
|
2045
|
-
metadata: JSON.stringify(resource.metadata)
|
|
2046
|
-
}
|
|
2047
|
-
});
|
|
2048
|
-
return resource;
|
|
2708
|
+
return this.stores.memory.saveResource({ resource });
|
|
2049
2709
|
}
|
|
2050
2710
|
async updateResource({
|
|
2051
2711
|
resourceId,
|
|
2052
2712
|
workingMemory,
|
|
2053
2713
|
metadata
|
|
2054
2714
|
}) {
|
|
2055
|
-
|
|
2056
|
-
if (!existingResource) {
|
|
2057
|
-
const newResource = {
|
|
2058
|
-
id: resourceId,
|
|
2059
|
-
workingMemory,
|
|
2060
|
-
metadata: metadata || {},
|
|
2061
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
2062
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
2063
|
-
};
|
|
2064
|
-
return this.saveResource({ resource: newResource });
|
|
2065
|
-
}
|
|
2066
|
-
const updatedResource = {
|
|
2067
|
-
...existingResource,
|
|
2068
|
-
workingMemory: workingMemory !== void 0 ? workingMemory : existingResource.workingMemory,
|
|
2069
|
-
metadata: {
|
|
2070
|
-
...existingResource.metadata,
|
|
2071
|
-
...metadata
|
|
2072
|
-
},
|
|
2073
|
-
updatedAt: /* @__PURE__ */ new Date()
|
|
2074
|
-
};
|
|
2075
|
-
const updates = [];
|
|
2076
|
-
const values = [];
|
|
2077
|
-
if (workingMemory !== void 0) {
|
|
2078
|
-
updates.push("workingMemory = ?");
|
|
2079
|
-
values.push(workingMemory);
|
|
2080
|
-
}
|
|
2081
|
-
if (metadata) {
|
|
2082
|
-
updates.push("metadata = ?");
|
|
2083
|
-
values.push(JSON.stringify(updatedResource.metadata));
|
|
2084
|
-
}
|
|
2085
|
-
updates.push("updatedAt = ?");
|
|
2086
|
-
values.push(updatedResource.updatedAt.toISOString());
|
|
2087
|
-
values.push(resourceId);
|
|
2088
|
-
await this.client.execute({
|
|
2089
|
-
sql: `UPDATE ${storage.TABLE_RESOURCES} SET ${updates.join(", ")} WHERE id = ?`,
|
|
2090
|
-
args: values
|
|
2091
|
-
});
|
|
2092
|
-
return updatedResource;
|
|
2093
|
-
}
|
|
2094
|
-
async hasColumn(table, column) {
|
|
2095
|
-
const result = await this.client.execute({
|
|
2096
|
-
sql: `PRAGMA table_info(${table})`
|
|
2097
|
-
});
|
|
2098
|
-
return (await result.rows)?.some((row) => row.name === column);
|
|
2099
|
-
}
|
|
2100
|
-
parseWorkflowRun(row) {
|
|
2101
|
-
let parsedSnapshot = row.snapshot;
|
|
2102
|
-
if (typeof parsedSnapshot === "string") {
|
|
2103
|
-
try {
|
|
2104
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
2105
|
-
} catch (e) {
|
|
2106
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
return {
|
|
2110
|
-
workflowName: row.workflow_name,
|
|
2111
|
-
runId: row.run_id,
|
|
2112
|
-
snapshot: parsedSnapshot,
|
|
2113
|
-
resourceId: row.resourceId,
|
|
2114
|
-
createdAt: new Date(row.createdAt),
|
|
2115
|
-
updatedAt: new Date(row.updatedAt)
|
|
2116
|
-
};
|
|
2715
|
+
return this.stores.memory.updateResource({ resourceId, workingMemory, metadata });
|
|
2117
2716
|
}
|
|
2118
2717
|
};
|
|
2119
2718
|
|
|
@@ -2220,3 +2819,5 @@ exports.DefaultStorage = LibSQLStore;
|
|
|
2220
2819
|
exports.LIBSQL_PROMPT = LIBSQL_PROMPT;
|
|
2221
2820
|
exports.LibSQLStore = LibSQLStore;
|
|
2222
2821
|
exports.LibSQLVector = LibSQLVector;
|
|
2822
|
+
//# sourceMappingURL=index.cjs.map
|
|
2823
|
+
//# sourceMappingURL=index.cjs.map
|