@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 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
- 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));
@@ -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
- threadId,
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 numbered_messages AS (
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(searchId, id, withPreviousMessages, withNextMessages);
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
- if (!threadId.trim()) {
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 conditions = [`thread_id = ?`];
1058
- const queryParams = [threadId];
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({ threadId, include });
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 returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
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
- const scorerValue = storage.safelyParseJSON(row.scorer);
2557
- const inputValue = storage.safelyParseJSON(row.input ?? "{}");
2558
- const outputValue = storage.safelyParseJSON(row.output ?? "{}");
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({