@mastra/libsql 1.0.0-beta.1 → 1.0.0-beta.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/CHANGELOG.md +32 -0
- package/README.md +3 -0
- package/dist/index.cjs +218 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +219 -74
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/scores/index.d.ts +4 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +4 -2
- package/dist/vector/index.d.ts.map +1 -1
- package/dist/vector/sql-builder.d.ts.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,37 @@
|
|
|
1
1
|
# @mastra/libsql
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- feat(storage): support querying messages from multiple threads ([#10663](https://github.com/mastra-ai/mastra/pull/10663))
|
|
8
|
+
- Fixed TypeScript errors where `threadId: string | string[]` was being passed to places expecting `Scalar` type
|
|
9
|
+
- Added proper multi-thread support for `listMessages` across all adapters when `threadId` is an array
|
|
10
|
+
- Updated `_getIncludedMessages` to look up message threadId by ID (since message IDs are globally unique)
|
|
11
|
+
- **upstash**: Added `msg-idx:{messageId}` index for O(1) message lookups (backwards compatible with fallback to scan for old messages, with automatic backfill)
|
|
12
|
+
|
|
13
|
+
- Unify transformScoreRow functions across storage adapters ([#10648](https://github.com/mastra-ai/mastra/pull/10648))
|
|
14
|
+
|
|
15
|
+
Added a unified `transformScoreRow` function in `@mastra/core/storage` that provides schema-driven row transformation for score data. This eliminates code duplication across 10 storage adapters while maintaining store-specific behavior through configurable options:
|
|
16
|
+
- `preferredTimestampFields`: Preferred source fields for timestamps (PostgreSQL, Cloudflare D1)
|
|
17
|
+
- `convertTimestamps`: Convert timestamp strings to Date objects (MSSQL, MongoDB, ClickHouse)
|
|
18
|
+
- `nullValuePattern`: Skip values matching pattern (ClickHouse's `'_null_'`)
|
|
19
|
+
- `fieldMappings`: Map source column names to schema fields (LibSQL's `additionalLLMContext`)
|
|
20
|
+
|
|
21
|
+
Each store adapter now uses the unified function with appropriate options, reducing ~200 lines of duplicate transformation logic while ensuring consistent behavior across all storage backends.
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [[`ac0d2f4`](https://github.com/mastra-ai/mastra/commit/ac0d2f4ff8831f72c1c66c2be809706d17f65789), [`1a0d3fc`](https://github.com/mastra-ai/mastra/commit/1a0d3fc811482c9c376cdf79ee615c23bae9b2d6), [`85a628b`](https://github.com/mastra-ai/mastra/commit/85a628b1224a8f64cd82ea7f033774bf22df7a7e), [`c237233`](https://github.com/mastra-ai/mastra/commit/c23723399ccedf7f5744b3f40997b79246bfbe64), [`15f9e21`](https://github.com/mastra-ai/mastra/commit/15f9e216177201ea6e3f6d0bfb063fcc0953444f), [`ff94dea`](https://github.com/mastra-ai/mastra/commit/ff94dea935f4e34545c63bcb6c29804732698809), [`5b2ff46`](https://github.com/mastra-ai/mastra/commit/5b2ff4651df70c146523a7fca773f8eb0a2272f8), [`db41688`](https://github.com/mastra-ai/mastra/commit/db4168806d007417e2e60b4f68656dca4e5f40c9), [`5ca599d`](https://github.com/mastra-ai/mastra/commit/5ca599d0bb59a1595f19f58473fcd67cc71cef58), [`bff1145`](https://github.com/mastra-ai/mastra/commit/bff114556b3cbadad9b2768488708f8ad0e91475), [`5c8ca24`](https://github.com/mastra-ai/mastra/commit/5c8ca247094e0cc2cdbd7137822fb47241f86e77), [`e191844`](https://github.com/mastra-ai/mastra/commit/e1918444ca3f80e82feef1dad506cd4ec6e2875f), [`22553f1`](https://github.com/mastra-ai/mastra/commit/22553f11c63ee5e966a9c034a349822249584691), [`7237163`](https://github.com/mastra-ai/mastra/commit/72371635dbf96a87df4b073cc48fc655afbdce3d), [`2500740`](https://github.com/mastra-ai/mastra/commit/2500740ea23da067d6e50ec71c625ab3ce275e64), [`873ecbb`](https://github.com/mastra-ai/mastra/commit/873ecbb517586aa17d2f1e99283755b3ebb2863f), [`4f9bbe5`](https://github.com/mastra-ai/mastra/commit/4f9bbe5968f42c86f4930b8193de3c3c17e5bd36), [`02e51fe`](https://github.com/mastra-ai/mastra/commit/02e51feddb3d4155cfbcc42624fd0d0970d032c0), [`8f3fa3a`](https://github.com/mastra-ai/mastra/commit/8f3fa3a652bb77da092f913ec51ae46e3a7e27dc), [`cd29ad2`](https://github.com/mastra-ai/mastra/commit/cd29ad23a255534e8191f249593849ed29160886), [`bdf4d8c`](https://github.com/mastra-ai/mastra/commit/bdf4d8cdc656d8a2c21d81834bfa3bfa70f56c16), [`854e3da`](https://github.com/mastra-ai/mastra/commit/854e3dad5daac17a91a20986399d3a51f54bf68b), [`ce18d38`](https://github.com/mastra-ai/mastra/commit/ce18d38678c65870350d123955014a8432075fd9), [`cccf9c8`](https://github.com/mastra-ai/mastra/commit/cccf9c8b2d2dfc1a5e63919395b83d78c89682a0), [`61a5705`](https://github.com/mastra-ai/mastra/commit/61a570551278b6743e64243b3ce7d73de915ca8a), [`db70a48`](https://github.com/mastra-ai/mastra/commit/db70a48aeeeeb8e5f92007e8ede52c364ce15287), [`f0fdc14`](https://github.com/mastra-ai/mastra/commit/f0fdc14ee233d619266b3d2bbdeea7d25cfc6d13), [`db18bc9`](https://github.com/mastra-ai/mastra/commit/db18bc9c3825e2c1a0ad9a183cc9935f6691bfa1), [`9b37b56`](https://github.com/mastra-ai/mastra/commit/9b37b565e1f2a76c24f728945cc740c2b09be9da), [`41a23c3`](https://github.com/mastra-ai/mastra/commit/41a23c32f9877d71810f37e24930515df2ff7a0f), [`5d171ad`](https://github.com/mastra-ai/mastra/commit/5d171ad9ef340387276b77c2bb3e83e83332d729), [`f03ae60`](https://github.com/mastra-ai/mastra/commit/f03ae60500fe350c9d828621006cdafe1975fdd8), [`d1e74a0`](https://github.com/mastra-ai/mastra/commit/d1e74a0a293866dece31022047f5dbab65a304d0), [`39e7869`](https://github.com/mastra-ai/mastra/commit/39e7869bc7d0ee391077ce291474d8a84eedccff), [`5761926`](https://github.com/mastra-ai/mastra/commit/57619260c4a2cdd598763abbacd90de594c6bc76), [`c900fdd`](https://github.com/mastra-ai/mastra/commit/c900fdd504c41348efdffb205cfe80d48c38fa33), [`604a79f`](https://github.com/mastra-ai/mastra/commit/604a79fecf276e26a54a3fe01bb94e65315d2e0e), [`887f0b4`](https://github.com/mastra-ai/mastra/commit/887f0b4746cdbd7cb7d6b17ac9f82aeb58037ea5), [`2562143`](https://github.com/mastra-ai/mastra/commit/256214336b4faa78646c9c1776612393790d8784), [`ef11a61`](https://github.com/mastra-ai/mastra/commit/ef11a61920fa0ed08a5b7ceedd192875af119749)]:
|
|
24
|
+
- @mastra/core@1.0.0-beta.6
|
|
25
|
+
|
|
26
|
+
## 1.0.0-beta.2
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- Add new deleteVectors, updateVector by filter ([#10408](https://github.com/mastra-ai/mastra/pull/10408))
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [[`21a15de`](https://github.com/mastra-ai/mastra/commit/21a15de369fe82aac26bb642ed7be73505475e8b), [`feb7ee4`](https://github.com/mastra-ai/mastra/commit/feb7ee4d09a75edb46c6669a3beaceec78811747), [`b0e2ea5`](https://github.com/mastra-ai/mastra/commit/b0e2ea5b52c40fae438b9e2f7baee6f0f89c5442), [`c456e01`](https://github.com/mastra-ai/mastra/commit/c456e0149e3c176afcefdbd9bb1d2c5917723725), [`ab035c2`](https://github.com/mastra-ai/mastra/commit/ab035c2ef6d8cc7bb25f06f1a38508bd9e6f126b), [`1a46a56`](https://github.com/mastra-ai/mastra/commit/1a46a566f45a3fcbadc1cf36bf86d351f264bfa3), [`3cf540b`](https://github.com/mastra-ai/mastra/commit/3cf540b9fbfea8f4fc8d3a2319a4e6c0b0cbfd52), [`1c6ce51`](https://github.com/mastra-ai/mastra/commit/1c6ce51f875915ab57fd36873623013699a2a65d), [`898a972`](https://github.com/mastra-ai/mastra/commit/898a9727d286c2510d6b702dfd367e6aaf5c6b0f), [`a97003a`](https://github.com/mastra-ai/mastra/commit/a97003aa1cf2f4022a41912324a1e77263b326b8), [`ccc141e`](https://github.com/mastra-ai/mastra/commit/ccc141ed27da0abc3a3fc28e9e5128152e8e37f4), [`fe3b897`](https://github.com/mastra-ai/mastra/commit/fe3b897c2ccbcd2b10e81b099438c7337feddf89), [`00123ba`](https://github.com/mastra-ai/mastra/commit/00123ba96dc9e5cd0b110420ebdba56d8f237b25), [`29c4309`](https://github.com/mastra-ai/mastra/commit/29c4309f818b24304c041bcb4a8f19b5f13f6b62), [`16785ce`](https://github.com/mastra-ai/mastra/commit/16785ced928f6f22638f4488cf8a125d99211799), [`de8239b`](https://github.com/mastra-ai/mastra/commit/de8239bdcb1d8c0cfa06da21f1569912a66bbc8a), [`b5e6cd7`](https://github.com/mastra-ai/mastra/commit/b5e6cd77fc8c8e64e0494c1d06cee3d84e795d1e), [`3759cb0`](https://github.com/mastra-ai/mastra/commit/3759cb064935b5f74c65ac2f52a1145f7352899d), [`651e772`](https://github.com/mastra-ai/mastra/commit/651e772eb1475fb13e126d3fcc01751297a88214), [`b61b93f`](https://github.com/mastra-ai/mastra/commit/b61b93f9e058b11dd2eec169853175d31dbdd567), [`bae33d9`](https://github.com/mastra-ai/mastra/commit/bae33d91a63fbb64d1e80519e1fc1acaed1e9013), [`c0b731f`](https://github.com/mastra-ai/mastra/commit/c0b731fb27d712dc8582e846df5c0332a6a0c5ba), [`43ca8f2`](https://github.com/mastra-ai/mastra/commit/43ca8f2c7334851cc7b4d3d2f037d8784bfbdd5f), [`2ca67cc`](https://github.com/mastra-ai/mastra/commit/2ca67cc3bb1f6a617353fdcab197d9efebe60d6f), [`9e67002`](https://github.com/mastra-ai/mastra/commit/9e67002b52c9be19936c420a489dbee9c5fd6a78), [`35edc49`](https://github.com/mastra-ai/mastra/commit/35edc49ac0556db609189641d6341e76771b81fc)]:
|
|
33
|
+
- @mastra/core@1.0.0-beta.5
|
|
34
|
+
|
|
3
35
|
## 1.0.0-beta.1
|
|
4
36
|
|
|
5
37
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -131,6 +131,9 @@ Example filter:
|
|
|
131
131
|
- `createIndex({indexName, dimension, metric?, indexConfig?, defineIndex?})`: Create a new table with vector support
|
|
132
132
|
- `upsert({indexName, vectors, metadata?, ids?})`: Add or update vectors
|
|
133
133
|
- `query({indexName, queryVector, topK?, filter?, includeVector?, minScore?})`: Search for similar vectors
|
|
134
|
+
- `updateVector({ indexName, id?, filter?, update })`: Update a single vector by ID or metadata filter
|
|
135
|
+
- `deleteVector({ indexName, id })`: Delete a single vector by ID
|
|
136
|
+
- `deleteVectors({ indexName, ids?, filter? })`: Delete multiple vectors by IDs or metadata filter
|
|
134
137
|
- `defineIndex({indexName, metric?, indexConfig?})`: Define an index
|
|
135
138
|
- `listIndexes()`: List all vector-enabled tables
|
|
136
139
|
- `describeIndex(indexName)`: Get table statistics
|
package/dist/index.cjs
CHANGED
|
@@ -92,12 +92,20 @@ var createBasicOperator = (symbol) => {
|
|
|
92
92
|
};
|
|
93
93
|
};
|
|
94
94
|
var createNumericOperator = (symbol) => {
|
|
95
|
-
return (key) => {
|
|
95
|
+
return (key, value) => {
|
|
96
96
|
const jsonPath = getJsonPath(key);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
const isNumeric = typeof value === "number" || typeof value === "string" && !isNaN(Number(value)) && value.trim() !== "";
|
|
98
|
+
if (isNumeric) {
|
|
99
|
+
return {
|
|
100
|
+
sql: `CAST(json_extract(metadata, ${jsonPath}) AS NUMERIC) ${symbol} ?`,
|
|
101
|
+
needsValue: true
|
|
102
|
+
};
|
|
103
|
+
} else {
|
|
104
|
+
return {
|
|
105
|
+
sql: `CAST(json_extract(metadata, ${jsonPath}) AS TEXT) ${symbol} ?`,
|
|
106
|
+
needsValue: true
|
|
107
|
+
};
|
|
108
|
+
}
|
|
101
109
|
};
|
|
102
110
|
};
|
|
103
111
|
var validateJsonArray = (key) => {
|
|
@@ -826,8 +834,27 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
826
834
|
updateVector(args) {
|
|
827
835
|
return this.executeWriteOperationWithRetry(() => this.doUpdateVector(args));
|
|
828
836
|
}
|
|
829
|
-
async doUpdateVector(
|
|
837
|
+
async doUpdateVector(params) {
|
|
838
|
+
const { indexName, update } = params;
|
|
830
839
|
const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
|
|
840
|
+
if ("id" in params && params.id && "filter" in params && params.filter) {
|
|
841
|
+
throw new error.MastraError({
|
|
842
|
+
id: "LIBSQL_VECTOR_UPDATE_MUTUALLY_EXCLUSIVE_PARAMS",
|
|
843
|
+
domain: error.ErrorDomain.STORAGE,
|
|
844
|
+
category: error.ErrorCategory.USER,
|
|
845
|
+
details: { indexName },
|
|
846
|
+
text: "id and filter are mutually exclusive - provide only one"
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
if (!update.vector && !update.metadata) {
|
|
850
|
+
throw new error.MastraError({
|
|
851
|
+
id: "LIBSQL_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
|
|
852
|
+
domain: error.ErrorDomain.STORAGE,
|
|
853
|
+
category: error.ErrorCategory.USER,
|
|
854
|
+
details: { indexName },
|
|
855
|
+
text: "No updates provided"
|
|
856
|
+
});
|
|
857
|
+
}
|
|
831
858
|
const updates = [];
|
|
832
859
|
const args = [];
|
|
833
860
|
if (update.vector) {
|
|
@@ -839,32 +866,81 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
839
866
|
args.push(JSON.stringify(update.metadata));
|
|
840
867
|
}
|
|
841
868
|
if (updates.length === 0) {
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
let whereClause;
|
|
872
|
+
let whereValues;
|
|
873
|
+
if ("id" in params && params.id) {
|
|
874
|
+
whereClause = "vector_id = ?";
|
|
875
|
+
whereValues = [params.id];
|
|
876
|
+
} else if ("filter" in params && params.filter) {
|
|
877
|
+
const filter = params.filter;
|
|
878
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
879
|
+
throw new error.MastraError({
|
|
880
|
+
id: "LIBSQL_VECTOR_UPDATE_EMPTY_FILTER",
|
|
881
|
+
domain: error.ErrorDomain.STORAGE,
|
|
882
|
+
category: error.ErrorCategory.USER,
|
|
883
|
+
details: { indexName },
|
|
884
|
+
text: "Cannot update with empty filter"
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
const translatedFilter = this.transformFilter(filter);
|
|
888
|
+
const { sql: filterSql, values: filterValues } = buildFilterQuery(translatedFilter);
|
|
889
|
+
if (!filterSql || filterSql.trim() === "") {
|
|
890
|
+
throw new error.MastraError({
|
|
891
|
+
id: "LIBSQL_VECTOR_UPDATE_INVALID_FILTER",
|
|
892
|
+
domain: error.ErrorDomain.STORAGE,
|
|
893
|
+
category: error.ErrorCategory.USER,
|
|
894
|
+
details: { indexName },
|
|
895
|
+
text: "Filter produced empty WHERE clause"
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
const normalizedCondition = filterSql.replace(/^\s*WHERE\s+/i, "").trim().toLowerCase();
|
|
899
|
+
const matchAllPatterns = ["true", "1 = 1", "1=1"];
|
|
900
|
+
if (matchAllPatterns.includes(normalizedCondition)) {
|
|
901
|
+
throw new error.MastraError({
|
|
902
|
+
id: "LIBSQL_VECTOR_UPDATE_MATCH_ALL_FILTER",
|
|
903
|
+
domain: error.ErrorDomain.STORAGE,
|
|
904
|
+
category: error.ErrorCategory.USER,
|
|
905
|
+
details: { indexName, filterSql: normalizedCondition },
|
|
906
|
+
text: "Filter matches all vectors. Provide a specific filter to update targeted vectors."
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
whereClause = filterSql.replace(/^WHERE\s+/i, "");
|
|
910
|
+
whereValues = filterValues;
|
|
911
|
+
} else {
|
|
842
912
|
throw new error.MastraError({
|
|
843
|
-
id: "
|
|
913
|
+
id: "LIBSQL_VECTOR_UPDATE_MISSING_PARAMS",
|
|
844
914
|
domain: error.ErrorDomain.STORAGE,
|
|
845
915
|
category: error.ErrorCategory.USER,
|
|
846
|
-
details: { indexName
|
|
847
|
-
text: "
|
|
916
|
+
details: { indexName },
|
|
917
|
+
text: "Either id or filter must be provided"
|
|
848
918
|
});
|
|
849
919
|
}
|
|
850
|
-
args.push(id);
|
|
851
920
|
const query = `
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
921
|
+
UPDATE ${parsedIndexName}
|
|
922
|
+
SET ${updates.join(", ")}
|
|
923
|
+
WHERE ${whereClause};
|
|
924
|
+
`;
|
|
856
925
|
try {
|
|
857
926
|
await this.turso.execute({
|
|
858
927
|
sql: query,
|
|
859
|
-
args
|
|
928
|
+
args: [...args, ...whereValues]
|
|
860
929
|
});
|
|
861
930
|
} catch (error$1) {
|
|
931
|
+
const errorDetails = { indexName };
|
|
932
|
+
if ("id" in params && params.id) {
|
|
933
|
+
errorDetails.id = params.id;
|
|
934
|
+
}
|
|
935
|
+
if ("filter" in params && params.filter) {
|
|
936
|
+
errorDetails.filter = JSON.stringify(params.filter);
|
|
937
|
+
}
|
|
862
938
|
throw new error.MastraError(
|
|
863
939
|
{
|
|
864
940
|
id: "LIBSQL_VECTOR_UPDATE_VECTOR_FAILED",
|
|
865
941
|
domain: error.ErrorDomain.STORAGE,
|
|
866
942
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
867
|
-
details:
|
|
943
|
+
details: errorDetails
|
|
868
944
|
},
|
|
869
945
|
error$1
|
|
870
946
|
);
|
|
@@ -886,7 +962,10 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
886
962
|
id: "LIBSQL_VECTOR_DELETE_VECTOR_FAILED",
|
|
887
963
|
domain: error.ErrorDomain.STORAGE,
|
|
888
964
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
889
|
-
details: {
|
|
965
|
+
details: {
|
|
966
|
+
indexName: args.indexName,
|
|
967
|
+
...args.id && { id: args.id }
|
|
968
|
+
}
|
|
890
969
|
},
|
|
891
970
|
error$1
|
|
892
971
|
);
|
|
@@ -899,6 +978,100 @@ var LibSQLVector = class extends vector.MastraVector {
|
|
|
899
978
|
args: [id]
|
|
900
979
|
});
|
|
901
980
|
}
|
|
981
|
+
deleteVectors(args) {
|
|
982
|
+
return this.executeWriteOperationWithRetry(() => this.doDeleteVectors(args));
|
|
983
|
+
}
|
|
984
|
+
async doDeleteVectors({ indexName, filter, ids }) {
|
|
985
|
+
const parsedIndexName = utils.parseSqlIdentifier(indexName, "index name");
|
|
986
|
+
if (!filter && !ids) {
|
|
987
|
+
throw new error.MastraError({
|
|
988
|
+
id: "LIBSQL_VECTOR_DELETE_MISSING_PARAMS",
|
|
989
|
+
domain: error.ErrorDomain.STORAGE,
|
|
990
|
+
category: error.ErrorCategory.USER,
|
|
991
|
+
details: { indexName },
|
|
992
|
+
text: "Either filter or ids must be provided"
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
if (filter && ids) {
|
|
996
|
+
throw new error.MastraError({
|
|
997
|
+
id: "LIBSQL_VECTOR_DELETE_CONFLICTING_PARAMS",
|
|
998
|
+
domain: error.ErrorDomain.STORAGE,
|
|
999
|
+
category: error.ErrorCategory.USER,
|
|
1000
|
+
details: { indexName },
|
|
1001
|
+
text: "Cannot provide both filter and ids - they are mutually exclusive"
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
let query;
|
|
1005
|
+
let values;
|
|
1006
|
+
if (ids) {
|
|
1007
|
+
if (ids.length === 0) {
|
|
1008
|
+
throw new error.MastraError({
|
|
1009
|
+
id: "LIBSQL_VECTOR_DELETE_EMPTY_IDS",
|
|
1010
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1011
|
+
category: error.ErrorCategory.USER,
|
|
1012
|
+
details: { indexName },
|
|
1013
|
+
text: "Cannot delete with empty ids array"
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
const placeholders = ids.map(() => "?").join(", ");
|
|
1017
|
+
query = `DELETE FROM ${parsedIndexName} WHERE vector_id IN (${placeholders})`;
|
|
1018
|
+
values = ids;
|
|
1019
|
+
} else {
|
|
1020
|
+
if (!filter || Object.keys(filter).length === 0) {
|
|
1021
|
+
throw new error.MastraError({
|
|
1022
|
+
id: "LIBSQL_VECTOR_DELETE_EMPTY_FILTER",
|
|
1023
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1024
|
+
category: error.ErrorCategory.USER,
|
|
1025
|
+
details: { indexName },
|
|
1026
|
+
text: "Cannot delete with empty filter. Use deleteIndex to delete all vectors."
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
const translatedFilter = this.transformFilter(filter);
|
|
1030
|
+
const { sql: filterSql, values: filterValues } = buildFilterQuery(translatedFilter);
|
|
1031
|
+
if (!filterSql || filterSql.trim() === "") {
|
|
1032
|
+
throw new error.MastraError({
|
|
1033
|
+
id: "LIBSQL_VECTOR_DELETE_INVALID_FILTER",
|
|
1034
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1035
|
+
category: error.ErrorCategory.USER,
|
|
1036
|
+
details: { indexName },
|
|
1037
|
+
text: "Filter produced empty WHERE clause"
|
|
1038
|
+
});
|
|
1039
|
+
}
|
|
1040
|
+
const normalizedCondition = filterSql.replace(/^\s*WHERE\s+/i, "").trim().toLowerCase();
|
|
1041
|
+
const matchAllPatterns = ["true", "1 = 1", "1=1"];
|
|
1042
|
+
if (matchAllPatterns.includes(normalizedCondition)) {
|
|
1043
|
+
throw new error.MastraError({
|
|
1044
|
+
id: "LIBSQL_VECTOR_DELETE_MATCH_ALL_FILTER",
|
|
1045
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1046
|
+
category: error.ErrorCategory.USER,
|
|
1047
|
+
details: { indexName, filterSql: normalizedCondition },
|
|
1048
|
+
text: "Filter matches all vectors. Use deleteIndex to delete all vectors from an index."
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
query = `DELETE FROM ${parsedIndexName} ${filterSql}`;
|
|
1052
|
+
values = filterValues;
|
|
1053
|
+
}
|
|
1054
|
+
try {
|
|
1055
|
+
await this.turso.execute({
|
|
1056
|
+
sql: query,
|
|
1057
|
+
args: values
|
|
1058
|
+
});
|
|
1059
|
+
} catch (error$1) {
|
|
1060
|
+
throw new error.MastraError(
|
|
1061
|
+
{
|
|
1062
|
+
id: "LIBSQL_VECTOR_DELETE_VECTORS_FAILED",
|
|
1063
|
+
domain: error.ErrorDomain.STORAGE,
|
|
1064
|
+
category: error.ErrorCategory.THIRD_PARTY,
|
|
1065
|
+
details: {
|
|
1066
|
+
indexName,
|
|
1067
|
+
...filter && { filter: JSON.stringify(filter) },
|
|
1068
|
+
...ids && { idsCount: ids.length }
|
|
1069
|
+
}
|
|
1070
|
+
},
|
|
1071
|
+
error$1
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
902
1075
|
truncateIndex(args) {
|
|
903
1076
|
try {
|
|
904
1077
|
return this.executeWriteOperationWithRetry(() => this._doTruncateIndex(args));
|
|
@@ -946,26 +1119,24 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
946
1119
|
if (row.type && row.type !== `v2`) result.type = row.type;
|
|
947
1120
|
return result;
|
|
948
1121
|
}
|
|
949
|
-
async _getIncludedMessages({
|
|
950
|
-
|
|
951
|
-
include
|
|
952
|
-
}) {
|
|
953
|
-
if (!threadId.trim()) throw new Error("threadId must be a non-empty string");
|
|
954
|
-
if (!include) return null;
|
|
1122
|
+
async _getIncludedMessages({ include }) {
|
|
1123
|
+
if (!include || include.length === 0) return null;
|
|
955
1124
|
const unionQueries = [];
|
|
956
1125
|
const params = [];
|
|
957
1126
|
for (const inc of include) {
|
|
958
1127
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
959
|
-
const searchId = inc.threadId || threadId;
|
|
960
1128
|
unionQueries.push(
|
|
961
1129
|
`
|
|
962
1130
|
SELECT * FROM (
|
|
963
|
-
WITH
|
|
1131
|
+
WITH target_thread AS (
|
|
1132
|
+
SELECT thread_id FROM "${storage.TABLE_MESSAGES}" WHERE id = ?
|
|
1133
|
+
),
|
|
1134
|
+
numbered_messages AS (
|
|
964
1135
|
SELECT
|
|
965
1136
|
id, content, role, type, "createdAt", thread_id, "resourceId",
|
|
966
1137
|
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
967
1138
|
FROM "${storage.TABLE_MESSAGES}"
|
|
968
|
-
WHERE thread_id =
|
|
1139
|
+
WHERE thread_id = (SELECT thread_id FROM target_thread)
|
|
969
1140
|
),
|
|
970
1141
|
target_positions AS (
|
|
971
1142
|
SELECT row_num as target_pos
|
|
@@ -980,7 +1151,7 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
980
1151
|
`
|
|
981
1152
|
// Keep ASC for final sorting after fetching context
|
|
982
1153
|
);
|
|
983
|
-
params.push(
|
|
1154
|
+
params.push(id, id, withPreviousMessages, withNextMessages);
|
|
984
1155
|
}
|
|
985
1156
|
const finalQuery = unionQueries.join(" UNION ALL ") + ' ORDER BY "createdAt" ASC';
|
|
986
1157
|
const includedResult = await this.client.execute({ sql: finalQuery, args: params });
|
|
@@ -1027,15 +1198,16 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
1027
1198
|
}
|
|
1028
1199
|
async listMessages(args) {
|
|
1029
1200
|
const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
|
|
1030
|
-
|
|
1201
|
+
const threadIds = Array.isArray(threadId) ? threadId : [threadId];
|
|
1202
|
+
if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
|
|
1031
1203
|
throw new error.MastraError(
|
|
1032
1204
|
{
|
|
1033
1205
|
id: "STORAGE_LIBSQL_LIST_MESSAGES_INVALID_THREAD_ID",
|
|
1034
1206
|
domain: error.ErrorDomain.STORAGE,
|
|
1035
1207
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1036
|
-
details: { threadId }
|
|
1208
|
+
details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
|
|
1037
1209
|
},
|
|
1038
|
-
new Error("threadId must be a non-empty string")
|
|
1210
|
+
new Error("threadId must be a non-empty string or array of non-empty strings")
|
|
1039
1211
|
);
|
|
1040
1212
|
}
|
|
1041
1213
|
if (page < 0) {
|
|
@@ -1054,8 +1226,9 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
1054
1226
|
try {
|
|
1055
1227
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
1056
1228
|
const orderByStatement = `ORDER BY "${field}" ${direction}`;
|
|
1057
|
-
const
|
|
1058
|
-
const
|
|
1229
|
+
const threadPlaceholders = threadIds.map(() => "?").join(", ");
|
|
1230
|
+
const conditions = [`thread_id IN (${threadPlaceholders})`];
|
|
1231
|
+
const queryParams = [...threadIds];
|
|
1059
1232
|
if (resourceId) {
|
|
1060
1233
|
conditions.push(`"resourceId" = ?`);
|
|
1061
1234
|
queryParams.push(resourceId);
|
|
@@ -1095,7 +1268,7 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
1095
1268
|
}
|
|
1096
1269
|
const messageIds = new Set(messages.map((m) => m.id));
|
|
1097
1270
|
if (include && include.length > 0) {
|
|
1098
|
-
const includeMessages = await this._getIncludedMessages({
|
|
1271
|
+
const includeMessages = await this._getIncludedMessages({ include });
|
|
1099
1272
|
if (includeMessages) {
|
|
1100
1273
|
for (const includeMsg of includeMessages) {
|
|
1101
1274
|
if (!messageIds.has(includeMsg.id)) {
|
|
@@ -1116,7 +1289,10 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
1116
1289
|
}
|
|
1117
1290
|
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1118
1291
|
});
|
|
1119
|
-
const
|
|
1292
|
+
const threadIdSet = new Set(threadIds);
|
|
1293
|
+
const returnedThreadMessageIds = new Set(
|
|
1294
|
+
finalMessages.filter((m) => m.threadId && threadIdSet.has(m.threadId)).map((m) => m.id)
|
|
1295
|
+
);
|
|
1120
1296
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
1121
1297
|
const hasMore = perPageInput !== false && !allThreadMessagesReturned && offset + perPage < total;
|
|
1122
1298
|
return {
|
|
@@ -1133,7 +1309,7 @@ var MemoryLibSQL = class extends storage.MemoryStorage {
|
|
|
1133
1309
|
domain: error.ErrorDomain.STORAGE,
|
|
1134
1310
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
1135
1311
|
details: {
|
|
1136
|
-
threadId,
|
|
1312
|
+
threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
|
|
1137
1313
|
resourceId: resourceId ?? ""
|
|
1138
1314
|
}
|
|
1139
1315
|
},
|
|
@@ -2552,45 +2728,14 @@ var ScoresLibSQL = class extends storage.ScoresStorage {
|
|
|
2552
2728
|
);
|
|
2553
2729
|
}
|
|
2554
2730
|
}
|
|
2731
|
+
/**
|
|
2732
|
+
* LibSQL-specific score row transformation.
|
|
2733
|
+
* Maps additionalLLMContext column to additionalContext field.
|
|
2734
|
+
*/
|
|
2555
2735
|
transformScoreRow(row) {
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
const additionalLLMContextValue = row.additionalLLMContext ? storage.safelyParseJSON(row.additionalLLMContext) : null;
|
|
2560
|
-
const requestContextValue = row.requestContext ? storage.safelyParseJSON(row.requestContext) : null;
|
|
2561
|
-
const metadataValue = row.metadata ? storage.safelyParseJSON(row.metadata) : null;
|
|
2562
|
-
const entityValue = row.entity ? storage.safelyParseJSON(row.entity) : null;
|
|
2563
|
-
const preprocessStepResultValue = row.preprocessStepResult ? storage.safelyParseJSON(row.preprocessStepResult) : null;
|
|
2564
|
-
const analyzeStepResultValue = row.analyzeStepResult ? storage.safelyParseJSON(row.analyzeStepResult) : null;
|
|
2565
|
-
return {
|
|
2566
|
-
id: row.id,
|
|
2567
|
-
traceId: row.traceId,
|
|
2568
|
-
spanId: row.spanId,
|
|
2569
|
-
runId: row.runId,
|
|
2570
|
-
scorer: scorerValue,
|
|
2571
|
-
score: row.score,
|
|
2572
|
-
reason: row.reason,
|
|
2573
|
-
preprocessStepResult: preprocessStepResultValue,
|
|
2574
|
-
analyzeStepResult: analyzeStepResultValue,
|
|
2575
|
-
analyzePrompt: row.analyzePrompt,
|
|
2576
|
-
preprocessPrompt: row.preprocessPrompt,
|
|
2577
|
-
generateScorePrompt: row.generateScorePrompt,
|
|
2578
|
-
generateReasonPrompt: row.generateReasonPrompt,
|
|
2579
|
-
metadata: metadataValue,
|
|
2580
|
-
input: inputValue,
|
|
2581
|
-
output: outputValue,
|
|
2582
|
-
additionalContext: additionalLLMContextValue,
|
|
2583
|
-
requestContext: requestContextValue,
|
|
2584
|
-
entityType: row.entityType,
|
|
2585
|
-
entity: entityValue,
|
|
2586
|
-
entityId: row.entityId,
|
|
2587
|
-
scorerId: row.scorerId,
|
|
2588
|
-
source: row.source,
|
|
2589
|
-
resourceId: row.resourceId,
|
|
2590
|
-
threadId: row.threadId,
|
|
2591
|
-
createdAt: row.createdAt,
|
|
2592
|
-
updatedAt: row.updatedAt
|
|
2593
|
-
};
|
|
2736
|
+
return storage.transformScoreRow(row, {
|
|
2737
|
+
fieldMappings: { additionalContext: "additionalLLMContext" }
|
|
2738
|
+
});
|
|
2594
2739
|
}
|
|
2595
2740
|
async getScoreById({ id }) {
|
|
2596
2741
|
const result = await this.client.execute({
|