@mastra/libsql 1.22.3-alpha.1 → 1.22.3-alpha.3
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/README.md +13 -107
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-studio-editor.md +1 -1
- package/dist/index.cjs +128 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +128 -27
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/agents/index.d.ts +1 -0
- package/dist/storage/domains/agents/index.d.ts.map +1 -1
- package/dist/storage/domains/skills/index.d.ts +1 -0
- package/dist/storage/domains/skills/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +6 -0
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/dist/vector/write-lock.d.ts +7 -0
- package/dist/vector/write-lock.d.ts.map +1 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -4,6 +4,8 @@ import { AGENTS_SCHEMA, AGENT_VERSIONS_SCHEMA, AgentsStorage, BackgroundTasksSto
|
|
|
4
4
|
import { parseFieldKey, parseSqlIdentifier } from "@mastra/core/utils";
|
|
5
5
|
import { MastraVector, validateTopK, validateUpsertInput } from "@mastra/core/vector";
|
|
6
6
|
import { BaseFilterTranslator } from "@mastra/core/vector/filter";
|
|
7
|
+
import { realpath } from "fs/promises";
|
|
8
|
+
import { basename, dirname, isAbsolute, join, resolve } from "path";
|
|
7
9
|
import { MastraBase } from "@mastra/core/base";
|
|
8
10
|
import { randomUUID } from "crypto";
|
|
9
11
|
import { MessageList } from "@mastra/core/agent";
|
|
@@ -236,13 +238,13 @@ const FILTER_OPERATORS = {
|
|
|
236
238
|
sql: `NOT (${key})`,
|
|
237
239
|
needsValue: false
|
|
238
240
|
}),
|
|
239
|
-
$size: (key,
|
|
241
|
+
$size: (key, value) => {
|
|
240
242
|
const jsonPath = getJsonPath(key);
|
|
241
243
|
return {
|
|
242
244
|
sql: `(
|
|
243
245
|
CASE
|
|
244
|
-
WHEN json_type(json_extract(metadata, ${jsonPath})) = 'array' THEN
|
|
245
|
-
json_array_length(json_extract(metadata, ${jsonPath})) =
|
|
246
|
+
WHEN json_type(json_extract(metadata, ${jsonPath})) = 'array' THEN
|
|
247
|
+
json_array_length(json_extract(metadata, ${jsonPath})) = ?
|
|
246
248
|
ELSE FALSE
|
|
247
249
|
END
|
|
248
250
|
)`,
|
|
@@ -384,6 +386,31 @@ const processOperator = (key, operator, operatorValue) => {
|
|
|
384
386
|
};
|
|
385
387
|
};
|
|
386
388
|
//#endregion
|
|
389
|
+
//#region src/vector/write-lock.ts
|
|
390
|
+
const databaseWriteChains = /* @__PURE__ */ new Map();
|
|
391
|
+
async function getLocalFileDatabaseKey({ url, syncUrl, cwd }) {
|
|
392
|
+
if (!url.startsWith("file:") || url.includes(":memory:") || syncUrl) return;
|
|
393
|
+
const uriPath = url.slice(5).split(/[?#]/, 1)[0];
|
|
394
|
+
const decodedPath = decodeURIComponent(uriPath);
|
|
395
|
+
const absolutePath = isAbsolute(decodedPath) ? decodedPath : resolve(cwd, decodedPath);
|
|
396
|
+
try {
|
|
397
|
+
return await realpath(absolutePath);
|
|
398
|
+
} catch (error) {
|
|
399
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "ENOENT") throw error;
|
|
400
|
+
}
|
|
401
|
+
return join(await realpath(dirname(absolutePath)), basename(absolutePath));
|
|
402
|
+
}
|
|
403
|
+
function withLocalFileDatabaseWriteLock(key, fn) {
|
|
404
|
+
if (!key) return fn();
|
|
405
|
+
const result = (databaseWriteChains.get(key) ?? Promise.resolve()).then(fn, fn);
|
|
406
|
+
const tail = result.then(() => void 0, () => void 0);
|
|
407
|
+
databaseWriteChains.set(key, tail);
|
|
408
|
+
tail.then(() => {
|
|
409
|
+
if (databaseWriteChains.get(key) === tail) databaseWriteChains.delete(key);
|
|
410
|
+
});
|
|
411
|
+
return result;
|
|
412
|
+
}
|
|
413
|
+
//#endregion
|
|
387
414
|
//#region src/vector/index.ts
|
|
388
415
|
var LibSQLVector = class extends MastraVector {
|
|
389
416
|
turso;
|
|
@@ -391,25 +418,57 @@ var LibSQLVector = class extends MastraVector {
|
|
|
391
418
|
initialBackoffMs;
|
|
392
419
|
overFetchMultiplier;
|
|
393
420
|
isMemoryDb;
|
|
394
|
-
|
|
421
|
+
initialization;
|
|
422
|
+
databaseKey;
|
|
423
|
+
vectorIndexes = /* @__PURE__ */ new Set();
|
|
395
424
|
constructor({ url, authToken, syncUrl, syncInterval, maxRetries = 5, initialBackoffMs = 100, vectorTopKOverFetchMultiplier = 10, id }) {
|
|
396
425
|
super({ id });
|
|
426
|
+
this.isMemoryDb = url.includes(":memory:");
|
|
427
|
+
const isLocalDb = (url.startsWith("file:") || this.isMemoryDb) && !syncUrl;
|
|
428
|
+
const cwd = process.cwd();
|
|
397
429
|
this.turso = createClient({
|
|
398
430
|
url,
|
|
399
431
|
syncUrl,
|
|
400
432
|
authToken,
|
|
401
|
-
syncInterval
|
|
433
|
+
syncInterval,
|
|
434
|
+
...isLocalDb ? { timeout: 5e3 } : {}
|
|
402
435
|
});
|
|
403
436
|
this.maxRetries = maxRetries;
|
|
404
437
|
this.initialBackoffMs = initialBackoffMs;
|
|
405
438
|
if (!Number.isInteger(vectorTopKOverFetchMultiplier) || vectorTopKOverFetchMultiplier < 1) throw new Error("vectorTopKOverFetchMultiplier must be a positive integer");
|
|
406
439
|
this.overFetchMultiplier = vectorTopKOverFetchMultiplier;
|
|
407
|
-
this.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
440
|
+
this.initialization = this.initialize({
|
|
441
|
+
url,
|
|
442
|
+
syncUrl,
|
|
443
|
+
cwd,
|
|
444
|
+
isLocalDb
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
async initialize({ url, syncUrl, cwd, isLocalDb }) {
|
|
448
|
+
if (isLocalDb) {
|
|
449
|
+
await this.applyLocalPragmas();
|
|
450
|
+
this.databaseKey = await getLocalFileDatabaseKey({
|
|
451
|
+
url,
|
|
452
|
+
syncUrl,
|
|
453
|
+
cwd
|
|
454
|
+
});
|
|
411
455
|
}
|
|
412
|
-
|
|
456
|
+
if (!this.isMemoryDb) this.vectorIndexes = await this.discoverVectorIndexes();
|
|
457
|
+
}
|
|
458
|
+
async applyLocalPragmas() {
|
|
459
|
+
for (const [label, sql] of [["journal_mode=WAL", "PRAGMA journal_mode=WAL;"], ["busy_timeout=5000", "PRAGMA busy_timeout = 5000;"]]) try {
|
|
460
|
+
await this.turso.execute(sql);
|
|
461
|
+
this.logger.debug(`LibSQLStore: PRAGMA ${label} set.`);
|
|
462
|
+
} catch (err) {
|
|
463
|
+
this.logger.warn(`LibSQLStore: Failed to set PRAGMA ${label}.`, err);
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
async ensureInitialized() {
|
|
467
|
+
await this.initialization;
|
|
468
|
+
}
|
|
469
|
+
async executeMutation(operation, isTransaction = false) {
|
|
470
|
+
await this.ensureInitialized();
|
|
471
|
+
return withLocalFileDatabaseWriteLock(this.databaseKey, () => this.executeWriteOperationWithRetry(operation, isTransaction));
|
|
413
472
|
}
|
|
414
473
|
/**
|
|
415
474
|
* Closes the underlying libsql client, releasing this vector store's OS file handles.
|
|
@@ -417,6 +476,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
417
476
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
418
477
|
*/
|
|
419
478
|
async close() {
|
|
479
|
+
await this.ensureInitialized();
|
|
420
480
|
if (!this.turso.closed) this.turso.close();
|
|
421
481
|
}
|
|
422
482
|
async discoverVectorIndexes() {
|
|
@@ -452,8 +512,8 @@ var LibSQLVector = class extends MastraVector {
|
|
|
452
512
|
transformFilter(filter) {
|
|
453
513
|
return new LibSQLFilterTranslator().translate(filter);
|
|
454
514
|
}
|
|
455
|
-
|
|
456
|
-
return
|
|
515
|
+
hasVectorIndex(parsedIndexName) {
|
|
516
|
+
return this.vectorIndexes.has(`${parsedIndexName}_vector_idx`);
|
|
457
517
|
}
|
|
458
518
|
async queryWithIndex(parsedIndexName, vectorStr, topK, filter, includeVector, minScore) {
|
|
459
519
|
const { sql: filterQuery, values: filterValues } = buildFilterQuery(this.transformFilter(filter));
|
|
@@ -508,9 +568,10 @@ var LibSQLVector = class extends MastraVector {
|
|
|
508
568
|
details: { message: "queryVector must be an array of finite numbers" }
|
|
509
569
|
});
|
|
510
570
|
try {
|
|
571
|
+
await this.ensureInitialized();
|
|
511
572
|
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
512
573
|
const vectorStr = `[${queryVector.join(",")}]`;
|
|
513
|
-
if (!this.isMemoryDb &&
|
|
574
|
+
if (!this.isMemoryDb && this.hasVectorIndex(parsedIndexName)) try {
|
|
514
575
|
const indexedResults = await this.queryWithIndex(parsedIndexName, vectorStr, topK, filter, includeVector, minScore);
|
|
515
576
|
if (!filter || indexedResults.length >= topK) return indexedResults;
|
|
516
577
|
} catch (err) {
|
|
@@ -551,9 +612,9 @@ var LibSQLVector = class extends MastraVector {
|
|
|
551
612
|
}, error);
|
|
552
613
|
}
|
|
553
614
|
}
|
|
554
|
-
upsert(args) {
|
|
615
|
+
async upsert(args) {
|
|
555
616
|
try {
|
|
556
|
-
return this.
|
|
617
|
+
return await this.executeMutation(() => this.doUpsert(args), true);
|
|
557
618
|
} catch (error) {
|
|
558
619
|
throw new MastraError({
|
|
559
620
|
id: createVectorErrorId("LIBSQL", "UPSERT", "FAILED"),
|
|
@@ -601,9 +662,9 @@ var LibSQLVector = class extends MastraVector {
|
|
|
601
662
|
throw error;
|
|
602
663
|
}
|
|
603
664
|
}
|
|
604
|
-
createIndex(args) {
|
|
665
|
+
async createIndex(args) {
|
|
605
666
|
try {
|
|
606
|
-
return this.
|
|
667
|
+
return await this.executeMutation(() => this.doCreateIndex(args));
|
|
607
668
|
} catch (error) {
|
|
608
669
|
throw new MastraError({
|
|
609
670
|
id: createVectorErrorId("LIBSQL", "CREATE_INDEX", "FAILED"),
|
|
@@ -637,11 +698,11 @@ var LibSQLVector = class extends MastraVector {
|
|
|
637
698
|
`,
|
|
638
699
|
args: []
|
|
639
700
|
});
|
|
640
|
-
this.vectorIndexes.
|
|
701
|
+
this.vectorIndexes.add(`${parsedIndexName}_vector_idx`);
|
|
641
702
|
}
|
|
642
|
-
deleteIndex(args) {
|
|
703
|
+
async deleteIndex(args) {
|
|
643
704
|
try {
|
|
644
|
-
return this.
|
|
705
|
+
return await this.executeMutation(() => this.doDeleteIndex(args));
|
|
645
706
|
} catch (error) {
|
|
646
707
|
throw new MastraError({
|
|
647
708
|
id: createVectorErrorId("LIBSQL", "DELETE_INDEX", "FAILED"),
|
|
@@ -657,10 +718,11 @@ var LibSQLVector = class extends MastraVector {
|
|
|
657
718
|
sql: `DROP TABLE IF EXISTS ${parsedIndexName}`,
|
|
658
719
|
args: []
|
|
659
720
|
});
|
|
660
|
-
this.vectorIndexes.
|
|
721
|
+
this.vectorIndexes.delete(`${parsedIndexName}_vector_idx`);
|
|
661
722
|
}
|
|
662
723
|
async listIndexes() {
|
|
663
724
|
try {
|
|
725
|
+
await this.ensureInitialized();
|
|
664
726
|
return (await this.turso.execute({
|
|
665
727
|
sql: `
|
|
666
728
|
SELECT name FROM sqlite_master
|
|
@@ -685,6 +747,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
685
747
|
*/
|
|
686
748
|
async describeIndex({ indexName }) {
|
|
687
749
|
try {
|
|
750
|
+
await this.ensureInitialized();
|
|
688
751
|
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
689
752
|
const tableInfo = await this.turso.execute({
|
|
690
753
|
sql: `
|
|
@@ -730,7 +793,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
730
793
|
* @throws Will throw an error if no updates are provided or if the update operation fails.
|
|
731
794
|
*/
|
|
732
795
|
updateVector(args) {
|
|
733
|
-
return this.
|
|
796
|
+
return this.executeMutation(() => this.doUpdateVector(args));
|
|
734
797
|
}
|
|
735
798
|
async doUpdateVector(params) {
|
|
736
799
|
const { indexName, update } = params;
|
|
@@ -835,9 +898,9 @@ var LibSQLVector = class extends MastraVector {
|
|
|
835
898
|
* @returns A promise that resolves when the deletion is complete.
|
|
836
899
|
* @throws Will throw an error if the deletion operation fails.
|
|
837
900
|
*/
|
|
838
|
-
deleteVector(args) {
|
|
901
|
+
async deleteVector(args) {
|
|
839
902
|
try {
|
|
840
|
-
return this.
|
|
903
|
+
return await this.executeMutation(() => this.doDeleteVector(args));
|
|
841
904
|
} catch (error) {
|
|
842
905
|
throw new MastraError({
|
|
843
906
|
id: createVectorErrorId("LIBSQL", "DELETE_VECTOR", "FAILED"),
|
|
@@ -858,7 +921,7 @@ var LibSQLVector = class extends MastraVector {
|
|
|
858
921
|
});
|
|
859
922
|
}
|
|
860
923
|
deleteVectors(args) {
|
|
861
|
-
return this.
|
|
924
|
+
return this.executeMutation(() => this.doDeleteVectors(args));
|
|
862
925
|
}
|
|
863
926
|
async doDeleteVectors({ indexName, filter, ids }) {
|
|
864
927
|
const parsedIndexName = parseSqlIdentifier(indexName, "index name");
|
|
@@ -940,9 +1003,9 @@ var LibSQLVector = class extends MastraVector {
|
|
|
940
1003
|
}, error);
|
|
941
1004
|
}
|
|
942
1005
|
}
|
|
943
|
-
truncateIndex(args) {
|
|
1006
|
+
async truncateIndex(args) {
|
|
944
1007
|
try {
|
|
945
|
-
return this.
|
|
1008
|
+
return await this.executeMutation(() => this._doTruncateIndex(args));
|
|
946
1009
|
} catch (error) {
|
|
947
1010
|
throw new MastraError({
|
|
948
1011
|
id: createVectorErrorId("LIBSQL", "TRUNCATE_INDEX", "FAILED"),
|
|
@@ -2498,6 +2561,26 @@ var AgentsLibSQL = class extends AgentsStorage {
|
|
|
2498
2561
|
}, error);
|
|
2499
2562
|
}
|
|
2500
2563
|
}
|
|
2564
|
+
async getVersions(ids) {
|
|
2565
|
+
if (ids.length === 0) return [];
|
|
2566
|
+
try {
|
|
2567
|
+
return (await this.#db.selectMany({
|
|
2568
|
+
tableName: TABLE_AGENT_VERSIONS,
|
|
2569
|
+
whereClause: {
|
|
2570
|
+
sql: `WHERE id IN (${ids.map(() => "?").join(", ")})`,
|
|
2571
|
+
args: ids
|
|
2572
|
+
}
|
|
2573
|
+
}) ?? []).map((row) => this.parseVersionRow(row));
|
|
2574
|
+
} catch (error) {
|
|
2575
|
+
if (error instanceof MastraError) throw error;
|
|
2576
|
+
throw new MastraError({
|
|
2577
|
+
id: createStorageErrorId("LIBSQL", "GET_VERSIONS", "FAILED"),
|
|
2578
|
+
domain: ErrorDomain.STORAGE,
|
|
2579
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
2580
|
+
details: { count: ids.length }
|
|
2581
|
+
}, error);
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2501
2584
|
async getVersionByNumber(agentId, versionNumber) {
|
|
2502
2585
|
try {
|
|
2503
2586
|
const rows = await this.#db.selectMany({
|
|
@@ -12241,6 +12324,24 @@ var SkillsLibSQL = class extends SkillsStorage {
|
|
|
12241
12324
|
}, error);
|
|
12242
12325
|
}
|
|
12243
12326
|
}
|
|
12327
|
+
async getVersions(ids) {
|
|
12328
|
+
if (ids.length === 0) return [];
|
|
12329
|
+
try {
|
|
12330
|
+
const placeholders = ids.map(() => "?").join(", ");
|
|
12331
|
+
return ((await this.#client.execute({
|
|
12332
|
+
sql: `SELECT ${buildSelectColumns(TABLE_SKILL_VERSIONS)} FROM "${TABLE_SKILL_VERSIONS}" WHERE id IN (${placeholders})`,
|
|
12333
|
+
args: ids
|
|
12334
|
+
})).rows ?? []).map((row) => this.#parseVersionRow(row));
|
|
12335
|
+
} catch (error) {
|
|
12336
|
+
if (error instanceof MastraError) throw error;
|
|
12337
|
+
throw new MastraError({
|
|
12338
|
+
id: createStorageErrorId("LIBSQL", "GET_SKILL_VERSIONS", "FAILED"),
|
|
12339
|
+
domain: ErrorDomain.STORAGE,
|
|
12340
|
+
category: ErrorCategory.THIRD_PARTY,
|
|
12341
|
+
details: { count: ids.length }
|
|
12342
|
+
}, error);
|
|
12343
|
+
}
|
|
12344
|
+
}
|
|
12244
12345
|
async getVersionByNumber(skillId, versionNumber) {
|
|
12245
12346
|
try {
|
|
12246
12347
|
const row = (await this.#client.execute({
|