codesearch-mcp 0.0.14-alpha → 0.0.16-alpha

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 ADDED
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
5
+
6
+ ## [0.0.16-alpha] - 2026-05-02
7
+
8
+ ### Added
9
+
10
+ - **Hybrid incremental indexing (mtime + SHA-256)** — `rag-index` now uses a two-step skip check per file: fast `mtime` comparison first (no file read), then SHA-256 content hash if `mtime` changed. Files with identical content but reset timestamps (after `git clone`, DB transfer, or `touch`) are skipped without re-embedding. `lastModified` is refreshed in a single batch SQL `UPDATE` after each project scan. `--reindex` clears both fields.
11
+ - `contentHash varchar(64)` column added to `code_chunk`; applied automatically via `ALTER TABLE ... ADD COLUMN IF NOT EXISTS` on startup — no manual migration needed.
12
+
13
+ ### Changed
14
+
15
+ - **Migrated from TypeORM to Drizzle ORM**
16
+ - **Batch AST parsing (`analyzeProject`)** — `IndexerService` now parses all project files in a single `MorphProject` instance instead of one per file, reducing ts-morph overhead on large projects
17
+ - **Enriched embedding context** — chunks now include `[Symbols: class Foo, function bar]` tag when the chunk overlaps known symbol definitions, improving semantic search quality for partial/truncated chunks. **Requires full re-index** (`rag-index /path --reindex`) — existing embeddings were built without symbol context and will produce degraded similarity scores against new chunks if mixed.
18
+ - **`endLine` added to `SymbolEntry`** — enables accurate chunk-to-symbol overlap detection used by enriched prompts
19
+ - **`analyzeProject` error isolation** — parse failures are caught per-file; one broken file no longer aborts the entire project scan
20
+ - **Memory cleanup in `analyzeProject`** — source files are explicitly removed from `MorphProject` after parsing to release memory
21
+ - **Logging improvements** — `AstParser: analyzeProject done` debug log reports total files, parsed count, and elapsed ms; per-file `depsMs` renamed to `astMs` (now ~0 since AST work is done upfront)
22
+
23
+ ## [0.0.15-alpha] - 2026-05-02
24
+
25
+ ### Changed
26
+
27
+ - **MCP server instructions restructured** — `Step 0` (query classification table) moved before the `Tools` list so it arrives before the truncation threshold and is always visible to the model
28
+ - **Lookup workflow fixed** — corrected order to `find_symbol` first (faster, exact match), `search_codebase` as fallback
29
+ - **Path distinction clarified** — `read_file_range` (relative path) and `read_file` (absolute path) now labelled directly in the Tools list, reducing wrong-path errors
30
+ - **Threshold contradiction resolved** — removed conflicting `0.35` example from Lookup/Conceptual workflow; canonical threshold guidance kept only in Relevance scores section
package/README.md CHANGED
@@ -6,6 +6,8 @@ Ask Claude things like *"where is the payment retry logic?"* or *"show me how au
6
6
 
7
7
  > **Alpha** — works well locally, API may change before 1.0.
8
8
 
9
+ See [CHANGELOG.md](./CHANGELOG.md) for version history.
10
+
9
11
  ## How it works
10
12
 
