@esankhan3/code-search-mcp 0.0.2 → 0.2.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.
Files changed (50) hide show
  1. package/README.md +343 -248
  2. package/dist/__tests__/config-resolver.test.js +153 -0
  3. package/dist/__tests__/daemon-rpc.test.js +100 -0
  4. package/dist/__tests__/observability.test.js +69 -0
  5. package/dist/__tests__/projects.test.js +141 -0
  6. package/dist/backends/daemon-client.js +87 -0
  7. package/dist/backends/in-process.js +104 -0
  8. package/dist/backends/index.js +29 -0
  9. package/dist/cli/index.js +231 -0
  10. package/dist/core/config.js +362 -49
  11. package/dist/core/env-config.js +45 -43
  12. package/dist/daemon/index.js +119 -0
  13. package/dist/daemon/rpc-server.js +99 -0
  14. package/dist/daemon/watcher.js +105 -0
  15. package/dist/index.js +7 -0
  16. package/dist/observability/logger.js +66 -0
  17. package/dist/observability/metrics.js +138 -0
  18. package/dist/projects/registry.js +146 -0
  19. package/dist/resources/resources.js +3 -3
  20. package/dist/server.js +6 -2
  21. package/dist/tools/graph.js +1 -1
  22. package/dist/tools/index-tools.js +1 -1
  23. package/dist/tools/profile.js +2 -2
  24. package/dist/tools/search.js +1 -1
  25. package/dist/transports/http-transport.js +38 -0
  26. package/package.json +31 -12
  27. package/scripts/smoke/run-smoke.sh +167 -0
  28. package/dist/core/ast-graph-builder.js +0 -800
  29. package/dist/core/chunker.js +0 -368
  30. package/dist/core/claude-runner.js +0 -173
  31. package/dist/core/cross-repo-detector.js +0 -887
  32. package/dist/core/embedder.js +0 -334
  33. package/dist/core/file-walker.js +0 -186
  34. package/dist/core/git-diff.js +0 -160
  35. package/dist/core/graph-metrics.js +0 -233
  36. package/dist/core/indexer.js +0 -552
  37. package/dist/core/project-graph-builder.js +0 -202
  38. package/dist/core/query-classifier.js +0 -144
  39. package/dist/core/query-router.js +0 -210
  40. package/dist/core/rag-evaluator.js +0 -213
  41. package/dist/core/repo-profiler.js +0 -383
  42. package/dist/core/reranker.js +0 -218
  43. package/dist/core/retriever.js +0 -242
  44. package/dist/core/semantic-edge-detector.js +0 -147
  45. package/dist/core/service-mesh-inferrer.js +0 -241
  46. package/dist/core/structural-hasher.js +0 -316
  47. package/dist/core/tree-sitter-parser.js +0 -539
  48. package/dist/core/vector-store.js +0 -259
  49. package/dist/core/workspace-detector.js +0 -481
  50. /package/dist/{core → backends}/types.js +0 -0
