@mastra/libsql 1.0.0-beta.12 → 1.0.0-beta.14
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 +104 -0
- package/dist/docs/README.md +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/SOURCE_MAP.json +1 -1
- package/dist/docs/agents/01-agent-memory.md +6 -0
- package/dist/docs/agents/03-agent-approval.md +61 -0
- package/dist/docs/memory/02-storage.md +21 -3
- package/dist/docs/memory/06-reference.md +1 -1
- package/dist/docs/storage/01-reference.md +15 -15
- package/dist/index.cjs +292 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +293 -35
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +42 -1
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +2 -2
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/observability/index.d.ts +23 -0
- package/dist/storage/domains/observability/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -244,10 +244,10 @@ var FILTER_OPERATORS = {
|
|
|
244
244
|
};
|
|
245
245
|
},
|
|
246
246
|
// Element Operators
|
|
247
|
-
$exists: (key) => {
|
|
247
|
+
$exists: (key, value) => {
|
|
248
248
|
const jsonPath = getJsonPath(key);
|
|
249
249
|
return {
|
|
250
|
-
sql: `json_extract(metadata, ${jsonPath}) IS NOT NULL`,
|
|
250
|
+
sql: value === false ? `json_extract(metadata, ${jsonPath}) IS NULL` : `json_extract(metadata, ${jsonPath}) IS NOT NULL`,
|
|
251
251
|
needsValue: false
|
|
252
252
|
};
|
|
253
253
|
},
|
|
@@ -540,7 +540,7 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
540
540
|
try {
|
|
541
541
|
return await operation();
|
|
542
542
|
} catch (error) {
|
|
543
|
-
if (error.code === "SQLITE_BUSY" || error.message && error.message.toLowerCase().includes("database is locked")) {
|
|
543
|
+
if (error.code === "SQLITE_BUSY" || error.code === "SQLITE_LOCKED" || error.code === "SQLITE_LOCKED_SHAREDCACHE" || error.message && error.message.toLowerCase().includes("database is locked") || error.message && error.message.toLowerCase().includes("database table is locked")) {
|
|
544
544
|
attempts++;
|
|
545
545
|
if (attempts >= this.maxRetries) {
|
|
546
546
|
this.logger.error(
|
|
@@ -574,22 +574,14 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
574
574
|
minScore = -1
|
|
575
575
|
// Default to -1 to include all results (cosine similarity ranges from -1 to 1)
|
|
576
576
|
}) {
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
throw new error.MastraError(
|
|
586
|
-
{
|
|
587
|
-
id: storage.createVectorErrorId("LIBSQL", "QUERY", "INVALID_ARGS"),
|
|
588
|
-
domain: error.ErrorDomain.STORAGE,
|
|
589
|
-
category: error.ErrorCategory.USER
|
|
590
|
-
},
|
|
591
|
-
error$1
|
|
592
|
-
);
|
|
577
|
+
vector.validateTopK("LIBSQL", topK);
|
|
578
|
+
if (!Array.isArray(queryVector) || !queryVector.every((x) => typeof x === "number" && Number.isFinite(x))) {
|
|
579
|
+
throw new error.MastraError({
|
|
580
|
+
id: storage.createVectorErrorId("LIBSQL", "QUERY", "INVALID_ARGS"),
|
|
581
|
+
domain: error.ErrorDomain.STORAGE,
|
|
582
|
+
category: error.ErrorCategory.USER,
|
|
583
|
+
details: { message: "queryVector must be an array of finite numbers" }
|
|
584
|
+
});
|
|
593
585
|
}
|
|
594
586
|
try {
|
|
595
587
|
const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
|
|
@@ -649,6 +641,7 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
649
641
|
}
|
|
650
642
|
}
|
|
651
643
|
async doUpsert({ indexName, vectors, metadata, ids }) {
|
|
644
|
+
vector.validateUpsertInput("LIBSQL", vectors, metadata, ids);
|
|
652
645
|
const tx = await this.turso.transaction("write");
|
|
653
646
|
try {
|
|
654
647
|
const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
|
|
@@ -1712,6 +1705,9 @@ var LibSQLDB = class extends base.MastraBase {
|
|
|
1712
1705
|
if (tableName === storage.TABLE_WORKFLOW_SNAPSHOT) {
|
|
1713
1706
|
tableConstraints.push("UNIQUE (workflow_name, run_id)");
|
|
1714
1707
|
}
|
|
1708
|
+
if (tableName === storage.TABLE_SPANS) {
|
|
1709
|
+
tableConstraints.push("UNIQUE (spanId, traceId)");
|
|
1710
|
+
}
|
|
1715
1711
|
const allDefinitions = [...columnDefinitions, ...tableConstraints].join(",\n ");
|
|
1716
1712
|
const sql = `CREATE TABLE IF NOT EXISTS ${parsedTableName} (
|
|
1717
1713
|
${allDefinitions}
|
|
@@ -1722,6 +1718,9 @@ var LibSQLDB = class extends base.MastraBase {
|
|
|
1722
1718
|
await this.migrateSpansTable();
|
|
1723
1719
|
}
|
|
1724
1720
|
} catch (error$1) {
|
|
1721
|
+
if (error$1 instanceof error.MastraError) {
|
|
1722
|
+
throw error$1;
|
|
1723
|
+
}
|
|
1725
1724
|
throw new error.MastraError(
|
|
1726
1725
|
{
|
|
1727
1726
|
id: storage.createStorageErrorId("LIBSQL", "CREATE_TABLE", "FAILED"),
|
|
@@ -1735,7 +1734,7 @@ var LibSQLDB = class extends base.MastraBase {
|
|
|
1735
1734
|
}
|
|
1736
1735
|
/**
|
|
1737
1736
|
* Migrates the spans table schema from OLD_SPAN_SCHEMA to current SPAN_SCHEMA.
|
|
1738
|
-
* This adds new columns that don't exist in old schema.
|
|
1737
|
+
* This adds new columns that don't exist in old schema and ensures required indexes exist.
|
|
1739
1738
|
*/
|
|
1740
1739
|
async migrateSpansTable() {
|
|
1741
1740
|
const schema = storage.TABLE_SCHEMAS[storage.TABLE_SPANS];
|
|
@@ -1749,9 +1748,203 @@ var LibSQLDB = class extends base.MastraBase {
|
|
|
1749
1748
|
this.logger.debug(`LibSQLDB: Added column '${columnName}' to ${storage.TABLE_SPANS}`);
|
|
1750
1749
|
}
|
|
1751
1750
|
}
|
|
1751
|
+
const indexExists = await this.spansUniqueIndexExists();
|
|
1752
|
+
if (!indexExists) {
|
|
1753
|
+
const duplicateInfo = await this.checkForDuplicateSpans();
|
|
1754
|
+
if (duplicateInfo.hasDuplicates) {
|
|
1755
|
+
const errorMessage = `
|
|
1756
|
+
===========================================================================
|
|
1757
|
+
MIGRATION REQUIRED: Duplicate spans detected in ${storage.TABLE_SPANS}
|
|
1758
|
+
===========================================================================
|
|
1759
|
+
|
|
1760
|
+
Found ${duplicateInfo.duplicateCount} duplicate (traceId, spanId) combinations.
|
|
1761
|
+
|
|
1762
|
+
The spans table requires a unique constraint on (traceId, spanId), but your
|
|
1763
|
+
database contains duplicate entries that must be resolved first.
|
|
1764
|
+
|
|
1765
|
+
To fix this, run the manual migration command:
|
|
1766
|
+
|
|
1767
|
+
npx mastra migrate
|
|
1768
|
+
|
|
1769
|
+
This command will:
|
|
1770
|
+
1. Remove duplicate spans (keeping the most complete/recent version)
|
|
1771
|
+
2. Add the required unique constraint
|
|
1772
|
+
|
|
1773
|
+
Note: This migration may take some time for large tables.
|
|
1774
|
+
===========================================================================
|
|
1775
|
+
`;
|
|
1776
|
+
throw new error.MastraError({
|
|
1777
|
+
id: storage.createStorageErrorId("LIBSQL", "MIGRATION_REQUIRED", "DUPLICATE_SPANS"),
|
|
1778
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1779
|
+
category: error.ErrorCategory.USER,
|
|
1780
|
+
text: errorMessage
|
|
1781
|
+
});
|
|
1782
|
+
} else {
|
|
1783
|
+
await this.client.execute(
|
|
1784
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS "mastra_ai_spans_spanid_traceid_idx" ON "${storage.TABLE_SPANS}" ("spanId", "traceId")`
|
|
1785
|
+
);
|
|
1786
|
+
this.logger.debug(`LibSQLDB: Created unique index on (spanId, traceId) for ${storage.TABLE_SPANS}`);
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1752
1789
|
this.logger.info(`LibSQLDB: Migration completed for ${storage.TABLE_SPANS}`);
|
|
1790
|
+
} catch (error$1) {
|
|
1791
|
+
if (error$1 instanceof error.MastraError) {
|
|
1792
|
+
throw error$1;
|
|
1793
|
+
}
|
|
1794
|
+
this.logger.warn(`LibSQLDB: Failed to migrate spans table ${storage.TABLE_SPANS}:`, error$1);
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
/**
|
|
1798
|
+
* Checks if the unique index on (spanId, traceId) already exists on the spans table.
|
|
1799
|
+
* Used to skip deduplication when the index already exists (migration already complete).
|
|
1800
|
+
*/
|
|
1801
|
+
async spansUniqueIndexExists() {
|
|
1802
|
+
try {
|
|
1803
|
+
const result = await this.client.execute(
|
|
1804
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'index' AND name = 'mastra_ai_spans_spanid_traceid_idx'`
|
|
1805
|
+
);
|
|
1806
|
+
return (result.rows?.length ?? 0) > 0;
|
|
1807
|
+
} catch {
|
|
1808
|
+
return false;
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* Checks for duplicate (traceId, spanId) combinations in the spans table.
|
|
1813
|
+
* Returns information about duplicates for logging/CLI purposes.
|
|
1814
|
+
*/
|
|
1815
|
+
async checkForDuplicateSpans() {
|
|
1816
|
+
try {
|
|
1817
|
+
const result = await this.client.execute(`
|
|
1818
|
+
SELECT COUNT(*) as duplicate_count FROM (
|
|
1819
|
+
SELECT "spanId", "traceId"
|
|
1820
|
+
FROM "${storage.TABLE_SPANS}"
|
|
1821
|
+
GROUP BY "spanId", "traceId"
|
|
1822
|
+
HAVING COUNT(*) > 1
|
|
1823
|
+
)
|
|
1824
|
+
`);
|
|
1825
|
+
const duplicateCount = Number(result.rows?.[0]?.duplicate_count ?? 0);
|
|
1826
|
+
return {
|
|
1827
|
+
hasDuplicates: duplicateCount > 0,
|
|
1828
|
+
duplicateCount
|
|
1829
|
+
};
|
|
1753
1830
|
} catch (error) {
|
|
1754
|
-
this.logger.
|
|
1831
|
+
this.logger.debug(`LibSQLDB: Could not check for duplicates: ${error}`);
|
|
1832
|
+
return { hasDuplicates: false, duplicateCount: 0 };
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
/**
|
|
1836
|
+
* Manually run the spans migration to deduplicate and add the unique constraint.
|
|
1837
|
+
* This is intended to be called from the CLI when duplicates are detected.
|
|
1838
|
+
*
|
|
1839
|
+
* @returns Migration result with status and details
|
|
1840
|
+
*/
|
|
1841
|
+
async migrateSpans() {
|
|
1842
|
+
const indexExists = await this.spansUniqueIndexExists();
|
|
1843
|
+
if (indexExists) {
|
|
1844
|
+
return {
|
|
1845
|
+
success: true,
|
|
1846
|
+
alreadyMigrated: true,
|
|
1847
|
+
duplicatesRemoved: 0,
|
|
1848
|
+
message: `Migration already complete. Unique index exists on ${storage.TABLE_SPANS}.`
|
|
1849
|
+
};
|
|
1850
|
+
}
|
|
1851
|
+
const duplicateInfo = await this.checkForDuplicateSpans();
|
|
1852
|
+
if (duplicateInfo.hasDuplicates) {
|
|
1853
|
+
this.logger.info(
|
|
1854
|
+
`Found ${duplicateInfo.duplicateCount} duplicate (traceId, spanId) combinations. Starting deduplication...`
|
|
1855
|
+
);
|
|
1856
|
+
await this.deduplicateSpans();
|
|
1857
|
+
} else {
|
|
1858
|
+
this.logger.info(`No duplicate spans found.`);
|
|
1859
|
+
}
|
|
1860
|
+
await this.client.execute(
|
|
1861
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS "mastra_ai_spans_spanid_traceid_idx" ON "${storage.TABLE_SPANS}" ("spanId", "traceId")`
|
|
1862
|
+
);
|
|
1863
|
+
return {
|
|
1864
|
+
success: true,
|
|
1865
|
+
alreadyMigrated: false,
|
|
1866
|
+
duplicatesRemoved: duplicateInfo.duplicateCount,
|
|
1867
|
+
message: duplicateInfo.hasDuplicates ? `Migration complete. Removed duplicates and added unique index to ${storage.TABLE_SPANS}.` : `Migration complete. Added unique index to ${storage.TABLE_SPANS}.`
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Check migration status for the spans table.
|
|
1872
|
+
* Returns information about whether migration is needed.
|
|
1873
|
+
*/
|
|
1874
|
+
async checkSpansMigrationStatus() {
|
|
1875
|
+
const indexExists = await this.spansUniqueIndexExists();
|
|
1876
|
+
if (indexExists) {
|
|
1877
|
+
return {
|
|
1878
|
+
needsMigration: false,
|
|
1879
|
+
hasDuplicates: false,
|
|
1880
|
+
duplicateCount: 0,
|
|
1881
|
+
constraintExists: true,
|
|
1882
|
+
tableName: storage.TABLE_SPANS
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
const duplicateInfo = await this.checkForDuplicateSpans();
|
|
1886
|
+
return {
|
|
1887
|
+
needsMigration: true,
|
|
1888
|
+
hasDuplicates: duplicateInfo.hasDuplicates,
|
|
1889
|
+
duplicateCount: duplicateInfo.duplicateCount,
|
|
1890
|
+
constraintExists: false,
|
|
1891
|
+
tableName: storage.TABLE_SPANS
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
/**
|
|
1895
|
+
* Deduplicates spans table by removing duplicate (spanId, traceId) combinations.
|
|
1896
|
+
* Keeps the "best" record for each duplicate group based on:
|
|
1897
|
+
* 1. Completed spans (endedAt IS NOT NULL) over incomplete ones
|
|
1898
|
+
* 2. Most recently updated (updatedAt DESC)
|
|
1899
|
+
* 3. Most recently created (createdAt DESC) as tiebreaker
|
|
1900
|
+
*/
|
|
1901
|
+
async deduplicateSpans() {
|
|
1902
|
+
try {
|
|
1903
|
+
const duplicateCheck = await this.client.execute(`
|
|
1904
|
+
SELECT COUNT(*) as duplicate_count FROM (
|
|
1905
|
+
SELECT "spanId", "traceId"
|
|
1906
|
+
FROM "${storage.TABLE_SPANS}"
|
|
1907
|
+
GROUP BY "spanId", "traceId"
|
|
1908
|
+
HAVING COUNT(*) > 1
|
|
1909
|
+
)
|
|
1910
|
+
`);
|
|
1911
|
+
const duplicateCount = Number(duplicateCheck.rows?.[0]?.duplicate_count ?? 0);
|
|
1912
|
+
if (duplicateCount === 0) {
|
|
1913
|
+
this.logger.debug(`LibSQLDB: No duplicate spans found, skipping deduplication`);
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
this.logger.warn(`LibSQLDB: Found ${duplicateCount} duplicate (spanId, traceId) combinations, deduplicating...`);
|
|
1917
|
+
const deleteResult = await this.client.execute(`
|
|
1918
|
+
DELETE FROM "${storage.TABLE_SPANS}"
|
|
1919
|
+
WHERE rowid NOT IN (
|
|
1920
|
+
SELECT MIN(best_rowid) FROM (
|
|
1921
|
+
SELECT
|
|
1922
|
+
rowid as best_rowid,
|
|
1923
|
+
"spanId",
|
|
1924
|
+
"traceId",
|
|
1925
|
+
ROW_NUMBER() OVER (
|
|
1926
|
+
PARTITION BY "spanId", "traceId"
|
|
1927
|
+
ORDER BY
|
|
1928
|
+
CASE WHEN "endedAt" IS NOT NULL THEN 0 ELSE 1 END,
|
|
1929
|
+
"updatedAt" DESC,
|
|
1930
|
+
"createdAt" DESC
|
|
1931
|
+
) as rn
|
|
1932
|
+
FROM "${storage.TABLE_SPANS}"
|
|
1933
|
+
) ranked
|
|
1934
|
+
WHERE rn = 1
|
|
1935
|
+
GROUP BY "spanId", "traceId"
|
|
1936
|
+
)
|
|
1937
|
+
AND ("spanId", "traceId") IN (
|
|
1938
|
+
SELECT "spanId", "traceId"
|
|
1939
|
+
FROM "${storage.TABLE_SPANS}"
|
|
1940
|
+
GROUP BY "spanId", "traceId"
|
|
1941
|
+
HAVING COUNT(*) > 1
|
|
1942
|
+
)
|
|
1943
|
+
`);
|
|
1944
|
+
const deletedCount = deleteResult.rowsAffected ?? 0;
|
|
1945
|
+
this.logger.warn(`LibSQLDB: Deleted ${deletedCount} duplicate span records`);
|
|
1946
|
+
} catch (error) {
|
|
1947
|
+
this.logger.warn(`LibSQLDB: Failed to deduplicate spans:`, error);
|
|
1755
1948
|
}
|
|
1756
1949
|
}
|
|
1757
1950
|
/**
|
|
@@ -2647,33 +2840,76 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
2647
2840
|
);
|
|
2648
2841
|
}
|
|
2649
2842
|
}
|
|
2650
|
-
async
|
|
2651
|
-
const {
|
|
2652
|
-
|
|
2843
|
+
async listThreads(args) {
|
|
2844
|
+
const { page = 0, perPage: perPageInput, orderBy, filter } = args;
|
|
2845
|
+
try {
|
|
2846
|
+
this.validatePaginationInput(page, perPageInput ?? 100);
|
|
2847
|
+
} catch (error$1) {
|
|
2653
2848
|
throw new error.MastraError(
|
|
2654
2849
|
{
|
|
2655
|
-
id: storage.createStorageErrorId("LIBSQL", "
|
|
2850
|
+
id: storage.createStorageErrorId("LIBSQL", "LIST_THREADS", "INVALID_PAGE"),
|
|
2656
2851
|
domain: error.ErrorDomain.STORAGE,
|
|
2657
2852
|
category: error.ErrorCategory.USER,
|
|
2658
|
-
details: { page }
|
|
2853
|
+
details: { page, ...perPageInput !== void 0 && { perPage: perPageInput } }
|
|
2659
2854
|
},
|
|
2660
|
-
new Error("
|
|
2855
|
+
error$1 instanceof Error ? error$1 : new Error("Invalid pagination parameters")
|
|
2661
2856
|
);
|
|
2662
2857
|
}
|
|
2663
2858
|
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
2859
|
+
try {
|
|
2860
|
+
this.validateMetadataKeys(filter?.metadata);
|
|
2861
|
+
} catch (error$1) {
|
|
2862
|
+
throw new error.MastraError(
|
|
2863
|
+
{
|
|
2864
|
+
id: storage.createStorageErrorId("LIBSQL", "LIST_THREADS", "INVALID_METADATA_KEY"),
|
|
2865
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2866
|
+
category: error.ErrorCategory.USER,
|
|
2867
|
+
details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(", ") : "" }
|
|
2868
|
+
},
|
|
2869
|
+
error$1 instanceof Error ? error$1 : new Error("Invalid metadata key")
|
|
2870
|
+
);
|
|
2871
|
+
}
|
|
2664
2872
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
2665
2873
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
2666
2874
|
try {
|
|
2667
|
-
const
|
|
2668
|
-
const queryParams = [
|
|
2875
|
+
const whereClauses = [];
|
|
2876
|
+
const queryParams = [];
|
|
2877
|
+
if (filter?.resourceId) {
|
|
2878
|
+
whereClauses.push("resourceId = ?");
|
|
2879
|
+
queryParams.push(filter.resourceId);
|
|
2880
|
+
}
|
|
2881
|
+
if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
|
|
2882
|
+
for (const [key, value] of Object.entries(filter.metadata)) {
|
|
2883
|
+
if (value === null) {
|
|
2884
|
+
whereClauses.push(`json_extract(metadata, '$.${key}') IS NULL`);
|
|
2885
|
+
} else if (typeof value === "boolean") {
|
|
2886
|
+
whereClauses.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
2887
|
+
queryParams.push(value ? 1 : 0);
|
|
2888
|
+
} else if (typeof value === "number") {
|
|
2889
|
+
whereClauses.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
2890
|
+
queryParams.push(value);
|
|
2891
|
+
} else if (typeof value === "string") {
|
|
2892
|
+
whereClauses.push(`json_extract(metadata, '$.${key}') = ?`);
|
|
2893
|
+
queryParams.push(value);
|
|
2894
|
+
} else {
|
|
2895
|
+
throw new error.MastraError({
|
|
2896
|
+
id: storage.createStorageErrorId("LIBSQL", "LIST_THREADS", "INVALID_METADATA_VALUE"),
|
|
2897
|
+
domain: error.ErrorDomain.STORAGE,
|
|
2898
|
+
category: error.ErrorCategory.USER,
|
|
2899
|
+
text: `Metadata filter value for key "${key}" must be a scalar type (string, number, boolean, or null), got ${typeof value}`,
|
|
2900
|
+
details: { key, valueType: typeof value }
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(" AND ")}` : "";
|
|
2906
|
+
const baseQuery = `FROM ${storage.TABLE_THREADS} ${whereClause}`;
|
|
2669
2907
|
const mapRowToStorageThreadType = (row) => ({
|
|
2670
2908
|
id: row.id,
|
|
2671
2909
|
resourceId: row.resourceId,
|
|
2672
2910
|
title: row.title,
|
|
2673
2911
|
createdAt: new Date(row.createdAt),
|
|
2674
|
-
// Convert string to Date
|
|
2675
2912
|
updatedAt: new Date(row.updatedAt),
|
|
2676
|
-
// Convert string to Date
|
|
2677
2913
|
metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata) : row.metadata
|
|
2678
2914
|
});
|
|
2679
2915
|
const countResult = await this.#client.execute({
|
|
@@ -2704,12 +2940,18 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
2704
2940
|
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
2705
2941
|
};
|
|
2706
2942
|
} catch (error$1) {
|
|
2943
|
+
if (error$1 instanceof error.MastraError && error$1.category === error.ErrorCategory.USER) {
|
|
2944
|
+
throw error$1;
|
|
2945
|
+
}
|
|
2707
2946
|
const mastraError = new error.MastraError(
|
|
2708
2947
|
{
|
|
2709
|
-
id: storage.createStorageErrorId("LIBSQL", "
|
|
2948
|
+
id: storage.createStorageErrorId("LIBSQL", "LIST_THREADS", "FAILED"),
|
|
2710
2949
|
domain: error.ErrorDomain.STORAGE,
|
|
2711
2950
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2712
|
-
details: {
|
|
2951
|
+
details: {
|
|
2952
|
+
...filter?.resourceId && { resourceId: filter.resourceId },
|
|
2953
|
+
hasMetadataFilter: !!filter?.metadata
|
|
2954
|
+
}
|
|
2713
2955
|
},
|
|
2714
2956
|
error$1
|
|
2715
2957
|
);
|
|
@@ -2972,6 +3214,22 @@ var ObservabilityLibSQL = class extends storage.ObservabilityStorage {
|
|
|
2972
3214
|
async dangerouslyClearAll() {
|
|
2973
3215
|
await this.#db.deleteData({ tableName: storage.TABLE_SPANS });
|
|
2974
3216
|
}
|
|
3217
|
+
/**
|
|
3218
|
+
* Manually run the spans migration to deduplicate and add the unique constraint.
|
|
3219
|
+
* This is intended to be called from the CLI when duplicates are detected.
|
|
3220
|
+
*
|
|
3221
|
+
* @returns Migration result with status and details
|
|
3222
|
+
*/
|
|
3223
|
+
async migrateSpans() {
|
|
3224
|
+
return this.#db.migrateSpans();
|
|
3225
|
+
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Check migration status for the spans table.
|
|
3228
|
+
* Returns information about whether migration is needed.
|
|
3229
|
+
*/
|
|
3230
|
+
async checkSpansMigrationStatus() {
|
|
3231
|
+
return this.#db.checkSpansMigrationStatus();
|
|
3232
|
+
}
|
|
2975
3233
|
get tracingStrategy() {
|
|
2976
3234
|
return {
|
|
2977
3235
|
preferred: "batch-with-updates",
|
|
@@ -4007,7 +4265,7 @@ var WorkflowsLibSQL = class extends storage.WorkflowsStorage {
|
|
|
4007
4265
|
};
|
|
4008
4266
|
|
|
4009
4267
|
// src/storage/index.ts
|
|
4010
|
-
var LibSQLStore = class extends storage.
|
|
4268
|
+
var LibSQLStore = class extends storage.MastraCompositeStore {
|
|
4011
4269
|
client;
|
|
4012
4270
|
maxRetries;
|
|
4013
4271
|
initialBackoffMs;
|