11
13
  1. `rag-index` scans your projects, chunks source files, embeds them with [bge-m3](https://huggingface.co/BAAI/bge-m3) via Ollama, and stores vectors in PostgreSQL
@@ -1,3 +1,2 @@
1
- export { CodeChunk } from './entities/code-chunk.entity';
2
- export { CodeDependency } from './entities/code-dependency.entity';
3
- export { CodeSymbol } from './entities/code-symbol.entity';
1
+ export { codeChunk, codeDependency, codeSymbol } from './schema';
2
+ export type { CodeChunkInsert } from './schema';
@@ -1,9 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CodeSymbol = exports.CodeDependency = exports.CodeChunk = void 0;
4
- var code_chunk_entity_1 = require("./entities/code-chunk.entity");
5
- Object.defineProperty(exports, "CodeChunk", { enumerable: true, get: function () { return code_chunk_entity_1.CodeChunk; } });
6
- var code_dependency_entity_1 = require("./entities/code-dependency.entity");
7
- Object.defineProperty(exports, "CodeDependency", { enumerable: true, get: function () { return code_dependency_entity_1.CodeDependency; } });
8
- var code_symbol_entity_1 = require("./entities/code-symbol.entity");
9
- Object.defineProperty(exports, "CodeSymbol", { enumerable: true, get: function () { return code_symbol_entity_1.CodeSymbol; } });
3
+ exports.codeSymbol = exports.codeDependency = exports.codeChunk = void 0;
4
+ var schema_1 = require("./schema");
5
+ Object.defineProperty(exports, "codeChunk", { enumerable: true, get: function () { return schema_1.codeChunk; } });
6
+ Object.defineProperty(exports, "codeDependency", { enumerable: true, get: function () { return schema_1.codeDependency; } });
7
+ Object.defineProperty(exports, "codeSymbol", { enumerable: true, get: function () { return schema_1.codeSymbol; } });
@@ -0,0 +1,417 @@
1
+ export declare const codeChunk: import("drizzle-orm/pg-core").PgTableWithColumns<{
2
+ name: "code_chunk";
3
+ schema: undefined;
4
+ columns: {
5
+ id: import("drizzle-orm/pg-core").PgColumn<{
6
+ name: "id";
7
+ tableName: "code_chunk";
8
+ dataType: "string";
9
+ columnType: "PgUUID";
10
+ data: string;
11
+ driverParam: string;
12
+ notNull: true;
13
+ hasDefault: true;
14
+ isPrimaryKey: true;
15
+ isAutoincrement: false;
16
+ hasRuntimeDefault: false;
17
+ enumValues: undefined;
18
+ baseColumn: never;
19
+ identity: undefined;
20
+ generated: undefined;
21
+ }, {}, {}>;
22
+ serviceName: import("drizzle-orm/pg-core").PgColumn<{
23
+ name: "serviceName";
24
+ tableName: "code_chunk";
25
+ dataType: "string";
26
+ columnType: "PgText";
27
+ data: string;
28
+ driverParam: string;
29
+ notNull: true;
30
+ hasDefault: false;
31
+ isPrimaryKey: false;
32
+ isAutoincrement: false;
33
+ hasRuntimeDefault: false;
34
+ enumValues: [string, ...string[]];
35
+ baseColumn: never;
36
+ identity: undefined;
37
+ generated: undefined;
38
+ }, {}, {}>;
39
+ filePath: import("drizzle-orm/pg-core").PgColumn<{
40
+ name: "filePath";
41
+ tableName: "code_chunk";
42
+ dataType: "string";
43
+ columnType: "PgText";
44
+ data: string;
45
+ driverParam: string;
46
+ notNull: true;
47
+ hasDefault: false;
48
+ isPrimaryKey: false;
49
+ isAutoincrement: false;
50
+ hasRuntimeDefault: false;
51
+ enumValues: [string, ...string[]];
52
+ baseColumn: never;
53
+ identity: undefined;
54
+ generated: undefined;
55
+ }, {}, {}>;
56
+ startLine: import("drizzle-orm/pg-core").PgColumn<{
57
+ name: "startLine";
58
+ tableName: "code_chunk";
59
+ dataType: "number";
60
+ columnType: "PgInteger";
61
+ data: number;
62
+ driverParam: string | number;
63
+ notNull: false;
64
+ hasDefault: false;
65
+ isPrimaryKey: false;
66
+ isAutoincrement: false;
67
+ hasRuntimeDefault: false;
68
+ enumValues: undefined;
69
+ baseColumn: never;
70
+ identity: undefined;
71
+ generated: undefined;
72
+ }, {}, {}>;
73
+ content: import("drizzle-orm/pg-core").PgColumn<{
74
+ name: "content";
75
+ tableName: "code_chunk";
76
+ dataType: "string";
77
+ columnType: "PgText";
78
+ data: string;
79
+ driverParam: string;
80
+ notNull: true;
81
+ hasDefault: false;
82
+ isPrimaryKey: false;
83
+ isAutoincrement: false;
84
+ hasRuntimeDefault: false;
85
+ enumValues: [string, ...string[]];
86
+ baseColumn: never;
87
+ identity: undefined;
88
+ generated: undefined;
89
+ }, {}, {}>;
90
+ embedding: import("drizzle-orm/pg-core").PgColumn<{
91
+ name: "embedding";
92
+ tableName: "code_chunk";
93
+ dataType: "custom";
94
+ columnType: "PgCustomColumn";
95
+ data: string;
96
+ driverParam: unknown;
97
+ notNull: true;
98
+ hasDefault: false;
99
+ isPrimaryKey: false;
100
+ isAutoincrement: false;
101
+ hasRuntimeDefault: false;
102
+ enumValues: undefined;
103
+ baseColumn: never;
104
+ identity: undefined;
105
+ generated: undefined;
106
+ }, {}, {
107
+ pgColumnBuilderBrand: "PgCustomColumnBuilderBrand";
108
+ }>;
109
+ lastModified: import("drizzle-orm/pg-core").PgColumn<{
110
+ name: "lastModified";
111
+ tableName: "code_chunk";
112
+ dataType: "number";
113
+ columnType: "PgDoublePrecision";
114
+ data: number;
115
+ driverParam: string | number;
116
+ notNull: false;
117
+ hasDefault: false;
118
+ isPrimaryKey: false;
119
+ isAutoincrement: false;
120
+ hasRuntimeDefault: false;
121
+ enumValues: undefined;
122
+ baseColumn: never;
123
+ identity: undefined;
124
+ generated: undefined;
125
+ }, {}, {}>;
126
+ contentHash: import("drizzle-orm/pg-core").PgColumn<{
127
+ name: "contentHash";
128
+ tableName: "code_chunk";
129
+ dataType: "string";
130
+ columnType: "PgVarchar";
131
+ data: string;
132
+ driverParam: string;
133
+ notNull: false;
134
+ hasDefault: false;
135
+ isPrimaryKey: false;
136
+ isAutoincrement: false;
137
+ hasRuntimeDefault: false;
138
+ enumValues: [string, ...string[]];
139
+ baseColumn: never;
140
+ identity: undefined;
141
+ generated: undefined;
142
+ }, {}, {
143
+ length: 64;
144
+ }>;
145
+ };
146
+ dialect: "pg";
147
+ }>;
148
+ export declare const codeDependency: import("drizzle-orm/pg-core").PgTableWithColumns<{
149
+ name: "code_dependency";
150
+ schema: undefined;
151
+ columns: {
152
+ id: import("drizzle-orm/pg-core").PgColumn<{
153
+ name: "id";
154
+ tableName: "code_dependency";
155
+ dataType: "string";
156
+ columnType: "PgUUID";
157
+ data: string;
158
+ driverParam: string;
159
+ notNull: true;
160
+ hasDefault: true;
161
+ isPrimaryKey: true;
162
+ isAutoincrement: false;
163
+ hasRuntimeDefault: false;
164
+ enumValues: undefined;
165
+ baseColumn: never;
166
+ identity: undefined;
167
+ generated: undefined;
168
+ }, {}, {}>;
169
+ project: import("drizzle-orm/pg-core").PgColumn<{
170
+ name: "project";
171
+ tableName: "code_dependency";
172
+ dataType: "string";
173
+ columnType: "PgText";
174
+ data: string;
175
+ driverParam: string;
176
+ notNull: true;
177
+ hasDefault: false;
178
+ isPrimaryKey: false;
179
+ isAutoincrement: false;
180
+ hasRuntimeDefault: false;
181
+ enumValues: [string, ...string[]];
182
+ baseColumn: never;
183
+ identity: undefined;
184
+ generated: undefined;
185
+ }, {}, {}>;
186
+ fromFile: import("drizzle-orm/pg-core").PgColumn<{
187
+ name: "fromFile";
188
+ tableName: "code_dependency";
189
+ dataType: "string";
190
+ columnType: "PgText";
191
+ data: string;
192
+ driverParam: string;
193
+ notNull: true;
194
+ hasDefault: false;
195
+ isPrimaryKey: false;
196
+ isAutoincrement: false;
197
+ hasRuntimeDefault: false;
198
+ enumValues: [string, ...string[]];
199
+ baseColumn: never;
200
+ identity: undefined;
201
+ generated: undefined;
202
+ }, {}, {}>;
203
+ fromSymbol: import("drizzle-orm/pg-core").PgColumn<{
204
+ name: "fromSymbol";
205
+ tableName: "code_dependency";
206
+ dataType: "string";
207
+ columnType: "PgText";
208
+ data: string;
209
+ driverParam: string;
210
+ notNull: false;
211
+ hasDefault: false;
212
+ isPrimaryKey: false;
213
+ isAutoincrement: false;
214
+ hasRuntimeDefault: false;
215
+ enumValues: [string, ...string[]];
216
+ baseColumn: never;
217
+ identity: undefined;
218
+ generated: undefined;
219
+ }, {}, {}>;
220
+ toFile: import("drizzle-orm/pg-core").PgColumn<{
221
+ name: "toFile";
222
+ tableName: "code_dependency";
223
+ dataType: "string";
224
+ columnType: "PgText";
225
+ data: string;
226
+ driverParam: string;
227
+ notNull: true;
228
+ hasDefault: false;
229
+ isPrimaryKey: false;
230
+ isAutoincrement: false;
231
+ hasRuntimeDefault: false;
232
+ enumValues: [string, ...string[]];
233
+ baseColumn: never;
234
+ identity: undefined;
235
+ generated: undefined;
236
+ }, {}, {}>;
237
+ toSymbol: import("drizzle-orm/pg-core").PgColumn<{
238
+ name: "toSymbol";
239
+ tableName: "code_dependency";
240
+ dataType: "string";
241
+ columnType: "PgText";
242
+ data: string;
243
+ driverParam: string;
244
+ notNull: false;
245
+ hasDefault: false;
246
+ isPrimaryKey: false;
247
+ isAutoincrement: false;
248
+ hasRuntimeDefault: false;
249
+ enumValues: [string, ...string[]];
250
+ baseColumn: never;
251
+ identity: undefined;
252
+ generated: undefined;
253
+ }, {}, {}>;
254
+ depType: import("drizzle-orm/pg-core").PgColumn<{
255
+ name: "depType";
256
+ tableName: "code_dependency";
257
+ dataType: "string";
258
+ columnType: "PgText";
259
+ data: string;
260
+ driverParam: string;
261
+ notNull: true;
262
+ hasDefault: false;
263
+ isPrimaryKey: false;
264
+ isAutoincrement: false;
265
+ hasRuntimeDefault: false;
266
+ enumValues: [string, ...string[]];
267
+ baseColumn: never;
268
+ identity: undefined;
269
+ generated: undefined;
270
+ }, {}, {}>;
271
+ };
272
+ dialect: "pg";
273
+ }>;
274
+ export declare const codeSymbol: import("drizzle-orm/pg-core").PgTableWithColumns<{
275
+ name: "code_symbol";
276
+ schema: undefined;
277
+ columns: {
278
+ id: import("drizzle-orm/pg-core").PgColumn<{
279
+ name: "id";
280
+ tableName: "code_symbol";
281
+ dataType: "string";
282
+ columnType: "PgUUID";
283
+ data: string;
284
+ driverParam: string;
285
+ notNull: true;
286
+ hasDefault: true;
287
+ isPrimaryKey: true;
288
+ isAutoincrement: false;
289
+ hasRuntimeDefault: false;
290
+ enumValues: undefined;
291
+ baseColumn: never;
292
+ identity: undefined;
293
+ generated: undefined;
294
+ }, {}, {}>;
295
+ project: import("drizzle-orm/pg-core").PgColumn<{
296
+ name: "project";
297
+ tableName: "code_symbol";
298
+ dataType: "string";
299
+ columnType: "PgText";
300
+ data: string;
301
+ driverParam: string;
302
+ notNull: true;
303
+ hasDefault: false;
304
+ isPrimaryKey: false;
305
+ isAutoincrement: false;
306
+ hasRuntimeDefault: false;
307
+ enumValues: [string, ...string[]];
308
+ baseColumn: never;
309
+ identity: undefined;
310
+ generated: undefined;
311
+ }, {}, {}>;
312
+ filePath: import("drizzle-orm/pg-core").PgColumn<{
313
+ name: "filePath";
314
+ tableName: "code_symbol";
315
+ dataType: "string";
316
+ columnType: "PgText";
317
+ data: string;
318
+ driverParam: string;
319
+ notNull: true;
320
+ hasDefault: false;
321
+ isPrimaryKey: false;
322
+ isAutoincrement: false;
323
+ hasRuntimeDefault: false;
324
+ enumValues: [string, ...string[]];
325
+ baseColumn: never;
326
+ identity: undefined;
327
+ generated: undefined;
328
+ }, {}, {}>;
329
+ name: import("drizzle-orm/pg-core").PgColumn<{
330
+ name: "name";
331
+ tableName: "code_symbol";
332
+ dataType: "string";
333
+ columnType: "PgText";
334
+ data: string;
335
+ driverParam: string;
336
+ notNull: true;
337
+ hasDefault: false;
338
+ isPrimaryKey: false;
339
+ isAutoincrement: false;
340
+ hasRuntimeDefault: false;
341
+ enumValues: [string, ...string[]];
342
+ baseColumn: never;
343
+ identity: undefined;
344
+ generated: undefined;
345
+ }, {}, {}>;
346
+ kind: import("drizzle-orm/pg-core").PgColumn<{
347
+ name: "kind";
348
+ tableName: "code_symbol";
349
+ dataType: "string";
350
+ columnType: "PgText";
351
+ data: string;
352
+ driverParam: string;
353
+ notNull: true;
354
+ hasDefault: false;
355
+ isPrimaryKey: false;
356
+ isAutoincrement: false;
357
+ hasRuntimeDefault: false;
358
+ enumValues: [string, ...string[]];
359
+ baseColumn: never;
360
+ identity: undefined;
361
+ generated: undefined;
362
+ }, {}, {}>;
363
+ signature: import("drizzle-orm/pg-core").PgColumn<{
364
+ name: "signature";
365
+ tableName: "code_symbol";
366
+ dataType: "string";
367
+ columnType: "PgText";
368
+ data: string;
369
+ driverParam: string;
370
+ notNull: false;
371
+ hasDefault: false;
372
+ isPrimaryKey: false;
373
+ isAutoincrement: false;
374
+ hasRuntimeDefault: false;
375
+ enumValues: [string, ...string[]];
376
+ baseColumn: never;
377
+ identity: undefined;
378
+ generated: undefined;
379
+ }, {}, {}>;
380
+ line: import("drizzle-orm/pg-core").PgColumn<{
381
+ name: "line";
382
+ tableName: "code_symbol";
383
+ dataType: "number";
384
+ columnType: "PgInteger";
385
+ data: number;
386
+ driverParam: string | number;
387
+ notNull: false;
388
+ hasDefault: false;
389
+ isPrimaryKey: false;
390
+ isAutoincrement: false;
391
+ hasRuntimeDefault: false;
392
+ enumValues: undefined;
393
+ baseColumn: never;
394
+ identity: undefined;
395
+ generated: undefined;
396
+ }, {}, {}>;
397
+ col: import("drizzle-orm/pg-core").PgColumn<{
398
+ name: "col";
399
+ tableName: "code_symbol";
400
+ dataType: "number";
401
+ columnType: "PgInteger";
402
+ data: number;
403
+ driverParam: string | number;
404
+ notNull: false;
405
+ hasDefault: false;
406
+ isPrimaryKey: false;
407
+ isAutoincrement: false;
408
+ hasRuntimeDefault: false;
409
+ enumValues: undefined;
410
+ baseColumn: never;
411
+ identity: undefined;
412
+ generated: undefined;
413
+ }, {}, {}>;
414
+ };
415
+ dialect: "pg";
416
+ }>;
417
+ export type CodeChunkInsert = typeof codeChunk.$inferInsert;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.codeSymbol = exports.codeDependency = exports.codeChunk = void 0;
4
+ const pg_core_1 = require("drizzle-orm/pg-core");
5
+ const vector = (0, pg_core_1.customType)({
6
+ dataType(config) { return `vector(${config?.dimensions ?? 1024})`; },
7
+ });
8
+ exports.codeChunk = (0, pg_core_1.pgTable)('code_chunk', {
9
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
10
+ serviceName: (0, pg_core_1.text)('serviceName').notNull(),
11
+ filePath: (0, pg_core_1.text)('filePath').notNull(),
12
+ startLine: (0, pg_core_1.integer)('startLine'),
13
+ content: (0, pg_core_1.text)('content').notNull(),
14
+ embedding: vector('embedding', { dimensions: 1024 }).notNull(),
15
+ lastModified: (0, pg_core_1.doublePrecision)('lastModified'),
16
+ contentHash: (0, pg_core_1.varchar)('contentHash', { length: 64 }),
17
+ });
18
+ exports.codeDependency = (0, pg_core_1.pgTable)('code_dependency', {
19
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
20
+ project: (0, pg_core_1.text)('project').notNull(),
21
+ fromFile: (0, pg_core_1.text)('fromFile').notNull(),
22
+ fromSymbol: (0, pg_core_1.text)('fromSymbol'),
23
+ toFile: (0, pg_core_1.text)('toFile').notNull(),
24
+ toSymbol: (0, pg_core_1.text)('toSymbol'),
25
+ depType: (0, pg_core_1.text)('depType').notNull(),
26
+ });
27
+ exports.codeSymbol = (0, pg_core_1.pgTable)('code_symbol', {
28
+ id: (0, pg_core_1.uuid)('id').primaryKey().defaultRandom(),
29
+ project: (0, pg_core_1.text)('project').notNull(),
30
+ filePath: (0, pg_core_1.text)('filePath').notNull(),
31
+ name: (0, pg_core_1.text)('name').notNull(),
32
+ kind: (0, pg_core_1.text)('kind').notNull(),
33
+ signature: (0, pg_core_1.text)('signature'),
34
+ line: (0, pg_core_1.integer)('line'),
35
+ col: (0, pg_core_1.integer)('col'),
36
+ });
@@ -13,6 +13,7 @@ export interface SymbolEntry {
13
13
  kind: 'function' | 'class' | 'interface' | 'type' | 'variable' | 'method';
14
14
  signature: string | null;
15
15
  line: number | null;
16
+ endLine: number | null;
16
17
  col: number | null;
17
18
  }
18
19
  export interface FileAnalysis {
@@ -20,5 +21,10 @@ export interface FileAnalysis {
20
21
  symbols: SymbolEntry[];
21
22
  }
22
23
  export interface IAstParser {
24
+ /**
25
+ * @deprecated Use analyzeProject instead for project-wide context.
26
+ */
23
27
  analyzeFile(filePath: string, serviceName: string, projectRoot?: string): Promise<FileAnalysis>;
28
+ analyzeProject(filePaths: string[], serviceName: string, projectRoot?: string): Promise<Map<string, FileAnalysis>>;
29
+ clearCache(projectRoot?: string): void;
24
30
  }
@@ -4,8 +4,11 @@ export declare class AstParserService implements IAstParser {
4
4
  private logger;
5
5
  private morphProjects;
6
6
  constructor(logger?: LoggerService);
7
+ analyzeProject(filePaths: string[], serviceName: string, projectRoot?: string): Promise<Map<string, FileAnalysis>>;
8
+ clearCache(projectRoot?: string): void;
7
9
  analyzeFile(filePath: string, serviceName: string, projectRoot?: string): Promise<FileAnalysis>;
8
10
  extractImportEdges(filePath: string, serviceName: string, projectRoot?: string): Promise<DepEdge[]>;
11
+ private createMorphProject;
9
12
  private getMorphProject;
10
13
  private extractEdges;
11
14
  private resolveFromSymbol;