@mastra/libsql 1.8.2-alpha.0 → 1.9.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-core-mastra-class.md +9 -1
- package/dist/index.cjs +115 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +115 -1
- package/dist/index.js.map +1 -1
- package/dist/storage/db/utils.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +2 -1
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +14 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -509,6 +509,9 @@ var LibSQLVector = class extends MastraVector {
|
|
|
509
509
|
turso;
|
|
510
510
|
maxRetries;
|
|
511
511
|
initialBackoffMs;
|
|
512
|
+
overFetchMultiplier;
|
|
513
|
+
isMemoryDb;
|
|
514
|
+
vectorIndexes;
|
|
512
515
|
constructor({
|
|
513
516
|
url,
|
|
514
517
|
authToken,
|
|
@@ -516,6 +519,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
516
519
|
syncInterval,
|
|
517
520
|
maxRetries = 5,
|
|
518
521
|
initialBackoffMs = 100,
|
|
522
|
+
vectorTopKOverFetchMultiplier = 10,
|
|
519
523
|
id
|
|
520
524
|
}) {
|
|
521
525
|
super({ id });
|
|
@@ -527,10 +531,27 @@ var LibSQLVector = class extends MastraVector {
|
|
|
527
531
|
});
|
|
528
532
|
this.maxRetries = maxRetries;
|
|
529
533
|
this.initialBackoffMs = initialBackoffMs;
|
|
530
|
-
if (
|
|
534
|
+
if (!Number.isInteger(vectorTopKOverFetchMultiplier) || vectorTopKOverFetchMultiplier < 1) {
|
|
535
|
+
throw new Error("vectorTopKOverFetchMultiplier must be a positive integer");
|
|
536
|
+
}
|
|
537
|
+
this.overFetchMultiplier = vectorTopKOverFetchMultiplier;
|
|
538
|
+
this.isMemoryDb = url.includes(":memory:");
|
|
539
|
+
if (url.includes(`file:`) || this.isMemoryDb) {
|
|
531
540
|
this.turso.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));
|
|
532
541
|
this.turso.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=5000.", err));
|
|
533
542
|
}
|
|
543
|
+
this.vectorIndexes = this.isMemoryDb ? Promise.resolve(/* @__PURE__ */ new Set()) : this.discoverVectorIndexes();
|
|
544
|
+
}
|
|
545
|
+
async discoverVectorIndexes() {
|
|
546
|
+
try {
|
|
547
|
+
const result = await this.turso.execute({
|
|
548
|
+
sql: `SELECT name FROM sqlite_master WHERE type='index' AND name LIKE '%_vector_idx'`,
|
|
549
|
+
args: []
|
|
550
|
+
});
|
|
551
|
+
return new Set(result.rows.map((row) => row.name));
|
|
552
|
+
} catch {
|
|
553
|
+
return /* @__PURE__ */ new Set();
|
|
554
|
+
}
|
|
534
555
|
}
|
|
535
556
|
async executeWriteOperationWithRetry(operation, isTransaction = false) {
|
|
536
557
|
let attempts = 0;
|
|
@@ -564,6 +585,40 @@ var LibSQLVector = class extends MastraVector {
|
|
|
564
585
|
const translator = new LibSQLFilterTranslator();
|
|
565
586
|
return translator.translate(filter);
|
|
566
587
|
}
|
|
588
|
+
async hasVectorIndex(parsedIndexName) {
|
|
589
|
+
const indexes = await this.vectorIndexes;
|
|
590
|
+
return indexes.has(`${parsedIndexName}_vector_idx`);
|
|
591
|
+
}
|
|
592
|
+
async queryWithIndex(parsedIndexName, vectorStr, topK, filter, includeVector, minScore) {
|
|
593
|
+
const translatedFilter = this.transformFilter(filter);
|
|
594
|
+
const { sql: filterQuery, values: filterValues } = buildFilterQuery(translatedFilter);
|
|
595
|
+
const hasFilter = filterQuery.length > 0;
|
|
596
|
+
const fetchCount = hasFilter ? topK * this.overFetchMultiplier : topK * 2;
|
|
597
|
+
const embeddingSelect = includeVector ? ", vector_extract(t.embedding) as embedding" : "";
|
|
598
|
+
const filterCondition = hasFilter ? filterQuery.replace(/^\s*WHERE\s+/i, "") : "";
|
|
599
|
+
const whereClause = hasFilter ? `WHERE ${filterCondition} AND score > ?` : "WHERE score > ?";
|
|
600
|
+
const query = `
|
|
601
|
+
WITH candidates AS (
|
|
602
|
+
SELECT t.vector_id AS id,
|
|
603
|
+
(1 - vector_distance_cos(t.embedding, vector32(?))) AS score,
|
|
604
|
+
t.metadata
|
|
605
|
+
${embeddingSelect}
|
|
606
|
+
FROM vector_top_k('${parsedIndexName}_vector_idx', vector32(?), ?) AS v
|
|
607
|
+
JOIN "${parsedIndexName}" AS t ON t.rowid = v.id
|
|
608
|
+
)
|
|
609
|
+
SELECT * FROM candidates
|
|
610
|
+
${whereClause}
|
|
611
|
+
ORDER BY score DESC
|
|
612
|
+
LIMIT ?`;
|
|
613
|
+
const args = [vectorStr, vectorStr, fetchCount, ...filterValues, minScore, topK];
|
|
614
|
+
const result = await this.turso.execute({ sql: query, args });
|
|
615
|
+
return result.rows.map(({ id, score, metadata, embedding }) => ({
|
|
616
|
+
id,
|
|
617
|
+
score,
|
|
618
|
+
metadata: JSON.parse(metadata ?? "{}"),
|
|
619
|
+
...includeVector && embedding && { vector: JSON.parse(embedding) }
|
|
620
|
+
}));
|
|
621
|
+
}
|
|
567
622
|
async query({
|
|
568
623
|
indexName,
|
|
569
624
|
queryVector,
|
|
@@ -594,6 +649,23 @@ var LibSQLVector = class extends MastraVector {
|
|
|
594
649
|
try {
|
|
595
650
|
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
596
651
|
const vectorStr = `[${queryVector.join(",")}]`;
|
|
652
|
+
if (!this.isMemoryDb && await this.hasVectorIndex(parsedIndexName)) {
|
|
653
|
+
try {
|
|
654
|
+
const indexedResults = await this.queryWithIndex(
|
|
655
|
+
parsedIndexName,
|
|
656
|
+
vectorStr,
|
|
657
|
+
topK,
|
|
658
|
+
filter,
|
|
659
|
+
includeVector,
|
|
660
|
+
minScore
|
|
661
|
+
);
|
|
662
|
+
if (!filter || indexedResults.length >= topK) {
|
|
663
|
+
return indexedResults;
|
|
664
|
+
}
|
|
665
|
+
} catch (err) {
|
|
666
|
+
this.logger.warn("LibSQLVector: indexed query failed, falling back to brute-force", err);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
597
669
|
const translatedFilter = this.transformFilter(filter);
|
|
598
670
|
const { sql: filterQuery, values: filterValues } = buildFilterQuery(translatedFilter);
|
|
599
671
|
filterValues.push(minScore);
|
|
@@ -727,6 +799,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
727
799
|
`,
|
|
728
800
|
args: []
|
|
729
801
|
});
|
|
802
|
+
void this.vectorIndexes.then((indexes) => indexes.add(`${parsedIndexName}_vector_idx`));
|
|
730
803
|
}
|
|
731
804
|
deleteIndex(args) {
|
|
732
805
|
try {
|
|
@@ -749,6 +822,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
749
822
|
sql: `DROP TABLE IF EXISTS ${parsedIndexName}`,
|
|
750
823
|
args: []
|
|
751
824
|
});
|
|
825
|
+
void this.vectorIndexes.then((indexes) => indexes.delete(`${parsedIndexName}_vector_idx`));
|
|
752
826
|
}
|
|
753
827
|
async listIndexes() {
|
|
754
828
|
try {
|
|
@@ -1285,6 +1359,9 @@ function transformFromSqlRow({
|
|
|
1285
1359
|
const dateColumns = new Set(
|
|
1286
1360
|
Object.keys(TABLE_SCHEMAS[tableName]).filter((key) => TABLE_SCHEMAS[tableName][key].type === "timestamp").map((key) => key)
|
|
1287
1361
|
);
|
|
1362
|
+
const booleanColumns = new Set(
|
|
1363
|
+
Object.keys(TABLE_SCHEMAS[tableName]).filter((key) => TABLE_SCHEMAS[tableName][key].type === "boolean").map((key) => key)
|
|
1364
|
+
);
|
|
1288
1365
|
for (const [key, value] of Object.entries(sqlRow)) {
|
|
1289
1366
|
if (value === null || value === void 0) {
|
|
1290
1367
|
result[key] = value;
|
|
@@ -1298,6 +1375,10 @@ function transformFromSqlRow({
|
|
|
1298
1375
|
result[key] = safelyParseJSON(value);
|
|
1299
1376
|
continue;
|
|
1300
1377
|
}
|
|
1378
|
+
if (booleanColumns.has(key)) {
|
|
1379
|
+
result[key] = Boolean(value);
|
|
1380
|
+
continue;
|
|
1381
|
+
}
|
|
1301
1382
|
result[key] = value;
|
|
1302
1383
|
}
|
|
1303
1384
|
return result;
|
|
@@ -7850,6 +7931,39 @@ var ObservabilityLibSQL = class extends ObservabilityStorage {
|
|
|
7850
7931
|
);
|
|
7851
7932
|
}
|
|
7852
7933
|
}
|
|
7934
|
+
async getTraceLight(args) {
|
|
7935
|
+
const { traceId } = args;
|
|
7936
|
+
try {
|
|
7937
|
+
const spans = await this.#db.selectMany({
|
|
7938
|
+
tableName: TABLE_SPANS,
|
|
7939
|
+
whereClause: { sql: " WHERE traceId = ?", args: [traceId] },
|
|
7940
|
+
orderBy: "startedAt ASC"
|
|
7941
|
+
});
|
|
7942
|
+
if (!spans || spans.length === 0) {
|
|
7943
|
+
return null;
|
|
7944
|
+
}
|
|
7945
|
+
return {
|
|
7946
|
+
traceId,
|
|
7947
|
+
spans: spans.map((span) => {
|
|
7948
|
+
const transformed = transformFromSqlRow({ tableName: TABLE_SPANS, sqlRow: span });
|
|
7949
|
+
const { input, output, attributes, metadata, tags, links, ...light } = transformed;
|
|
7950
|
+
return light;
|
|
7951
|
+
})
|
|
7952
|
+
};
|
|
7953
|
+
} catch (error) {
|
|
7954
|
+
throw new MastraError(
|
|
7955
|
+
{
|
|
7956
|
+
id: createStorageErrorId("LIBSQL", "GET_TRACE_LIGHT", "FAILED"),
|
|
7957
|
+
domain: ErrorDomain.STORAGE,
|
|
7958
|
+
category: ErrorCategory.USER,
|
|
7959
|
+
details: {
|
|
7960
|
+
traceId
|
|
7961
|
+
}
|
|
7962
|
+
},
|
|
7963
|
+
error
|
|
7964
|
+
);
|
|
7965
|
+
}
|
|
7966
|
+
}
|
|
7853
7967
|
async updateSpan(args) {
|
|
7854
7968
|
const { traceId, spanId, updates } = args;
|
|
7855
7969
|
try {
|