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