@mastra/lance 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,39 @@
1
1
  # @mastra/lance
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
+ - fix: ensure score responses match saved payloads for Mastra Stores. ([#10557](https://github.com/mastra-ai/mastra/pull/10557))
14
+
15
+ - Unify transformScoreRow functions across storage adapters ([#10648](https://github.com/mastra-ai/mastra/pull/10648))
16
+
17
+ 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:
18
+ - `preferredTimestampFields`: Preferred source fields for timestamps (PostgreSQL, Cloudflare D1)
19
+ - `convertTimestamps`: Convert timestamp strings to Date objects (MSSQL, MongoDB, ClickHouse)
20
+ - `nullValuePattern`: Skip values matching pattern (ClickHouse's `'_null_'`)
21
+ - `fieldMappings`: Map source column names to schema fields (LibSQL's `additionalLLMContext`)
22
+
23
+ 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.
24
+
25
+ - 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)]:
26
+ - @mastra/core@1.0.0-beta.6
27
+
28
+ ## 1.0.0-beta.2
29
+
30
+ ### Patch Changes
31
+
32
+ - Add new deleteVectors, updateVector by filter ([#10408](https://github.com/mastra-ai/mastra/pull/10408))
33
+
34
+ - 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)]:
35
+ - @mastra/core@1.0.0-beta.5
36
+
3
37
  ## 1.0.0-beta.1
4
38
 
5
39
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -294,15 +294,16 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
294
294
  }
295
295
  async listMessages(args) {
296
296
  const { threadId, resourceId, include, filter, perPage: perPageInput, page = 0, orderBy } = args;
297
- if (!threadId.trim()) {
297
+ const threadIds = Array.isArray(threadId) ? threadId : [threadId];
298
+ if (threadIds.length === 0 || threadIds.some((id) => !id.trim())) {
298
299
  throw new error.MastraError(
299
300
  {
300
301
  id: "STORAGE_LANCE_LIST_MESSAGES_INVALID_THREAD_ID",
301
302
  domain: error.ErrorDomain.STORAGE,
302
303
  category: error.ErrorCategory.THIRD_PARTY,
303
- details: { threadId }
304
+ details: { threadId: Array.isArray(threadId) ? threadId.join(",") : threadId }
304
305
  },
305
- new Error("threadId must be a non-empty string")
306
+ new Error("threadId must be a non-empty string or array of non-empty strings")
306
307
  );
307
308
  }
308
309
  const perPage = storage.normalizePerPage(perPageInput, 40);
@@ -321,7 +322,8 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
321
322
  }
322
323
  const { field, direction } = this.parseOrderBy(orderBy, "ASC");
323
324
  const table = await this.client.openTable(storage.TABLE_MESSAGES);
324
- const conditions = [`thread_id = '${this.escapeSql(threadId)}'`];
325
+ const threadCondition = threadIds.length === 1 ? `thread_id = '${this.escapeSql(threadIds[0])}'` : `thread_id IN (${threadIds.map((t) => `'${this.escapeSql(t)}'`).join(", ")})`;
326
+ const conditions = [threadCondition];
325
327
  if (resourceId) {
326
328
  conditions.push(`\`resourceId\` = '${this.escapeSql(resourceId)}'`);
327
329
  }
@@ -361,9 +363,9 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
361
363
  }
362
364
  const messageIds = new Set(messages.map((m) => m.id));
363
365
  if (include && include.length > 0) {
364
- const threadIds = [...new Set(include.map((item) => item.threadId || threadId))];
366
+ const threadIds2 = [...new Set(include.map((item) => item.threadId || threadId))];
365
367
  const allThreadMessages = [];
366
- for (const tid of threadIds) {
368
+ for (const tid of threadIds2) {
367
369
  const threadQuery = table.query().where(`thread_id = '${tid}'`);
368
370
  let threadRecords = await threadQuery.toArray();
369
371
  allThreadMessages.push(...threadRecords);
@@ -409,7 +411,7 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
409
411
  domain: error.ErrorDomain.STORAGE,
410
412
  category: error.ErrorCategory.THIRD_PARTY,
411
413
  details: {
412
- threadId,
414
+ threadId: Array.isArray(threadId) ? threadId.join(",") : threadId,
413
415
  resourceId: resourceId ?? ""
414
416
  }
415
417
  },
@@ -1268,6 +1270,8 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1268
1270
  filteredScore[key] = JSON.stringify(filteredScore[key]);
1269
1271
  }
1270
1272
  }
1273
+ filteredScore.createdAt = /* @__PURE__ */ new Date();
1274
+ filteredScore.updatedAt = /* @__PURE__ */ new Date();
1271
1275
  filteredScore.id = id;
1272
1276
  await table.add([filteredScore], { mode: "append" });
1273
1277
  return { score };
@@ -1290,8 +1294,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1290
1294
  const query = table.query().where(`id = '${id}'`).limit(1);
1291
1295
  const records = await query.toArray();
1292
1296
  if (records.length === 0) return null;
1293
- const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1294
- return processResultWithTypeConversion(records[0], schema);
1297
+ return await this.transformScoreRow(records[0]);
1295
1298
  } catch (error$1) {
1296
1299
  throw new error.MastraError(
1297
1300
  {
@@ -1305,6 +1308,22 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1305
1308
  );
1306
1309
  }
1307
1310
  }
1311
+ /**
1312
+ * LanceDB-specific score row transformation.
1313
+ *
1314
+ * Note: This implementation does NOT use coreTransformScoreRow because:
1315
+ * 1. LanceDB stores schema information in the table itself (requires async fetch)
1316
+ * 2. Uses processResultWithTypeConversion utility for LanceDB-specific type handling
1317
+ */
1318
+ async transformScoreRow(row) {
1319
+ const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1320
+ const transformed = processResultWithTypeConversion(row, schema);
1321
+ return {
1322
+ ...transformed,
1323
+ createdAt: row.createdAt,
1324
+ updatedAt: row.updatedAt
1325
+ };
1326
+ }
1308
1327
  async listScoresByScorerId({
1309
1328
  scorerId,
1310
1329
  pagination,
@@ -1345,8 +1364,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1345
1364
  if (start > 0) query = query.offset(start);
1346
1365
  }
1347
1366
  const records = await query.toArray();
1348
- const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1349
- const scores = processResultWithTypeConversion(records, schema);
1367
+ const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
1350
1368
  return {
1351
1369
  pagination: {
1352
1370
  page,
@@ -1387,8 +1405,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1387
1405
  if (start > 0) query = query.offset(start);
1388
1406
  }
1389
1407
  const records = await query.toArray();
1390
- const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1391
- const scores = processResultWithTypeConversion(records, schema);
1408
+ const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
1392
1409
  return {
1393
1410
  pagination: {
1394
1411
  page,
@@ -1430,8 +1447,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1430
1447
  if (start > 0) query = query.offset(start);
1431
1448
  }
1432
1449
  const records = await query.toArray();
1433
- const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1434
- const scores = processResultWithTypeConversion(records, schema);
1450
+ const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
1435
1451
  return {
1436
1452
  pagination: {
1437
1453
  page,
@@ -1473,8 +1489,7 @@ var StoreScoresLance = class extends storage.ScoresStorage {
1473
1489
  if (start > 0) query = query.offset(start);
1474
1490
  }
1475
1491
  const records = await query.toArray();
1476
- const schema = await getTableSchema({ tableName: storage.TABLE_SCORERS, client: this.client });
1477
- const scores = processResultWithTypeConversion(records, schema);
1492
+ const scores = await Promise.all(records.map(async (record) => await this.transformScoreRow(record)));
1478
1493
  return {
1479
1494
  pagination: {
1480
1495
  page,
@@ -2845,7 +2860,44 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2845
2860
  );
2846
2861
  }
2847
2862
  }
2848
- async updateVector({ indexName, id, update }) {
2863
+ async updateVector(params) {
2864
+ const { indexName, update } = params;
2865
+ if ("id" in params && "filter" in params && params.id && params.filter) {
2866
+ throw new error.MastraError({
2867
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2868
+ domain: error.ErrorDomain.STORAGE,
2869
+ category: error.ErrorCategory.USER,
2870
+ text: "id and filter are mutually exclusive",
2871
+ details: { indexName }
2872
+ });
2873
+ }
2874
+ if (!("id" in params || "filter" in params) || !params.id && !params.filter) {
2875
+ throw new error.MastraError({
2876
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2877
+ domain: error.ErrorDomain.STORAGE,
2878
+ category: error.ErrorCategory.USER,
2879
+ text: "Either id or filter must be provided",
2880
+ details: { indexName }
2881
+ });
2882
+ }
2883
+ if ("filter" in params && params.filter && Object.keys(params.filter).length === 0) {
2884
+ throw new error.MastraError({
2885
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2886
+ domain: error.ErrorDomain.STORAGE,
2887
+ category: error.ErrorCategory.USER,
2888
+ text: "Cannot update with empty filter",
2889
+ details: { indexName }
2890
+ });
2891
+ }
2892
+ if (!update.vector && !update.metadata) {
2893
+ throw new error.MastraError({
2894
+ id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_INVALID_ARGS",
2895
+ domain: error.ErrorDomain.STORAGE,
2896
+ category: error.ErrorCategory.USER,
2897
+ text: "No updates provided",
2898
+ details: { indexName }
2899
+ });
2900
+ }
2849
2901
  try {
2850
2902
  if (!this.lanceClient) {
2851
2903
  throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
@@ -2853,21 +2905,6 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2853
2905
  if (!indexName) {
2854
2906
  throw new Error("indexName is required");
2855
2907
  }
2856
- if (!id) {
2857
- throw new Error("id is required");
2858
- }
2859
- } catch (err) {
2860
- throw new error.MastraError(
2861
- {
2862
- id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED_INVALID_ARGS",
2863
- domain: error.ErrorDomain.STORAGE,
2864
- category: error.ErrorCategory.USER,
2865
- details: { indexName, id }
2866
- },
2867
- err
2868
- );
2869
- }
2870
- try {
2871
2908
  const tables = await this.lanceClient.tableNames();
2872
2909
  for (const tableName of tables) {
2873
2910
  this.logger.debug("Checking table:" + tableName);
@@ -2877,39 +2914,66 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2877
2914
  const hasColumn = schema.fields.some((field) => field.name === indexName);
2878
2915
  if (hasColumn) {
2879
2916
  this.logger.debug(`Found column ${indexName} in table ${tableName}`);
2880
- const existingRecord = await table.query().where(`id = '${id}'`).select(schema.fields.map((field) => field.name)).limit(1).toArray();
2881
- if (existingRecord.length === 0) {
2882
- throw new Error(`Record with id '${id}' not found in table ${tableName}`);
2917
+ let whereClause;
2918
+ if ("id" in params && params.id) {
2919
+ whereClause = `id = '${params.id}'`;
2920
+ } else if ("filter" in params && params.filter) {
2921
+ const translator = new LanceFilterTranslator();
2922
+ const processFilterKeys = (filter) => {
2923
+ const processedFilter = {};
2924
+ Object.entries(filter).forEach(([key, value]) => {
2925
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
2926
+ Object.entries(value).forEach(([nestedKey, nestedValue]) => {
2927
+ processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
2928
+ });
2929
+ } else {
2930
+ processedFilter[`metadata_${key}`] = value;
2931
+ }
2932
+ });
2933
+ return processedFilter;
2934
+ };
2935
+ const prefixedFilter = processFilterKeys(params.filter);
2936
+ whereClause = translator.translate(prefixedFilter) || "";
2937
+ if (!whereClause) {
2938
+ throw new Error("Failed to translate filter to SQL");
2939
+ }
2940
+ } else {
2941
+ throw new Error("Either id or filter must be provided");
2883
2942
  }
2884
- const rowData = {
2885
- id
2886
- };
2887
- Object.entries(existingRecord[0]).forEach(([key, value]) => {
2888
- if (key !== "id" && key !== "_distance") {
2889
- if (key === indexName) {
2890
- if (!update.vector) {
2891
- if (Array.isArray(value)) {
2892
- rowData[key] = [...value];
2893
- } else if (typeof value === "object" && value !== null) {
2894
- rowData[key] = Array.from(value);
2943
+ const existingRecords = await table.query().where(whereClause).select(schema.fields.map((field) => field.name)).toArray();
2944
+ if (existingRecords.length === 0) {
2945
+ this.logger.info(`No records found matching criteria in table ${tableName}`);
2946
+ return;
2947
+ }
2948
+ const updatedRecords = existingRecords.map((record) => {
2949
+ const rowData = {};
2950
+ Object.entries(record).forEach(([key, value]) => {
2951
+ if (key !== "_distance") {
2952
+ if (key === indexName) {
2953
+ if (update.vector) {
2954
+ rowData[key] = update.vector;
2895
2955
  } else {
2896
- rowData[key] = value;
2956
+ if (Array.isArray(value)) {
2957
+ rowData[key] = [...value];
2958
+ } else if (typeof value === "object" && value !== null) {
2959
+ rowData[key] = Array.from(value);
2960
+ } else {
2961
+ rowData[key] = value;
2962
+ }
2897
2963
  }
2964
+ } else {
2965
+ rowData[key] = value;
2898
2966
  }
2899
- } else {
2900
- rowData[key] = value;
2901
2967
  }
2968
+ });
2969
+ if (update.metadata) {
2970
+ Object.entries(update.metadata).forEach(([key, value]) => {
2971
+ rowData[`metadata_${key}`] = value;
2972
+ });
2902
2973
  }
2974
+ return rowData;
2903
2975
  });
2904
- if (update.vector) {
2905
- rowData[indexName] = update.vector;
2906
- }
2907
- if (update.metadata) {
2908
- Object.entries(update.metadata).forEach(([key, value]) => {
2909
- rowData[`metadata_${key}`] = value;
2910
- });
2911
- }
2912
- await table.add([rowData], { mode: "overwrite" });
2976
+ await table.add(updatedRecords, { mode: "overwrite" });
2913
2977
  return;
2914
2978
  }
2915
2979
  } catch (err) {
@@ -2919,12 +2983,19 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2919
2983
  }
2920
2984
  throw new Error(`No table found with column/index '${indexName}'`);
2921
2985
  } catch (error$1) {
2986
+ if (error$1 instanceof error.MastraError) throw error$1;
2922
2987
  throw new error.MastraError(
2923
2988
  {
2924
2989
  id: "STORAGE_LANCE_VECTOR_UPDATE_VECTOR_FAILED",
2925
2990
  domain: error.ErrorDomain.STORAGE,
2926
2991
  category: error.ErrorCategory.THIRD_PARTY,
2927
- details: { indexName, id, hasVector: !!update.vector, hasMetadata: !!update.metadata }
2992
+ details: {
2993
+ indexName,
2994
+ ..."id" in params && params.id && { id: params.id },
2995
+ ..."filter" in params && params.filter && { filter: JSON.stringify(params.filter) },
2996
+ hasVector: !!update.vector,
2997
+ hasMetadata: !!update.metadata
2998
+ }
2928
2999
  },
2929
3000
  error$1
2930
3001
  );
@@ -2947,7 +3018,10 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2947
3018
  id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED_INVALID_ARGS",
2948
3019
  domain: error.ErrorDomain.STORAGE,
2949
3020
  category: error.ErrorCategory.USER,
2950
- details: { indexName, id }
3021
+ details: {
3022
+ indexName,
3023
+ ...id && { id }
3024
+ }
2951
3025
  },
2952
3026
  err
2953
3027
  );
@@ -2977,7 +3051,10 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
2977
3051
  id: "STORAGE_LANCE_VECTOR_DELETE_VECTOR_FAILED",
2978
3052
  domain: error.ErrorDomain.STORAGE,
2979
3053
  category: error.ErrorCategory.THIRD_PARTY,
2980
- details: { indexName, id }
3054
+ details: {
3055
+ indexName,
3056
+ ...id && { id }
3057
+ }
2981
3058
  },
2982
3059
  error$1
2983
3060
  );
@@ -3008,6 +3085,109 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
3008
3085
  });
3009
3086
  return result;
3010
3087
  }
3088
+ async deleteVectors({ indexName, filter, ids }) {
3089
+ if (ids && filter) {
3090
+ throw new error.MastraError({
3091
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3092
+ domain: error.ErrorDomain.STORAGE,
3093
+ category: error.ErrorCategory.USER,
3094
+ text: "ids and filter are mutually exclusive",
3095
+ details: { indexName }
3096
+ });
3097
+ }
3098
+ if (!ids && !filter) {
3099
+ throw new error.MastraError({
3100
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3101
+ domain: error.ErrorDomain.STORAGE,
3102
+ category: error.ErrorCategory.USER,
3103
+ text: "Either filter or ids must be provided",
3104
+ details: { indexName }
3105
+ });
3106
+ }
3107
+ if (ids && ids.length === 0) {
3108
+ throw new error.MastraError({
3109
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3110
+ domain: error.ErrorDomain.STORAGE,
3111
+ category: error.ErrorCategory.USER,
3112
+ text: "Cannot delete with empty ids array",
3113
+ details: { indexName }
3114
+ });
3115
+ }
3116
+ if (filter && Object.keys(filter).length === 0) {
3117
+ throw new error.MastraError({
3118
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_INVALID_ARGS",
3119
+ domain: error.ErrorDomain.STORAGE,
3120
+ category: error.ErrorCategory.USER,
3121
+ text: "Cannot delete with empty filter",
3122
+ details: { indexName }
3123
+ });
3124
+ }
3125
+ try {
3126
+ if (!this.lanceClient) {
3127
+ throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
3128
+ }
3129
+ if (!indexName) {
3130
+ throw new Error("indexName is required");
3131
+ }
3132
+ const tables = await this.lanceClient.tableNames();
3133
+ for (const tableName of tables) {
3134
+ this.logger.debug("Checking table:" + tableName);
3135
+ const table = await this.lanceClient.openTable(tableName);
3136
+ try {
3137
+ const schema = await table.schema();
3138
+ const hasColumn = schema.fields.some((field) => field.name === indexName);
3139
+ if (hasColumn) {
3140
+ this.logger.debug(`Found column ${indexName} in table ${tableName}`);
3141
+ if (ids) {
3142
+ const idsConditions = ids.map((id) => `id = '${id}'`).join(" OR ");
3143
+ await table.delete(idsConditions);
3144
+ } else if (filter) {
3145
+ const translator = new LanceFilterTranslator();
3146
+ const processFilterKeys = (filter2) => {
3147
+ const processedFilter = {};
3148
+ Object.entries(filter2).forEach(([key, value]) => {
3149
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
3150
+ Object.entries(value).forEach(([nestedKey, nestedValue]) => {
3151
+ processedFilter[`metadata_${key}_${nestedKey}`] = nestedValue;
3152
+ });
3153
+ } else {
3154
+ processedFilter[`metadata_${key}`] = value;
3155
+ }
3156
+ });
3157
+ return processedFilter;
3158
+ };
3159
+ const prefixedFilter = processFilterKeys(filter);
3160
+ const whereClause = translator.translate(prefixedFilter);
3161
+ if (!whereClause) {
3162
+ throw new Error("Failed to translate filter to SQL");
3163
+ }
3164
+ await table.delete(whereClause);
3165
+ }
3166
+ return;
3167
+ }
3168
+ } catch (err) {
3169
+ this.logger.error(`Error checking schema for table ${tableName}:` + err);
3170
+ continue;
3171
+ }
3172
+ }
3173
+ throw new Error(`No table found with column/index '${indexName}'`);
3174
+ } catch (error$1) {
3175
+ if (error$1 instanceof error.MastraError) throw error$1;
3176
+ throw new error.MastraError(
3177
+ {
3178
+ id: "STORAGE_LANCE_VECTOR_DELETE_VECTORS_FAILED",
3179
+ domain: error.ErrorDomain.STORAGE,
3180
+ category: error.ErrorCategory.THIRD_PARTY,
3181
+ details: {
3182
+ indexName,
3183
+ ...filter && { filter: JSON.stringify(filter) },
3184
+ ...ids && { idsCount: ids.length }
3185
+ }
3186
+ },
3187
+ error$1
3188
+ );
3189
+ }
3190
+ }
3011
3191
  };
3012
3192
 
3013
3193
  exports.LanceStorage = LanceStorage;