@@ -1,259 +0,0 @@
1
- class VectorStore {
2
- db;
3
- // lancedb.Connection
4
- table;
5
- // lancedb.Table
6
- dbPath;
7
- initialized = false;
8
- constructor(dbPath) {
9
- this.dbPath = dbPath;
10
- }
11
- /** Initialize connection, create or open table */
12
- async init() {
13
- let lancedb;
14
- try {
15
- lancedb = await import("@lancedb/lancedb");
16
- } catch {
17
- throw new Error(
18
- "@lancedb/lancedb is not installed. Install it with: npm install @lancedb/lancedb"
19
- );
20
- }
21
- this.db = await lancedb.connect(this.dbPath);
22
- try {
23
- this.table = await this.db.openTable("chunks");
24
- await this.ensureFtsIndex();
25
- this.initialized = true;
26
- } catch {
27
- this.initialized = true;
28
- }
29
- }
30
- /** Create or rebuild the full-text search index on contextualizedContent */
31
- async ensureFtsIndex() {
32
- if (!this.table) return;
33
- try {
34
- const lancedb = await import("@lancedb/lancedb");
35
- await this.table.createIndex("contextualizedContent", {
36
- config: lancedb.Index.fts(),
37
- replace: true
38
- });
39
- } catch {
40
- }
41
- }
42
- /** Insert or replace chunks with embeddings */
43
- async upsertChunks(chunks) {
44
- const rows = chunks.map((c) => ({
45
- id: c.id,
46
- vector: c.embedding,
47
- // LanceDB uses 'vector' field for embeddings
48
- content: c.content,
49
- contextualizedContent: c.contextualizedContent,
50
- contextPrefix: c.contextPrefix,
51
- filePath: c.filePath,
52
- repoName: c.repoName,
53
- project: c.project,
54
- entityType: c.entityType,
55
- entityName: c.entityName ?? "",
56
- parentEntity: c.parentEntity ?? "",
57
- language: c.language,
58
- startLine: c.startLine,
59
- endLine: c.endLine,
60
- tokens: c.tokens
61
- }));
62
- if (!this.table) {
63
- this.table = await this.db.createTable("chunks", rows, { mode: "overwrite" });
64
- } else {
65
- const project = chunks[0]?.project;
66
- if (project) {
67
- try {
68
- await this.table.delete(`project = '${project.replace(/'/g, "''")}'`);
69
- } catch {
70
- }
71
- }
72
- await this.table.add(rows);
73
- }
74
- await this.ensureFtsIndex();
75
- }
76
- /** Semantic vector search */
77
- async vectorSearch(queryEmbedding, opts) {
78
- if (!this.table) return [];
79
- let query = this.table.search(queryEmbedding).limit(opts?.limit ?? 20);
80
- if (opts?.filter) query = query.where(opts.filter);
81
- const results = await query.toArray();
82
- return results.map((r) => ({
83
- chunk: rowToChunk(r),
84
- score: r._distance != null ? 1 / (1 + r._distance) : 0.5,
85
- source: "vector"
86
- }));
87
- }
88
- /** Full-text BM25 search (LanceDB built-in FTS) */
89
- async fullTextSearch(queryText, limit = 20) {
90
- if (!this.table) return [];
91
- try {
92
- const results = await this.table.search(queryText, "fts", "contextualizedContent").limit(limit).toArray();
93
- return results.map((r) => ({
94
- chunk: rowToChunk(r),
95
- score: r._relevance_score ?? 0.5,
96
- source: "bm25"
97
- }));
98
- } catch {
99
- return [];
100
- }
101
- }
102
- /** Get specific chunks by their IDs */
103
- async getByIds(ids) {
104
- if (!this.table || ids.length === 0) return [];
105
- const filter = ids.map((id) => `id = '${id}'`).join(" OR ");
106
- try {
107
- const results = await this.table.filter(filter).toArray();
108
- return results.map((r) => rowToChunk(r));
109
- } catch {
110
- return [];
111
- }
112
- }
113
- /** Look up chunks by repo + file + entity name — for direct AST graph expansion.
114
- * Returns ScoredChunks with a fixed graph-expansion score. */
115
- async getChunksByEntity(lookups) {
116
- if (!this.table || lookups.length === 0) return [];
117
- const esc = (s) => s.replace(/'/g, "''");
118
- const conditions = lookups.map((l) => {
119
- const base = `repoName = '${esc(l.repoName)}' AND filePath = '${esc(l.filePath)}'`;
120
- return l.entityName ? `(${base} AND entityName = '${esc(l.entityName)}')` : `(${base})`;
121
- });
122
- try {
123
- const allResults = [];
124
- const batchSize = 20;
125
- for (let i = 0; i < conditions.length; i += batchSize) {
126
- const batch = conditions.slice(i, i + batchSize).join(" OR ");
127
- const results = await this.table.filter(batch).limit(batchSize * 2).toArray();
128
- for (const r of results) {
129
- allResults.push({
130
- chunk: rowToChunk(r),
131
- score: 0.75,
132
- source: "graph"
133
- });
134
- }
135
- }
136
- return allResults;
137
- } catch {
138
- return [];
139
- }
140
- }
141
- /** Get all chunks for a specific file in a repo (for incremental comparison) */
142
- async getChunksByFile(repoName, filePath) {
143
- if (!this.table) return [];
144
- const esc = (s) => s.replace(/'/g, "''");
145
- try {
146
- const results = await this.table.filter(`repoName = '${esc(repoName)}' AND filePath = '${esc(filePath)}'`).toArray();
147
- return results.map((r) => ({
148
- id: r.id,
149
- content: r.content,
150
- entityName: r.entityName || "",
151
- tokens: r.tokens || 0
152
- }));
153
- } catch {
154
- return [];
155
- }
156
- }
157
- /** Delete specific chunks by their IDs (for surgical updates) */
158
- async deleteChunksByIds(ids) {
159
- if (!this.table || ids.length === 0) return;
160
- const batchSize = 50;
161
- for (let i = 0; i < ids.length; i += batchSize) {
162
- const batch = ids.slice(i, i + batchSize);
163
- const filter = batch.map((id) => `id = '${id.replace(/'/g, "''")}'`).join(" OR ");
164
- try {
165
- await this.table.delete(filter);
166
- } catch {
167
- }
168
- }
169
- }
170
- /** Get all chunk IDs for a project (for incremental diff) */
171
- async getChunkIds(project) {
172
- if (!this.table) return [];
173
- try {
174
- const escapedProject = project.replace(/'/g, "''");
175
- const results = await this.table.query().where(`project = '${escapedProject}'`).select(["id"]).toArray();
176
- return results.map((r) => r.id);
177
- } catch {
178
- return [];
179
- }
180
- }
181
- /** Get index statistics */
182
- async getStats() {
183
- if (!this.table) return null;
184
- try {
185
- const count = await this.table.countRows();
186
- return { rowCount: count };
187
- } catch {
188
- return null;
189
- }
190
- }
191
- /** Check if the store has data */
192
- async hasData() {
193
- const stats = await this.getStats();
194
- return (stats?.rowCount ?? 0) > 0;
195
- }
196
- /** Delete chunks for specific files within a repo (for incremental re-indexing) */
197
- async deleteFileChunks(project, repoName, filePaths) {
198
- if (!this.table || filePaths.length === 0) return;
199
- const escapedProject = project.replace(/'/g, "''");
200
- const escapedRepo = repoName.replace(/'/g, "''");
201
- const fileFilter = filePaths.map((f) => `'${f.replace(/'/g, "''")}'`).join(", ");
202
- try {
203
- await this.table.delete(
204
- `project = '${escapedProject}' AND repoName = '${escapedRepo}' AND filePath IN (${fileFilter})`
205
- );
206
- } catch {
207
- }
208
- }
209
- /** Add chunks without deleting existing project data (for incremental updates) */
210
- async addChunks(chunks) {
211
- if (chunks.length === 0) return;
212
- const rows = chunks.map((c) => ({
213
- id: c.id,
214
- vector: c.embedding,
215
- content: c.content,
216
- contextualizedContent: c.contextualizedContent,
217
- contextPrefix: c.contextPrefix,
218
- filePath: c.filePath,
219
- repoName: c.repoName,
220
- project: c.project,
221
- entityType: c.entityType,
222
- entityName: c.entityName ?? "",
223
- parentEntity: c.parentEntity ?? "",
224
- language: c.language,
225
- startLine: c.startLine,
226
- endLine: c.endLine,
227
- tokens: c.tokens
228
- }));
229
- if (!this.table) {
230
- this.table = await this.db.createTable("chunks", rows, { mode: "overwrite" });
231
- } else {
232
- await this.table.add(rows);
233
- }
234
- await this.ensureFtsIndex();
235
- }
236
- }
237
- function rowToChunk(row) {
238
- return {
239
- id: row.id,
240
- filePath: row.filePath,
241
- repoName: row.repoName,
242
- project: row.project,
243
- startLine: row.startLine,
244
- endLine: row.endLine,
245
- content: row.content,
246
- contextPrefix: row.contextPrefix,
247
- contextualizedContent: row.contextualizedContent,
248
- language: row.language,
249
- entityType: row.entityType,
250
- entityName: row.entityName || void 0,
251
- parentEntity: row.parentEntity || void 0,
252
- tokens: row.tokens,
253
- imports: [],
254
- exports: []
255
- };
256
- }
257
- export {
258
- VectorStore
259
- };