@mastra/lance 1.0.0-beta.10 → 1.0.0-beta.12
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 +129 -0
- package/dist/docs/README.md +1 -1
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/SOURCE_MAP.json +1 -1
- package/dist/docs/rag/01-vector-databases.md +13 -8
- package/dist/index.cjs +188 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +189 -72
- package/dist/index.js.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +2 -2
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts +1 -0
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/vector/index.d.ts +15 -5
- package/dist/vector/index.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -952,27 +952,63 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
952
952
|
);
|
|
953
953
|
}
|
|
954
954
|
}
|
|
955
|
-
async
|
|
955
|
+
async listThreads(args) {
|
|
956
|
+
const { page = 0, perPage: perPageInput, orderBy, filter } = args;
|
|
957
|
+
try {
|
|
958
|
+
this.validatePaginationInput(page, perPageInput ?? 100);
|
|
959
|
+
} catch (error$1) {
|
|
960
|
+
throw new error.MastraError(
|
|
961
|
+
{
|
|
962
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS", "INVALID_PAGE"),
|
|
963
|
+
domain: error.ErrorDomain.STORAGE,
|
|
964
|
+
category: error.ErrorCategory.USER,
|
|
965
|
+
details: { page, ...perPageInput !== void 0 && { perPage: perPageInput } }
|
|
966
|
+
},
|
|
967
|
+
error$1 instanceof Error ? error$1 : new Error("Invalid pagination parameters")
|
|
968
|
+
);
|
|
969
|
+
}
|
|
970
|
+
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
971
|
+
try {
|
|
972
|
+
this.validateMetadataKeys(filter?.metadata);
|
|
973
|
+
} catch (error$1) {
|
|
974
|
+
throw new error.MastraError(
|
|
975
|
+
{
|
|
976
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS", "INVALID_METADATA_KEY"),
|
|
977
|
+
domain: error.ErrorDomain.STORAGE,
|
|
978
|
+
category: error.ErrorCategory.USER,
|
|
979
|
+
details: { metadataKeys: filter?.metadata ? Object.keys(filter.metadata).join(", ") : "" }
|
|
980
|
+
},
|
|
981
|
+
error$1 instanceof Error ? error$1 : new Error("Invalid metadata key")
|
|
982
|
+
);
|
|
983
|
+
}
|
|
956
984
|
try {
|
|
957
|
-
const { resourceId, page = 0, perPage: perPageInput, orderBy } = args;
|
|
958
|
-
const perPage = storage.normalizePerPage(perPageInput, 100);
|
|
959
|
-
if (page < 0) {
|
|
960
|
-
throw new error.MastraError(
|
|
961
|
-
{
|
|
962
|
-
id: storage.createStorageErrorId("LANCE", "LIST_THREADS_BY_RESOURCE_ID", "INVALID_PAGE"),
|
|
963
|
-
domain: error.ErrorDomain.STORAGE,
|
|
964
|
-
category: error.ErrorCategory.USER,
|
|
965
|
-
details: { page }
|
|
966
|
-
},
|
|
967
|
-
new Error("page must be >= 0")
|
|
968
|
-
);
|
|
969
|
-
}
|
|
970
985
|
const { offset, perPage: perPageForResponse } = storage.calculatePagination(page, perPageInput, perPage);
|
|
971
986
|
const { field, direction } = this.parseOrderBy(orderBy);
|
|
972
987
|
const table = await this.client.openTable(storage.TABLE_THREADS);
|
|
973
|
-
const
|
|
974
|
-
|
|
975
|
-
|
|
988
|
+
const whereClauses = [];
|
|
989
|
+
if (filter?.resourceId) {
|
|
990
|
+
whereClauses.push(`\`resourceId\` = '${this.escapeSql(filter.resourceId)}'`);
|
|
991
|
+
}
|
|
992
|
+
const whereClause = whereClauses.length > 0 ? whereClauses.join(" AND ") : "";
|
|
993
|
+
const query = whereClause ? table.query().where(whereClause) : table.query();
|
|
994
|
+
let records = await query.toArray();
|
|
995
|
+
if (filter?.metadata && Object.keys(filter.metadata).length > 0) {
|
|
996
|
+
records = records.filter((record) => {
|
|
997
|
+
if (!record.metadata) return false;
|
|
998
|
+
let recordMeta;
|
|
999
|
+
if (typeof record.metadata === "string") {
|
|
1000
|
+
try {
|
|
1001
|
+
recordMeta = JSON.parse(record.metadata);
|
|
1002
|
+
} catch {
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
recordMeta = record.metadata;
|
|
1007
|
+
}
|
|
1008
|
+
return Object.entries(filter.metadata).every(([key, value]) => recordMeta[key] === value);
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
const total = records.length;
|
|
976
1012
|
records.sort((a, b) => {
|
|
977
1013
|
const aValue = ["createdAt", "updatedAt"].includes(field) ? new Date(a[field]).getTime() : a[field];
|
|
978
1014
|
const bValue = ["createdAt", "updatedAt"].includes(field) ? new Date(b[field]).getTime() : b[field];
|
|
@@ -999,7 +1035,7 @@ var StoreMemoryLance = class extends storage.MemoryStorage {
|
|
|
999
1035
|
} catch (error$1) {
|
|
1000
1036
|
throw new error.MastraError(
|
|
1001
1037
|
{
|
|
1002
|
-
id: storage.createStorageErrorId("LANCE", "
|
|
1038
|
+
id: storage.createStorageErrorId("LANCE", "LIST_THREADS", "FAILED"),
|
|
1003
1039
|
domain: error.ErrorDomain.STORAGE,
|
|
1004
1040
|
category: error.ErrorCategory.THIRD_PARTY
|
|
1005
1041
|
},
|
|
@@ -1605,24 +1641,6 @@ var StoreScoresLance = class extends storage.ScoresStorage {
|
|
|
1605
1641
|
function escapeSql(str) {
|
|
1606
1642
|
return str.replace(/'/g, "''");
|
|
1607
1643
|
}
|
|
1608
|
-
function parseWorkflowRun(row) {
|
|
1609
|
-
let parsedSnapshot = row.snapshot;
|
|
1610
|
-
if (typeof parsedSnapshot === "string") {
|
|
1611
|
-
try {
|
|
1612
|
-
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1613
|
-
} catch (e) {
|
|
1614
|
-
console.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
return {
|
|
1618
|
-
workflowName: row.workflow_name,
|
|
1619
|
-
runId: row.run_id,
|
|
1620
|
-
snapshot: parsedSnapshot,
|
|
1621
|
-
createdAt: storage.ensureDate(row.createdAt),
|
|
1622
|
-
updatedAt: storage.ensureDate(row.updatedAt),
|
|
1623
|
-
resourceId: row.resourceId
|
|
1624
|
-
};
|
|
1625
|
-
}
|
|
1626
1644
|
var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
1627
1645
|
client;
|
|
1628
1646
|
#db;
|
|
@@ -1632,6 +1650,24 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1632
1650
|
this.client = client;
|
|
1633
1651
|
this.#db = new LanceDB({ client });
|
|
1634
1652
|
}
|
|
1653
|
+
parseWorkflowRun(row) {
|
|
1654
|
+
let parsedSnapshot = row.snapshot;
|
|
1655
|
+
if (typeof parsedSnapshot === "string") {
|
|
1656
|
+
try {
|
|
1657
|
+
parsedSnapshot = JSON.parse(row.snapshot);
|
|
1658
|
+
} catch (e) {
|
|
1659
|
+
this.logger.warn(`Failed to parse snapshot for workflow ${row.workflow_name}: ${e}`);
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
return {
|
|
1663
|
+
workflowName: row.workflow_name,
|
|
1664
|
+
runId: row.run_id,
|
|
1665
|
+
snapshot: parsedSnapshot,
|
|
1666
|
+
createdAt: storage.ensureDate(row.createdAt),
|
|
1667
|
+
updatedAt: storage.ensureDate(row.updatedAt),
|
|
1668
|
+
resourceId: row.resourceId
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1635
1671
|
async init() {
|
|
1636
1672
|
const schema = storage.TABLE_SCHEMAS[storage.TABLE_WORKFLOW_SNAPSHOT];
|
|
1637
1673
|
await this.#db.createTable({ tableName: storage.TABLE_WORKFLOW_SNAPSHOT, schema });
|
|
@@ -1763,7 +1799,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1763
1799
|
const records = await query.toArray();
|
|
1764
1800
|
if (records.length === 0) return null;
|
|
1765
1801
|
const record = records[0];
|
|
1766
|
-
return parseWorkflowRun(record);
|
|
1802
|
+
return this.parseWorkflowRun(record);
|
|
1767
1803
|
} catch (error$1) {
|
|
1768
1804
|
throw new error.MastraError(
|
|
1769
1805
|
{
|
|
@@ -1840,7 +1876,7 @@ var StoreWorkflowsLance = class extends storage.WorkflowsStorage {
|
|
|
1840
1876
|
}
|
|
1841
1877
|
const records = await query.toArray();
|
|
1842
1878
|
return {
|
|
1843
|
-
runs: records.map((record) => parseWorkflowRun(record)),
|
|
1879
|
+
runs: records.map((record) => this.parseWorkflowRun(record)),
|
|
1844
1880
|
total: total || records.length
|
|
1845
1881
|
};
|
|
1846
1882
|
} catch (error$1) {
|
|
@@ -2330,6 +2366,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2330
2366
|
}
|
|
2331
2367
|
async query({
|
|
2332
2368
|
tableName,
|
|
2369
|
+
indexName,
|
|
2333
2370
|
queryVector,
|
|
2334
2371
|
filter,
|
|
2335
2372
|
includeVector = false,
|
|
@@ -2337,12 +2374,13 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2337
2374
|
columns = [],
|
|
2338
2375
|
includeAllColumns = false
|
|
2339
2376
|
}) {
|
|
2377
|
+
const resolvedTableName = tableName ?? indexName;
|
|
2340
2378
|
try {
|
|
2341
2379
|
if (!this.lanceClient) {
|
|
2342
2380
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
2343
2381
|
}
|
|
2344
|
-
if (!
|
|
2345
|
-
throw new Error("tableName is required");
|
|
2382
|
+
if (!resolvedTableName) {
|
|
2383
|
+
throw new Error("tableName or indexName is required");
|
|
2346
2384
|
}
|
|
2347
2385
|
if (!queryVector) {
|
|
2348
2386
|
throw new Error("queryVector is required");
|
|
@@ -2353,25 +2391,30 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2353
2391
|
id: storage.createVectorErrorId("LANCE", "QUERY", "INVALID_ARGS"),
|
|
2354
2392
|
domain: error.ErrorDomain.STORAGE,
|
|
2355
2393
|
category: error.ErrorCategory.USER,
|
|
2356
|
-
text:
|
|
2357
|
-
details: { tableName }
|
|
2394
|
+
text: error$1 instanceof Error ? error$1.message : "Invalid query arguments",
|
|
2395
|
+
details: { tableName: resolvedTableName }
|
|
2358
2396
|
},
|
|
2359
2397
|
error$1
|
|
2360
2398
|
);
|
|
2361
2399
|
}
|
|
2362
2400
|
try {
|
|
2363
|
-
const
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2401
|
+
const tables = await this.lanceClient.tableNames();
|
|
2402
|
+
if (!tables.includes(resolvedTableName)) {
|
|
2403
|
+
this.logger.debug(`Table ${resolvedTableName} does not exist. Returning empty results.`);
|
|
2404
|
+
return [];
|
|
2367
2405
|
}
|
|
2406
|
+
const table = await this.lanceClient.openTable(resolvedTableName);
|
|
2368
2407
|
let query = table.search(queryVector);
|
|
2369
2408
|
if (filter && Object.keys(filter).length > 0) {
|
|
2370
2409
|
const whereClause = this.filterTranslator(filter);
|
|
2371
2410
|
this.logger.debug(`Where clause generated: ${whereClause}`);
|
|
2372
2411
|
query = query.where(whereClause);
|
|
2373
2412
|
}
|
|
2374
|
-
if (!includeAllColumns &&
|
|
2413
|
+
if (!includeAllColumns && columns.length > 0) {
|
|
2414
|
+
const selectColumns = [...columns];
|
|
2415
|
+
if (!selectColumns.includes("id")) {
|
|
2416
|
+
selectColumns.push("id");
|
|
2417
|
+
}
|
|
2375
2418
|
query = query.select(selectColumns);
|
|
2376
2419
|
}
|
|
2377
2420
|
query = query.limit(topK);
|
|
@@ -2401,7 +2444,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2401
2444
|
id: storage.createVectorErrorId("LANCE", "QUERY", "FAILED"),
|
|
2402
2445
|
domain: error.ErrorDomain.STORAGE,
|
|
2403
2446
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2404
|
-
details: { tableName, includeVector, columnsCount: columns?.length, includeAllColumns }
|
|
2447
|
+
details: { tableName: resolvedTableName, includeVector, columnsCount: columns?.length, includeAllColumns }
|
|
2405
2448
|
},
|
|
2406
2449
|
error$1
|
|
2407
2450
|
);
|
|
@@ -2436,13 +2479,14 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2436
2479
|
const translator = new LanceFilterTranslator();
|
|
2437
2480
|
return translator.translate(prefixedFilter);
|
|
2438
2481
|
}
|
|
2439
|
-
async upsert({ tableName, vectors, metadata = [], ids = [] }) {
|
|
2482
|
+
async upsert({ tableName, indexName, vectors, metadata = [], ids = [] }) {
|
|
2483
|
+
const resolvedTableName = tableName ?? indexName;
|
|
2440
2484
|
try {
|
|
2441
2485
|
if (!this.lanceClient) {
|
|
2442
2486
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
2443
2487
|
}
|
|
2444
|
-
if (!
|
|
2445
|
-
throw new Error("tableName is required");
|
|
2488
|
+
if (!resolvedTableName) {
|
|
2489
|
+
throw new Error("tableName or indexName is required");
|
|
2446
2490
|
}
|
|
2447
2491
|
if (!vectors || !Array.isArray(vectors) || vectors.length === 0) {
|
|
2448
2492
|
throw new Error("vectors array is required and must not be empty");
|
|
@@ -2453,18 +2497,21 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2453
2497
|
id: storage.createVectorErrorId("LANCE", "UPSERT", "INVALID_ARGS"),
|
|
2454
2498
|
domain: error.ErrorDomain.STORAGE,
|
|
2455
2499
|
category: error.ErrorCategory.USER,
|
|
2456
|
-
text:
|
|
2457
|
-
details: { tableName }
|
|
2500
|
+
text: error$1 instanceof Error ? error$1.message : "Invalid upsert arguments",
|
|
2501
|
+
details: { tableName: resolvedTableName }
|
|
2458
2502
|
},
|
|
2459
2503
|
error$1
|
|
2460
2504
|
);
|
|
2461
2505
|
}
|
|
2462
2506
|
try {
|
|
2463
2507
|
const tables = await this.lanceClient.tableNames();
|
|
2464
|
-
|
|
2465
|
-
|
|
2508
|
+
const tableExists = tables.includes(resolvedTableName);
|
|
2509
|
+
let table = null;
|
|
2510
|
+
if (!tableExists) {
|
|
2511
|
+
this.logger.debug(`Table ${resolvedTableName} does not exist. Creating it with the first upsert data.`);
|
|
2512
|
+
} else {
|
|
2513
|
+
table = await this.lanceClient.openTable(resolvedTableName);
|
|
2466
2514
|
}
|
|
2467
|
-
const table = await this.lanceClient.openTable(tableName);
|
|
2468
2515
|
const vectorIds = ids.length === vectors.length ? ids : vectors.map((_, i) => ids[i] || crypto.randomUUID());
|
|
2469
2516
|
const data = vectors.map((vector, i) => {
|
|
2470
2517
|
const id = String(vectorIds[i]);
|
|
@@ -2481,7 +2528,42 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2481
2528
|
}
|
|
2482
2529
|
return rowData;
|
|
2483
2530
|
});
|
|
2484
|
-
|
|
2531
|
+
if (table !== null) {
|
|
2532
|
+
const rowCount = await table.countRows();
|
|
2533
|
+
const schema = await table.schema();
|
|
2534
|
+
const existingColumns = new Set(schema.fields.map((f) => f.name));
|
|
2535
|
+
const dataColumns = new Set(Object.keys(data[0] || {}));
|
|
2536
|
+
const extraColumns = [...dataColumns].filter((col) => !existingColumns.has(col));
|
|
2537
|
+
const missingSchemaColumns = [...existingColumns].filter((col) => !dataColumns.has(col));
|
|
2538
|
+
const hasSchemaMismatch = extraColumns.length > 0 || missingSchemaColumns.length > 0;
|
|
2539
|
+
if (rowCount === 0 && extraColumns.length > 0) {
|
|
2540
|
+
this.logger.warn(
|
|
2541
|
+
`Table ${resolvedTableName} is empty and data has extra columns ${extraColumns.join(", ")}. Recreating with new schema.`
|
|
2542
|
+
);
|
|
2543
|
+
await this.lanceClient.dropTable(resolvedTableName);
|
|
2544
|
+
await this.lanceClient.createTable(resolvedTableName, data);
|
|
2545
|
+
} else if (hasSchemaMismatch) {
|
|
2546
|
+
if (extraColumns.length > 0) {
|
|
2547
|
+
this.logger.warn(
|
|
2548
|
+
`Table ${resolvedTableName} has ${rowCount} rows. Columns ${extraColumns.join(", ")} will be dropped from upsert.`
|
|
2549
|
+
);
|
|
2550
|
+
}
|
|
2551
|
+
const schemaFieldNames = schema.fields.map((f) => f.name);
|
|
2552
|
+
const normalizedData = data.map((row) => {
|
|
2553
|
+
const normalized = {};
|
|
2554
|
+
for (const col of schemaFieldNames) {
|
|
2555
|
+
normalized[col] = col in row ? row[col] : null;
|
|
2556
|
+
}
|
|
2557
|
+
return normalized;
|
|
2558
|
+
});
|
|
2559
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(normalizedData);
|
|
2560
|
+
} else {
|
|
2561
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(data);
|
|
2562
|
+
}
|
|
2563
|
+
} else {
|
|
2564
|
+
this.logger.debug(`Creating table ${resolvedTableName} with initial data`);
|
|
2565
|
+
await this.lanceClient.createTable(resolvedTableName, data);
|
|
2566
|
+
}
|
|
2485
2567
|
return vectorIds;
|
|
2486
2568
|
} catch (error$1) {
|
|
2487
2569
|
throw new error.MastraError(
|
|
@@ -2489,7 +2571,12 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2489
2571
|
id: storage.createVectorErrorId("LANCE", "UPSERT", "FAILED"),
|
|
2490
2572
|
domain: error.ErrorDomain.STORAGE,
|
|
2491
2573
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2492
|
-
details: {
|
|
2574
|
+
details: {
|
|
2575
|
+
tableName: resolvedTableName,
|
|
2576
|
+
vectorCount: vectors.length,
|
|
2577
|
+
metadataCount: metadata.length,
|
|
2578
|
+
idsCount: ids.length
|
|
2579
|
+
}
|
|
2493
2580
|
},
|
|
2494
2581
|
error$1
|
|
2495
2582
|
);
|
|
@@ -2586,7 +2673,17 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2586
2673
|
}
|
|
2587
2674
|
}
|
|
2588
2675
|
/**
|
|
2589
|
-
*
|
|
2676
|
+
* Creates a vector index on a table.
|
|
2677
|
+
*
|
|
2678
|
+
* The behavior of `indexName` depends on whether `tableName` is provided:
|
|
2679
|
+
* - With `tableName`: `indexName` is the column to index (advanced use case)
|
|
2680
|
+
* - Without `tableName`: `indexName` becomes the table name, and 'vector' is used as the column (Memory compatibility)
|
|
2681
|
+
*
|
|
2682
|
+
* @param tableName - Optional table name. If not provided, defaults to indexName.
|
|
2683
|
+
* @param indexName - The index/column name, or table name if tableName is not provided.
|
|
2684
|
+
* @param dimension - Vector dimension size.
|
|
2685
|
+
* @param metric - Distance metric: 'cosine', 'euclidean', or 'dotproduct'.
|
|
2686
|
+
* @param indexConfig - Optional index configuration.
|
|
2590
2687
|
*/
|
|
2591
2688
|
async createIndex({
|
|
2592
2689
|
tableName,
|
|
@@ -2595,13 +2692,12 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2595
2692
|
metric = "cosine",
|
|
2596
2693
|
indexConfig = {}
|
|
2597
2694
|
}) {
|
|
2695
|
+
const resolvedTableName = tableName ?? indexName;
|
|
2696
|
+
const columnToIndex = tableName ? indexName : "vector";
|
|
2598
2697
|
try {
|
|
2599
2698
|
if (!this.lanceClient) {
|
|
2600
2699
|
throw new Error("LanceDB client not initialized. Use LanceVectorStore.create() to create an instance");
|
|
2601
2700
|
}
|
|
2602
|
-
if (!tableName) {
|
|
2603
|
-
throw new Error("tableName is required");
|
|
2604
|
-
}
|
|
2605
2701
|
if (!indexName) {
|
|
2606
2702
|
throw new Error("indexName is required");
|
|
2607
2703
|
}
|
|
@@ -2614,19 +2710,33 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2614
2710
|
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "INVALID_ARGS"),
|
|
2615
2711
|
domain: error.ErrorDomain.STORAGE,
|
|
2616
2712
|
category: error.ErrorCategory.USER,
|
|
2617
|
-
details: { tableName:
|
|
2713
|
+
details: { tableName: resolvedTableName, indexName, dimension, metric }
|
|
2618
2714
|
},
|
|
2619
2715
|
err
|
|
2620
2716
|
);
|
|
2621
2717
|
}
|
|
2622
2718
|
try {
|
|
2623
2719
|
const tables = await this.lanceClient.tableNames();
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2720
|
+
let table;
|
|
2721
|
+
if (!tables.includes(resolvedTableName)) {
|
|
2722
|
+
this.logger.debug(
|
|
2723
|
+
`Table ${resolvedTableName} does not exist. Creating empty table with dimension ${dimension}.`
|
|
2627
2724
|
);
|
|
2725
|
+
const initVector = new Array(dimension).fill(0);
|
|
2726
|
+
table = await this.lanceClient.createTable(resolvedTableName, [{ id: "__init__", vector: initVector }]);
|
|
2727
|
+
try {
|
|
2728
|
+
await table.delete("id = '__init__'");
|
|
2729
|
+
} catch (deleteError) {
|
|
2730
|
+
this.logger.warn(
|
|
2731
|
+
`Failed to delete initialization row from ${resolvedTableName}. Subsequent queries may include '__init__' row.`,
|
|
2732
|
+
deleteError
|
|
2733
|
+
);
|
|
2734
|
+
}
|
|
2735
|
+
this.logger.debug(`Table ${resolvedTableName} created. Index creation deferred until data is available.`);
|
|
2736
|
+
return;
|
|
2737
|
+
} else {
|
|
2738
|
+
table = await this.lanceClient.openTable(resolvedTableName);
|
|
2628
2739
|
}
|
|
2629
|
-
const table = await this.lanceClient.openTable(tableName);
|
|
2630
2740
|
let metricType;
|
|
2631
2741
|
if (metric === "euclidean") {
|
|
2632
2742
|
metricType = "l2";
|
|
@@ -2635,8 +2745,15 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2635
2745
|
} else if (metric === "cosine") {
|
|
2636
2746
|
metricType = "cosine";
|
|
2637
2747
|
}
|
|
2748
|
+
const rowCount = await table.countRows();
|
|
2749
|
+
if (rowCount < 256) {
|
|
2750
|
+
this.logger.warn(
|
|
2751
|
+
`Table ${resolvedTableName} has ${rowCount} rows, which is below the 256 row minimum for index creation. Skipping index creation.`
|
|
2752
|
+
);
|
|
2753
|
+
return;
|
|
2754
|
+
}
|
|
2638
2755
|
if (indexConfig.type === "ivfflat") {
|
|
2639
|
-
await table.createIndex(
|
|
2756
|
+
await table.createIndex(columnToIndex, {
|
|
2640
2757
|
config: lancedb.Index.ivfPq({
|
|
2641
2758
|
numPartitions: indexConfig.numPartitions || 128,
|
|
2642
2759
|
numSubVectors: indexConfig.numSubVectors || 16,
|
|
@@ -2645,7 +2762,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2645
2762
|
});
|
|
2646
2763
|
} else {
|
|
2647
2764
|
this.logger.debug("Creating HNSW PQ index with config:", indexConfig);
|
|
2648
|
-
await table.createIndex(
|
|
2765
|
+
await table.createIndex(columnToIndex, {
|
|
2649
2766
|
config: lancedb.Index.hnswPq({
|
|
2650
2767
|
m: indexConfig?.hnsw?.m || 16,
|
|
2651
2768
|
efConstruction: indexConfig?.hnsw?.efConstruction || 100,
|
|
@@ -2659,7 +2776,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2659
2776
|
id: storage.createVectorErrorId("LANCE", "CREATE_INDEX", "FAILED"),
|
|
2660
2777
|
domain: error.ErrorDomain.STORAGE,
|
|
2661
2778
|
category: error.ErrorCategory.THIRD_PARTY,
|
|
2662
|
-
details: { tableName:
|
|
2779
|
+
details: { tableName: resolvedTableName, indexName, dimension }
|
|
2663
2780
|
},
|
|
2664
2781
|
error$1
|
|
2665
2782
|
);
|
|
@@ -2957,7 +3074,7 @@ var LanceVectorStore = class _LanceVectorStore extends vector.MastraVector {
|
|
|
2957
3074
|
}
|
|
2958
3075
|
return rowData;
|
|
2959
3076
|
});
|
|
2960
|
-
await table.
|
|
3077
|
+
await table.mergeInsert("id").whenMatchedUpdateAll().whenNotMatchedInsertAll().execute(updatedRecords);
|
|
2961
3078
|
return;
|
|
2962
3079
|
}
|
|
2963
3080
|
} catch (err) {
|