@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 +34 -0
- package/dist/index.cjs +242 -62
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +242 -62
- 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 +8 -0
- package/dist/storage/domains/scores/index.d.ts.map +1 -1
- package/dist/vector/filter.d.ts +5 -5
- package/dist/vector/index.d.ts +3 -2
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +6 -6
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
|
-
|
|
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
|
|
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
|
|
366
|
+
const threadIds2 = [...new Set(include.map((item) => item.threadId || threadId))];
|
|
365
367
|
const allThreadMessages = [];
|
|
366
|
-
for (const tid of
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
2881
|
-
if (
|
|
2882
|
-
|
|
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
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: {
|
|
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: {
|
|
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: {
|
|
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;
|