@liendev/core 0.19.5
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/README.md +336 -0
- package/dist/config/loader.d.ts +12 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +46 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/merge.d.ts +20 -0
- package/dist/config/merge.d.ts.map +1 -0
- package/dist/config/merge.js +71 -0
- package/dist/config/merge.js.map +1 -0
- package/dist/config/migration-manager.d.ts +46 -0
- package/dist/config/migration-manager.d.ts.map +1 -0
- package/dist/config/migration-manager.js +119 -0
- package/dist/config/migration-manager.js.map +1 -0
- package/dist/config/migration.d.ts +20 -0
- package/dist/config/migration.d.ts.map +1 -0
- package/dist/config/migration.js +155 -0
- package/dist/config/migration.js.map +1 -0
- package/dist/config/schema.d.ts +101 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +58 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/service.d.ts +122 -0
- package/dist/config/service.d.ts.map +1 -0
- package/dist/config/service.js +477 -0
- package/dist/config/service.js.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +43 -0
- package/dist/constants.js.map +1 -0
- package/dist/embeddings/cache.d.ts +45 -0
- package/dist/embeddings/cache.d.ts.map +1 -0
- package/dist/embeddings/cache.js +109 -0
- package/dist/embeddings/cache.js.map +1 -0
- package/dist/embeddings/local.d.ts +10 -0
- package/dist/embeddings/local.d.ts.map +1 -0
- package/dist/embeddings/local.js +63 -0
- package/dist/embeddings/local.js.map +1 -0
- package/dist/embeddings/types.d.ts +9 -0
- package/dist/embeddings/types.d.ts.map +1 -0
- package/dist/embeddings/types.js +5 -0
- package/dist/embeddings/types.js.map +1 -0
- package/dist/errors/codes.d.ts +18 -0
- package/dist/errors/codes.d.ts.map +1 -0
- package/dist/errors/codes.js +25 -0
- package/dist/errors/codes.js.map +1 -0
- package/dist/errors/index.d.ts +85 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +134 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/frameworks/detector-service.d.ts +59 -0
- package/dist/frameworks/detector-service.d.ts.map +1 -0
- package/dist/frameworks/detector-service.js +219 -0
- package/dist/frameworks/detector-service.js.map +1 -0
- package/dist/frameworks/laravel/config.d.ts +6 -0
- package/dist/frameworks/laravel/config.d.ts.map +1 -0
- package/dist/frameworks/laravel/config.js +68 -0
- package/dist/frameworks/laravel/config.js.map +1 -0
- package/dist/frameworks/laravel/detector.d.ts +6 -0
- package/dist/frameworks/laravel/detector.d.ts.map +1 -0
- package/dist/frameworks/laravel/detector.js +96 -0
- package/dist/frameworks/laravel/detector.js.map +1 -0
- package/dist/frameworks/nodejs/config.d.ts +6 -0
- package/dist/frameworks/nodejs/config.d.ts.map +1 -0
- package/dist/frameworks/nodejs/config.js +57 -0
- package/dist/frameworks/nodejs/config.js.map +1 -0
- package/dist/frameworks/nodejs/detector.d.ts +6 -0
- package/dist/frameworks/nodejs/detector.d.ts.map +1 -0
- package/dist/frameworks/nodejs/detector.js +77 -0
- package/dist/frameworks/nodejs/detector.js.map +1 -0
- package/dist/frameworks/php/config.d.ts +6 -0
- package/dist/frameworks/php/config.d.ts.map +1 -0
- package/dist/frameworks/php/config.js +53 -0
- package/dist/frameworks/php/config.js.map +1 -0
- package/dist/frameworks/php/detector.d.ts +7 -0
- package/dist/frameworks/php/detector.d.ts.map +1 -0
- package/dist/frameworks/php/detector.js +101 -0
- package/dist/frameworks/php/detector.js.map +1 -0
- package/dist/frameworks/registry.d.ts +20 -0
- package/dist/frameworks/registry.d.ts.map +1 -0
- package/dist/frameworks/registry.js +38 -0
- package/dist/frameworks/registry.js.map +1 -0
- package/dist/frameworks/shopify/config.d.ts +6 -0
- package/dist/frameworks/shopify/config.d.ts.map +1 -0
- package/dist/frameworks/shopify/config.js +50 -0
- package/dist/frameworks/shopify/config.js.map +1 -0
- package/dist/frameworks/shopify/detector.d.ts +6 -0
- package/dist/frameworks/shopify/detector.d.ts.map +1 -0
- package/dist/frameworks/shopify/detector.js +103 -0
- package/dist/frameworks/shopify/detector.js.map +1 -0
- package/dist/frameworks/types.d.ts +51 -0
- package/dist/frameworks/types.d.ts.map +1 -0
- package/dist/frameworks/types.js +21 -0
- package/dist/frameworks/types.js.map +1 -0
- package/dist/git/tracker.d.ts +56 -0
- package/dist/git/tracker.d.ts.map +1 -0
- package/dist/git/tracker.js +189 -0
- package/dist/git/tracker.js.map +1 -0
- package/dist/git/utils.d.ts +60 -0
- package/dist/git/utils.d.ts.map +1 -0
- package/dist/git/utils.js +152 -0
- package/dist/git/utils.js.map +1 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -0
- package/dist/indexer/ast/chunker.d.ts +28 -0
- package/dist/indexer/ast/chunker.d.ts.map +1 -0
- package/dist/indexer/ast/chunker.js +268 -0
- package/dist/indexer/ast/chunker.js.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts +16 -0
- package/dist/indexer/ast/complexity/cognitive.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cognitive.js +106 -0
- package/dist/indexer/ast/complexity/cognitive.js.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts +12 -0
- package/dist/indexer/ast/complexity/cyclomatic.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/cyclomatic.js +61 -0
- package/dist/indexer/ast/complexity/cyclomatic.js.map +1 -0
- package/dist/indexer/ast/complexity/halstead.d.ts +55 -0
- package/dist/indexer/ast/complexity/halstead.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/halstead.js +290 -0
- package/dist/indexer/ast/complexity/halstead.js.map +1 -0
- package/dist/indexer/ast/complexity/index.d.ts +13 -0
- package/dist/indexer/ast/complexity/index.d.ts.map +1 -0
- package/dist/indexer/ast/complexity/index.js +12 -0
- package/dist/indexer/ast/complexity/index.js.map +1 -0
- package/dist/indexer/ast/parser.d.ts +27 -0
- package/dist/indexer/ast/parser.d.ts.map +1 -0
- package/dist/indexer/ast/parser.js +103 -0
- package/dist/indexer/ast/parser.js.map +1 -0
- package/dist/indexer/ast/symbols.d.ts +17 -0
- package/dist/indexer/ast/symbols.d.ts.map +1 -0
- package/dist/indexer/ast/symbols.js +265 -0
- package/dist/indexer/ast/symbols.js.map +1 -0
- package/dist/indexer/ast/traversers/index.d.ts +19 -0
- package/dist/indexer/ast/traversers/index.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/index.js +42 -0
- package/dist/indexer/ast/traversers/index.js.map +1 -0
- package/dist/indexer/ast/traversers/php.d.ts +21 -0
- package/dist/indexer/ast/traversers/php.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/php.js +67 -0
- package/dist/indexer/ast/traversers/php.js.map +1 -0
- package/dist/indexer/ast/traversers/python.d.ts +28 -0
- package/dist/indexer/ast/traversers/python.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/python.js +67 -0
- package/dist/indexer/ast/traversers/python.js.map +1 -0
- package/dist/indexer/ast/traversers/types.d.ts +98 -0
- package/dist/indexer/ast/traversers/types.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/types.js +2 -0
- package/dist/indexer/ast/traversers/types.js.map +1 -0
- package/dist/indexer/ast/traversers/typescript.d.ts +29 -0
- package/dist/indexer/ast/traversers/typescript.d.ts.map +1 -0
- package/dist/indexer/ast/traversers/typescript.js +88 -0
- package/dist/indexer/ast/traversers/typescript.js.map +1 -0
- package/dist/indexer/ast/types.d.ts +59 -0
- package/dist/indexer/ast/types.d.ts.map +1 -0
- package/dist/indexer/ast/types.js +2 -0
- package/dist/indexer/ast/types.js.map +1 -0
- package/dist/indexer/change-detector.d.ts +17 -0
- package/dist/indexer/change-detector.d.ts.map +1 -0
- package/dist/indexer/change-detector.js +207 -0
- package/dist/indexer/change-detector.js.map +1 -0
- package/dist/indexer/chunk-batch-processor.d.ts +103 -0
- package/dist/indexer/chunk-batch-processor.d.ts.map +1 -0
- package/dist/indexer/chunk-batch-processor.js +179 -0
- package/dist/indexer/chunk-batch-processor.js.map +1 -0
- package/dist/indexer/chunker.d.ts +10 -0
- package/dist/indexer/chunker.d.ts.map +1 -0
- package/dist/indexer/chunker.js +96 -0
- package/dist/indexer/chunker.js.map +1 -0
- package/dist/indexer/dependency-analyzer.d.ts +60 -0
- package/dist/indexer/dependency-analyzer.d.ts.map +1 -0
- package/dist/indexer/dependency-analyzer.js +261 -0
- package/dist/indexer/dependency-analyzer.js.map +1 -0
- package/dist/indexer/incremental.d.ts +47 -0
- package/dist/indexer/incremental.d.ts.map +1 -0
- package/dist/indexer/incremental.js +284 -0
- package/dist/indexer/incremental.js.map +1 -0
- package/dist/indexer/index.d.ts +80 -0
- package/dist/indexer/index.d.ts.map +1 -0
- package/dist/indexer/index.js +364 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/json-template-chunker.d.ts +9 -0
- package/dist/indexer/json-template-chunker.d.ts.map +1 -0
- package/dist/indexer/json-template-chunker.js +83 -0
- package/dist/indexer/json-template-chunker.js.map +1 -0
- package/dist/indexer/liquid-chunker.d.ts +13 -0
- package/dist/indexer/liquid-chunker.d.ts.map +1 -0
- package/dist/indexer/liquid-chunker.js +272 -0
- package/dist/indexer/liquid-chunker.js.map +1 -0
- package/dist/indexer/manifest.d.ts +122 -0
- package/dist/indexer/manifest.d.ts.map +1 -0
- package/dist/indexer/manifest.js +262 -0
- package/dist/indexer/manifest.js.map +1 -0
- package/dist/indexer/progress-tracker.d.ts +35 -0
- package/dist/indexer/progress-tracker.d.ts.map +1 -0
- package/dist/indexer/progress-tracker.js +33 -0
- package/dist/indexer/progress-tracker.js.map +1 -0
- package/dist/indexer/scanner.d.ts +16 -0
- package/dist/indexer/scanner.d.ts.map +1 -0
- package/dist/indexer/scanner.js +159 -0
- package/dist/indexer/scanner.js.map +1 -0
- package/dist/indexer/symbol-extractor.d.ts +18 -0
- package/dist/indexer/symbol-extractor.d.ts.map +1 -0
- package/dist/indexer/symbol-extractor.js +351 -0
- package/dist/indexer/symbol-extractor.js.map +1 -0
- package/dist/indexer/types.d.ts +34 -0
- package/dist/indexer/types.d.ts.map +1 -0
- package/dist/indexer/types.js +2 -0
- package/dist/indexer/types.js.map +1 -0
- package/dist/insights/complexity-analyzer.d.ts +82 -0
- package/dist/insights/complexity-analyzer.d.ts.map +1 -0
- package/dist/insights/complexity-analyzer.js +356 -0
- package/dist/insights/complexity-analyzer.js.map +1 -0
- package/dist/insights/formatters/index.d.ts +11 -0
- package/dist/insights/formatters/index.d.ts.map +1 -0
- package/dist/insights/formatters/index.js +20 -0
- package/dist/insights/formatters/index.js.map +1 -0
- package/dist/insights/formatters/json.d.ts +7 -0
- package/dist/insights/formatters/json.d.ts.map +1 -0
- package/dist/insights/formatters/json.js +14 -0
- package/dist/insights/formatters/json.js.map +1 -0
- package/dist/insights/formatters/sarif.d.ts +6 -0
- package/dist/insights/formatters/sarif.d.ts.map +1 -0
- package/dist/insights/formatters/sarif.js +113 -0
- package/dist/insights/formatters/sarif.js.map +1 -0
- package/dist/insights/formatters/text.d.ts +6 -0
- package/dist/insights/formatters/text.d.ts.map +1 -0
- package/dist/insights/formatters/text.js +154 -0
- package/dist/insights/formatters/text.js.map +1 -0
- package/dist/insights/types.d.ts +73 -0
- package/dist/insights/types.d.ts.map +1 -0
- package/dist/insights/types.js +9 -0
- package/dist/insights/types.js.map +1 -0
- package/dist/types/index.d.ts +14 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/path-matching.d.ts +69 -0
- package/dist/utils/path-matching.d.ts.map +1 -0
- package/dist/utils/path-matching.js +123 -0
- package/dist/utils/path-matching.js.map +1 -0
- package/dist/utils/result.d.ts +65 -0
- package/dist/utils/result.d.ts.map +1 -0
- package/dist/utils/result.js +67 -0
- package/dist/utils/result.js.map +1 -0
- package/dist/utils/version.d.ts +22 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +28 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/vectordb/batch-insert.d.ts +14 -0
- package/dist/vectordb/batch-insert.d.ts.map +1 -0
- package/dist/vectordb/batch-insert.js +185 -0
- package/dist/vectordb/batch-insert.js.map +1 -0
- package/dist/vectordb/boosting/composer.d.ts +51 -0
- package/dist/vectordb/boosting/composer.d.ts.map +1 -0
- package/dist/vectordb/boosting/composer.js +65 -0
- package/dist/vectordb/boosting/composer.js.map +1 -0
- package/dist/vectordb/boosting/index.d.ts +22 -0
- package/dist/vectordb/boosting/index.d.ts.map +1 -0
- package/dist/vectordb/boosting/index.js +22 -0
- package/dist/vectordb/boosting/index.js.map +1 -0
- package/dist/vectordb/boosting/strategies.d.ts +40 -0
- package/dist/vectordb/boosting/strategies.d.ts.map +1 -0
- package/dist/vectordb/boosting/strategies.js +174 -0
- package/dist/vectordb/boosting/strategies.js.map +1 -0
- package/dist/vectordb/boosting/types.d.ts +20 -0
- package/dist/vectordb/boosting/types.d.ts.map +1 -0
- package/dist/vectordb/boosting/types.js +2 -0
- package/dist/vectordb/boosting/types.js.map +1 -0
- package/dist/vectordb/intent-classifier.d.ts +99 -0
- package/dist/vectordb/intent-classifier.d.ts.map +1 -0
- package/dist/vectordb/intent-classifier.js +193 -0
- package/dist/vectordb/intent-classifier.js.map +1 -0
- package/dist/vectordb/lancedb.d.ts +45 -0
- package/dist/vectordb/lancedb.d.ts.map +1 -0
- package/dist/vectordb/lancedb.js +203 -0
- package/dist/vectordb/lancedb.js.map +1 -0
- package/dist/vectordb/maintenance.d.ts +18 -0
- package/dist/vectordb/maintenance.d.ts.map +1 -0
- package/dist/vectordb/maintenance.js +87 -0
- package/dist/vectordb/maintenance.js.map +1 -0
- package/dist/vectordb/query.d.ts +34 -0
- package/dist/vectordb/query.d.ts.map +1 -0
- package/dist/vectordb/query.js +303 -0
- package/dist/vectordb/query.js.map +1 -0
- package/dist/vectordb/relevance.d.ts +15 -0
- package/dist/vectordb/relevance.d.ts.map +1 -0
- package/dist/vectordb/relevance.js +19 -0
- package/dist/vectordb/relevance.js.map +1 -0
- package/dist/vectordb/types.d.ts +29 -0
- package/dist/vectordb/types.d.ts.map +1 -0
- package/dist/vectordb/types.js +2 -0
- package/dist/vectordb/types.js.map +1 -0
- package/dist/vectordb/version.d.ts +16 -0
- package/dist/vectordb/version.d.ts.map +1 -0
- package/dist/vectordb/version.js +40 -0
- package/dist/vectordb/version.js.map +1 -0
- package/package.json +66 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import * as lancedb from '@lancedb/lancedb';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import crypto from 'crypto';
|
|
5
|
+
import { EMBEDDING_DIMENSION } from '../embeddings/types.js';
|
|
6
|
+
import { readVersionFile } from './version.js';
|
|
7
|
+
import { DatabaseError, wrapError } from '../errors/index.js';
|
|
8
|
+
import * as queryOps from './query.js';
|
|
9
|
+
import * as batchOps from './batch-insert.js';
|
|
10
|
+
import * as maintenanceOps from './maintenance.js';
|
|
11
|
+
export class VectorDB {
|
|
12
|
+
db = null;
|
|
13
|
+
table = null;
|
|
14
|
+
dbPath;
|
|
15
|
+
tableName = 'code_chunks';
|
|
16
|
+
lastVersionCheck = 0;
|
|
17
|
+
currentVersion = 0;
|
|
18
|
+
constructor(projectRoot) {
|
|
19
|
+
// Store in user's home directory under ~/.lien/indices/{projectName-hash}
|
|
20
|
+
const projectName = path.basename(projectRoot);
|
|
21
|
+
// Create unique identifier from full path to prevent collisions
|
|
22
|
+
const pathHash = crypto
|
|
23
|
+
.createHash('md5')
|
|
24
|
+
.update(projectRoot)
|
|
25
|
+
.digest('hex')
|
|
26
|
+
.substring(0, 8);
|
|
27
|
+
this.dbPath = path.join(os.homedir(), '.lien', 'indices', `${projectName}-${pathHash}`);
|
|
28
|
+
}
|
|
29
|
+
async initialize() {
|
|
30
|
+
try {
|
|
31
|
+
this.db = await lancedb.connect(this.dbPath);
|
|
32
|
+
try {
|
|
33
|
+
this.table = await this.db.openTable(this.tableName);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Table doesn't exist yet - will be created on first insert
|
|
37
|
+
this.table = null;
|
|
38
|
+
}
|
|
39
|
+
// Read and cache the current version
|
|
40
|
+
try {
|
|
41
|
+
this.currentVersion = await readVersionFile(this.dbPath);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
// Version file doesn't exist yet, will be created on first index
|
|
45
|
+
this.currentVersion = 0;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw wrapError(error, 'Failed to initialize vector database', { dbPath: this.dbPath });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async insertBatch(vectors, metadatas, contents) {
|
|
53
|
+
if (!this.db) {
|
|
54
|
+
throw new DatabaseError('Vector database not initialized');
|
|
55
|
+
}
|
|
56
|
+
// Note: insertBatch may return null for empty batches when table is null
|
|
57
|
+
// This is correct behavior - empty batches are no-ops and don't create tables
|
|
58
|
+
this.table = await batchOps.insertBatch(this.db, this.table, this.tableName, vectors, metadatas, contents);
|
|
59
|
+
}
|
|
60
|
+
async search(queryVector, limit = 5, query) {
|
|
61
|
+
if (!this.table) {
|
|
62
|
+
throw new DatabaseError('Vector database not initialized');
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
return await queryOps.search(this.table, queryVector, limit, query);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const errorMsg = String(error);
|
|
69
|
+
// Detect corrupted index or missing data files
|
|
70
|
+
if (errorMsg.includes('Not found:') || errorMsg.includes('.lance')) {
|
|
71
|
+
// Attempt to reconnect - index may have been rebuilt
|
|
72
|
+
try {
|
|
73
|
+
await this.initialize();
|
|
74
|
+
if (!this.table) {
|
|
75
|
+
throw new DatabaseError('Vector database not initialized after reconnection');
|
|
76
|
+
}
|
|
77
|
+
return await queryOps.search(this.table, queryVector, limit, query);
|
|
78
|
+
}
|
|
79
|
+
catch (retryError) {
|
|
80
|
+
throw new DatabaseError(`Index appears corrupted or outdated. Please restart the MCP server or run 'lien reindex' in the project directory.`, { originalError: retryError });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async scanWithFilter(options) {
|
|
87
|
+
if (!this.table) {
|
|
88
|
+
throw new DatabaseError('Vector database not initialized');
|
|
89
|
+
}
|
|
90
|
+
return queryOps.scanWithFilter(this.table, options);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Scan all chunks in the database
|
|
94
|
+
* Fetches total count first, then retrieves all chunks in a single optimized query
|
|
95
|
+
* @param options - Filter options (language, pattern)
|
|
96
|
+
* @returns All matching chunks
|
|
97
|
+
*/
|
|
98
|
+
async scanAll(options = {}) {
|
|
99
|
+
if (!this.table) {
|
|
100
|
+
throw new DatabaseError('Vector database not initialized');
|
|
101
|
+
}
|
|
102
|
+
return queryOps.scanAll(this.table, options);
|
|
103
|
+
}
|
|
104
|
+
async querySymbols(options) {
|
|
105
|
+
if (!this.table) {
|
|
106
|
+
throw new DatabaseError('Vector database not initialized');
|
|
107
|
+
}
|
|
108
|
+
return queryOps.querySymbols(this.table, options);
|
|
109
|
+
}
|
|
110
|
+
async clear() {
|
|
111
|
+
if (!this.db) {
|
|
112
|
+
throw new DatabaseError('Vector database not initialized');
|
|
113
|
+
}
|
|
114
|
+
// Close connections first to release file handles
|
|
115
|
+
this.table = null;
|
|
116
|
+
await maintenanceOps.clear(this.db, null, this.tableName, this.dbPath);
|
|
117
|
+
}
|
|
118
|
+
async deleteByFile(filepath) {
|
|
119
|
+
if (!this.table) {
|
|
120
|
+
throw new DatabaseError('Vector database not initialized');
|
|
121
|
+
}
|
|
122
|
+
await maintenanceOps.deleteByFile(this.table, filepath);
|
|
123
|
+
}
|
|
124
|
+
async updateFile(filepath, vectors, metadatas, contents) {
|
|
125
|
+
if (!this.db) {
|
|
126
|
+
throw new DatabaseError('Vector database connection not initialized');
|
|
127
|
+
}
|
|
128
|
+
if (!this.table) {
|
|
129
|
+
throw new DatabaseError('Vector database table not initialized');
|
|
130
|
+
}
|
|
131
|
+
this.table = await maintenanceOps.updateFile(this.db, this.table, this.tableName, this.dbPath, filepath, vectors, metadatas, contents);
|
|
132
|
+
}
|
|
133
|
+
async checkVersion() {
|
|
134
|
+
const now = Date.now();
|
|
135
|
+
// Cache version checks for 1 second to minimize I/O
|
|
136
|
+
if (now - this.lastVersionCheck < 1000) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
this.lastVersionCheck = now;
|
|
140
|
+
try {
|
|
141
|
+
const version = await readVersionFile(this.dbPath);
|
|
142
|
+
if (version > this.currentVersion) {
|
|
143
|
+
this.currentVersion = version;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
// If we can't read version file, don't reconnect
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
async reconnect() {
|
|
154
|
+
try {
|
|
155
|
+
// Close existing connections to force reload from disk
|
|
156
|
+
this.table = null;
|
|
157
|
+
this.db = null;
|
|
158
|
+
// Reinitialize with fresh connection
|
|
159
|
+
await this.initialize();
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
throw wrapError(error, 'Failed to reconnect to vector database');
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
getCurrentVersion() {
|
|
166
|
+
return this.currentVersion;
|
|
167
|
+
}
|
|
168
|
+
getVersionDate() {
|
|
169
|
+
if (this.currentVersion === 0) {
|
|
170
|
+
return 'Unknown';
|
|
171
|
+
}
|
|
172
|
+
return new Date(this.currentVersion).toLocaleString();
|
|
173
|
+
}
|
|
174
|
+
async hasData() {
|
|
175
|
+
if (!this.table) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
const count = await this.table.countRows();
|
|
180
|
+
if (count === 0) {
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
// Sample a few rows to verify they contain real data
|
|
184
|
+
const sample = await this.table
|
|
185
|
+
.search(Array(EMBEDDING_DIMENSION).fill(0))
|
|
186
|
+
.limit(Math.min(count, 5))
|
|
187
|
+
.toArray();
|
|
188
|
+
const hasRealData = sample.some((r) => r.content &&
|
|
189
|
+
r.content.trim().length > 0);
|
|
190
|
+
return hasRealData;
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// If any error occurs, assume no data
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
static async load(projectRoot) {
|
|
198
|
+
const db = new VectorDB(projectRoot);
|
|
199
|
+
await db.initialize();
|
|
200
|
+
return db;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//# sourceMappingURL=lancedb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lancedb.js","sourceRoot":"","sources":["../../src/vectordb/lancedb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ChunkMetadata } from '../indexer/types.js';
|
|
2
|
+
type LanceDBConnection = any;
|
|
3
|
+
type LanceDBTable = any;
|
|
4
|
+
/**
|
|
5
|
+
* Clear all data from the vector database.
|
|
6
|
+
* Drops the table AND cleans up the .lance directory to prevent corrupted state.
|
|
7
|
+
*/
|
|
8
|
+
export declare function clear(db: LanceDBConnection, table: LanceDBTable | null, tableName: string, dbPath?: string): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Delete all chunks from a specific file
|
|
11
|
+
*/
|
|
12
|
+
export declare function deleteByFile(table: LanceDBTable, filepath: string): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Update a file in the index by atomically deleting old chunks and inserting new ones
|
|
15
|
+
*/
|
|
16
|
+
export declare function updateFile(db: LanceDBConnection, table: LanceDBTable | null, tableName: string, dbPath: string, filepath: string, vectors: Float32Array[], metadatas: ChunkMetadata[], contents: string[]): Promise<LanceDBTable>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=maintenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance.d.ts","sourceRoot":"","sources":["../../src/vectordb/maintenance.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAQpD,KAAK,iBAAiB,GAAG,GAAG,CAAC;AAC7B,KAAK,YAAY,GAAG,GAAG,CAAC;AAExB;;;GAGG;AACH,wBAAsB,KAAK,CACzB,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,iBAAiB,EACrB,KAAK,EAAE,YAAY,GAAG,IAAI,EAC1B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EAAE,EACvB,SAAS,EAAE,aAAa,EAAE,EAC1B,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,YAAY,CAAC,CAyBvB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import fs from 'fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { DatabaseError, wrapError } from '../errors/index.js';
|
|
4
|
+
import { writeVersionFile } from './version.js';
|
|
5
|
+
import { insertBatch } from './batch-insert.js';
|
|
6
|
+
/**
|
|
7
|
+
* Clear all data from the vector database.
|
|
8
|
+
* Drops the table AND cleans up the .lance directory to prevent corrupted state.
|
|
9
|
+
*/
|
|
10
|
+
export async function clear(db, table, tableName, dbPath) {
|
|
11
|
+
if (!db) {
|
|
12
|
+
throw new DatabaseError('Vector database not initialized');
|
|
13
|
+
}
|
|
14
|
+
try {
|
|
15
|
+
// Clean up the .lance directory directly
|
|
16
|
+
// This is more reliable than dropTable which can have locking issues
|
|
17
|
+
if (dbPath) {
|
|
18
|
+
const lanceDir = path.join(dbPath, `${tableName}.lance`);
|
|
19
|
+
try {
|
|
20
|
+
await fs.rm(lanceDir, { recursive: true, force: true });
|
|
21
|
+
}
|
|
22
|
+
catch (err) {
|
|
23
|
+
// If deletion fails, try dropping the table first
|
|
24
|
+
if (err?.code === 'ENOTEMPTY' || err?.message?.includes('not empty')) {
|
|
25
|
+
try {
|
|
26
|
+
await db.dropTable(tableName);
|
|
27
|
+
// Try deletion again after dropping
|
|
28
|
+
await fs.rm(lanceDir, { recursive: true, force: true });
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Ignore - best effort cleanup
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// No dbPath provided, just drop the table
|
|
38
|
+
if (table) {
|
|
39
|
+
await db.dropTable(tableName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
throw wrapError(error, 'Failed to clear vector database');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Delete all chunks from a specific file
|
|
49
|
+
*/
|
|
50
|
+
export async function deleteByFile(table, filepath) {
|
|
51
|
+
if (!table) {
|
|
52
|
+
throw new DatabaseError('Vector database not initialized');
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
await table.delete(`file = "${filepath}"`);
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw wrapError(error, 'Failed to delete file from vector database');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Update a file in the index by atomically deleting old chunks and inserting new ones
|
|
63
|
+
*/
|
|
64
|
+
export async function updateFile(db, table, tableName, dbPath, filepath, vectors, metadatas, contents) {
|
|
65
|
+
if (!table) {
|
|
66
|
+
throw new DatabaseError('Vector database not initialized');
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
// 1. Delete old chunks from this file
|
|
70
|
+
await deleteByFile(table, filepath);
|
|
71
|
+
// 2. Insert new chunks (if any)
|
|
72
|
+
let updatedTable = table;
|
|
73
|
+
if (vectors.length > 0) {
|
|
74
|
+
updatedTable = await insertBatch(db, table, tableName, vectors, metadatas, contents);
|
|
75
|
+
if (!updatedTable) {
|
|
76
|
+
throw new DatabaseError('insertBatch unexpectedly returned null');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// 3. Update version file to trigger MCP reconnection
|
|
80
|
+
await writeVersionFile(dbPath);
|
|
81
|
+
return updatedTable;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
throw wrapError(error, 'Failed to update file in vector database');
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=maintenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"maintenance.js","sourceRoot":"","sources":["../../src/vectordb/maintenance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { SearchResult } from './types.js';
|
|
2
|
+
type LanceDBTable = any;
|
|
3
|
+
/**
|
|
4
|
+
* Search the vector database
|
|
5
|
+
*/
|
|
6
|
+
export declare function search(table: LanceDBTable, queryVector: Float32Array, limit?: number, query?: string): Promise<SearchResult[]>;
|
|
7
|
+
/**
|
|
8
|
+
* Scan the database with filters
|
|
9
|
+
*/
|
|
10
|
+
export declare function scanWithFilter(table: LanceDBTable, options: {
|
|
11
|
+
language?: string;
|
|
12
|
+
pattern?: string;
|
|
13
|
+
limit?: number;
|
|
14
|
+
}): Promise<SearchResult[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Query symbols (functions, classes, interfaces)
|
|
17
|
+
*/
|
|
18
|
+
export declare function querySymbols(table: LanceDBTable, options: {
|
|
19
|
+
language?: string;
|
|
20
|
+
pattern?: string;
|
|
21
|
+
symbolType?: 'function' | 'class' | 'interface';
|
|
22
|
+
limit?: number;
|
|
23
|
+
}): Promise<SearchResult[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Scan all chunks in the database
|
|
26
|
+
* First gets the total count, then fetches all with a single query
|
|
27
|
+
* This is more efficient than pagination for local/embedded databases like LanceDB
|
|
28
|
+
*/
|
|
29
|
+
export declare function scanAll(table: LanceDBTable, options?: {
|
|
30
|
+
language?: string;
|
|
31
|
+
pattern?: string;
|
|
32
|
+
}): Promise<SearchResult[]>;
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../../src/vectordb/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAU1C,KAAK,YAAY,GAAG,GAAG,CAAC;AAiLxB;;GAEG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,YAAY,EACnB,WAAW,EAAE,YAAY,EACzB,KAAK,GAAE,MAAU,EACjB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,YAAY,EAAE,CAAC,CA+BzB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,YAAY,EAAE,CAAC,CAuCzB;AA+ED;;GAEG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,WAAW,CAAC;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,YAAY,EAAE,CAAC,CA+BzB;AAED;;;;GAIG;AACH,wBAAsB,OAAO,CAC3B,KAAK,EAAE,YAAY,EACnB,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,OAAO,CAAC,YAAY,EAAE,CAAC,CAuBzB"}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
import { EMBEDDING_DIMENSION } from '../embeddings/types.js';
|
|
2
|
+
import { DatabaseError, wrapError } from '../errors/index.js';
|
|
3
|
+
import { calculateRelevance } from './relevance.js';
|
|
4
|
+
import { classifyQueryIntent, QueryIntent } from './intent-classifier.js';
|
|
5
|
+
import { BoostingComposer, PathBoostingStrategy, FilenameBoostingStrategy, FileTypeBoostingStrategy } from './boosting/index.js';
|
|
6
|
+
/**
|
|
7
|
+
* Cached strategy instances to avoid repeated instantiation overhead.
|
|
8
|
+
* These strategies are stateless and can be safely reused across queries.
|
|
9
|
+
*/
|
|
10
|
+
const PATH_STRATEGY = new PathBoostingStrategy();
|
|
11
|
+
const FILENAME_STRATEGY = new FilenameBoostingStrategy();
|
|
12
|
+
/**
|
|
13
|
+
* Cached FileTypeBoostingStrategy instances for each intent.
|
|
14
|
+
* Since there are only three possible intents, we can cache all three.
|
|
15
|
+
*/
|
|
16
|
+
const FILE_TYPE_STRATEGIES = {
|
|
17
|
+
[QueryIntent.LOCATION]: new FileTypeBoostingStrategy(QueryIntent.LOCATION),
|
|
18
|
+
[QueryIntent.CONCEPTUAL]: new FileTypeBoostingStrategy(QueryIntent.CONCEPTUAL),
|
|
19
|
+
[QueryIntent.IMPLEMENTATION]: new FileTypeBoostingStrategy(QueryIntent.IMPLEMENTATION),
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Cached BoostingComposer instances for each intent.
|
|
23
|
+
* Pre-configured with the appropriate strategy pipeline for each intent type.
|
|
24
|
+
* This avoids creating a new composer instance on every search result.
|
|
25
|
+
*/
|
|
26
|
+
const BOOSTING_COMPOSERS = {
|
|
27
|
+
[QueryIntent.LOCATION]: new BoostingComposer()
|
|
28
|
+
.addStrategy(PATH_STRATEGY)
|
|
29
|
+
.addStrategy(FILENAME_STRATEGY)
|
|
30
|
+
.addStrategy(FILE_TYPE_STRATEGIES[QueryIntent.LOCATION]),
|
|
31
|
+
[QueryIntent.CONCEPTUAL]: new BoostingComposer()
|
|
32
|
+
.addStrategy(PATH_STRATEGY)
|
|
33
|
+
.addStrategy(FILENAME_STRATEGY)
|
|
34
|
+
.addStrategy(FILE_TYPE_STRATEGIES[QueryIntent.CONCEPTUAL]),
|
|
35
|
+
[QueryIntent.IMPLEMENTATION]: new BoostingComposer()
|
|
36
|
+
.addStrategy(PATH_STRATEGY)
|
|
37
|
+
.addStrategy(FILENAME_STRATEGY)
|
|
38
|
+
.addStrategy(FILE_TYPE_STRATEGIES[QueryIntent.IMPLEMENTATION]),
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Check if a DB record has valid content and file path.
|
|
42
|
+
* Used to filter out empty/invalid records from query results.
|
|
43
|
+
*/
|
|
44
|
+
function isValidRecord(r) {
|
|
45
|
+
return Boolean(r.content &&
|
|
46
|
+
r.content.trim().length > 0 &&
|
|
47
|
+
r.file &&
|
|
48
|
+
r.file.length > 0);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Check if an array field has valid (non-empty) entries.
|
|
52
|
+
* LanceDB stores empty arrays as [''] which we need to filter out.
|
|
53
|
+
*/
|
|
54
|
+
function hasValidArrayEntries(arr) {
|
|
55
|
+
return Boolean(arr && arr.length > 0 && arr[0] !== '');
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get symbols for a specific type from a DB record.
|
|
59
|
+
* Consolidates the symbol extraction logic used across query functions.
|
|
60
|
+
*/
|
|
61
|
+
function getSymbolsForType(r, symbolType) {
|
|
62
|
+
if (symbolType === 'function')
|
|
63
|
+
return r.functionNames || [];
|
|
64
|
+
if (symbolType === 'class')
|
|
65
|
+
return r.classNames || [];
|
|
66
|
+
if (symbolType === 'interface')
|
|
67
|
+
return r.interfaceNames || [];
|
|
68
|
+
return [
|
|
69
|
+
...(r.functionNames || []),
|
|
70
|
+
...(r.classNames || []),
|
|
71
|
+
...(r.interfaceNames || []),
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Convert a DB record to base SearchResult metadata.
|
|
76
|
+
* Shared between all query functions to avoid duplication.
|
|
77
|
+
*/
|
|
78
|
+
function buildSearchResultMetadata(r) {
|
|
79
|
+
return {
|
|
80
|
+
file: r.file,
|
|
81
|
+
startLine: r.startLine,
|
|
82
|
+
endLine: r.endLine,
|
|
83
|
+
type: r.type,
|
|
84
|
+
language: r.language,
|
|
85
|
+
symbolName: r.symbolName || undefined,
|
|
86
|
+
symbolType: r.symbolType,
|
|
87
|
+
parentClass: r.parentClass || undefined,
|
|
88
|
+
complexity: r.complexity || undefined,
|
|
89
|
+
cognitiveComplexity: r.cognitiveComplexity || undefined,
|
|
90
|
+
parameters: hasValidArrayEntries(r.parameters) ? r.parameters : undefined,
|
|
91
|
+
signature: r.signature || undefined,
|
|
92
|
+
imports: hasValidArrayEntries(r.imports) ? r.imports : undefined,
|
|
93
|
+
// Halstead metrics (v0.19.0) - use explicit null check to preserve valid 0 values
|
|
94
|
+
halsteadVolume: r.halsteadVolume != null ? r.halsteadVolume : undefined,
|
|
95
|
+
halsteadDifficulty: r.halsteadDifficulty != null ? r.halsteadDifficulty : undefined,
|
|
96
|
+
halsteadEffort: r.halsteadEffort != null ? r.halsteadEffort : undefined,
|
|
97
|
+
halsteadBugs: r.halsteadBugs != null ? r.halsteadBugs : undefined,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Apply relevance boosting strategies to a search score.
|
|
102
|
+
*
|
|
103
|
+
* Uses composable boosting strategies based on query intent:
|
|
104
|
+
* - Path matching: Boost files with query tokens in path
|
|
105
|
+
* - Filename matching: Boost files with query tokens in filename
|
|
106
|
+
* - File type boosting: Intent-specific boosting (docs for conceptual, etc.)
|
|
107
|
+
*/
|
|
108
|
+
function applyRelevanceBoosting(query, filepath, baseScore) {
|
|
109
|
+
if (!query) {
|
|
110
|
+
return baseScore;
|
|
111
|
+
}
|
|
112
|
+
const intent = classifyQueryIntent(query);
|
|
113
|
+
// Use cached composer instance configured for this intent
|
|
114
|
+
return BOOSTING_COMPOSERS[intent].apply(query, filepath, baseScore);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Convert a DBRecord to a SearchResult
|
|
118
|
+
*/
|
|
119
|
+
function dbRecordToSearchResult(r, query) {
|
|
120
|
+
const baseScore = r._distance ?? 0;
|
|
121
|
+
const boostedScore = applyRelevanceBoosting(query, r.file, baseScore);
|
|
122
|
+
return {
|
|
123
|
+
content: r.content,
|
|
124
|
+
metadata: buildSearchResultMetadata(r),
|
|
125
|
+
score: boostedScore,
|
|
126
|
+
relevance: calculateRelevance(boostedScore),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Search the vector database
|
|
131
|
+
*/
|
|
132
|
+
export async function search(table, queryVector, limit = 5, query) {
|
|
133
|
+
if (!table) {
|
|
134
|
+
throw new DatabaseError('Vector database not initialized');
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const results = await table
|
|
138
|
+
.search(Array.from(queryVector))
|
|
139
|
+
.limit(limit + 20)
|
|
140
|
+
.toArray();
|
|
141
|
+
const filtered = results
|
|
142
|
+
.filter(isValidRecord)
|
|
143
|
+
.map((r) => dbRecordToSearchResult(r, query))
|
|
144
|
+
.sort((a, b) => a.score - b.score)
|
|
145
|
+
.slice(0, limit);
|
|
146
|
+
return filtered;
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
const errorMsg = String(error);
|
|
150
|
+
// Detect corrupted index
|
|
151
|
+
if (errorMsg.includes('Not found:') || errorMsg.includes('.lance')) {
|
|
152
|
+
throw new DatabaseError(`Index appears corrupted or outdated. Please restart the MCP server or run 'lien reindex' in the project directory.`, { originalError: error });
|
|
153
|
+
}
|
|
154
|
+
throw wrapError(error, 'Failed to search vector database');
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Scan the database with filters
|
|
159
|
+
*/
|
|
160
|
+
export async function scanWithFilter(table, options) {
|
|
161
|
+
if (!table) {
|
|
162
|
+
throw new DatabaseError('Vector database not initialized');
|
|
163
|
+
}
|
|
164
|
+
const { language, pattern, limit = 100 } = options;
|
|
165
|
+
try {
|
|
166
|
+
const zeroVector = Array(EMBEDDING_DIMENSION).fill(0);
|
|
167
|
+
const query = table.search(zeroVector)
|
|
168
|
+
.where('file != ""')
|
|
169
|
+
.limit(Math.max(limit * 5, 200));
|
|
170
|
+
const results = await query.toArray();
|
|
171
|
+
let filtered = results.filter(isValidRecord);
|
|
172
|
+
if (language) {
|
|
173
|
+
filtered = filtered.filter((r) => r.language && r.language.toLowerCase() === language.toLowerCase());
|
|
174
|
+
}
|
|
175
|
+
if (pattern) {
|
|
176
|
+
const regex = new RegExp(pattern, 'i');
|
|
177
|
+
filtered = filtered.filter((r) => regex.test(r.content) || regex.test(r.file));
|
|
178
|
+
}
|
|
179
|
+
return filtered.slice(0, limit).map((r) => ({
|
|
180
|
+
content: r.content,
|
|
181
|
+
metadata: buildSearchResultMetadata(r),
|
|
182
|
+
score: 0,
|
|
183
|
+
relevance: calculateRelevance(0),
|
|
184
|
+
}));
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
throw wrapError(error, 'Failed to scan with filter');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Helper to check if a record matches the requested symbol type
|
|
192
|
+
*/
|
|
193
|
+
/** Maps query symbolType to acceptable AST symbolType values */
|
|
194
|
+
const SYMBOL_TYPE_MATCHES = {
|
|
195
|
+
function: new Set(['function', 'method']),
|
|
196
|
+
class: new Set(['class']),
|
|
197
|
+
interface: new Set(['interface']),
|
|
198
|
+
};
|
|
199
|
+
function matchesSymbolType(record, symbolType, symbols) {
|
|
200
|
+
// If AST-based symbolType exists, use lookup table
|
|
201
|
+
if (record.symbolType) {
|
|
202
|
+
return SYMBOL_TYPE_MATCHES[symbolType]?.has(record.symbolType) ?? false;
|
|
203
|
+
}
|
|
204
|
+
// Fallback: check if pre-AST symbols array has valid entries
|
|
205
|
+
return symbols.length > 0 && symbols.some((s) => s.length > 0 && s !== '');
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Check if a record matches the symbol query filters.
|
|
209
|
+
* Extracted to reduce complexity of querySymbols.
|
|
210
|
+
*/
|
|
211
|
+
function matchesSymbolFilter(r, { language, pattern, symbolType }) {
|
|
212
|
+
// Language filter
|
|
213
|
+
if (language && (!r.language || r.language.toLowerCase() !== language.toLowerCase())) {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const symbols = getSymbolsForType(r, symbolType);
|
|
217
|
+
const astSymbolName = r.symbolName || '';
|
|
218
|
+
// Must have at least one symbol (legacy or AST-based)
|
|
219
|
+
if (symbols.length === 0 && !astSymbolName) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
// Pattern filter (if provided)
|
|
223
|
+
if (pattern) {
|
|
224
|
+
const regex = new RegExp(pattern, 'i');
|
|
225
|
+
const nameMatches = symbols.some((s) => regex.test(s)) || regex.test(astSymbolName);
|
|
226
|
+
if (!nameMatches)
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
// Symbol type filter (if provided)
|
|
230
|
+
if (symbolType) {
|
|
231
|
+
return matchesSymbolType(r, symbolType, symbols);
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Build legacy symbols object for backwards compatibility.
|
|
237
|
+
*/
|
|
238
|
+
function buildLegacySymbols(r) {
|
|
239
|
+
return {
|
|
240
|
+
functions: hasValidArrayEntries(r.functionNames) ? r.functionNames : [],
|
|
241
|
+
classes: hasValidArrayEntries(r.classNames) ? r.classNames : [],
|
|
242
|
+
interfaces: hasValidArrayEntries(r.interfaceNames) ? r.interfaceNames : [],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Query symbols (functions, classes, interfaces)
|
|
247
|
+
*/
|
|
248
|
+
export async function querySymbols(table, options) {
|
|
249
|
+
if (!table) {
|
|
250
|
+
throw new DatabaseError('Vector database not initialized');
|
|
251
|
+
}
|
|
252
|
+
const { language, pattern, symbolType, limit = 50 } = options;
|
|
253
|
+
const filterOpts = { language, pattern, symbolType };
|
|
254
|
+
try {
|
|
255
|
+
const zeroVector = Array(EMBEDDING_DIMENSION).fill(0);
|
|
256
|
+
const query = table.search(zeroVector)
|
|
257
|
+
.where('file != ""')
|
|
258
|
+
.limit(Math.max(limit * 10, 500));
|
|
259
|
+
const results = await query.toArray();
|
|
260
|
+
const filtered = results
|
|
261
|
+
.filter((r) => isValidRecord(r) && matchesSymbolFilter(r, filterOpts));
|
|
262
|
+
return filtered.slice(0, limit).map((r) => ({
|
|
263
|
+
content: r.content,
|
|
264
|
+
metadata: {
|
|
265
|
+
...buildSearchResultMetadata(r),
|
|
266
|
+
symbols: buildLegacySymbols(r),
|
|
267
|
+
},
|
|
268
|
+
score: 0,
|
|
269
|
+
relevance: calculateRelevance(0),
|
|
270
|
+
}));
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
throw wrapError(error, 'Failed to query symbols');
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Scan all chunks in the database
|
|
278
|
+
* First gets the total count, then fetches all with a single query
|
|
279
|
+
* This is more efficient than pagination for local/embedded databases like LanceDB
|
|
280
|
+
*/
|
|
281
|
+
export async function scanAll(table, options = {}) {
|
|
282
|
+
if (!table) {
|
|
283
|
+
throw new DatabaseError('Vector database not initialized');
|
|
284
|
+
}
|
|
285
|
+
try {
|
|
286
|
+
// Get total row count to determine limit
|
|
287
|
+
const totalRows = await table.countRows();
|
|
288
|
+
// Fetch all rows in one query (LanceDB is local, this is efficient)
|
|
289
|
+
// Note: scanWithFilter internally fetches 5x the limit to handle filtering overhead,
|
|
290
|
+
// then caps output to 'limit'. We pass totalRows so we get all rows back after
|
|
291
|
+
// filtering. The 5x overfetch is acceptable overhead for local DBs.
|
|
292
|
+
const MIN_SCAN_LIMIT = 1000;
|
|
293
|
+
const results = await scanWithFilter(table, {
|
|
294
|
+
...options,
|
|
295
|
+
limit: Math.max(totalRows, MIN_SCAN_LIMIT),
|
|
296
|
+
});
|
|
297
|
+
return results;
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
throw wrapError(error, 'Failed to scan all chunks');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
//# sourceMappingURL=query.js.map
|