@mastra/libsql 1.0.0-beta.1 → 1.0.0-beta.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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @mastra/libsql
2
2
 
3
+ ## 1.0.0-beta.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Add new deleteVectors, updateVector by filter ([#10408](https://github.com/mastra-ai/mastra/pull/10408))
8
+
9
+ - 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)]:
10
+ - @mastra/core@1.0.0-beta.5
11
+
3
12
  ## 1.0.0-beta.1
4
13
 
5
14
  ### 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
- return {
98
- sql: `CAST(json_extract(metadata, ${jsonPath}) AS NUMERIC) ${symbol} ?`,
99
- needsValue: true
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({ indexName, id, update }) {
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: "LIBSQL_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
913
+ id: "LIBSQL_VECTOR_UPDATE_MISSING_PARAMS",
844
914
  domain: error.ErrorDomain.STORAGE,
845
915
  category: error.ErrorCategory.USER,
846
- details: { indexName, id },
847
- text: "No updates provided"
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
- UPDATE ${parsedIndexName}
853
- SET ${updates.join(", ")}
854
- WHERE vector_id = ?;
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: { indexName, id }
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: { indexName: args.indexName, id: args.id }
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));