@mduenas/codegraph 0.4.0
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/LICENSE +21 -0
- package/README.md +641 -0
- package/dist/bin/codegraph.d.ts +20 -0
- package/dist/bin/codegraph.d.ts.map +1 -0
- package/dist/bin/codegraph.js +704 -0
- package/dist/bin/codegraph.js.map +1 -0
- package/dist/config.d.ts +51 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +291 -0
- package/dist/config.js.map +1 -0
- package/dist/context/formatter.d.ts +30 -0
- package/dist/context/formatter.d.ts.map +1 -0
- package/dist/context/formatter.js +244 -0
- package/dist/context/formatter.js.map +1 -0
- package/dist/context/index.d.ts +86 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +402 -0
- package/dist/context/index.js.map +1 -0
- package/dist/db/index.d.ts +64 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +170 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrations.d.ts +44 -0
- package/dist/db/migrations.d.ts.map +1 -0
- package/dist/db/migrations.js +105 -0
- package/dist/db/migrations.js.map +1 -0
- package/dist/db/queries.d.ts +148 -0
- package/dist/db/queries.d.ts.map +1 -0
- package/dist/db/queries.js +669 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/directory.d.ts +45 -0
- package/dist/directory.d.ts.map +1 -0
- package/dist/directory.js +191 -0
- package/dist/directory.js.map +1 -0
- package/dist/errors.d.ts +136 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +219 -0
- package/dist/errors.js.map +1 -0
- package/dist/extraction/grammars.d.ts +36 -0
- package/dist/extraction/grammars.d.ts.map +1 -0
- package/dist/extraction/grammars.js +181 -0
- package/dist/extraction/grammars.js.map +1 -0
- package/dist/extraction/index.d.ts +91 -0
- package/dist/extraction/index.d.ts.map +1 -0
- package/dist/extraction/index.js +493 -0
- package/dist/extraction/index.js.map +1 -0
- package/dist/extraction/tree-sitter.d.ts +176 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -0
- package/dist/extraction/tree-sitter.js +1798 -0
- package/dist/extraction/tree-sitter.js.map +1 -0
- package/dist/graph/index.d.ts +8 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +13 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/queries.d.ts +106 -0
- package/dist/graph/queries.d.ts.map +1 -0
- package/dist/graph/queries.js +355 -0
- package/dist/graph/queries.js.map +1 -0
- package/dist/graph/traversal.d.ts +127 -0
- package/dist/graph/traversal.d.ts.map +1 -0
- package/dist/graph/traversal.js +465 -0
- package/dist/graph/traversal.js.map +1 -0
- package/dist/index.d.ts +496 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +818 -0
- package/dist/index.js.map +1 -0
- package/dist/installer/banner.d.ts +40 -0
- package/dist/installer/banner.d.ts.map +1 -0
- package/dist/installer/banner.js +162 -0
- package/dist/installer/banner.js.map +1 -0
- package/dist/installer/claude-md-template.d.ts +10 -0
- package/dist/installer/claude-md-template.d.ts.map +1 -0
- package/dist/installer/claude-md-template.js +46 -0
- package/dist/installer/claude-md-template.js.map +1 -0
- package/dist/installer/config-writer.d.ts +36 -0
- package/dist/installer/config-writer.d.ts.map +1 -0
- package/dist/installer/config-writer.js +282 -0
- package/dist/installer/config-writer.js.map +1 -0
- package/dist/installer/index.d.ts +13 -0
- package/dist/installer/index.d.ts.map +1 -0
- package/dist/installer/index.js +155 -0
- package/dist/installer/index.js.map +1 -0
- package/dist/installer/prompts.d.ts +18 -0
- package/dist/installer/prompts.d.ts.map +1 -0
- package/dist/installer/prompts.js +113 -0
- package/dist/installer/prompts.js.map +1 -0
- package/dist/mcp/index.d.ts +64 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +207 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/tools.d.ts +93 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +442 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/mcp/transport.d.ts +89 -0
- package/dist/mcp/transport.d.ts.map +1 -0
- package/dist/mcp/transport.js +170 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/resolution/frameworks/csharp.d.ts +8 -0
- package/dist/resolution/frameworks/csharp.d.ts.map +1 -0
- package/dist/resolution/frameworks/csharp.js +274 -0
- package/dist/resolution/frameworks/csharp.js.map +1 -0
- package/dist/resolution/frameworks/express.d.ts +8 -0
- package/dist/resolution/frameworks/express.d.ts.map +1 -0
- package/dist/resolution/frameworks/express.js +208 -0
- package/dist/resolution/frameworks/express.js.map +1 -0
- package/dist/resolution/frameworks/go.d.ts +8 -0
- package/dist/resolution/frameworks/go.d.ts.map +1 -0
- package/dist/resolution/frameworks/go.js +225 -0
- package/dist/resolution/frameworks/go.js.map +1 -0
- package/dist/resolution/frameworks/index.d.ts +33 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -0
- package/dist/resolution/frameworks/index.js +113 -0
- package/dist/resolution/frameworks/index.js.map +1 -0
- package/dist/resolution/frameworks/java.d.ts +8 -0
- package/dist/resolution/frameworks/java.d.ts.map +1 -0
- package/dist/resolution/frameworks/java.js +239 -0
- package/dist/resolution/frameworks/java.js.map +1 -0
- package/dist/resolution/frameworks/laravel.d.ts +13 -0
- package/dist/resolution/frameworks/laravel.d.ts.map +1 -0
- package/dist/resolution/frameworks/laravel.js +198 -0
- package/dist/resolution/frameworks/laravel.js.map +1 -0
- package/dist/resolution/frameworks/python.d.ts +10 -0
- package/dist/resolution/frameworks/python.d.ts.map +1 -0
- package/dist/resolution/frameworks/python.js +331 -0
- package/dist/resolution/frameworks/python.js.map +1 -0
- package/dist/resolution/frameworks/react.d.ts +8 -0
- package/dist/resolution/frameworks/react.d.ts.map +1 -0
- package/dist/resolution/frameworks/react.js +294 -0
- package/dist/resolution/frameworks/react.js.map +1 -0
- package/dist/resolution/frameworks/ruby.d.ts +8 -0
- package/dist/resolution/frameworks/ruby.d.ts.map +1 -0
- package/dist/resolution/frameworks/ruby.js +262 -0
- package/dist/resolution/frameworks/ruby.js.map +1 -0
- package/dist/resolution/frameworks/rust.d.ts +8 -0
- package/dist/resolution/frameworks/rust.d.ts.map +1 -0
- package/dist/resolution/frameworks/rust.js +222 -0
- package/dist/resolution/frameworks/rust.js.map +1 -0
- package/dist/resolution/frameworks/swift.d.ts +10 -0
- package/dist/resolution/frameworks/swift.d.ts.map +1 -0
- package/dist/resolution/frameworks/swift.js +486 -0
- package/dist/resolution/frameworks/swift.js.map +1 -0
- package/dist/resolution/import-resolver.d.ts +20 -0
- package/dist/resolution/import-resolver.d.ts.map +1 -0
- package/dist/resolution/import-resolver.js +445 -0
- package/dist/resolution/import-resolver.js.map +1 -0
- package/dist/resolution/index.d.ts +72 -0
- package/dist/resolution/index.d.ts.map +1 -0
- package/dist/resolution/index.js +301 -0
- package/dist/resolution/index.js.map +1 -0
- package/dist/resolution/name-matcher.d.ts +27 -0
- package/dist/resolution/name-matcher.d.ts.map +1 -0
- package/dist/resolution/name-matcher.js +210 -0
- package/dist/resolution/name-matcher.js.map +1 -0
- package/dist/resolution/types.d.ts +108 -0
- package/dist/resolution/types.d.ts.map +1 -0
- package/dist/resolution/types.js +8 -0
- package/dist/resolution/types.js.map +1 -0
- package/dist/sync/git-hooks.d.ts +66 -0
- package/dist/sync/git-hooks.d.ts.map +1 -0
- package/dist/sync/git-hooks.js +281 -0
- package/dist/sync/git-hooks.js.map +1 -0
- package/dist/sync/index.d.ts +13 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +18 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/types.d.ts +410 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +165 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +116 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +295 -0
- package/dist/utils.js.map +1 -0
- package/dist/vectors/embedder.d.ts +140 -0
- package/dist/vectors/embedder.d.ts.map +1 -0
- package/dist/vectors/embedder.js +336 -0
- package/dist/vectors/embedder.js.map +1 -0
- package/dist/vectors/index.d.ts +9 -0
- package/dist/vectors/index.d.ts.map +1 -0
- package/dist/vectors/index.js +20 -0
- package/dist/vectors/index.js.map +1 -0
- package/dist/vectors/manager.d.ts +119 -0
- package/dist/vectors/manager.d.ts.map +1 -0
- package/dist/vectors/manager.js +274 -0
- package/dist/vectors/manager.js.map +1 -0
- package/dist/vectors/search.d.ts +134 -0
- package/dist/vectors/search.d.ts.map +1 -0
- package/dist/vectors/search.js +409 -0
- package/dist/vectors/search.js.map +1 -0
- package/package.json +67 -0
- package/scripts/postinstall.js +68 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Vector Manager
|
|
4
|
+
*
|
|
5
|
+
* High-level manager that coordinates embedding generation and vector search.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.VectorManager = void 0;
|
|
9
|
+
exports.createVectorManager = createVectorManager;
|
|
10
|
+
const embedder_1 = require("./embedder");
|
|
11
|
+
const search_1 = require("./search");
|
|
12
|
+
/**
|
|
13
|
+
* Default node kinds to embed
|
|
14
|
+
*/
|
|
15
|
+
const DEFAULT_NODE_KINDS = [
|
|
16
|
+
'function',
|
|
17
|
+
'method',
|
|
18
|
+
'class',
|
|
19
|
+
'interface',
|
|
20
|
+
'type_alias',
|
|
21
|
+
'module',
|
|
22
|
+
'component',
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Vector Manager
|
|
26
|
+
*
|
|
27
|
+
* Provides high-level interface for semantic search:
|
|
28
|
+
* - Generates embeddings for code nodes
|
|
29
|
+
* - Stores embeddings in the database
|
|
30
|
+
* - Performs semantic similarity search
|
|
31
|
+
*/
|
|
32
|
+
class VectorManager {
|
|
33
|
+
embedder;
|
|
34
|
+
searchManager;
|
|
35
|
+
queries;
|
|
36
|
+
nodeKinds;
|
|
37
|
+
batchSize;
|
|
38
|
+
initialized = false;
|
|
39
|
+
constructor(db, queries, options = {}) {
|
|
40
|
+
this.embedder = (0, embedder_1.createEmbedder)(options.embedder);
|
|
41
|
+
this.searchManager = (0, search_1.createVectorSearch)(db, embedder_1.EMBEDDING_DIMENSION);
|
|
42
|
+
this.queries = queries;
|
|
43
|
+
this.nodeKinds = options.nodeKinds || DEFAULT_NODE_KINDS;
|
|
44
|
+
this.batchSize = options.batchSize || 32;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Initialize the vector manager
|
|
48
|
+
*
|
|
49
|
+
* Loads the embedding model and initializes vector search.
|
|
50
|
+
*/
|
|
51
|
+
async initialize() {
|
|
52
|
+
if (this.initialized) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Initialize embedder (downloads model if needed)
|
|
56
|
+
await this.embedder.initialize();
|
|
57
|
+
// Initialize vector search (loads sqlite-vss if available)
|
|
58
|
+
await this.searchManager.initialize();
|
|
59
|
+
this.initialized = true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if the vector manager is initialized
|
|
63
|
+
*/
|
|
64
|
+
isInitialized() {
|
|
65
|
+
return this.initialized;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Generate embeddings for all eligible nodes
|
|
69
|
+
*
|
|
70
|
+
* @param onProgress - Optional progress callback
|
|
71
|
+
* @returns Number of nodes embedded
|
|
72
|
+
*/
|
|
73
|
+
async embedAllNodes(onProgress) {
|
|
74
|
+
if (!this.initialized) {
|
|
75
|
+
throw new Error('VectorManager not initialized. Call initialize() first.');
|
|
76
|
+
}
|
|
77
|
+
// Get all nodes that should be embedded
|
|
78
|
+
const nodesToEmbed = [];
|
|
79
|
+
for (const kind of this.nodeKinds) {
|
|
80
|
+
const nodes = this.queries.getNodesByKind(kind);
|
|
81
|
+
nodesToEmbed.push(...nodes);
|
|
82
|
+
}
|
|
83
|
+
// Filter out nodes that already have embeddings
|
|
84
|
+
const existingIds = new Set(this.searchManager.getIndexedNodeIds());
|
|
85
|
+
const newNodes = nodesToEmbed.filter((n) => !existingIds.has(n.id));
|
|
86
|
+
if (newNodes.length === 0) {
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
// Process in batches
|
|
90
|
+
let processed = 0;
|
|
91
|
+
const model = this.embedder.getModelId();
|
|
92
|
+
for (let i = 0; i < newNodes.length; i += this.batchSize) {
|
|
93
|
+
const batch = newNodes.slice(i, i + this.batchSize);
|
|
94
|
+
// Create text representations
|
|
95
|
+
const texts = batch.map((node) => embedder_1.TextEmbedder.createNodeText(node));
|
|
96
|
+
// Generate embeddings
|
|
97
|
+
const result = await this.embedder.embedBatch(texts, 'document');
|
|
98
|
+
// Store embeddings
|
|
99
|
+
const entries = [];
|
|
100
|
+
for (let idx = 0; idx < batch.length; idx++) {
|
|
101
|
+
const node = batch[idx];
|
|
102
|
+
const embedding = result.embeddings[idx];
|
|
103
|
+
if (node && embedding) {
|
|
104
|
+
entries.push({ nodeId: node.id, embedding });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
this.searchManager.storeVectorBatch(entries, model);
|
|
108
|
+
processed += batch.length;
|
|
109
|
+
// Report progress
|
|
110
|
+
if (onProgress) {
|
|
111
|
+
onProgress({
|
|
112
|
+
current: processed,
|
|
113
|
+
total: newNodes.length,
|
|
114
|
+
nodeName: batch[batch.length - 1]?.name,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return processed;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Generate embedding for a single node
|
|
122
|
+
*
|
|
123
|
+
* @param node - Node to embed
|
|
124
|
+
*/
|
|
125
|
+
async embedNode(node) {
|
|
126
|
+
if (!this.initialized) {
|
|
127
|
+
throw new Error('VectorManager not initialized. Call initialize() first.');
|
|
128
|
+
}
|
|
129
|
+
const text = embedder_1.TextEmbedder.createNodeText(node);
|
|
130
|
+
const result = await this.embedder.embed(text);
|
|
131
|
+
this.searchManager.storeVector(node.id, result.embedding, result.model);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Semantic search for nodes matching a query
|
|
135
|
+
*
|
|
136
|
+
* @param query - Natural language query
|
|
137
|
+
* @param options - Search options
|
|
138
|
+
* @returns Array of search results with similarity scores
|
|
139
|
+
*/
|
|
140
|
+
async search(query, options = {}) {
|
|
141
|
+
if (!this.initialized) {
|
|
142
|
+
throw new Error('VectorManager not initialized. Call initialize() first.');
|
|
143
|
+
}
|
|
144
|
+
const { limit = 10, kinds } = options;
|
|
145
|
+
// Generate query embedding
|
|
146
|
+
const queryResult = await this.embedder.embedQuery(query);
|
|
147
|
+
// Search for similar vectors
|
|
148
|
+
const vectorResults = this.searchManager.search(queryResult.embedding, {
|
|
149
|
+
limit: limit * 2, // Get more results to filter
|
|
150
|
+
minScore: 0.3, // Minimum similarity threshold
|
|
151
|
+
});
|
|
152
|
+
// Get nodes and filter by kind if specified
|
|
153
|
+
const results = [];
|
|
154
|
+
for (const vr of vectorResults) {
|
|
155
|
+
const node = this.queries.getNodeById(vr.nodeId);
|
|
156
|
+
if (!node) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
// Filter by node kind if specified
|
|
160
|
+
if (kinds && kinds.length > 0 && !kinds.includes(node.kind)) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
results.push({
|
|
164
|
+
node,
|
|
165
|
+
score: vr.score,
|
|
166
|
+
});
|
|
167
|
+
if (results.length >= limit) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return results;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Find nodes similar to a given node
|
|
175
|
+
*
|
|
176
|
+
* @param nodeId - ID of the node to find similar nodes for
|
|
177
|
+
* @param options - Search options
|
|
178
|
+
* @returns Array of similar nodes with similarity scores
|
|
179
|
+
*/
|
|
180
|
+
async findSimilar(nodeId, options = {}) {
|
|
181
|
+
if (!this.initialized) {
|
|
182
|
+
throw new Error('VectorManager not initialized. Call initialize() first.');
|
|
183
|
+
}
|
|
184
|
+
const { limit = 10, kinds } = options;
|
|
185
|
+
// Get the node's embedding
|
|
186
|
+
let embedding = this.searchManager.getVector(nodeId);
|
|
187
|
+
// If no embedding exists, generate one
|
|
188
|
+
if (!embedding) {
|
|
189
|
+
const node = this.queries.getNodeById(nodeId);
|
|
190
|
+
if (!node) {
|
|
191
|
+
throw new Error(`Node not found: ${nodeId}`);
|
|
192
|
+
}
|
|
193
|
+
await this.embedNode(node);
|
|
194
|
+
embedding = this.searchManager.getVector(nodeId);
|
|
195
|
+
if (!embedding) {
|
|
196
|
+
throw new Error(`Failed to generate embedding for node: ${nodeId}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Search for similar vectors (excluding the source node)
|
|
200
|
+
const vectorResults = this.searchManager.search(embedding, {
|
|
201
|
+
limit: limit + 1, // Get one extra to exclude the source
|
|
202
|
+
minScore: 0.3,
|
|
203
|
+
});
|
|
204
|
+
// Get nodes and filter
|
|
205
|
+
const results = [];
|
|
206
|
+
for (const vr of vectorResults) {
|
|
207
|
+
// Skip the source node
|
|
208
|
+
if (vr.nodeId === nodeId) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
const node = this.queries.getNodeById(vr.nodeId);
|
|
212
|
+
if (!node) {
|
|
213
|
+
continue;
|
|
214
|
+
}
|
|
215
|
+
// Filter by node kind if specified
|
|
216
|
+
if (kinds && kinds.length > 0 && !kinds.includes(node.kind)) {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
results.push({
|
|
220
|
+
node,
|
|
221
|
+
score: vr.score,
|
|
222
|
+
});
|
|
223
|
+
if (results.length >= limit) {
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return results;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Delete embedding for a node
|
|
231
|
+
*
|
|
232
|
+
* @param nodeId - ID of the node
|
|
233
|
+
*/
|
|
234
|
+
deleteNodeEmbedding(nodeId) {
|
|
235
|
+
this.searchManager.deleteVector(nodeId);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Get statistics about vector storage
|
|
239
|
+
*/
|
|
240
|
+
getStats() {
|
|
241
|
+
return {
|
|
242
|
+
totalVectors: this.searchManager.getVectorCount(),
|
|
243
|
+
vssEnabled: this.searchManager.isVssEnabled(),
|
|
244
|
+
modelId: this.embedder.getModelId(),
|
|
245
|
+
dimension: this.embedder.getDimension(),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Clear all vectors
|
|
250
|
+
*/
|
|
251
|
+
clear() {
|
|
252
|
+
this.searchManager.clear();
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Rebuild the VSS index
|
|
256
|
+
*/
|
|
257
|
+
rebuildIndex() {
|
|
258
|
+
this.searchManager.rebuildVssIndex();
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Release resources
|
|
262
|
+
*/
|
|
263
|
+
dispose() {
|
|
264
|
+
this.embedder.dispose();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
exports.VectorManager = VectorManager;
|
|
268
|
+
/**
|
|
269
|
+
* Create a vector manager
|
|
270
|
+
*/
|
|
271
|
+
function createVectorManager(db, queries, options) {
|
|
272
|
+
return new VectorManager(db, queries, options);
|
|
273
|
+
}
|
|
274
|
+
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/vectors/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vector Search
|
|
3
|
+
*
|
|
4
|
+
* Provides vector similarity search using sqlite-vss extension.
|
|
5
|
+
* Falls back to brute-force cosine similarity if sqlite-vss is not available.
|
|
6
|
+
*/
|
|
7
|
+
import Database from 'better-sqlite3';
|
|
8
|
+
import { Node } from '../types';
|
|
9
|
+
/**
|
|
10
|
+
* Options for vector search
|
|
11
|
+
*/
|
|
12
|
+
export interface VectorSearchOptions {
|
|
13
|
+
/** Maximum number of results to return */
|
|
14
|
+
limit?: number;
|
|
15
|
+
/** Minimum similarity score (0-1) */
|
|
16
|
+
minScore?: number;
|
|
17
|
+
/** Node kinds to filter results */
|
|
18
|
+
nodeKinds?: Node['kind'][];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Vector Search Manager
|
|
22
|
+
*
|
|
23
|
+
* Handles vector storage and similarity search for semantic code search.
|
|
24
|
+
*/
|
|
25
|
+
export declare class VectorSearchManager {
|
|
26
|
+
private db;
|
|
27
|
+
private vssEnabled;
|
|
28
|
+
private embeddingDimension;
|
|
29
|
+
constructor(db: Database.Database, dimension?: number);
|
|
30
|
+
/**
|
|
31
|
+
* Initialize vector search
|
|
32
|
+
*
|
|
33
|
+
* Attempts to load sqlite-vss extension. Falls back to brute-force
|
|
34
|
+
* search if the extension is not available.
|
|
35
|
+
*/
|
|
36
|
+
initialize(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Load the sqlite-vss extension
|
|
39
|
+
*/
|
|
40
|
+
private loadVssExtension;
|
|
41
|
+
/**
|
|
42
|
+
* Create the VSS virtual table for vector search
|
|
43
|
+
*/
|
|
44
|
+
private createVssTable;
|
|
45
|
+
/**
|
|
46
|
+
* Ensure the basic vectors table exists (for fallback mode)
|
|
47
|
+
*/
|
|
48
|
+
private ensureVectorsTable;
|
|
49
|
+
/**
|
|
50
|
+
* Check if VSS extension is enabled
|
|
51
|
+
*/
|
|
52
|
+
isVssEnabled(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Store a vector embedding for a node
|
|
55
|
+
*
|
|
56
|
+
* @param nodeId - ID of the node
|
|
57
|
+
* @param embedding - Vector embedding
|
|
58
|
+
* @param model - Model used to generate embedding
|
|
59
|
+
*/
|
|
60
|
+
storeVector(nodeId: string, embedding: Float32Array, model: string): void;
|
|
61
|
+
/**
|
|
62
|
+
* Store vector in VSS virtual table
|
|
63
|
+
*/
|
|
64
|
+
private storeInVss;
|
|
65
|
+
/**
|
|
66
|
+
* Store multiple vectors in a batch
|
|
67
|
+
*
|
|
68
|
+
* @param entries - Array of node IDs and embeddings
|
|
69
|
+
* @param model - Model used to generate embeddings
|
|
70
|
+
*/
|
|
71
|
+
storeVectorBatch(entries: Array<{
|
|
72
|
+
nodeId: string;
|
|
73
|
+
embedding: Float32Array;
|
|
74
|
+
}>, model: string): void;
|
|
75
|
+
/**
|
|
76
|
+
* Get vector for a node
|
|
77
|
+
*
|
|
78
|
+
* @param nodeId - ID of the node
|
|
79
|
+
* @returns Embedding or null if not found
|
|
80
|
+
*/
|
|
81
|
+
getVector(nodeId: string): Float32Array | null;
|
|
82
|
+
/**
|
|
83
|
+
* Delete vector for a node
|
|
84
|
+
*
|
|
85
|
+
* @param nodeId - ID of the node
|
|
86
|
+
*/
|
|
87
|
+
deleteVector(nodeId: string): void;
|
|
88
|
+
/**
|
|
89
|
+
* Search for similar vectors
|
|
90
|
+
*
|
|
91
|
+
* @param queryEmbedding - Query vector to search for
|
|
92
|
+
* @param options - Search options
|
|
93
|
+
* @returns Array of node IDs with similarity scores
|
|
94
|
+
*/
|
|
95
|
+
search(queryEmbedding: Float32Array, options?: VectorSearchOptions): Array<{
|
|
96
|
+
nodeId: string;
|
|
97
|
+
score: number;
|
|
98
|
+
}>;
|
|
99
|
+
/**
|
|
100
|
+
* Search using sqlite-vss KNN search
|
|
101
|
+
*/
|
|
102
|
+
private searchWithVss;
|
|
103
|
+
/**
|
|
104
|
+
* Brute-force search using cosine similarity
|
|
105
|
+
*/
|
|
106
|
+
private searchBruteForce;
|
|
107
|
+
/**
|
|
108
|
+
* Get count of stored vectors
|
|
109
|
+
*/
|
|
110
|
+
getVectorCount(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Check if a node has a vector
|
|
113
|
+
*/
|
|
114
|
+
hasVector(nodeId: string): boolean;
|
|
115
|
+
/**
|
|
116
|
+
* Get all node IDs that have vectors
|
|
117
|
+
*/
|
|
118
|
+
getIndexedNodeIds(): string[];
|
|
119
|
+
/**
|
|
120
|
+
* Clear all vectors
|
|
121
|
+
*/
|
|
122
|
+
clear(): void;
|
|
123
|
+
/**
|
|
124
|
+
* Rebuild VSS index from vectors table
|
|
125
|
+
*
|
|
126
|
+
* Useful after bulk operations or if VSS index gets out of sync.
|
|
127
|
+
*/
|
|
128
|
+
rebuildVssIndex(): void;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create a vector search manager
|
|
132
|
+
*/
|
|
133
|
+
export declare function createVectorSearch(db: Database.Database, dimension?: number): VectorSearchManager;
|
|
134
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/vectors/search.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGhC;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,0CAA0C;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,mCAAmC;IACnC,SAAS,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,EAAE,CAAoB;IAC9B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,kBAAkB,CAAS;gBAEvB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,GAAE,MAA4B;IAK1E;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAsBjC;;OAEG;YACW,gBAAgB;IAkB9B;;OAEG;IACH,OAAO,CAAC,cAAc;IA8BtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAW1B;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;;;;;OAMG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAoBzE;;OAEG;IACH,OAAO,CAAC,UAAU;IAwClB;;;;;OAKG;IACH,gBAAgB,CACd,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,YAAY,CAAA;KAAE,CAAC,EAC3D,KAAK,EAAE,MAAM,GACZ,IAAI;IAuBP;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAe9C;;;;OAIG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgBlC;;;;;;OAMG;IACH,MAAM,CACJ,cAAc,EAAE,YAAY,EAC5B,OAAO,GAAE,mBAAwB,GAChC,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAU3C;;OAEG;IACH,OAAO,CAAC,aAAa;IA4CrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,cAAc,IAAI,MAAM;IAOxB;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAOlC;;OAEG;IACH,iBAAiB,IAAI,MAAM,EAAE;IAO7B;;OAEG;IACH,KAAK,IAAI,IAAI;IASb;;;;OAIG;IACH,eAAe,IAAI,IAAI;CAwBxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,CAAC,EAAE,MAAM,GACjB,mBAAmB,CAErB"}
|